)]}' {"version": 3, "sources": ["/web/static/src/legacy/js/promise_extension.js", "/web/static/src/boot.js", "/web/static/src/session.js", "/web/static/src/legacy/js/core/cookie_utils.js", "/web/static/src/legacy/js/core/menu.js", "/web/static/src/legacy/js/public/lazyloader.js", "/web_editor/static/src/js/frontend/loader_loading.js", "/website/static/src/js/content/inject_dom.js", "/website/static/src/js/content/auto_hide_menu.js", "/website/static/src/js/content/redirect.js", "/website/static/src/js/content/adapt_content.js"], "mappings": "AAAA;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACvBA;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC5bA;;;;;;;;AAAA;AACA;AACA;AACA;AACA;;;;ACJA;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AC1EA;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;AC1PA;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACnHA;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;ACjCA;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACpDA;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACjCA;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;;;;ACtDA;;;;;;;;AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA", "sourcesContent": ["/**\n * This file adds a 'guardedCatch' function to the Promise API. This function\n * has to be used when we don't want to swallow real errors (crashes), like\n * 'catch' does (i.e. basically all the time in Odoo). We only execute the\n * 'onRejected' handler if the rejection's reason is not an Error, and we always\n * return a rejected Promise to let the rejection bubble up (and trigger the\n * 'unhandledrejection' event).\n */\n\n(function () {\n var _catch = Promise.prototype.catch;\n Promise.prototype.guardedCatch = function (onRejected) {\n return _catch.call(this, function (reason) {\n const error = (reason instanceof Error && \"cause\" in reason) ? reason.cause : reason;\n if (!error || !(error instanceof Error)) {\n if (onRejected) {\n onRejected.call(this, reason);\n }\n }\n return Promise.reject(reason);\n });\n };\n})();\n", "/**\n *------------------------------------------------------------------------------\n * Odoo Web Boostrap Code\n *------------------------------------------------------------------------------\n *\n * Each module can return a promise. In that case, the module is marked as loaded\n * only when the promise is resolved, and its value is equal to the resolved value.\n * The module can be rejected (unloaded). This will be logged in the console as info.\n *\n * logs:\n * Missing dependencies:\n * These modules do not appear in the page. It is possible that the\n * JavaScript file is not in the page or that the module name is wrong\n * Failed modules:\n * A javascript error is detected\n * Rejected modules:\n * The module returns a rejected promise. It (and its dependent modules)\n * is not loaded.\n * Rejected linked modules:\n * Modules who depend on a rejected module\n * Non loaded modules:\n * Modules who depend on a missing or a failed module\n * Debug:\n * Non loaded or failed module informations for debugging\n */\n(function () {\n \"use strict\";\n\n var jobUID = Date.now();\n\n var jobs = [];\n var factories = Object.create(null);\n var jobDeps = [];\n var jobPromises = [];\n\n var services = Object.create({});\n\n var commentRegExp = /(\\/\\*([\\s\\S]*?)\\*\\/|([^:]|^)\\/\\/(.*)$)/gm;\n var cjsRequireRegExp = /[^.]\\s*require\\s*\\(\\s*[\"']([^'\"\\s]+)[\"']\\s*\\)/g;\n if (!globalThis.odoo) {\n globalThis.odoo = {};\n }\n var odoo = globalThis.odoo;\n var debug = odoo.debug;\n\n var didLogInfoResolve;\n var didLogInfoPromise = new Promise(function (resolve) {\n didLogInfoResolve = resolve;\n });\n\n odoo.remainingJobs = jobs;\n odoo.__DEBUG__ = {\n didLogInfo: didLogInfoPromise,\n getDependencies: function (name, transitive) {\n var deps = name instanceof Array ? name : [name];\n var changed;\n do {\n changed = false;\n jobDeps.forEach(function (dep) {\n if (deps.indexOf(dep.to) >= 0 && deps.indexOf(dep.from) < 0) {\n deps.push(dep.from);\n changed = true;\n }\n });\n } while (changed && transitive);\n return deps;\n },\n getDependents: function (name) {\n return jobDeps\n .filter(function (dep) {\n return dep.from === name;\n })\n .map(function (dep) {\n return dep.to;\n });\n },\n getWaitedJobs: function () {\n return jobs\n .map(function (job) {\n return job.name;\n })\n .filter(function (item, index, self) {\n // uniq\n return self.indexOf(item) === index;\n });\n },\n getMissingJobs: function () {\n var self = this;\n var waited = this.getWaitedJobs();\n var missing = [];\n waited.forEach(function (job) {\n self.getDependencies(job).forEach(function (job) {\n if (!(job in self.services)) {\n missing.push(job);\n }\n });\n });\n return missing\n .filter(function (item, index, self) {\n return self.indexOf(item) === index;\n })\n .filter(function (item) {\n return waited.indexOf(item) < 0;\n })\n .filter(function (job) {\n return !job.error;\n });\n },\n getFailedJobs: function () {\n return jobs.filter(function (job) {\n return !!job.error;\n });\n },\n processJobs: function () {\n var job;\n\n function processJob(job) {\n var require = makeRequire(job);\n\n var jobExec;\n function onError(e) {\n job.error = e;\n console.error(`Error while loading ${job.name}: ${e.message}`, e);\n Promise.reject(e);\n }\n var def = new Promise(function (resolve) {\n try {\n jobExec = job.factory.call(null, require);\n jobs.splice(jobs.indexOf(job), 1);\n } catch (e) {\n onError(e);\n }\n if (!job.error) {\n Promise.resolve(jobExec)\n .then(function (data) {\n services[job.name] = data;\n resolve();\n odoo.__DEBUG__.processJobs();\n })\n .guardedCatch(function (e) {\n job.rejected = e || true;\n jobs.push(job);\n })\n .catch(function (e) {\n if (e instanceof Error) {\n onError(e);\n }\n resolve();\n });\n } else {\n resolve();\n }\n });\n jobPromises.push(def);\n def.then(job.resolve);\n }\n\n function isReady(job) {\n return (\n !job.error &&\n !job.rejected &&\n job.factory.deps.every(function (name) {\n return name in services;\n })\n );\n }\n\n function makeRequire(job) {\n var deps = {};\n Object.keys(services)\n .filter(function (item) {\n return job.deps.indexOf(item) >= 0;\n })\n .forEach(function (key) {\n deps[key] = services[key];\n });\n\n return function require(name) {\n if (!(name in deps)) {\n console.error(\"Undefined dependency: \", name);\n }\n return deps[name];\n };\n }\n\n while (jobs.length) {\n job = undefined;\n for (var i = 0; i < jobs.length; i++) {\n if (isReady(jobs[i])) {\n job = jobs[i];\n break;\n }\n }\n if (!job) {\n break;\n }\n processJob(job);\n }\n\n return services;\n },\n factories: factories,\n services: services,\n };\n odoo.define = function () {\n var args = Array.prototype.slice.call(arguments);\n var name = typeof args[0] === \"string\" ? args.shift() : \"__odoo_job\" + jobUID++;\n var factory = args[args.length - 1];\n var deps;\n if (args[0] instanceof Array) {\n deps = args[0];\n } else {\n deps = [];\n factory\n .toString()\n .replace(commentRegExp, \"\")\n .replace(cjsRequireRegExp, function (match, dep) {\n deps.push(dep);\n });\n }\n\n if (!(deps instanceof Array)) {\n throw new Error(\"Dependencies should be defined by an array\", deps);\n }\n if (typeof factory !== \"function\") {\n throw new Error(\"Factory should be defined by a function\", factory);\n }\n if (typeof name !== \"string\") {\n throw new Error(\"Invalid name definition (should be a string\", name);\n }\n if (name in factories) {\n throw new Error(\"Service \" + name + \" already defined\");\n }\n\n factory.deps = deps;\n factories[name] = factory;\n\n let promiseResolve;\n const promise = new Promise((resolve) => {\n promiseResolve = resolve;\n });\n jobs.push({\n name: name,\n factory: factory,\n deps: deps,\n resolve: promiseResolve,\n promise: promise,\n });\n\n deps.forEach(function (dep) {\n jobDeps.push({ from: dep, to: name });\n });\n\n odoo.__DEBUG__.processJobs();\n };\n odoo.log = function () {\n var missing = [];\n var failed = [];\n var cycle = null;\n\n if (jobs.length) {\n var debugJobs = {};\n var rejected = [];\n var rejectedLinked = [];\n var job;\n var jobdep;\n\n for (var k = 0; k < jobs.length; k++) {\n debugJobs[jobs[k].name] = job = {\n dependencies: jobs[k].deps,\n dependents: odoo.__DEBUG__.getDependents(jobs[k].name),\n name: jobs[k].name,\n };\n if (jobs[k].error) {\n job.error = jobs[k].error;\n }\n if (jobs[k].rejected) {\n job.rejected = jobs[k].rejected;\n rejected.push(job.name);\n }\n var deps = odoo.__DEBUG__.getDependencies(job.name);\n for (var i = 0; i < deps.length; i++) {\n if (job.name !== deps[i] && !(deps[i] in services)) {\n jobdep = debugJobs[deps[i]];\n if (!jobdep && deps[i] in factories) {\n for (var j = 0; j < jobs.length; j++) {\n if (jobs[j].name === deps[i]) {\n jobdep = jobs[j];\n break;\n }\n }\n }\n if (jobdep && jobdep.rejected) {\n if (!job.rejected) {\n job.rejected = [];\n rejectedLinked.push(job.name);\n }\n job.rejected.push(deps[i]);\n } else {\n if (!job.missing) {\n job.missing = [];\n }\n job.missing.push(deps[i]);\n }\n }\n }\n }\n missing = odoo.__DEBUG__.getMissingJobs();\n failed = odoo.__DEBUG__.getFailedJobs();\n var unloaded = Object.keys(debugJobs) // Object.values is not supported\n .map(function (key) {\n return debugJobs[key];\n })\n .filter(function (job) {\n return job.missing;\n });\n\n if (debug || failed.length || unloaded.length) {\n var log = globalThis.console[\n !failed.length || !unloaded.length ? \"info\" : \"error\"\n ].bind(globalThis.console);\n log(\n (failed.length ? \"error\" : unloaded.length ? \"warning\" : \"info\") +\n \": Some modules could not be started\"\n );\n if (missing.length) {\n log(\"Missing dependencies: \", missing);\n }\n if (failed.length) {\n log(\n \"Failed modules: \",\n failed.map(function (fail) {\n return fail.name;\n })\n );\n }\n if (rejected.length) {\n log(\"Rejected modules: \", rejected);\n }\n if (rejectedLinked.length) {\n log(\"Rejected linked modules: \", rejectedLinked);\n }\n if (unloaded.length) {\n cycle = findCycle(unloaded);\n if (cycle) {\n console.error(\"Cyclic dependencies: \" + cycle);\n }\n log(\n \"Non loaded modules: \",\n unloaded.map(function (unload) {\n return unload.name;\n })\n );\n }\n if (debug && Object.keys(debugJobs).length) {\n log(\"Debug: \", debugJobs);\n }\n }\n }\n odoo.__DEBUG__.jsModules = {\n missing: missing,\n failed: failed.map((mod) => mod.name),\n unloaded: unloaded ? unloaded.map((mod) => mod.name) : [],\n cycle,\n };\n didLogInfoResolve(true);\n };\n /**\n * Returns a resolved promise when the targeted services are loaded.\n * If no service is found the promise is used directly.\n *\n * @param {string|RegExp} serviceName name of the service to expect\n * or regular expression matching the service.\n * @returns {Promise} resolved when the services ares\n * loaded. The value is equal to the number of services found.\n */\n odoo.ready = async function (serviceName) {\n function match(name) {\n return typeof serviceName === \"string\" ? name === serviceName : serviceName.test(name);\n }\n await Promise.all(jobs.filter((job) => match(job.name)).map((job) => job.promise));\n return Object.keys(factories).filter(match).length;\n };\n\n odoo.runtimeImport = function (moduleName) {\n if (!(moduleName in services)) {\n throw new Error(`Service \"${moduleName} is not defined or isn't finished loading.\"`);\n }\n return services[moduleName];\n };\n\n // Automatically log errors detected when loading modules\n globalThis.addEventListener(\"load\", function logWhenLoaded() {\n const len = jobPromises.length;\n Promise.all(jobPromises).then(function () {\n if (len === jobPromises.length) {\n odoo.log();\n } else {\n logWhenLoaded();\n }\n });\n });\n\n /**\n * Visit the list of jobs, and return the first found cycle, if any\n *\n * @param {any[]} jobs\n * @returns {null | string} either a string describing a cycle, or null\n */\n function findCycle(jobs) {\n // build dependency graph\n const dependencyGraph = new Map();\n for (const job of jobs) {\n dependencyGraph.set(job.name, job.dependencies);\n }\n\n // helpers\n function visitJobs(jobs, visited = new Set()) {\n for (const job of jobs) {\n const result = visitJob(job, visited);\n if (result) {\n return result;\n }\n }\n return null;\n }\n\n function visitJob(job, visited) {\n if (visited.has(job)) {\n const jobs = Array.from(visited).concat([job]);\n const index = jobs.indexOf(job);\n return jobs\n .slice(index)\n .map((j) => `\"${j}\"`)\n .join(\" => \");\n }\n const deps = dependencyGraph.get(job);\n return deps ? visitJobs(deps, new Set(visited).add(job)) : null;\n }\n\n // visit each root to find cycles\n return visitJobs(jobs.map((j) => j.name));\n }\n})();\n", "/** @odoo-module **/\n\nexport const session = odoo.__session_info__ || {};\ndelete odoo.__session_info__;\n", "odoo.define('web.utils.cookies', function (require) {\n\"use strict\";\n\nconst utils = {\n /**\n * Reads the cookie described by the given name.\n *\n * @param {string} cookieName\n * @returns {string}\n */\n getCookie(cookieName) {\n var cookies = document.cookie ? document.cookie.split('; ') : [];\n for (var i = 0, l = cookies.length; i < l; i++) {\n var parts = cookies[i].split('=');\n var name = parts.shift();\n var cookie = parts.join('=');\n\n if (cookieName && cookieName === name) {\n if (cookie.startsWith('\"')) {\n if (cookie.includes('\\\\')){\n // see werkzeug _cookie_quote\n throw new Error(\n `Cookie value contains unknown characters ${cookie}`\n )\n }\n cookie = cookie.slice(1, -1);\n }\n return cookie;\n }\n }\n return \"\";\n },\n /**\n * Check if cookie can be written.\n *\n * @param {String} type the type of the cookie\n * @returns {boolean}\n */\n isAllowedCookie(type) {\n return true;\n },\n /**\n * Creates a cookie.\n *\n * @param {string} name the name of the cookie\n * @param {string} value the value stored in the cookie\n * @param {integer} ttl time to live of the cookie in millis. -1 to erase the cookie.\n * @param {string} type the type of the cookies ('required' as default value)\n */\n setCookie(name, value, ttl = 31536000, type = 'required') {\n ttl = utils.isAllowedCookie(type) ? ttl || 24 * 60 * 60 * 365 : -1;\n document.cookie = [\n `${name}=${value}`,\n 'path=/',\n `max-age=${ttl}`,\n `expires=${new Date(new Date().getTime() + ttl * 1000).toGMTString()}`,\n ].join(';');\n },\n /**\n * Deletes a cookie.\n *\n * @param {string} name the name of the cookie\n */\n deleteCookie(name) {\n document.cookie = [\n `${name}=`,\n 'path=/',\n `max-age=-1`,\n `expires=${new Date(new Date().getTime() - 1000).toGMTString()}`,\n ].join(';');\n },\n};\nreturn utils;\n});\n", "/** @odoo-module **/\n\nconst BREAKPOINT_SIZES = {sm: '575', md: '767', lg: '991', xl: '1199', xxl: '1399'};\n\n/**\n * Creates an automatic 'more' dropdown-menu for a set of navbar items.\n *\n * @param {HTMLElement} el\n * @param {Object} [options]\n * @param {string} [options.unfoldable='none'] selector for items that do not\n * need to be added to dropdown-menu.\n * @param {float} [options.maxWidth] The max width value that menu content\n * can take => the overflowing (foldable) items are added in the dropdown-menu.\n * @param {string} [options.minSize] the menu auto-hide option will be disabled\n * if viewport is smaller than minSize.\n * @param {Array} [options.images=[]] images to wait for before menu update.\n * @param {Array} [options.loadingStyleClasses=[]] list of CSS classes to add while\n * updating the menu.\n*/\nexport async function initAutoMoreMenu(el, options) {\n if (!el) {\n return;\n }\n const navbar = el.closest('.navbar');\n // Get breakpoint related information from the navbar to correctly handle\n // the \"auto-hide\" on mobile menu.\n const [breakpoint = 'md'] = navbar ? Object.keys(BREAKPOINT_SIZES)\n .filter(suffix => navbar.classList.contains(`navbar-expand-${suffix}`)) : [];\n const isNoHamburgerMenu = !!navbar && navbar.classList.contains('navbar-expand');\n\n options = Object.assign({\n unfoldable: 'none',\n maxWidth: false,\n // We cannot use `--breakpoint-xx` properties to get values with BS5.\n minSize: BREAKPOINT_SIZES[breakpoint],\n images: [],\n loadingStyleClasses: [],\n }, options || {});\n\n const isUserNavbar = el.parentElement.classList.contains('o_main_navbar');\n const dropdownSubMenuClasses = ['show', 'border-0', 'position-static'];\n const dropdownToggleClasses = ['h-auto', 'py-2', 'text-secondary'];\n const autoMarginLeftRegex = /\\bm[sx]?(?:-(?:sm|md|lg|xl|xxl))?-auto\\b/; // grep: ms-auto mx-auto\n const autoMarginRightRegex = /\\bm[ex]?(?:-(?:sm|md|lg|xl|xxl))?-auto\\b/; // grep: me-auto mx-auto\n var extraItemsToggle = null;\n let debounce;\n const afterFontsloading = new Promise((resolve) => {\n if (document.fonts) {\n document.fonts.ready.then(resolve);\n } else {\n // IE: don't wait more than max .15s.\n setTimeout(resolve, 150);\n }\n });\n afterFontsloading.then(_adapt);\n\n if (options.images.length) {\n await _afterImagesLoading(options.images);\n _adapt();\n }\n\n const debouncedAdapt = () => {\n clearTimeout(debounce);\n debounce = setTimeout(_adapt, 250);\n };\n window.addEventListener('resize', debouncedAdapt);\n\n el.addEventListener('dom:autoMoreMenu:adapt', _adapt);\n el.addEventListener('dom:autoMoreMenu:destroy', destroy, {once: true});\n\n function _restore() {\n if (!extraItemsToggle) {\n return;\n }\n // Move extra menu items from dropdown-menu to menu element in the same order.\n [...extraItemsToggle.querySelector('.dropdown-menu').children].forEach((item) => {\n if (!isUserNavbar) {\n item.classList.add('nav-item');\n const itemLink = item.querySelector('.dropdown-item');\n if (itemLink) {\n itemLink.classList.remove('dropdown-item');\n itemLink.classList.add('nav-link');\n }\n } else {\n item.classList.remove('dropdown-item');\n const dropdownSubMenu = item.querySelector('.dropdown-menu');\n const dropdownSubMenuButton = item.querySelector('.dropdown-toggle');\n if (dropdownSubMenu) {\n dropdownSubMenu.classList.remove(...dropdownSubMenuClasses);\n }\n if (dropdownSubMenuButton) {\n dropdownSubMenuButton.classList.remove(...dropdownToggleClasses);\n }\n }\n el.insertBefore(item, extraItemsToggle);\n });\n extraItemsToggle.remove();\n extraItemsToggle = null;\n }\n\n function _adapt() {\n if (options.loadingStyleClasses.length) {\n el.classList.add(...options.loadingStyleClasses);\n }\n _restore();\n\n // Ignore invisible/toggleable top menu element & small viewports.\n if (!el.getClientRects().length || el.closest('.show')\n || (window.matchMedia(`(max-width: ${options.minSize}px)`).matches && !isNoHamburgerMenu)) {\n return _endAutoMoreMenu();\n }\n\n let unfoldableItems = [];\n const items = [...el.children].filter((node) => {\n if (node.matches && !node.matches(options.unfoldable)) {\n return true;\n }\n unfoldableItems.push(node);\n return false;\n });\n var nbItems = items.length;\n var menuItemsWidth = items.reduce((sum, el) => sum + computeFloatOuterWidthWithMargins(el, true, true, false), 0);\n let maxWidth = 0;\n\n if (options.maxWidth) {\n maxWidth = options.maxWidth();\n }\n if (!maxWidth) {\n maxWidth = computeFloatOuterWidthWithMargins(el, true, true, true);\n var style = window.getComputedStyle(el);\n maxWidth -= (parseFloat(style.paddingLeft) + parseFloat(style.paddingRight) + parseFloat(style.borderLeftWidth) + parseFloat(style.borderRightWidth));\n maxWidth -= unfoldableItems.reduce((sum, el) => sum + computeFloatOuterWidthWithMargins(el, true, true, false), 0);\n }\n // Ignore if there is no overflow.\n if (maxWidth - menuItemsWidth >= -0.001) {\n return _endAutoMoreMenu();\n }\n\n const dropdownMenu = _addExtraItemsButton(items[nbItems - 1].nextElementSibling);\n menuItemsWidth += computeFloatOuterWidthWithMargins(extraItemsToggle, true, true, false);\n do {\n menuItemsWidth -= computeFloatOuterWidthWithMargins(items[--nbItems], true, true, false);\n } while (!(maxWidth - menuItemsWidth >= -0.001) && (nbItems > 0));\n\n const extraItems = items.slice(nbItems);\n extraItems.forEach((el) => {\n if (!isUserNavbar) {\n const navLink = el.querySelector('.nav-link, a');\n el.classList.remove('nav-item');\n if (navLink) {\n navLink.classList.remove('nav-link');\n navLink.classList.add('dropdown-item');\n navLink.classList.toggle('active', el.classList.contains('active'));\n }\n } else {\n const dropdownSubMenu = el.querySelector('.dropdown-menu');\n const dropdownSubMenuButton = el.querySelector('.dropdown-toggle');\n el.classList.add('dropdown-item', 'p-0');\n if (dropdownSubMenu) {\n dropdownSubMenu.classList.add(...dropdownSubMenuClasses);\n }\n if (dropdownSubMenuButton) {\n dropdownSubMenuButton.classList.add(...dropdownToggleClasses);\n }\n }\n dropdownMenu.appendChild(el);\n });\n _endAutoMoreMenu();\n }\n\n function computeFloatOuterWidthWithMargins(el, mLeft, mRight, considerAutoMargins) {\n var rect = el.getBoundingClientRect();\n var style = window.getComputedStyle(el);\n var outerWidth = rect.right - rect.left;\n const isRTL = style.direction === 'rtl';\n if (mLeft !== false && (considerAutoMargins || !(isRTL ? autoMarginRightRegex : autoMarginLeftRegex).test(el.getAttribute('class')))) {\n outerWidth += parseFloat(style.marginLeft);\n }\n if (mRight !== false && (considerAutoMargins || !(isRTL ? autoMarginLeftRegex : autoMarginRightRegex).test(el.getAttribute('class')))) {\n outerWidth += parseFloat(style.marginRight);\n }\n // Would be NaN for invisible elements for example\n return isNaN(outerWidth) ? 0 : outerWidth;\n }\n\n function _addExtraItemsButton(target) {\n let dropdownMenu = document.createElement('div');\n extraItemsToggle = dropdownMenu.cloneNode();\n const extraItemsToggleIcon = document.createElement('i');\n const extraItemsToggleLink = document.createElement('a');\n\n dropdownMenu.className = 'dropdown-menu';\n extraItemsToggle.className = 'nav-item dropdown o_extra_menu_items';\n extraItemsToggleIcon.className = 'fa fa-plus';\n Object.entries({\n role: 'button',\n href: '#',\n class: 'nav-link dropdown-toggle o-no-caret',\n 'data-bs-toggle': 'dropdown',\n 'aria-expanded': false,\n }).forEach(([key, value]) => {\n extraItemsToggleLink.setAttribute(key, value);\n });\n\n extraItemsToggleLink.appendChild(extraItemsToggleIcon);\n extraItemsToggle.appendChild(extraItemsToggleLink);\n extraItemsToggle.appendChild(dropdownMenu);\n el.insertBefore(extraItemsToggle, target);\n return dropdownMenu;\n }\n\n function destroy() {\n _restore();\n window.removeEventListener('resize', debouncedAdapt);\n el.removeEventListener('dom:autoMoreMenu:adapt', _adapt);\n }\n\n function _afterImagesLoading(images) {\n const defs = images.map((image) => {\n if (image.complete || !image.getClientRects().length) {\n return null;\n }\n return new Promise(function (resolve, reject) {\n if (!image.width) {\n // The purpose of the 'o_menu_image_placeholder' class is to add a default\n // size to non loaded images (on the first update) to prevent flickering.\n image.classList.add('o_menu_image_placeholder');\n }\n image.addEventListener('load', () => {\n image.classList.remove('o_menu_image_placeholder');\n resolve();\n });\n });\n });\n return Promise.all(defs);\n }\n\n function _endAutoMoreMenu() {\n el.classList.remove(...options.loadingStyleClasses);\n }\n}\n\n/**\n * Cleans what has been done by ``initAutoMoreMenu``.\n *\n * @param {HTMLElement} el\n */\nexport function destroyAutoMoreMenu(el) {\n el.dispatchEvent(new Event('dom:autoMoreMenu:destroy'));\n}\n", "odoo.define('web.public.lazyloader', function (require) {\n'use strict';\n\nvar blockEvents = ['submit', 'click'];\nvar blockFunction = function (ev) {\n ev.preventDefault();\n ev.stopImmediatePropagation();\n};\n\nvar waitingLazy = false;\n\n/**\n * Blocks the DOM sections which explicitly require the lazy loaded JS to be\n * working (those sections should be marked with the 'o_wait_lazy_js' class).\n *\n * @see stopWaitingLazy\n */\nfunction waitLazy() {\n if (waitingLazy) {\n return;\n }\n waitingLazy = true;\n\n var lazyEls = document.querySelectorAll('.o_wait_lazy_js');\n for (var i = 0; i < lazyEls.length; i++) {\n var element = lazyEls[i];\n blockEvents.forEach(function (evType) {\n element.addEventListener(evType, blockFunction);\n });\n }\n\n document.body.classList.add('o_lazy_js_waiting');\n}\n/**\n * Unblocks the DOM sections blocked by @see waitLazy and removes the related\n * 'o_wait_lazy_js' class from the whole DOM.\n */\nfunction stopWaitingLazy() {\n if (!waitingLazy) {\n return;\n }\n waitingLazy = false;\n\n var lazyEls = document.querySelectorAll('.o_wait_lazy_js');\n for (var i = 0; i < lazyEls.length; i++) {\n var element = lazyEls[i];\n blockEvents.forEach(function (evType) {\n element.removeEventListener(evType, blockFunction);\n });\n element.classList.remove('o_wait_lazy_js');\n }\n\n document.body.classList.remove('o_lazy_js_waiting');\n}\n\n// Start waiting for lazy loading as soon as the DOM is available\nif (document.readyState !== 'loading') {\n waitLazy();\n} else {\n document.addEventListener('DOMContentLoaded', function () {\n waitLazy();\n });\n}\n\n// As soon as everything is fully loaded, start loading all the remaining JS\n// and unblock the related DOM section when all of it have been loaded and\n// executed\nvar doResolve = null;\nvar _allScriptsLoaded = new Promise(function (resolve) {\n if (doResolve) {\n resolve();\n } else {\n doResolve = resolve;\n }\n}).then(function () {\n stopWaitingLazy();\n});\nif (document.readyState === 'complete') {\n setTimeout(_loadScripts, 0);\n} else {\n window.addEventListener('load', function () {\n setTimeout(_loadScripts, 0);\n });\n}\n\n/**\n * @param {DOMElement[]} scripts\n * @param {integer} index\n */\nfunction _loadScripts(scripts, index) {\n if (scripts === undefined) {\n scripts = document.querySelectorAll('script[data-src]');\n }\n if (index === undefined) {\n index = 0;\n }\n if (index >= scripts.length) {\n if (typeof doResolve === 'function') {\n doResolve();\n } else {\n doResolve = true;\n }\n return;\n }\n var script = scripts[index];\n script.addEventListener('load', _loadScripts.bind(this, scripts, index + 1));\n script.src = script.dataset.src;\n script.removeAttribute('data-src');\n}\n\nreturn {\n loadScripts: _loadScripts,\n allScriptsLoaded: _allScriptsLoaded,\n};\n});\n", "(function () {\n'use strict';\n\n/**\n * This file makes sure textarea elements with a specific editor class are\n * tweaked as soon as the DOM is ready so that they appear to be loading.\n *\n * They must then be loaded using standard Odoo modules system. In particular,\n * @see web_editor.loader\n */\n\ndocument.addEventListener('DOMContentLoaded', () => {\n // Standard loop for better browser support\n var textareaEls = document.querySelectorAll('textarea.o_wysiwyg_loader');\n for (var i = 0; i < textareaEls.length; i++) {\n var textarea = textareaEls[i];\n var wrapper = document.createElement('div');\n wrapper.classList.add('position-relative', 'o_wysiwyg_textarea_wrapper');\n\n var loadingElement = document.createElement('div');\n loadingElement.classList.add('o_wysiwyg_loading');\n var loadingIcon = document.createElement('i');\n loadingIcon.classList.add('text-600', 'text-center',\n 'fa', 'fa-circle-o-notch', 'fa-spin', 'fa-2x');\n loadingElement.appendChild(loadingIcon);\n wrapper.appendChild(loadingElement);\n\n textarea.parentNode.insertBefore(wrapper, textarea);\n wrapper.insertBefore(textarea, loadingElement);\n }\n});\n\n})();\n", "/** @odoo-module */\n\nimport {getCookie} from 'web.utils.cookies';\nimport { session } from '@web/session';\n\n/**\n * Unhide elements that are hidden by default and that should be visible\n * according to the snippet visibility option.\n */\nexport function unhideConditionalElements() {\n // Create CSS rules in a dedicated style tag according to the snippet\n // visibility option's computed ones (saved as data attributes).\n const styleEl = document.createElement('style');\n styleEl.id = \"conditional_visibility\";\n document.head.appendChild(styleEl);\n const conditionalEls = document.querySelectorAll('[data-visibility=\"conditional\"]');\n for (const conditionalEl of conditionalEls) {\n const selectors = conditionalEl.dataset.visibilitySelectors;\n styleEl.sheet.insertRule(`${selectors} { display: none !important; }`);\n }\n\n // Now remove the classes that makes them always invisible\n for (const conditionalEl of conditionalEls) {\n conditionalEl.classList.remove('o_conditional_hidden');\n }\n}\n\ndocument.addEventListener('DOMContentLoaded', () => {\n // Transfer cookie/session data as HTML element's attributes so that CSS\n // selectors can be based on them.\n const htmlEl = document.documentElement;\n const cookieNamesToDataNames = {\n 'utm_source': 'utmSource',\n 'utm_medium': 'utmMedium',\n 'utm_campaign': 'utmCampaign',\n };\n for (const [name, dsName] of Object.entries(cookieNamesToDataNames)) {\n const cookie = getCookie(`odoo_${name}`);\n if (cookie) {\n // Remove leading and trailing \" and '\n htmlEl.dataset[dsName] = cookie.replace(/(^[\"']|[\"']$)/g, '');\n }\n }\n const country = session.geoip_country_code;\n if (country) {\n htmlEl.dataset.country = country;\n }\n\n htmlEl.dataset.logged = !session.is_website_user;\n\n unhideConditionalElements();\n});\n", "/** @odoo-module **/\n\nimport { initAutoMoreMenu } from '@web/legacy/js/core/menu';\n\n/**\n * Auto adapt the header layout so that elements are not wrapped on a new line.\n */\ndocument.addEventListener('DOMContentLoaded', async () => {\n const header = document.querySelector('header#top');\n if (header) {\n const topMenu = header.querySelector('#top_menu');\n if (header.classList.contains('o_no_autohide_menu')) {\n topMenu.classList.remove('o_menu_loading');\n return;\n }\n const unfoldable = '.divider, .divider ~ li, .o_no_autohide_item, .js_language_selector';\n const excludedImagesSelector = '.o_mega_menu, .o_offcanvas_logo_container, .o_lang_flag';\n const excludedImages = [...header.querySelectorAll(excludedImagesSelector)];\n const images = [...header.querySelectorAll('img')].filter((img) => {\n excludedImages.forEach(node => {\n if (node.contains(img)) {\n return false;\n }\n });\n return img.matches && !img.matches(excludedImagesSelector);\n });\n initAutoMoreMenu(topMenu, {\n unfoldable: unfoldable,\n images: images,\n loadingStyleClasses: ['o_menu_loading']\n });\n }\n});\n", "/** @odoo-module */\n\nimport { session } from '@web/session';\n\n/**\n * This script, served with frontend pages, displays buttons in the top left\n * corner to provide the authenticated user an access to his odoo backend.\n * In the case of the page being viewed in the website_preview client action,\n * it will forward some events to its parent.\n */\ndocument.addEventListener('DOMContentLoaded', () => {\n if (session.is_website_user) {\n return;\n }\n\n if (!window.frameElement) {\n const frontendToBackendNavEl = document.querySelector('.o_frontend_to_backend_nav');\n if (frontendToBackendNavEl) {\n frontendToBackendNavEl.classList.add('d-flex');\n frontendToBackendNavEl.classList.remove('d-none');\n }\n // Auto redirect to frontend if edit/translation mode is requested\n const currentUrl = new URL(window.location.href);\n currentUrl.pathname = `/@${currentUrl.pathname}`;\n if (currentUrl.searchParams.get('enable_editor') || currentUrl.searchParams.get('edit_translations')) {\n document.body.innerHTML = '';\n window.location.replace(currentUrl.href);\n return;\n }\n const backendEditBtnEl = document.querySelector('.o_frontend_to_backend_edit_btn');\n if (backendEditBtnEl) {\n backendEditBtnEl.href = currentUrl.href;\n document.addEventListener(\"keydown\", ev => {\n if (ev.key === \"a\" && ev.altKey) {\n currentUrl.searchParams.set('enable_editor', 1);\n window.location.replace(currentUrl.href);\n }\n }, true);\n }\n } else {\n const backendUserDropdownLinkEl = document.getElementById('o_backend_user_dropdown_link');\n if (backendUserDropdownLinkEl) {\n backendUserDropdownLinkEl.classList.add('d-none');\n backendUserDropdownLinkEl.classList.remove('d-flex');\n }\n // Multiple reasons to do this:\n // - It seems like DOMContentLoaded doesn't always trigger when\n // listened from the parent window\n // - Having an event that's fire only when the page is from Odoo avoids\n // weird behaviours. (e.g. if we want to clear out the iframe, it might\n // fire an DOMContentLoaded on a non odoo page)\n window.frameElement.dispatchEvent(new CustomEvent('OdooFrameContentLoaded'));\n }\n});\n", "/** @odoo-module */\n\ndocument.addEventListener('DOMContentLoaded', () => {\n const htmlEl = document.documentElement;\n const editTranslations = !!htmlEl.dataset.edit_translations;\n // Hack: on translation editor, textareas with translatable text content\n // will get a `` as translation value which stays visible until\n // the values are updated on the editor. The same issue was fixed on CSS\n // for `placeholder` and `value` attributes (since we can get the elements\n // with attribute translation on CSS). But here, we need to hide the text\n // on JS until the editor's code sets the right values on textareas.\n if (editTranslations) {\n [...document.querySelectorAll('textarea')].map(textarea => {\n if (textarea.value.indexOf('data-oe-translation-initial-sha') !== -1) {\n textarea.classList.add('o_text_content_invisible');\n }\n });\n }\n});\n"], "file": "/web/assets/6796-efdeb42/1/web.assets_frontend_minimal.js", "sourceRoot": "../../../../"}