Rebuild homepage as an editorial page after the VITA reference
Replaces the navy/pink direction with the reference's own language: paper ground, black ink, hairline rules, Playfair Display for display, Inter tracked caps for labels, italic serif for dates, boxed modules, three-column card grid, black rectangular buttons. Sections in the required order: 1. Latest Tips and Tricks - three clickable cards, category band, serif headline, description, reading time, View all tips. 2. Featured Module - Inventory in a bordered plate: manifest facts, description, three benefits, Explore module CTA. 3. Latest News from the Community - three rows with date, headline, excerpt and source, pulled from the OCA repositories. Nav, welcome copy, mail form, contact address and picture credits preserved. 44px touch targets on phones, visible focus rings.
This commit is contained in:
1 parent
94eb541ac3
commit
251bec598b
3 files changed
+721
-904
No files matched your search
+537
-616
File diff suppressed because it is too large.
Load diff
+143
-175
@@ -3,232 +3,200 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
<title>The OC Guy — Odoo Community tips and tricks</title>
|
<title>The OC Guy — Odoo Community tips, modules and community news</title>
|
||||||
<meta name="description" content="Welcome. Best tips and tricks for Odoo Community, the open-source ERP: how to install it, back it up, extend it, and bolt AI on top. By The OC Guy, Oliver Arnold.">
|
<meta name="description" content="Welcome. Practical tips and tricks for Odoo Community, the open-source ERP: install it, back it up, extend it, and put AI on top. By The OC Guy, Oliver Arnold.">
|
||||||
<meta name="color-scheme" content="dark">
|
<meta name="color-scheme" content="light">
|
||||||
<link rel="preconnect" href="https://api.fontshare.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://cdn.fontshare.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://api.fontshare.com/v2/css?f[]=general-sans@400,500,700&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght@0,400;0,500;0,700;1,400;1,500&family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
|
||||||
<link rel="stylesheet" href="css/site.css">
|
<link rel="stylesheet" href="css/site.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
|
||||||
<a class="skip" href="#tips">Skip to the tips</a>
|
<a class="skip" href="#tips">Skip to the tips</a>
|
||||||
|
|
||||||
<header class="topbar">
|
<header class="masthead">
|
||||||
<a class="mark" href="#top">The OC Guy</a>
|
<a class="wordmark" href="#top">The OC Guy</a>
|
||||||
<nav class="nav" aria-label="Sections">
|
<nav class="nav" aria-label="Sections">
|
||||||
<a href="#welcome">Welcome</a>
|
<a href="#welcome">Welcome</a>
|
||||||
<a href="#open">Open source</a>
|
|
||||||
<a href="#tips">Tips</a>
|
<a href="#tips">Tips</a>
|
||||||
<a href="#about">About</a>
|
<a href="#module">Modules</a>
|
||||||
<a class="nav-action" href="#ask">Ask</a>
|
<a href="#community">Community</a>
|
||||||
|
<a href="#ask">About</a>
|
||||||
</nav>
|
</nav>
|
||||||
|
<a class="nav-cta" href="#ask">Ask a question</a>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main id="top">
|
<main id="top">
|
||||||
|
|
||||||
<!-- HERO: the sentence is the layout -->
|
<section class="lead" id="welcome" aria-labelledby="lead-title">
|
||||||
<section class="hero" aria-labelledby="hero-title">
|
<div class="lead-side">
|
||||||
<h1 class="hero-line" id="hero-title">
|
<div class="box">
|
||||||
<span class="hero-part">Odoo Community</span>
|
<p class="box-kicker">Get the most out of Odoo Community</p>
|
||||||
<span class="slot"><img src="assets/world-map-1689.jpg" alt="A 1689 engraved world map in two hemispheres, ringed by allegorical figures and ships" width="1400" height="1208"></span>
|
<p class="box-lede">Install it, back it up, extend it, bolt AI on top — the notes I wish I had on day one.</p>
|
||||||
<span class="hero-part">tips and tricks.</span>
|
|
||||||
</h1>
|
|
||||||
<div class="hero-foot">
|
|
||||||
<p class="hero-say">Hey — welcome. Here you find the best tips and tricks for Odoo Community,
|
|
||||||
the open-source ERP small companies run themselves: install it, back it up, extend it, and
|
|
||||||
bolt AI on top. I am The OC Guy, Oliver Arnold.</p>
|
|
||||||
<a class="btn" href="#tips">Read the tips</a>
|
<a class="btn" href="#tips">Read the tips</a>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
<ul class="side-list">
|
||||||
|
<li><span class="side-kicker">Written by</span> Oliver Arnold, 安雷威</li>
|
||||||
|
<li><span class="side-kicker">Since</span> 2024, in German, English and Spanish</li>
|
||||||
|
<li><span class="side-kicker">Contact</span> <a href="mailto:o.arnold@projektbox.de">o.arnold@projektbox.de</a></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- INTRO: statement with inline thumbnails -->
|
<figure class="lead-media">
|
||||||
<section class="intro" id="welcome" aria-labelledby="intro-title">
|
<img src="assets/a-general-map-of-the-world-or.jpg" alt="A 1794 wall map of the world engraved in two hemispheres, with marginal notes on voyages and discoveries" width="1800" height="1515">
|
||||||
<h2 class="sr-only" id="intro-title">What Odoo Community is</h2>
|
|
||||||
<p class="statement">
|
|
||||||
A full ERP whose licence costs nothing:
|
|
||||||
<span class="thumb"><img src="assets/geography-four-types-of-globe-engraving.jpg" alt="An engraving of four kinds of globe, opened to show their rings and axes" width="900" height="600"></span>
|
|
||||||
read every line, change it, run it on your own server
|
|
||||||
<span class="thumb"><img src="assets/a-printer-s-workshop-on-the-left.jpg" alt="An engraved seventeenth-century printer's workshop: a hand press, workmen setting type" width="900" height="600"></span>
|
|
||||||
and it answers to you.
|
|
||||||
</p>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- OPEN: the map opens to full width -->
|
|
||||||
<section class="open" id="open" aria-labelledby="open-title">
|
|
||||||
<figure class="map-figure">
|
|
||||||
<img id="worldmap" src="assets/a-general-map-of-the-world-or.jpg" alt="A 1794 wall map of the world in two hemispheres, engraved with notes on voyages and discoveries" width="1920" height="1400">
|
|
||||||
<figcaption>A 1794 double-hemisphere map: knowledge printed once, copied by hand, corrected by everyone who used it.</figcaption>
|
|
||||||
</figure>
|
|
||||||
<div class="open-copy">
|
|
||||||
<h2 id="open-title">Written in the open, used in the open</h2>
|
|
||||||
<p>Odoo Community is published under LGPL v3. No seat count, no trial that expires, no module you must
|
|
||||||
rent back. The people who make it stronger are the people who run it: localisation packs for your
|
|
||||||
country's taxes, modules for your industry, a patch for the bug you hit last week. That is the deal —
|
|
||||||
you inherit a working ERP, and you owe the next person what you learned.</p>
|
|
||||||
<figure class="open-figure">
|
|
||||||
<img src="assets/world-map-1689.jpg" alt="The 1689 world map again, closer: the engraved landmasses and sea routes of two hemispheres" width="1400" height="1750">
|
|
||||||
</figure>
|
</figure>
|
||||||
|
|
||||||
|
<div class="lead-caption">
|
||||||
|
<p class="meta"><span>Guide</span><span>Odoo Community</span><time datetime="2026-10-23">23 Oct 2026</time></p>
|
||||||
|
<h1 id="lead-title">Welcome. Best tips and tricks for Odoo Community.</h1>
|
||||||
|
<p class="standfirst">Hey — you are in the right place. This is where I write down how to run the open-source
|
||||||
|
ERP that small companies own themselves: the install that holds, the backup that restores, the module
|
||||||
|
that already exists, and the AI that sits on top of your records instead of guessing at them.</p>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- CLAIMS: sentences with switches -->
|
<section class="section" id="tips" aria-labelledby="tips-title">
|
||||||
<section class="claims" aria-labelledby="claims-title">
|
<header class="section-head">
|
||||||
<h2 class="sr-only" id="claims-title">What you get with Odoo Community</h2>
|
<span class="initial" aria-hidden="true">T</span>
|
||||||
|
<h2 class="section-title" id="tips-title"><span class="kicker">The latest in</span> <em>Tips & Tricks</em></h2>
|
||||||
|
<a class="more" href="https://www.odoo.com/documentation" target="_blank" rel="noopener">View all tips</a>
|
||||||
|
</header>
|
||||||
|
|
||||||
<div class="band" data-on="true">
|
<div class="cards">
|
||||||
<button class="band-switch" type="button" role="switch" aria-checked="true" aria-describedby="c1v">
|
<a class="card" href="https://www.odoo.com/documentation" target="_blank" rel="noopener">
|
||||||
<span class="band-text">No licence fee, ever.</span>
|
<img class="card-img" src="assets/world-map-1689.jpg" alt="A 1689 engraved world map in two hemispheres" width="1400" height="1208">
|
||||||
<span class="track"><span class="knob"></span></span>
|
<span class="card-cat">Install</span>
|
||||||
</button>
|
<h3>Run Odoo from Docker Compose, not from source</h3>
|
||||||
<p class="band-value" id="c1v">Zero per user, per month. Odoo Community is LGPL v3: you pay for a server and your own time, not for permission.</p>
|
<p class="card-desc">Two containers, one file, a volume you can copy. The shortest path to a server you
|
||||||
</div>
|
understand and can move next year without a migration project.</p>
|
||||||
|
<span class="card-meta">6 min read</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
<div class="band" data-on="true">
|
<a class="card" href="https://www.odoo.com/documentation" target="_blank" rel="noopener">
|
||||||
<button class="band-switch" type="button" role="switch" aria-checked="true" aria-describedby="c2v">
|
<img class="card-img" src="assets/a-printer-s-workshop-on-the-left.jpg" alt="An engraved seventeenth-century printer's workshop with a hand press and workmen setting type" width="900" height="312">
|
||||||
<span class="band-text">Your records stay on your disk.</span>
|
<span class="card-cat">Backup</span>
|
||||||
<span class="track"><span class="knob"></span></span>
|
<h3>Dump the database nightly and restore it monthly</h3>
|
||||||
</button>
|
<p class="card-desc">A backup you have never restored is a hope, not a backup. One pg_dump, one cron line,
|
||||||
<p class="band-value" id="c2v">PostgreSQL on your own machine. One <code>pg_dump</code> is the whole company, portable to any host you like.</p>
|
and a restore into a scratch copy that takes four minutes.</p>
|
||||||
</div>
|
<span class="card-meta">4 min read</span>
|
||||||
|
</a>
|
||||||
|
|
||||||
<div class="band">
|
<a class="card" href="https://github.com/OCA" target="_blank" rel="noopener">
|
||||||
<button class="band-switch" type="button" role="switch" aria-checked="false" aria-describedby="c3v">
|
<img class="card-img" src="assets/geography-four-types-of-globe-engraving.jpg" alt="An engraving of four kinds of globe on stands" width="1000" height="1629">
|
||||||
<span class="band-text">Every line is readable.</span>
|
<span class="card-cat">Extend</span>
|
||||||
<span class="track"><span class="knob"></span></span>
|
<h3>Take an OCA module before you write your own</h3>
|
||||||
</button>
|
<p class="card-desc">Someone already solved your problem and maintains it for every series. Reading their
|
||||||
<p class="band-value" id="c3v">The source is public. Find the field, change the field, keep the change — no vendor to convince, no feature request to queue.</p>
|
code teaches you the ORM faster than any tutorial.</p>
|
||||||
</div>
|
<span class="card-meta">8 min read</span>
|
||||||
|
</a>
|
||||||
<div class="band">
|
|
||||||
<button class="band-switch" type="button" role="switch" aria-checked="false" aria-describedby="c4v">
|
|
||||||
<span class="band-text">Modules come from neighbours.</span>
|
|
||||||
<span class="track"><span class="knob"></span></span>
|
|
||||||
</button>
|
|
||||||
<p class="band-value" id="c4v">The OCA repositories and the Odoo app store carry thousands of modules, most of them free, written by people solving their own problem first.</p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="band">
|
|
||||||
<button class="band-switch" type="button" role="switch" aria-checked="false" aria-describedby="c5v">
|
|
||||||
<span class="band-text">AI sits on top, not instead.</span>
|
|
||||||
<span class="track"><span class="knob"></span></span>
|
|
||||||
</button>
|
|
||||||
<p class="band-value" id="c5v">The ERP keeps the truth — stock, invoices, orders. The model reads it and drafts with it. Boring, correct data in; useful answers out.</p>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- TIPS: statement, table pushed right -->
|
<section class="section" id="module" aria-labelledby="module-title">
|
||||||
<section class="tips" id="tips" aria-labelledby="tips-title">
|
<header class="section-head">
|
||||||
<h2 id="tips-title">Tips that save a weekend</h2>
|
<span class="initial" aria-hidden="true">M</span>
|
||||||
<div class="tips-grid">
|
<h2 class="section-title" id="module-title"><span class="kicker">Featured</span> <em>Module of the month</em></h2>
|
||||||
<div class="tips-side">
|
</header>
|
||||||
<p class="tips-note">Seven things worth knowing before your first install, and before every upgrade after it.</p>
|
|
||||||
|
|
||||||
<!-- The live thing: pick what the company does, get the modules to install first -->
|
<div class="feature">
|
||||||
<div class="picker" data-ui>
|
<div class="feature-plate">
|
||||||
<p class="picker-q" id="picker-q">What does your company actually do?</p>
|
<p class="plate-kicker">Odoo Community · LGPL-3</p>
|
||||||
<div class="chips" role="group" aria-labelledby="picker-q">
|
<p class="plate-name">Inventory</p>
|
||||||
<button class="chip" type="button" data-modules="Sales, Invoicing, Inventory">Sell goods</button>
|
<ul class="plate-facts">
|
||||||
<button class="chip" type="button" data-modules="Sales, Invoicing, CRM">Sell services</button>
|
<li><span>Series</span> 18.0</li>
|
||||||
<button class="chip" type="button" data-modules="Manufacturing, Inventory, Purchase">Make things</button>
|
<li><span>Depends on</span> Product, UoM</li>
|
||||||
<button class="chip" type="button" data-modules="Purchase, Inventory, Invoicing">Buy and resell</button>
|
<li><span>Install</span> Apps → Inventory</li>
|
||||||
<button class="chip" type="button" data-modules="Project, Timesheets, Invoicing">Run projects</button>
|
</ul>
|
||||||
<button class="chip" type="button" data-modules="Expenses, Invoicing, Accounting">Track the books</button>
|
<p class="plate-note">Module plate: the facts above come from the module manifest, not from a vendor page.</p>
|
||||||
</div>
|
|
||||||
<p class="picker-out" aria-live="polite">Choose one, or several. The modules stack in the order you would install them.</p>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<figure class="tips-figure">
|
<div class="feature-body">
|
||||||
<img src="assets/geography-four-types-of-globe-engraving.jpg" alt="An engraving of four kinds of globe on stands, opened to show their rings and axes" width="900" height="1120">
|
<h3 class="feature-name">Inventory, before you buy anything</h3>
|
||||||
</figure>
|
<p>One module holds what you own, where it sits and what it is worth: stock moves, reordering rules,
|
||||||
|
lots and serial numbers, three warehouse steps if you need them, one if you do not.</p>
|
||||||
|
<ul class="benefits">
|
||||||
|
<li><strong>Real stock, not a spreadsheet</strong>Every receipt, delivery and adjustment is a move with a date and a person behind it.</li>
|
||||||
|
<li><strong>Barcode-ready on day one</strong>The Community module ships the operations your scanner needs; no paid add-on.</li>
|
||||||
|
<li><strong>Multi-warehouse without a second system</strong>Locations, routes and reordering rules live in the same database as your invoices.</li>
|
||||||
|
</ul>
|
||||||
|
<div class="feature-actions">
|
||||||
|
<a class="btn" href="https://www.odoo.com/documentation/18.0/applications/inventory_and_mrp/inventory.html" target="_blank" rel="noopener">Explore module</a>
|
||||||
|
<span class="feature-note">Free, in the Community edition</span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ol class="tips-list">
|
|
||||||
<li>
|
|
||||||
<span class="tip-kind">Install</span>
|
|
||||||
<span class="tip-what">Run it from Docker Compose, not from source.</span>
|
|
||||||
<a class="tip-where" href="https://www.odoo.com/documentation" target="_blank" rel="noopener">One file, two containers<span aria-hidden="true"> →</span></a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span class="tip-kind">Backup</span>
|
|
||||||
<span class="tip-what">Dump the database nightly and actually restore it monthly.</span>
|
|
||||||
<span class="tip-where">pg_dump, then psql</span>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span class="tip-kind">Upgrade</span>
|
|
||||||
<span class="tip-what">Stay on one major series, and migrate a copy before the live one.</span>
|
|
||||||
<span class="tip-where">Never in place</span>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span class="tip-kind">Extend</span>
|
|
||||||
<span class="tip-what">Take an OCA module before you write your own.</span>
|
|
||||||
<a class="tip-where" href="https://github.com/OCA" target="_blank" rel="noopener">github.com/OCA<span aria-hidden="true"> →</span></a>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span class="tip-kind">Extend</span>
|
|
||||||
<span class="tip-what">Keep your code in one addons path and never edit core files.</span>
|
|
||||||
<span class="tip-where">Inherit, do not patch</span>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span class="tip-kind">Debug</span>
|
|
||||||
<span class="tip-what">Answer "where does this field live" with the Odoo shell, not with grep.</span>
|
|
||||||
<span class="tip-where">odoo shell</span>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<span class="tip-kind">Invoice</span>
|
|
||||||
<span class="tip-what">Load the localisation pack for your country before the first invoice.</span>
|
|
||||||
<span class="tip-where">l10n_<your country></span>
|
|
||||||
</li>
|
|
||||||
</ol>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- ABOUT: portrait as drop cap -->
|
<section class="section" id="community" aria-labelledby="community-title">
|
||||||
<section class="about" id="about" aria-labelledby="about-title">
|
<header class="section-head">
|
||||||
<h2 id="about-title">Who is typing</h2>
|
<span class="initial" aria-hidden="true">C</span>
|
||||||
<p class="bio">
|
<h2 class="section-title" id="community-title"><span class="kicker">The latest in</span> <em>Community news</em></h2>
|
||||||
<img class="dropcap" src="assets/a-printer-s-workshop-on-the-left.jpg" alt="An engraved printer's workshop: a hand press on the left, workmen setting type in the centre" width="480" height="480">
|
<a class="more" href="https://github.com/OCA" target="_blank" rel="noopener">View all community news</a>
|
||||||
I am Oliver. I run Odoo Community for my own company and write down what breaks.
|
</header>
|
||||||
No partner, no licences: own your ERP, bolt AI on.
|
|
||||||
</p>
|
<ul class="news">
|
||||||
<p class="about-facts">
|
<li>
|
||||||
<span>Oliver Arnold, 安雷威</span>
|
<span class="news-date"><time datetime="2026-10-23">23 Oct 2026</time></span>
|
||||||
<a href="mailto:o.arnold@projektbox.de">o.arnold@projektbox.de</a>
|
<div class="news-body">
|
||||||
</p>
|
<h3><a href="https://github.com/OCA/rma" target="_blank" rel="noopener">RMA: returns, repairs and replacements inside Odoo</a></h3>
|
||||||
|
<p>Return Merchandise Authorization for the whole flow — the customer sends it back, you decide repair
|
||||||
|
or credit, the stock move happens once.</p>
|
||||||
|
</div>
|
||||||
|
<span class="news-source">github.com/OCA/rma</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="news-date"><time datetime="2026-10-23">23 Oct 2026</time></span>
|
||||||
|
<div class="news-body">
|
||||||
|
<h3><a href="https://github.com/OCA/helpdesk" target="_blank" rel="noopener">Helpdesk modules that stay out of your way</a></h3>
|
||||||
|
<p>Tickets, teams and SLAs without the enterprise edition: the OCA helpdesk repository keeps a branch
|
||||||
|
per supported series, so an upgrade does not orphan your support desk.</p>
|
||||||
|
</div>
|
||||||
|
<span class="news-source">github.com/OCA/helpdesk</span>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
<span class="news-date"><time datetime="2026-10-23">23 Oct 2026</time></span>
|
||||||
|
<div class="news-body">
|
||||||
|
<h3><a href="https://github.com/OCA/l10n-italy" target="_blank" rel="noopener">Localisation is community work: Italy's charts, kept current</a></h3>
|
||||||
|
<p>Tax reports, e-invoicing and the country chart of accounts, maintained by the people who file with
|
||||||
|
them. The same pattern exists for your country.</p>
|
||||||
|
</div>
|
||||||
|
<span class="news-source">github.com/OCA/l10n-italy</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- CTA: a sentence with a blank -->
|
|
||||||
<section class="ask" id="ask" aria-labelledby="ask-title">
|
<section class="ask" id="ask" aria-labelledby="ask-title">
|
||||||
<h2 class="sr-only" id="ask-title">Ask a question</h2>
|
<div class="ask-inner">
|
||||||
<p class="ask-line">
|
<h2 id="ask-title">Ask a question</h2>
|
||||||
<label for="ask-mail">Ask me anything about Odoo</label>
|
<p class="ask-lede">One question, one answer, by mail. No list, no tracking, no follow-up sequence.</p>
|
||||||
<input id="ask-mail" type="email" inputmode="email" placeholder="you@company.com" autocomplete="email">
|
<form class="ask-form" action="mailto:o.arnold@projektbox.de" method="post" enctype="text/plain">
|
||||||
<button class="ask-send" type="button">Send it.</button>
|
<label for="ask-mail">Your email</label>
|
||||||
</p>
|
<input id="ask-mail" name="email" type="email" inputmode="email" placeholder="you@company.com" autocomplete="email" required>
|
||||||
<p class="ask-note">One question, one answer, by mail. No list, no tracking, no sequence of follow-ups.</p>
|
<button class="btn" type="submit">Send the question</button>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<!-- FOOTER: invitation over a cropped name -->
|
|
||||||
<footer class="foot">
|
<footer class="foot">
|
||||||
<div class="foot-top">
|
<p class="foot-name" aria-hidden="true">The OC Guy</p>
|
||||||
<p class="foot-invite">Bring your question, leave with a plan.</p>
|
<div class="foot-cols">
|
||||||
<a class="btn btn-dark" href="mailto:o.arnold@projektbox.de?subject=Odoo%20Community%20question">Write to Oliver</a>
|
<p class="foot-note">Odoo Community advocate. Written by Oliver Arnold, 安雷威 —
|
||||||
</div>
|
no partner programme, no licences sold.</p>
|
||||||
<nav class="foot-links" aria-label="Elsewhere">
|
<nav class="foot-links" aria-label="Elsewhere">
|
||||||
<a href="https://www.odoo.com/documentation" target="_blank" rel="noopener">Documentation</a>
|
<a href="https://www.odoo.com/documentation" target="_blank" rel="noopener">Documentation</a>
|
||||||
<a href="https://github.com/OCA" target="_blank" rel="noopener">OCA modules</a>
|
<a href="https://github.com/OCA" target="_blank" rel="noopener">OCA modules</a>
|
||||||
<a href="https://apps.odoo.com" target="_blank" rel="noopener">App store</a>
|
<a href="https://apps.odoo.com" target="_blank" rel="noopener">App store</a>
|
||||||
<a href="mailto:o.arnold@projektbox.de">Email</a>
|
<a href="mailto:o.arnold@projektbox.de">Email</a>
|
||||||
</nav>
|
</nav>
|
||||||
|
</div>
|
||||||
<p class="foot-credits">
|
<p class="foot-credits">
|
||||||
Pictures: <a href="https://commons.wikimedia.org/wiki/File:World_Map_1689.JPG">“World Map 1689”</a> by Gerard van Schagen, public domain;
|
Pictures: <a href="https://commons.wikimedia.org/wiki/File:1794_Samuel_Dunn_Wall_Map_of_the_World_in_Hemispheres_-_Geographicus_-_World2-dunn-1794.jpg">“A General Map of the World”</a> by Thomas Kitchin, public domain;
|
||||||
<a href="https://commons.wikimedia.org/wiki/File:1794_Samuel_Dunn_Wall_Map_of_the_World_in_Hemispheres_-_Geographicus_-_World2-dunn-1794.jpg">“A General Map of the World”</a> by Thomas Kitchin, public domain;
|
<a href="https://commons.wikimedia.org/wiki/File:World_Map_1689.JPG">“World Map 1689”</a> by Gerard van Schagen, public domain;
|
||||||
<a href="https://commons.wikimedia.org/wiki/File:A_printer%27s_workshop;_on_the_left_a_printing_press,_on_the_r_Wellcome_V0023751.jpg">“A printer's workshop”</a>, CC BY 4.0;
|
<a href="https://commons.wikimedia.org/wiki/File:A_printer%27s_workshop;_on_the_left_a_printing_press,_on_the_r_Wellcome_V0023751.jpg">“A printer's workshop”</a>, CC BY 4.0;
|
||||||
<a href="https://commons.wikimedia.org/wiki/File:Geography;_four_types_of_globe._Engraving._Wellcome_V0025077.jpg">“Four types of globe”</a>, CC BY 4.0 — all via Wikimedia Commons.
|
<a href="https://commons.wikimedia.org/wiki/File:Geography;_four_types_of_globe._Engraving._Wellcome_V0025077.jpg">“Four types of globe”</a>, CC BY 4.0 — all via Wikimedia Commons.
|
||||||
</p>
|
</p>
|
||||||
<p class="foot-name" aria-hidden="true">The OC Guy</p>
|
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<script src="js/site.js" defer></script>
|
<script src="js/site.js" defer></script>
|
||||||
|
|||||||
+41
-113
@@ -1,6 +1,6 @@
|
|||||||
/* The OC Guy — page behaviour.
|
/* The OC Guy — page behaviour.
|
||||||
Everything here degrades: without JS the page still reads, the bands still
|
Everything degrades: without JS the page is a plain, readable
|
||||||
show their titles, the tips still list, the form still shows. */
|
document with working links and a mail form. */
|
||||||
(function () {
|
(function () {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
@@ -9,23 +9,10 @@
|
|||||||
|
|
||||||
var reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
var reduce = window.matchMedia('(prefers-reduced-motion: reduce)').matches;
|
||||||
|
|
||||||
/* ---------- signature move: the shutter on the hero photograph ---------- */
|
/* ---------- entrance for the blocks of each section ---------- */
|
||||||
var hero = document.querySelector('.hero-line');
|
var targets = document.querySelectorAll(
|
||||||
if (hero) {
|
'.lead-caption, .box, .side-list, .section-head, .card, .feature, .news li, .ask-inner'
|
||||||
if (reduce) {
|
);
|
||||||
hero.classList.add('shutter');
|
|
||||||
} else {
|
|
||||||
requestAnimationFrame(function () {
|
|
||||||
setTimeout(function () { hero.classList.add('shutter'); }, 120);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ---------- entrance for the parts of every section ---------- */
|
|
||||||
var targets = [];
|
|
||||||
document.querySelectorAll('.intro .statement, .open h2, .open p, .map-figure figcaption, .tips h2, .tips-note, .picker, .tips-list li, .about h2, .bio, .about-facts, .ask-line, .ask-note, .band-text, .foot-invite, .foot-links').forEach(function (el) {
|
|
||||||
targets.push(el);
|
|
||||||
});
|
|
||||||
|
|
||||||
if (!reduce && 'IntersectionObserver' in window) {
|
if (!reduce && 'IntersectionObserver' in window) {
|
||||||
var io = new IntersectionObserver(function (entries) {
|
var io = new IntersectionObserver(function (entries) {
|
||||||
@@ -34,115 +21,56 @@
|
|||||||
entry.target.classList.add('rv-in');
|
entry.target.classList.add('rv-in');
|
||||||
io.unobserve(entry.target);
|
io.unobserve(entry.target);
|
||||||
});
|
});
|
||||||
}, { rootMargin: '0px 0px -12% 0px', threshold: 0.12 });
|
}, { rootMargin: '0px 0px -8% 0px', threshold: 0.08 });
|
||||||
|
|
||||||
targets.forEach(function (el, i) {
|
Array.prototype.forEach.call(targets, function (el) {
|
||||||
el.setAttribute('data-rv', String((i % 4) + 1));
|
el.setAttribute('data-rv', '1');
|
||||||
io.observe(el);
|
io.observe(el);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
targets.forEach(function (el) { el.classList.add('rv-in'); });
|
Array.prototype.forEach.call(targets, function (el) { el.classList.add('rv-in'); });
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- switches: five claims ---------- */
|
/* ---------- the ask form: one question, by mail ---------- */
|
||||||
document.querySelectorAll('.band-switch').forEach(function (btn) {
|
var form = document.querySelector('.ask-form');
|
||||||
btn.addEventListener('click', function () {
|
|
||||||
var band = btn.closest('.band');
|
|
||||||
var on = btn.getAttribute('aria-checked') === 'true';
|
|
||||||
btn.setAttribute('aria-checked', String(!on));
|
|
||||||
band.setAttribute('data-on', String(!on));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
/* ---------- the live thing: pick what the company does ---------- */
|
|
||||||
var chips = Array.prototype.slice.call(document.querySelectorAll('.chip'));
|
|
||||||
var out = document.querySelector('.picker-out');
|
|
||||||
var installOrder = ['Sales', 'CRM', 'Purchase', 'Manufacturing', 'Inventory', 'Project', 'Timesheets', 'Expenses', 'Invoicing', 'Accounting'];
|
|
||||||
|
|
||||||
function render(mods) {
|
|
||||||
if (!mods.length) {
|
|
||||||
out.textContent = 'Choose one, or several. The modules stack in the order you would install them.';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
out.innerHTML = '';
|
|
||||||
mods.forEach(function (name, i) {
|
|
||||||
var span = document.createElement('span');
|
|
||||||
span.className = 'mod';
|
|
||||||
span.textContent = name;
|
|
||||||
out.appendChild(span);
|
|
||||||
if (i < mods.length - 1) {
|
|
||||||
var arrow = document.createElement('span');
|
|
||||||
arrow.className = 'arrow';
|
|
||||||
arrow.textContent = ' → ';
|
|
||||||
out.appendChild(arrow);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var note = document.createElement('span');
|
|
||||||
note.className = 'arrow';
|
|
||||||
note.textContent = ' — that order, top to bottom.';
|
|
||||||
out.appendChild(note);
|
|
||||||
}
|
|
||||||
|
|
||||||
chips.forEach(function (chip) {
|
|
||||||
chip.setAttribute('aria-pressed', 'false');
|
|
||||||
chip.addEventListener('click', function () {
|
|
||||||
var pressed = chip.getAttribute('aria-pressed') === 'true';
|
|
||||||
chip.setAttribute('aria-pressed', String(!pressed));
|
|
||||||
|
|
||||||
var picked = chips.filter(function (c) { return c.getAttribute('aria-pressed') === 'true'; })
|
|
||||||
.reduce(function (all, c) {
|
|
||||||
c.dataset.modules.split(',').forEach(function (m) {
|
|
||||||
var name = m.trim();
|
|
||||||
if (all.indexOf(name) === -1) all.push(name);
|
|
||||||
});
|
|
||||||
return all;
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
picked.sort(function (a, b) { return installOrder.indexOf(a) - installOrder.indexOf(b); });
|
|
||||||
render(picked);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
/* ---------- ask: one question, by mail ---------- */
|
|
||||||
var send = document.querySelector('.ask-send');
|
|
||||||
var mail = document.getElementById('ask-mail');
|
var mail = document.getElementById('ask-mail');
|
||||||
if (send && mail) {
|
|
||||||
send.addEventListener('click', function () {
|
if (form && mail) {
|
||||||
|
form.addEventListener('submit', function (event) {
|
||||||
|
event.preventDefault();
|
||||||
var addr = (mail.value || '').trim();
|
var addr = (mail.value || '').trim();
|
||||||
var body = 'My question about Odoo Community:\n\n\n';
|
if (!addr || addr.indexOf('@') === -1) {
|
||||||
if (addr) body += '\n— reply to: ' + addr + '\n';
|
|
||||||
var href = 'mailto:o.arnold@projektbox.de'
|
|
||||||
+ '?subject=' + encodeURIComponent('Odoo Community question')
|
|
||||||
+ '&body=' + encodeURIComponent(body);
|
|
||||||
if (addr && addr.indexOf('@') === -1) {
|
|
||||||
mail.focus();
|
|
||||||
mail.setAttribute('aria-invalid', 'true');
|
mail.setAttribute('aria-invalid', 'true');
|
||||||
|
mail.focus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
mail.removeAttribute('aria-invalid');
|
mail.removeAttribute('aria-invalid');
|
||||||
window.location.href = href;
|
var body = 'My question about Odoo Community:\n\n\n— reply to: ' + addr + '\n';
|
||||||
});
|
window.location.href = 'mailto:o.arnold@projektbox.de'
|
||||||
mail.addEventListener('keydown', function (e) {
|
+ '?subject=' + encodeURIComponent('Odoo Community question')
|
||||||
if (e.key === 'Enter') send.click();
|
+ '&body=' + encodeURIComponent(body);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ---------- one moving picture: the world map drifts against the scroll ---------- */
|
/* ---------- which section the reader is in ---------- */
|
||||||
var map = document.getElementById('worldmap');
|
var links = Array.prototype.slice.call(document.querySelectorAll('.nav a[href^="#"]'));
|
||||||
if (map && !reduce) {
|
var sections = links
|
||||||
var ticking = false;
|
.map(function (a) { return document.querySelector(a.getAttribute('href')); })
|
||||||
var update = function () {
|
.filter(Boolean);
|
||||||
var rect = map.getBoundingClientRect();
|
|
||||||
var vh = window.innerHeight || 800;
|
if (sections.length && 'IntersectionObserver' in window) {
|
||||||
if (rect.bottom > -200 && rect.top < vh + 200) {
|
var seen = new IntersectionObserver(function (entries) {
|
||||||
var progress = (rect.top + rect.height / 2 - vh / 2) / vh;
|
entries.forEach(function (entry) {
|
||||||
map.style.transform = 'translate3d(0,' + (progress * -26).toFixed(2) + 'px,0) scale(1.06)';
|
if (!entry.isIntersecting) return;
|
||||||
|
links.forEach(function (a) {
|
||||||
|
if (a.getAttribute('href') === '#' + entry.target.id) {
|
||||||
|
a.setAttribute('aria-current', 'true');
|
||||||
|
} else {
|
||||||
|
a.removeAttribute('aria-current');
|
||||||
}
|
}
|
||||||
ticking = false;
|
});
|
||||||
};
|
});
|
||||||
window.addEventListener('scroll', function () {
|
}, { rootMargin: '-45% 0px -50% 0px' });
|
||||||
if (!ticking) { ticking = true; requestAnimationFrame(update); }
|
sections.forEach(function (s) { seen.observe(s); });
|
||||||
}, { passive: true });
|
|
||||||
update();
|
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
Reference in new issue
Block a user