/* /web/static/lib/luxon/luxon.js */ var luxon=(function(exports){'use strict';class LuxonError extends Error{} class InvalidDateTimeError extends LuxonError{constructor(reason){super(`Invalid DateTime: ${reason.toMessage()}`);}} class InvalidIntervalError extends LuxonError{constructor(reason){super(`Invalid Interval: ${reason.toMessage()}`);}} class InvalidDurationError extends LuxonError{constructor(reason){super(`Invalid Duration: ${reason.toMessage()}`);}} class ConflictingSpecificationError extends LuxonError{} class InvalidUnitError extends LuxonError{constructor(unit){super(`Invalid unit ${unit}`);}} class InvalidArgumentError extends LuxonError{} class ZoneIsAbstractError extends LuxonError{constructor(){super("Zone is an abstract class");}} const n="numeric",s="short",l="long";const DATE_SHORT={year:n,month:n,day:n,};const DATE_MED={year:n,month:s,day:n,};const DATE_MED_WITH_WEEKDAY={year:n,month:s,day:n,weekday:s,};const DATE_FULL={year:n,month:l,day:n,};const DATE_HUGE={year:n,month:l,day:n,weekday:l,};const TIME_SIMPLE={hour:n,minute:n,};const TIME_WITH_SECONDS={hour:n,minute:n,second:n,};const TIME_WITH_SHORT_OFFSET={hour:n,minute:n,second:n,timeZoneName:s,};const TIME_WITH_LONG_OFFSET={hour:n,minute:n,second:n,timeZoneName:l,};const TIME_24_SIMPLE={hour:n,minute:n,hourCycle:"h23",};const TIME_24_WITH_SECONDS={hour:n,minute:n,second:n,hourCycle:"h23",};const TIME_24_WITH_SHORT_OFFSET={hour:n,minute:n,second:n,hourCycle:"h23",timeZoneName:s,};const TIME_24_WITH_LONG_OFFSET={hour:n,minute:n,second:n,hourCycle:"h23",timeZoneName:l,};const DATETIME_SHORT={year:n,month:n,day:n,hour:n,minute:n,};const DATETIME_SHORT_WITH_SECONDS={year:n,month:n,day:n,hour:n,minute:n,second:n,};const DATETIME_MED={year:n,month:s,day:n,hour:n,minute:n,};const DATETIME_MED_WITH_SECONDS={year:n,month:s,day:n,hour:n,minute:n,second:n,};const DATETIME_MED_WITH_WEEKDAY={year:n,month:s,day:n,weekday:s,hour:n,minute:n,};const DATETIME_FULL={year:n,month:l,day:n,hour:n,minute:n,timeZoneName:s,};const DATETIME_FULL_WITH_SECONDS={year:n,month:l,day:n,hour:n,minute:n,second:n,timeZoneName:s,};const DATETIME_HUGE={year:n,month:l,day:n,weekday:l,hour:n,minute:n,timeZoneName:l,};const DATETIME_HUGE_WITH_SECONDS={year:n,month:l,day:n,weekday:l,hour:n,minute:n,second:n,timeZoneName:l,};class Zone{get type(){throw new ZoneIsAbstractError();} get name(){throw new ZoneIsAbstractError();} get ianaName(){return this.name;} get isUniversal(){throw new ZoneIsAbstractError();} offsetName(ts,opts){throw new ZoneIsAbstractError();} formatOffset(ts,format){throw new ZoneIsAbstractError();} offset(ts){throw new ZoneIsAbstractError();} equals(otherZone){throw new ZoneIsAbstractError();} get isValid(){throw new ZoneIsAbstractError();}} let singleton$1=null;class SystemZone extends Zone{static get instance(){if(singleton$1===null){singleton$1=new SystemZone();} return singleton$1;} get type(){return"system";} get name(){return new Intl.DateTimeFormat().resolvedOptions().timeZone;} get isUniversal(){return false;} offsetName(ts,{format,locale}){return parseZoneInfo(ts,format,locale);} formatOffset(ts,format){return formatOffset(this.offset(ts),format);} offset(ts){return-new Date(ts).getTimezoneOffset();} equals(otherZone){return otherZone.type==="system";} get isValid(){return true;}} let dtfCache={};function makeDTF(zone){if(!dtfCache[zone]){dtfCache[zone]=new Intl.DateTimeFormat("en-US",{hour12:false,timeZone:zone,year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit",era:"short",});} return dtfCache[zone];} const typeToPos={year:0,month:1,day:2,era:3,hour:4,minute:5,second:6,};function hackyOffset(dtf,date){const formatted=dtf.format(date).replace(/\u200E/g,""),parsed=/(\d+)\/(\d+)\/(\d+) (AD|BC),? (\d+):(\d+):(\d+)/.exec(formatted),[,fMonth,fDay,fYear,fadOrBc,fHour,fMinute,fSecond]=parsed;return[fYear,fMonth,fDay,fadOrBc,fHour,fMinute,fSecond];} function partsOffset(dtf,date){const formatted=dtf.formatToParts(date);const filled=[];for(let i=0;i=0?over:1000+over;return(asUTC-asTS)/(60*1000);} equals(otherZone){return otherZone.type==="iana"&&otherZone.name===this.name;} get isValid(){return this.valid;}} let intlLFCache={};function getCachedLF(locString,opts={}){const key=JSON.stringify([locString,opts]);let dtf=intlLFCache[key];if(!dtf){dtf=new Intl.ListFormat(locString,opts);intlLFCache[key]=dtf;} return dtf;} let intlDTCache={};function getCachedDTF(locString,opts={}){const key=JSON.stringify([locString,opts]);let dtf=intlDTCache[key];if(!dtf){dtf=new Intl.DateTimeFormat(locString,opts);intlDTCache[key]=dtf;} return dtf;} let intlNumCache={};function getCachedINF(locString,opts={}){const key=JSON.stringify([locString,opts]);let inf=intlNumCache[key];if(!inf){inf=new Intl.NumberFormat(locString,opts);intlNumCache[key]=inf;} return inf;} let intlRelCache={};function getCachedRTF(locString,opts={}){const{base,...cacheKeyOpts}=opts;const key=JSON.stringify([locString,cacheKeyOpts]);let inf=intlRelCache[key];if(!inf){inf=new Intl.RelativeTimeFormat(locString,opts);intlRelCache[key]=inf;} return inf;} let sysLocaleCache=null;function systemLocale(){if(sysLocaleCache){return sysLocaleCache;}else{sysLocaleCache=new Intl.DateTimeFormat().resolvedOptions().locale;return sysLocaleCache;}} let weekInfoCache={};function getCachedWeekInfo(locString){let data=weekInfoCache[locString];if(!data){const locale=new Intl.Locale(locString);data="getWeekInfo"in locale?locale.getWeekInfo():locale.weekInfo;weekInfoCache[locString]=data;} return data;} function parseLocaleString(localeStr){const xIndex=localeStr.indexOf("-x-");if(xIndex!==-1){localeStr=localeStr.substring(0,xIndex);} const uIndex=localeStr.indexOf("-u-");if(uIndex===-1){return[localeStr];}else{let options;let selectedStr;try{options=getCachedDTF(localeStr).resolvedOptions();selectedStr=localeStr;}catch(e){const smaller=localeStr.substring(0,uIndex);options=getCachedDTF(smaller).resolvedOptions();selectedStr=smaller;} const{numberingSystem,calendar}=options;return[selectedStr,numberingSystem,calendar];}} function intlConfigString(localeStr,numberingSystem,outputCalendar){if(outputCalendar||numberingSystem){if(!localeStr.includes("-u-")){localeStr+="-u";} if(outputCalendar){localeStr+=`-ca-${outputCalendar}`;} if(numberingSystem){localeStr+=`-nu-${numberingSystem}`;} return localeStr;}else{return localeStr;}} function mapMonths(f){const ms=[];for(let i=1;i<=12;i++){const dt=DateTime.utc(2009,i,1);ms.push(f(dt));} return ms;} function mapWeekdays(f){const ms=[];for(let i=1;i<=7;i++){const dt=DateTime.utc(2016,11,13+i);ms.push(f(dt));} return ms;} function listStuff(loc,length,englishFn,intlFn){const mode=loc.listingMode();if(mode==="error"){return null;}else if(mode==="en"){return englishFn(length);}else{return intlFn(length);}} function supportsFastNumbers(loc){if(loc.numberingSystem&&loc.numberingSystem!=="latn"){return false;}else{return(loc.numberingSystem==="latn"||!loc.locale||loc.locale.startsWith("en")||new Intl.DateTimeFormat(loc.intl).resolvedOptions().numberingSystem==="latn");}} class PolyNumberFormatter{constructor(intl,forceSimple,opts){this.padTo=opts.padTo||0;this.floor=opts.floor||false;const{padTo,floor,...otherOpts}=opts;if(!forceSimple||Object.keys(otherOpts).length>0){const intlOpts={useGrouping:false,...opts};if(opts.padTo>0)intlOpts.minimumIntegerDigits=opts.padTo;this.inf=getCachedINF(intl,intlOpts);}} format(i){if(this.inf){const fixed=this.floor?Math.floor(i):i;return this.inf.format(fixed);}else{const fixed=this.floor?Math.floor(i):roundTo(i,3);return padStart(fixed,this.padTo);}}} class PolyDateFormatter{constructor(dt,intl,opts){this.opts=opts;this.originalZone=undefined;let z=undefined;if(this.opts.timeZone){this.dt=dt;}else if(dt.zone.type==="fixed"){const gmtOffset=-1*(dt.offset/60);const offsetZ=gmtOffset>=0?`Etc/GMT+${gmtOffset}`:`Etc/GMT${gmtOffset}`;if(dt.offset!==0&&IANAZone.create(offsetZ).valid){z=offsetZ;this.dt=dt;}else{z="UTC";this.dt=dt.offset===0?dt:dt.setZone("UTC").plus({minutes:dt.offset});this.originalZone=dt.zone;}}else if(dt.zone.type==="system"){this.dt=dt;}else if(dt.zone.type==="iana"){this.dt=dt;z=dt.zone.name;}else{z="UTC";this.dt=dt.setZone("UTC").plus({minutes:dt.offset});this.originalZone=dt.zone;} const intlOpts={...this.opts};intlOpts.timeZone=intlOpts.timeZone||z;this.dtf=getCachedDTF(intl,intlOpts);} format(){if(this.originalZone){return this.formatToParts().map(({value})=>value).join("");} return this.dtf.format(this.dt.toJSDate());} formatToParts(){const parts=this.dtf.formatToParts(this.dt.toJSDate());if(this.originalZone){return parts.map((part)=>{if(part.type==="timeZoneName"){const offsetName=this.originalZone.offsetName(this.dt.ts,{locale:this.dt.locale,format:this.opts.timeZoneName,});return{...part,value:offsetName,};}else{return part;}});} return parts;} resolvedOptions(){return this.dtf.resolvedOptions();}} class PolyRelFormatter{constructor(intl,isEnglish,opts){this.opts={style:"long",...opts};if(!isEnglish&&hasRelative()){this.rtf=getCachedRTF(intl,opts);}} format(count,unit){if(this.rtf){return this.rtf.format(count,unit);}else{return formatRelativeTime(unit,count,this.opts.numeric,this.opts.style!=="long");}} formatToParts(count,unit){if(this.rtf){return this.rtf.formatToParts(count,unit);}else{return[];}}} const fallbackWeekSettings={firstDay:1,minimalDays:4,weekend:[6,7],};class Locale{static fromOpts(opts){return Locale.create(opts.locale,opts.numberingSystem,opts.outputCalendar,opts.weekSettings,opts.defaultToEN);} static create(locale,numberingSystem,outputCalendar,weekSettings,defaultToEN=false){const specifiedLocale=locale||Settings.defaultLocale;const localeR=specifiedLocale||(defaultToEN?"en-US":systemLocale());const numberingSystemR=numberingSystem||Settings.defaultNumberingSystem;const outputCalendarR=outputCalendar||Settings.defaultOutputCalendar;const weekSettingsR=validateWeekSettings(weekSettings)||Settings.defaultWeekSettings;return new Locale(localeR,numberingSystemR,outputCalendarR,weekSettingsR,specifiedLocale);} static resetCache(){sysLocaleCache=null;intlDTCache={};intlNumCache={};intlRelCache={};} static fromObject({locale,numberingSystem,outputCalendar,weekSettings}={}){return Locale.create(locale,numberingSystem,outputCalendar,weekSettings);} constructor(locale,numbering,outputCalendar,weekSettings,specifiedLocale){const[parsedLocale,parsedNumberingSystem,parsedOutputCalendar]=parseLocaleString(locale);this.locale=parsedLocale;this.numberingSystem=numbering||parsedNumberingSystem||null;this.outputCalendar=outputCalendar||parsedOutputCalendar||null;this.weekSettings=weekSettings;this.intl=intlConfigString(this.locale,this.numberingSystem,this.outputCalendar);this.weekdaysCache={format:{},standalone:{}};this.monthsCache={format:{},standalone:{}};this.meridiemCache=null;this.eraCache={};this.specifiedLocale=specifiedLocale;this.fastNumbersCached=null;} get fastNumbers(){if(this.fastNumbersCached==null){this.fastNumbersCached=supportsFastNumbers(this);} return this.fastNumbersCached;} listingMode(){const isActuallyEn=this.isEnglish();const hasNoWeirdness=(this.numberingSystem===null||this.numberingSystem==="latn")&&(this.outputCalendar===null||this.outputCalendar==="gregory");return isActuallyEn&&hasNoWeirdness?"en":"intl";} clone(alts){if(!alts||Object.getOwnPropertyNames(alts).length===0){return this;}else{return Locale.create(alts.locale||this.specifiedLocale,alts.numberingSystem||this.numberingSystem,alts.outputCalendar||this.outputCalendar,validateWeekSettings(alts.weekSettings)||this.weekSettings,alts.defaultToEN||false);}} redefaultToEN(alts={}){return this.clone({...alts,defaultToEN:true});} redefaultToSystem(alts={}){return this.clone({...alts,defaultToEN:false});} months(length,format=false){return listStuff(this,length,months,()=>{const intl=format?{month:length,day:"numeric"}:{month:length},formatStr=format?"format":"standalone";if(!this.monthsCache[formatStr][length]){this.monthsCache[formatStr][length]=mapMonths((dt)=>this.extract(dt,intl,"month"));} return this.monthsCache[formatStr][length];});} weekdays(length,format=false){return listStuff(this,length,weekdays,()=>{const intl=format?{weekday:length,year:"numeric",month:"long",day:"numeric"}:{weekday:length},formatStr=format?"format":"standalone";if(!this.weekdaysCache[formatStr][length]){this.weekdaysCache[formatStr][length]=mapWeekdays((dt)=>this.extract(dt,intl,"weekday"));} return this.weekdaysCache[formatStr][length];});} meridiems(){return listStuff(this,undefined,()=>meridiems,()=>{if(!this.meridiemCache){const intl={hour:"numeric",hourCycle:"h12"};this.meridiemCache=[DateTime.utc(2016,11,13,9),DateTime.utc(2016,11,13,19)].map((dt)=>this.extract(dt,intl,"dayperiod"));} return this.meridiemCache;});} eras(length){return listStuff(this,length,eras,()=>{const intl={era:length};if(!this.eraCache[length]){this.eraCache[length]=[DateTime.utc(-40,1,1),DateTime.utc(2017,1,1)].map((dt)=>this.extract(dt,intl,"era"));} return this.eraCache[length];});} extract(dt,intlOpts,field){const df=this.dtFormatter(dt,intlOpts),results=df.formatToParts(),matching=results.find((m)=>m.type.toLowerCase()===field);return matching?matching.value:null;} numberFormatter(opts={}){return new PolyNumberFormatter(this.intl,opts.forceSimple||this.fastNumbers,opts);} dtFormatter(dt,intlOpts={}){return new PolyDateFormatter(dt,this.intl,intlOpts);} relFormatter(opts={}){return new PolyRelFormatter(this.intl,this.isEnglish(),opts);} listFormatter(opts={}){return getCachedLF(this.intl,opts);} isEnglish(){return(this.locale==="en"||this.locale.toLowerCase()==="en-us"||new Intl.DateTimeFormat(this.intl).resolvedOptions().locale.startsWith("en-us"));} getWeekSettings(){if(this.weekSettings){return this.weekSettings;}else if(!hasLocaleWeekInfo()){return fallbackWeekSettings;}else{return getCachedWeekInfo(this.locale);}} getStartOfWeek(){return this.getWeekSettings().firstDay;} getMinDaysInFirstWeek(){return this.getWeekSettings().minimalDays;} getWeekendDays(){return this.getWeekSettings().weekend;} equals(other){return(this.locale===other.locale&&this.numberingSystem===other.numberingSystem&&this.outputCalendar===other.outputCalendar);}} let singleton=null;class FixedOffsetZone extends Zone{static get utcInstance(){if(singleton===null){singleton=new FixedOffsetZone(0);} return singleton;} static instance(offset){return offset===0?FixedOffsetZone.utcInstance:new FixedOffsetZone(offset);} static parseSpecifier(s){if(s){const r=s.match(/^utc(?:([+-]\d{1,2})(?::(\d{2}))?)?$/i);if(r){return new FixedOffsetZone(signedOffset(r[1],r[2]));}} return null;} constructor(offset){super();this.fixed=offset;} get type(){return"fixed";} get name(){return this.fixed===0?"UTC":`UTC${formatOffset(this.fixed, "narrow")}`;} get ianaName(){if(this.fixed===0){return"Etc/UTC";}else{return`Etc/GMT${formatOffset(-this.fixed, "narrow")}`;}} offsetName(){return this.name;} formatOffset(ts,format){return formatOffset(this.fixed,format);} get isUniversal(){return true;} offset(){return this.fixed;} equals(otherZone){return otherZone.type==="fixed"&&otherZone.fixed===this.fixed;} get isValid(){return true;}} class InvalidZone extends Zone{constructor(zoneName){super();this.zoneName=zoneName;} get type(){return"invalid";} get name(){return this.zoneName;} get isUniversal(){return false;} offsetName(){return null;} formatOffset(){return"";} offset(){return NaN;} equals(){return false;} get isValid(){return false;}} function normalizeZone(input,defaultZone){if(isUndefined(input)||input===null){return defaultZone;}else if(input instanceof Zone){return input;}else if(isString(input)){const lowered=input.toLowerCase();if(lowered==="default")return defaultZone;else if(lowered==="local"||lowered==="system")return SystemZone.instance;else if(lowered==="utc"||lowered==="gmt")return FixedOffsetZone.utcInstance;else return FixedOffsetZone.parseSpecifier(lowered)||IANAZone.create(input);}else if(isNumber(input)){return FixedOffsetZone.instance(input);}else if(typeof input==="object"&&"offset"in input&&typeof input.offset==="function"){return input;}else{return new InvalidZone(input);}} let now=()=>Date.now(),defaultZone="system",defaultLocale=null,defaultNumberingSystem=null,defaultOutputCalendar=null,twoDigitCutoffYear=60,throwOnInvalid,defaultWeekSettings=null;class Settings{static get now(){return now;} static set now(n){now=n;} static set defaultZone(zone){defaultZone=zone;} static get defaultZone(){return normalizeZone(defaultZone,SystemZone.instance);} static get defaultLocale(){return defaultLocale;} static set defaultLocale(locale){defaultLocale=locale;} static get defaultNumberingSystem(){return defaultNumberingSystem;} static set defaultNumberingSystem(numberingSystem){defaultNumberingSystem=numberingSystem;} static get defaultOutputCalendar(){return defaultOutputCalendar;} static set defaultOutputCalendar(outputCalendar){defaultOutputCalendar=outputCalendar;} static get defaultWeekSettings(){return defaultWeekSettings;} static set defaultWeekSettings(weekSettings){defaultWeekSettings=validateWeekSettings(weekSettings);} static get twoDigitCutoffYear(){return twoDigitCutoffYear;} static set twoDigitCutoffYear(cutoffYear){twoDigitCutoffYear=cutoffYear%100;} static get throwOnInvalid(){return throwOnInvalid;} static set throwOnInvalid(t){throwOnInvalid=t;} static resetCaches(){Locale.resetCache();IANAZone.resetCache();}} class Invalid{constructor(reason,explanation){this.reason=reason;this.explanation=explanation;} toMessage(){if(this.explanation){return`${this.reason}: ${this.explanation}`;}else{return this.reason;}}} const nonLeapLadder=[0,31,59,90,120,151,181,212,243,273,304,334],leapLadder=[0,31,60,91,121,152,182,213,244,274,305,335];function unitOutOfRange(unit,value){return new Invalid("unit out of range",`you specified ${value} (of type ${typeof value}) as a ${unit}, which is invalid`);} function dayOfWeek(year,month,day){const d=new Date(Date.UTC(year,month-1,day));if(year<100&&year>=0){d.setUTCFullYear(d.getUTCFullYear()-1900);} const js=d.getUTCDay();return js===0?7:js;} function computeOrdinal(year,month,day){return day+(isLeapYear(year)?leapLadder:nonLeapLadder)[month-1];} function uncomputeOrdinal(year,ordinal){const table=isLeapYear(year)?leapLadder:nonLeapLadder,month0=table.findIndex((i)=>iweeksInWeekYear(year,minDaysInFirstWeek,startOfWeek)){weekYear=year+1;weekNumber=1;}else{weekYear=year;} return{weekYear,weekNumber,weekday,...timeObject(gregObj)};} function weekToGregorian(weekData,minDaysInFirstWeek=4,startOfWeek=1){const{weekYear,weekNumber,weekday}=weekData,weekdayOfJan4=isoWeekdayToLocal(dayOfWeek(weekYear,1,minDaysInFirstWeek),startOfWeek),yearInDays=daysInYear(weekYear);let ordinal=weekNumber*7+weekday-weekdayOfJan4-7+minDaysInFirstWeek,year;if(ordinal<1){year=weekYear-1;ordinal+=daysInYear(year);}else if(ordinal>yearInDays){year=weekYear+1;ordinal-=daysInYear(weekYear);}else{year=weekYear;} const{month,day}=uncomputeOrdinal(year,ordinal);return{year,month,day,...timeObject(weekData)};} function gregorianToOrdinal(gregData){const{year,month,day}=gregData;const ordinal=computeOrdinal(year,month,day);return{year,ordinal,...timeObject(gregData)};} function ordinalToGregorian(ordinalData){const{year,ordinal}=ordinalData;const{month,day}=uncomputeOrdinal(year,ordinal);return{year,month,day,...timeObject(ordinalData)};} function usesLocalWeekValues(obj,loc){const hasLocaleWeekData=!isUndefined(obj.localWeekday)||!isUndefined(obj.localWeekNumber)||!isUndefined(obj.localWeekYear);if(hasLocaleWeekData){const hasIsoWeekData=!isUndefined(obj.weekday)||!isUndefined(obj.weekNumber)||!isUndefined(obj.weekYear);if(hasIsoWeekData){throw new ConflictingSpecificationError("Cannot mix locale-based week fields with ISO-based week fields");} if(!isUndefined(obj.localWeekday))obj.weekday=obj.localWeekday;if(!isUndefined(obj.localWeekNumber))obj.weekNumber=obj.localWeekNumber;if(!isUndefined(obj.localWeekYear))obj.weekYear=obj.localWeekYear;delete obj.localWeekday;delete obj.localWeekNumber;delete obj.localWeekYear;return{minDaysInFirstWeek:loc.getMinDaysInFirstWeek(),startOfWeek:loc.getStartOfWeek(),};}else{return{minDaysInFirstWeek:4,startOfWeek:1};}} function hasInvalidWeekData(obj,minDaysInFirstWeek=4,startOfWeek=1){const validYear=isInteger(obj.weekYear),validWeek=integerBetween(obj.weekNumber,1,weeksInWeekYear(obj.weekYear,minDaysInFirstWeek,startOfWeek)),validWeekday=integerBetween(obj.weekday,1,7);if(!validYear){return unitOutOfRange("weekYear",obj.weekYear);}else if(!validWeek){return unitOutOfRange("week",obj.weekNumber);}else if(!validWeekday){return unitOutOfRange("weekday",obj.weekday);}else return false;} function hasInvalidOrdinalData(obj){const validYear=isInteger(obj.year),validOrdinal=integerBetween(obj.ordinal,1,daysInYear(obj.year));if(!validYear){return unitOutOfRange("year",obj.year);}else if(!validOrdinal){return unitOutOfRange("ordinal",obj.ordinal);}else return false;} function hasInvalidGregorianData(obj){const validYear=isInteger(obj.year),validMonth=integerBetween(obj.month,1,12),validDay=integerBetween(obj.day,1,daysInMonth(obj.year,obj.month));if(!validYear){return unitOutOfRange("year",obj.year);}else if(!validMonth){return unitOutOfRange("month",obj.month);}else if(!validDay){return unitOutOfRange("day",obj.day);}else return false;} function hasInvalidTimeData(obj){const{hour,minute,second,millisecond}=obj;const validHour=integerBetween(hour,0,23)||(hour===24&&minute===0&&second===0&&millisecond===0),validMinute=integerBetween(minute,0,59),validSecond=integerBetween(second,0,59),validMillisecond=integerBetween(millisecond,0,999);if(!validHour){return unitOutOfRange("hour",hour);}else if(!validMinute){return unitOutOfRange("minute",minute);}else if(!validSecond){return unitOutOfRange("second",second);}else if(!validMillisecond){return unitOutOfRange("millisecond",millisecond);}else return false;} function isUndefined(o){return typeof o==="undefined";} function isNumber(o){return typeof o==="number";} function isInteger(o){return typeof o==="number"&&o%1===0;} function isString(o){return typeof o==="string";} function isDate(o){return Object.prototype.toString.call(o)==="[object Date]";} function hasRelative(){try{return typeof Intl!=="undefined"&&!!Intl.RelativeTimeFormat;}catch(e){return false;}} function hasLocaleWeekInfo(){try{return(typeof Intl!=="undefined"&&!!Intl.Locale&&("weekInfo"in Intl.Locale.prototype||"getWeekInfo"in Intl.Locale.prototype));}catch(e){return false;}} function maybeArray(thing){return Array.isArray(thing)?thing:[thing];} function bestBy(arr,by,compare){if(arr.length===0){return undefined;} return arr.reduce((best,next)=>{const pair=[by(next),next];if(!best){return pair;}else if(compare(best[0],pair[0])===best[0]){return best;}else{return pair;}},null)[1];} function pick(obj,keys){return keys.reduce((a,k)=>{a[k]=obj[k];return a;},{});} function hasOwnProperty(obj,prop){return Object.prototype.hasOwnProperty.call(obj,prop);} function validateWeekSettings(settings){if(settings==null){return null;}else if(typeof settings!=="object"){throw new InvalidArgumentError("Week settings must be an object");}else{if(!integerBetween(settings.firstDay,1,7)||!integerBetween(settings.minimalDays,1,7)||!Array.isArray(settings.weekend)||settings.weekend.some((v)=>!integerBetween(v,1,7))){throw new InvalidArgumentError("Invalid week settings");} return{firstDay:settings.firstDay,minimalDays:settings.minimalDays,weekend:Array.from(settings.weekend),};}} function integerBetween(thing,bottom,top){return isInteger(thing)&&thing>=bottom&&thing<=top;} function floorMod(x,n){return x-n*Math.floor(x/n);} function padStart(input,n=2){const isNeg=input<0;let padded;if(isNeg){padded="-"+(""+-input).padStart(n,"0");}else{padded=(""+input).padStart(n,"0");} return padded;} function parseInteger(string){if(isUndefined(string)||string===null||string===""){return undefined;}else{return parseInt(string,10);}} function parseFloating(string){if(isUndefined(string)||string===null||string===""){return undefined;}else{return parseFloat(string);}} function parseMillis(fraction){if(isUndefined(fraction)||fraction===null||fraction===""){return undefined;}else{const f=parseFloat("0."+fraction)*1000;return Math.floor(f);}} function roundTo(number,digits,towardZero=false){const factor=10**digits,rounder=towardZero?Math.trunc:Math.round;return rounder(number*factor)/factor;} function isLeapYear(year){return year%4===0&&(year%100!==0||year%400===0);} function daysInYear(year){return isLeapYear(year)?366:365;} function daysInMonth(year,month){const modMonth=floorMod(month-1,12)+1,modYear=year+(month-modMonth)/12;if(modMonth===2){return isLeapYear(modYear)?29:28;}else{return[31,null,31,30,31,30,31,31,30,31,30,31][modMonth-1];}} function objToLocalTS(obj){let d=Date.UTC(obj.year,obj.month-1,obj.day,obj.hour,obj.minute,obj.second,obj.millisecond);if(obj.year<100&&obj.year>=0){d=new Date(d);d.setUTCFullYear(obj.year,obj.month-1,obj.day);} return+d;} function firstWeekOffset(year,minDaysInFirstWeek,startOfWeek){const fwdlw=isoWeekdayToLocal(dayOfWeek(year,1,minDaysInFirstWeek),startOfWeek);return-fwdlw+minDaysInFirstWeek-1;} function weeksInWeekYear(weekYear,minDaysInFirstWeek=4,startOfWeek=1){const weekOffset=firstWeekOffset(weekYear,minDaysInFirstWeek,startOfWeek);const weekOffsetNext=firstWeekOffset(weekYear+1,minDaysInFirstWeek,startOfWeek);return(daysInYear(weekYear)-weekOffset+weekOffsetNext)/7;} function untruncateYear(year){if(year>99){return year;}else return year>Settings.twoDigitCutoffYear?1900+year:2000+year;} function parseZoneInfo(ts,offsetFormat,locale,timeZone=null){const date=new Date(ts),intlOpts={hourCycle:"h23",year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",};if(timeZone){intlOpts.timeZone=timeZone;} const modified={timeZoneName:offsetFormat,...intlOpts};const parsed=new Intl.DateTimeFormat(locale,modified).formatToParts(date).find((m)=>m.type.toLowerCase()==="timezonename");return parsed?parsed.value:null;} function signedOffset(offHourStr,offMinuteStr){let offHour=parseInt(offHourStr,10);if(Number.isNaN(offHour)){offHour=0;} const offMin=parseInt(offMinuteStr,10)||0,offMinSigned=offHour<0||Object.is(offHour,-0)?-offMin:offMin;return offHour*60+offMinSigned;} function asNumber(value){const numericValue=Number(value);if(typeof value==="boolean"||value===""||Number.isNaN(numericValue)) throw new InvalidArgumentError(`Invalid unit value ${value}`);return numericValue;} function normalizeObject(obj,normalizer){const normalized={};for(const u in obj){if(hasOwnProperty(obj,u)){const v=obj[u];if(v===undefined||v===null)continue;normalized[normalizer(u)]=asNumber(v);}} return normalized;} function formatOffset(offset,format){const hours=Math.trunc(Math.abs(offset/60)),minutes=Math.trunc(Math.abs(offset%60)),sign=offset>=0?"+":"-";switch(format){case"short":return`${sign}${padStart(hours, 2)}:${padStart(minutes, 2)}`;case"narrow":return`${sign}${hours}${minutes > 0 ? `:${minutes}` : ""}`;case"techie":return`${sign}${padStart(hours, 2)}${padStart(minutes, 2)}`;default:throw new RangeError(`Value format ${format} is out of range for property format`);}} function timeObject(obj){return pick(obj,["hour","minute","second","millisecond"]);} const monthsLong=["January","February","March","April","May","June","July","August","September","October","November","December",];const monthsShort=["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec",];const monthsNarrow=["J","F","M","A","M","J","J","A","S","O","N","D"];function months(length){switch(length){case"narrow":return[...monthsNarrow];case"short":return[...monthsShort];case"long":return[...monthsLong];case"numeric":return["1","2","3","4","5","6","7","8","9","10","11","12"];case"2-digit":return["01","02","03","04","05","06","07","08","09","10","11","12"];default:return null;}} const weekdaysLong=["Monday","Tuesday","Wednesday","Thursday","Friday","Saturday","Sunday",];const weekdaysShort=["Mon","Tue","Wed","Thu","Fri","Sat","Sun"];const weekdaysNarrow=["M","T","W","T","F","S","S"];function weekdays(length){switch(length){case"narrow":return[...weekdaysNarrow];case"short":return[...weekdaysShort];case"long":return[...weekdaysLong];case"numeric":return["1","2","3","4","5","6","7"];default:return null;}} const meridiems=["AM","PM"];const erasLong=["Before Christ","Anno Domini"];const erasShort=["BC","AD"];const erasNarrow=["B","A"];function eras(length){switch(length){case"narrow":return[...erasNarrow];case"short":return[...erasShort];case"long":return[...erasLong];default:return null;}} function meridiemForDateTime(dt){return meridiems[dt.hour<12?0:1];} function weekdayForDateTime(dt,length){return weekdays(length)[dt.weekday-1];} function monthForDateTime(dt,length){return months(length)[dt.month-1];} function eraForDateTime(dt,length){return eras(length)[dt.year<0?0:1];} function formatRelativeTime(unit,count,numeric="always",narrow=false){const units={years:["year","yr."],quarters:["quarter","qtr."],months:["month","mo."],weeks:["week","wk."],days:["day","day","days"],hours:["hour","hr."],minutes:["minute","min."],seconds:["second","sec."],};const lastable=["hours","minutes","seconds"].indexOf(unit)===-1;if(numeric==="auto"&&lastable){const isDay=unit==="days";switch(count){case 1:return isDay?"tomorrow":`next ${units[unit][0]}`;case-1:return isDay?"yesterday":`last ${units[unit][0]}`;case 0:return isDay?"today":`this ${units[unit][0]}`;}} const isInPast=Object.is(count,-0)||count<0,fmtValue=Math.abs(count),singular=fmtValue===1,lilUnits=units[unit],fmtUnit=narrow?singular?lilUnits[1]:lilUnits[2]||lilUnits[1]:singular?units[unit][0]:unit;return isInPast?`${fmtValue} ${fmtUnit} ago`:`in ${fmtValue} ${fmtUnit}`;} function stringifyTokens(splits,tokenToString){let s="";for(const token of splits){if(token.literal){s+=token.val;}else{s+=tokenToString(token.val);}} return s;} const macroTokenToFormatOpts={D:DATE_SHORT,DD:DATE_MED,DDD:DATE_FULL,DDDD:DATE_HUGE,t:TIME_SIMPLE,tt:TIME_WITH_SECONDS,ttt:TIME_WITH_SHORT_OFFSET,tttt:TIME_WITH_LONG_OFFSET,T:TIME_24_SIMPLE,TT:TIME_24_WITH_SECONDS,TTT:TIME_24_WITH_SHORT_OFFSET,TTTT:TIME_24_WITH_LONG_OFFSET,f:DATETIME_SHORT,ff:DATETIME_MED,fff:DATETIME_FULL,ffff:DATETIME_HUGE,F:DATETIME_SHORT_WITH_SECONDS,FF:DATETIME_MED_WITH_SECONDS,FFF:DATETIME_FULL_WITH_SECONDS,FFFF:DATETIME_HUGE_WITH_SECONDS,};class Formatter{static create(locale,opts={}){return new Formatter(locale,opts);} static parseFormat(fmt){let current=null,currentFull="",bracketed=false;const splits=[];for(let i=0;i0){splits.push({literal:bracketed||/^\s+$/.test(currentFull),val:currentFull});} current=null;currentFull="";bracketed=!bracketed;}else if(bracketed){currentFull+=c;}else if(c===current){currentFull+=c;}else{if(currentFull.length>0){splits.push({literal:/^\s+$/.test(currentFull),val:currentFull});} currentFull=c;current=c;}} if(currentFull.length>0){splits.push({literal:bracketed||/^\s+$/.test(currentFull),val:currentFull});} return splits;} static macroTokenToFormatOpts(token){return macroTokenToFormatOpts[token];} constructor(locale,formatOpts){this.opts=formatOpts;this.loc=locale;this.systemLoc=null;} formatWithSystemDefault(dt,opts){if(this.systemLoc===null){this.systemLoc=this.loc.redefaultToSystem();} const df=this.systemLoc.dtFormatter(dt,{...this.opts,...opts});return df.format();} dtFormatter(dt,opts={}){return this.loc.dtFormatter(dt,{...this.opts,...opts});} formatDateTime(dt,opts){return this.dtFormatter(dt,opts).format();} formatDateTimeParts(dt,opts){return this.dtFormatter(dt,opts).formatToParts();} formatInterval(interval,opts){const df=this.dtFormatter(interval.start,opts);return df.dtf.formatRange(interval.start.toJSDate(),interval.end.toJSDate());} resolvedOptions(dt,opts){return this.dtFormatter(dt,opts).resolvedOptions();} num(n,p=0){if(this.opts.forceSimple){return padStart(n,p);} const opts={...this.opts};if(p>0){opts.padTo=p;} return this.loc.numberFormatter(opts).format(n);} formatDateTimeFromString(dt,fmt){const knownEnglish=this.loc.listingMode()==="en",useDateTimeFormatter=this.loc.outputCalendar&&this.loc.outputCalendar!=="gregory",string=(opts,extract)=>this.loc.extract(dt,opts,extract),formatOffset=(opts)=>{if(dt.isOffsetFixed&&dt.offset===0&&opts.allowZ){return"Z";} return dt.isValid?dt.zone.formatOffset(dt.ts,opts.format):"";},meridiem=()=>knownEnglish?meridiemForDateTime(dt):string({hour:"numeric",hourCycle:"h12"},"dayperiod"),month=(length,standalone)=>knownEnglish?monthForDateTime(dt,length):string(standalone?{month:length}:{month:length,day:"numeric"},"month"),weekday=(length,standalone)=>knownEnglish?weekdayForDateTime(dt,length):string(standalone?{weekday:length}:{weekday:length,month:"long",day:"numeric"},"weekday"),maybeMacro=(token)=>{const formatOpts=Formatter.macroTokenToFormatOpts(token);if(formatOpts){return this.formatWithSystemDefault(dt,formatOpts);}else{return token;}},era=(length)=>knownEnglish?eraForDateTime(dt,length):string({era:length},"era"),tokenToString=(token)=>{switch(token){case"S":return this.num(dt.millisecond);case"u":case"SSS":return this.num(dt.millisecond,3);case"s":return this.num(dt.second);case"ss":return this.num(dt.second,2);case"uu":return this.num(Math.floor(dt.millisecond/10),2);case"uuu":return this.num(Math.floor(dt.millisecond/100));case"m":return this.num(dt.minute);case"mm":return this.num(dt.minute,2);case"h":return this.num(dt.hour%12===0?12:dt.hour%12);case"hh":return this.num(dt.hour%12===0?12:dt.hour%12,2);case"H":return this.num(dt.hour);case"HH":return this.num(dt.hour,2);case"Z":return formatOffset({format:"narrow",allowZ:this.opts.allowZ});case"ZZ":return formatOffset({format:"short",allowZ:this.opts.allowZ});case"ZZZ":return formatOffset({format:"techie",allowZ:this.opts.allowZ});case"ZZZZ":return dt.zone.offsetName(dt.ts,{format:"short",locale:this.loc.locale});case"ZZZZZ":return dt.zone.offsetName(dt.ts,{format:"long",locale:this.loc.locale});case"z":return dt.zoneName;case"a":return meridiem();case"d":return useDateTimeFormatter?string({day:"numeric"},"day"):this.num(dt.day);case"dd":return useDateTimeFormatter?string({day:"2-digit"},"day"):this.num(dt.day,2);case"c":return this.num(dt.weekday);case"ccc":return weekday("short",true);case"cccc":return weekday("long",true);case"ccccc":return weekday("narrow",true);case"E":return this.num(dt.weekday);case"EEE":return weekday("short",false);case"EEEE":return weekday("long",false);case"EEEEE":return weekday("narrow",false);case"L":return useDateTimeFormatter?string({month:"numeric",day:"numeric"},"month"):this.num(dt.month);case"LL":return useDateTimeFormatter?string({month:"2-digit",day:"numeric"},"month"):this.num(dt.month,2);case"LLL":return month("short",true);case"LLLL":return month("long",true);case"LLLLL":return month("narrow",true);case"M":return useDateTimeFormatter?string({month:"numeric"},"month"):this.num(dt.month);case"MM":return useDateTimeFormatter?string({month:"2-digit"},"month"):this.num(dt.month,2);case"MMM":return month("short",false);case"MMMM":return month("long",false);case"MMMMM":return month("narrow",false);case"y":return useDateTimeFormatter?string({year:"numeric"},"year"):this.num(dt.year);case"yy":return useDateTimeFormatter?string({year:"2-digit"},"year"):this.num(dt.year.toString().slice(-2),2);case"yyyy":return useDateTimeFormatter?string({year:"numeric"},"year"):this.num(dt.year,4);case"yyyyyy":return useDateTimeFormatter?string({year:"numeric"},"year"):this.num(dt.year,6);case"G":return era("short");case"GG":return era("long");case"GGGGG":return era("narrow");case"kk":return this.num(dt.weekYear.toString().slice(-2),2);case"kkkk":return this.num(dt.weekYear,4);case"W":return this.num(dt.weekNumber);case"WW":return this.num(dt.weekNumber,2);case"n":return this.num(dt.localWeekNumber);case"nn":return this.num(dt.localWeekNumber,2);case"ii":return this.num(dt.localWeekYear.toString().slice(-2),2);case"iiii":return this.num(dt.localWeekYear,4);case"o":return this.num(dt.ordinal);case"ooo":return this.num(dt.ordinal,3);case"q":return this.num(dt.quarter);case"qq":return this.num(dt.quarter,2);case"X":return this.num(Math.floor(dt.ts/1000));case"x":return this.num(dt.ts);default:return maybeMacro(token);}};return stringifyTokens(Formatter.parseFormat(fmt),tokenToString);} formatDurationFromString(dur,fmt){const tokenToField=(token)=>{switch(token[0]){case"S":return"millisecond";case"s":return"second";case"m":return"minute";case"h":return"hour";case"d":return"day";case"w":return"week";case"M":return"month";case"y":return"year";default:return null;}},tokenToString=(lildur)=>(token)=>{const mapped=tokenToField(token);if(mapped){return this.num(lildur.get(mapped),token.length);}else{return token;}},tokens=Formatter.parseFormat(fmt),realTokens=tokens.reduce((found,{literal,val})=>(literal?found:found.concat(val)),[]),collapsed=dur.shiftTo(...realTokens.map(tokenToField).filter((t)=>t));return stringifyTokens(tokens,tokenToString(collapsed));}} const ianaRegex=/[A-Za-z_+-]{1,256}(?::?\/[A-Za-z0-9_+-]{1,256}(?:\/[A-Za-z0-9_+-]{1,256})?)?/;function combineRegexes(...regexes){const full=regexes.reduce((f,r)=>f+r.source,"");return RegExp(`^${full}$`);} function combineExtractors(...extractors){return(m)=>extractors.reduce(([mergedVals,mergedZone,cursor],ex)=>{const[val,zone,next]=ex(m,cursor);return[{...mergedVals,...val},zone||mergedZone,next];},[{},null,1]).slice(0,2);} function parse(s,...patterns){if(s==null){return[null,null];} for(const[regex,extractor]of patterns){const m=regex.exec(s);if(m){return extractor(m);}} return[null,null];} function simpleParse(...keys){return(match,cursor)=>{const ret={};let i;for(i=0;inum!==undefined&&(force||(num&&hasNegativePrefix))?-num:num;return[{years:maybeNegate(parseFloating(yearStr)),months:maybeNegate(parseFloating(monthStr)),weeks:maybeNegate(parseFloating(weekStr)),days:maybeNegate(parseFloating(dayStr)),hours:maybeNegate(parseFloating(hourStr)),minutes:maybeNegate(parseFloating(minuteStr)),seconds:maybeNegate(parseFloating(secondStr),secondStr==="-0"),milliseconds:maybeNegate(parseMillis(millisecondsStr),negativeSeconds),},];} const obsOffsets={GMT:0,EDT:-4*60,EST:-5*60,CDT:-5*60,CST:-6*60,MDT:-6*60,MST:-7*60,PDT:-7*60,PST:-8*60,};function fromStrings(weekdayStr,yearStr,monthStr,dayStr,hourStr,minuteStr,secondStr){const result={year:yearStr.length===2?untruncateYear(parseInteger(yearStr)):parseInteger(yearStr),month:monthsShort.indexOf(monthStr)+1,day:parseInteger(dayStr),hour:parseInteger(hourStr),minute:parseInteger(minuteStr),};if(secondStr)result.second=parseInteger(secondStr);if(weekdayStr){result.weekday=weekdayStr.length>3?weekdaysLong.indexOf(weekdayStr)+1:weekdaysShort.indexOf(weekdayStr)+1;} return result;} const rfc2822=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|(?:([+-]\d\d)(\d\d)))$/;function extractRFC2822(match){const[,weekdayStr,dayStr,monthStr,yearStr,hourStr,minuteStr,secondStr,obsOffset,milOffset,offHourStr,offMinuteStr,]=match,result=fromStrings(weekdayStr,yearStr,monthStr,dayStr,hourStr,minuteStr,secondStr);let offset;if(obsOffset){offset=obsOffsets[obsOffset];}else if(milOffset){offset=0;}else{offset=signedOffset(offHourStr,offMinuteStr);} return[result,new FixedOffsetZone(offset)];} function preprocessRFC2822(s){return s.replace(/\([^()]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").trim();} const rfc1123=/^(Mon|Tue|Wed|Thu|Fri|Sat|Sun), (\d\d) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) (\d{4}) (\d\d):(\d\d):(\d\d) GMT$/,rfc850=/^(Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday), (\d\d)-(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)-(\d\d) (\d\d):(\d\d):(\d\d) GMT$/,ascii=/^(Mon|Tue|Wed|Thu|Fri|Sat|Sun) (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) ( \d|\d\d) (\d\d):(\d\d):(\d\d) (\d{4})$/;function extractRFC1123Or850(match){const[,weekdayStr,dayStr,monthStr,yearStr,hourStr,minuteStr,secondStr]=match,result=fromStrings(weekdayStr,yearStr,monthStr,dayStr,hourStr,minuteStr,secondStr);return[result,FixedOffsetZone.utcInstance];} function extractASCII(match){const[,weekdayStr,monthStr,dayStr,hourStr,minuteStr,secondStr,yearStr]=match,result=fromStrings(weekdayStr,yearStr,monthStr,dayStr,hourStr,minuteStr,secondStr);return[result,FixedOffsetZone.utcInstance];} const isoYmdWithTimeExtensionRegex=combineRegexes(isoYmdRegex,isoTimeExtensionRegex);const isoWeekWithTimeExtensionRegex=combineRegexes(isoWeekRegex,isoTimeExtensionRegex);const isoOrdinalWithTimeExtensionRegex=combineRegexes(isoOrdinalRegex,isoTimeExtensionRegex);const isoTimeCombinedRegex=combineRegexes(isoTimeRegex);const extractISOYmdTimeAndOffset=combineExtractors(extractISOYmd,extractISOTime,extractISOOffset,extractIANAZone);const extractISOWeekTimeAndOffset=combineExtractors(extractISOWeekData,extractISOTime,extractISOOffset,extractIANAZone);const extractISOOrdinalDateAndTime=combineExtractors(extractISOOrdinalData,extractISOTime,extractISOOffset,extractIANAZone);const extractISOTimeAndOffset=combineExtractors(extractISOTime,extractISOOffset,extractIANAZone);function parseISODate(s){return parse(s,[isoYmdWithTimeExtensionRegex,extractISOYmdTimeAndOffset],[isoWeekWithTimeExtensionRegex,extractISOWeekTimeAndOffset],[isoOrdinalWithTimeExtensionRegex,extractISOOrdinalDateAndTime],[isoTimeCombinedRegex,extractISOTimeAndOffset]);} function parseRFC2822Date(s){return parse(preprocessRFC2822(s),[rfc2822,extractRFC2822]);} function parseHTTPDate(s){return parse(s,[rfc1123,extractRFC1123Or850],[rfc850,extractRFC1123Or850],[ascii,extractASCII]);} function parseISODuration(s){return parse(s,[isoDuration,extractISODuration]);} const extractISOTimeOnly=combineExtractors(extractISOTime);function parseISOTimeOnly(s){return parse(s,[isoTimeOnly,extractISOTimeOnly]);} const sqlYmdWithTimeExtensionRegex=combineRegexes(sqlYmdRegex,sqlTimeExtensionRegex);const sqlTimeCombinedRegex=combineRegexes(sqlTimeRegex);const extractISOTimeOffsetAndIANAZone=combineExtractors(extractISOTime,extractISOOffset,extractIANAZone);function parseSQL(s){return parse(s,[sqlYmdWithTimeExtensionRegex,extractISOYmdTimeAndOffset],[sqlTimeCombinedRegex,extractISOTimeOffsetAndIANAZone]);} const INVALID$2="Invalid Duration";const lowOrderMatrix={weeks:{days:7,hours:7*24,minutes:7*24*60,seconds:7*24*60*60,milliseconds:7*24*60*60*1000,},days:{hours:24,minutes:24*60,seconds:24*60*60,milliseconds:24*60*60*1000,},hours:{minutes:60,seconds:60*60,milliseconds:60*60*1000},minutes:{seconds:60,milliseconds:60*1000},seconds:{milliseconds:1000},},casualMatrix={years:{quarters:4,months:12,weeks:52,days:365,hours:365*24,minutes:365*24*60,seconds:365*24*60*60,milliseconds:365*24*60*60*1000,},quarters:{months:3,weeks:13,days:91,hours:91*24,minutes:91*24*60,seconds:91*24*60*60,milliseconds:91*24*60*60*1000,},months:{weeks:4,days:30,hours:30*24,minutes:30*24*60,seconds:30*24*60*60,milliseconds:30*24*60*60*1000,},...lowOrderMatrix,},daysInYearAccurate=146097.0/400,daysInMonthAccurate=146097.0/4800,accurateMatrix={years:{quarters:4,months:12,weeks:daysInYearAccurate/7,days:daysInYearAccurate,hours:daysInYearAccurate*24,minutes:daysInYearAccurate*24*60,seconds:daysInYearAccurate*24*60*60,milliseconds:daysInYearAccurate*24*60*60*1000,},quarters:{months:3,weeks:daysInYearAccurate/28,days:daysInYearAccurate/4,hours:(daysInYearAccurate*24)/4,minutes:(daysInYearAccurate*24*60)/4,seconds:(daysInYearAccurate*24*60*60)/4,milliseconds:(daysInYearAccurate*24*60*60*1000)/4,},months:{weeks:daysInMonthAccurate/7,days:daysInMonthAccurate,hours:daysInMonthAccurate*24,minutes:daysInMonthAccurate*24*60,seconds:daysInMonthAccurate*24*60*60,milliseconds:daysInMonthAccurate*24*60*60*1000,},...lowOrderMatrix,};const orderedUnits$1=["years","quarters","months","weeks","days","hours","minutes","seconds","milliseconds",];const reverseUnits=orderedUnits$1.slice(0).reverse();function clone$1(dur,alts,clear=false){const conf={values:clear?alts.values:{...dur.values,...(alts.values||{})},loc:dur.loc.clone(alts.loc),conversionAccuracy:alts.conversionAccuracy||dur.conversionAccuracy,matrix:alts.matrix||dur.matrix,};return new Duration(conf);} function durationToMillis(matrix,vals){let sum=vals.milliseconds??0;for(const unit of reverseUnits.slice(1)){if(vals[unit]){sum+=vals[unit]*matrix[unit]["milliseconds"];}} return sum;} function normalizeValues(matrix,vals){const factor=durationToMillis(matrix,vals)<0?-1:1;orderedUnits$1.reduceRight((previous,current)=>{if(!isUndefined(vals[current])){if(previous){const previousVal=vals[previous]*factor;const conv=matrix[current][previous];const rollUp=Math.floor(previousVal/conv);vals[current]+=rollUp*factor;vals[previous]-=rollUp*conv*factor;} return current;}else{return previous;}},null);orderedUnits$1.reduce((previous,current)=>{if(!isUndefined(vals[current])){if(previous){const fraction=vals[previous]%1;vals[previous]-=fraction;vals[current]+=fraction*matrix[previous][current];} return current;}else{return previous;}},null);} function removeZeroes(vals){const newVals={};for(const[key,value]of Object.entries(vals)){if(value!==0){newVals[key]=value;}} return newVals;} class Duration{constructor(config){const accurate=config.conversionAccuracy==="longterm"||false;let matrix=accurate?accurateMatrix:casualMatrix;if(config.matrix){matrix=config.matrix;} this.values=config.values;this.loc=config.loc||Locale.create();this.conversionAccuracy=accurate?"longterm":"casual";this.invalid=config.invalid||null;this.matrix=matrix;this.isLuxonDuration=true;} static fromMillis(count,opts){return Duration.fromObject({milliseconds:count},opts);} static fromObject(obj,opts={}){if(obj==null||typeof obj!=="object"){throw new InvalidArgumentError(`Duration.fromObject: argument expected to be an object, got ${ obj === null ? "null" : typeof obj }`);} return new Duration({values:normalizeObject(obj,Duration.normalizeUnit),loc:Locale.fromObject(opts),conversionAccuracy:opts.conversionAccuracy,matrix:opts.matrix,});} static fromDurationLike(durationLike){if(isNumber(durationLike)){return Duration.fromMillis(durationLike);}else if(Duration.isDuration(durationLike)){return durationLike;}else if(typeof durationLike==="object"){return Duration.fromObject(durationLike);}else{throw new InvalidArgumentError(`Unknown duration argument ${durationLike} of type ${typeof durationLike}`);}} static fromISO(text,opts){const[parsed]=parseISODuration(text);if(parsed){return Duration.fromObject(parsed,opts);}else{return Duration.invalid("unparsable",`the input "${text}" can't be parsed as ISO 8601`);}} static fromISOTime(text,opts){const[parsed]=parseISOTimeOnly(text);if(parsed){return Duration.fromObject(parsed,opts);}else{return Duration.invalid("unparsable",`the input "${text}" can't be parsed as ISO 8601`);}} static invalid(reason,explanation=null){if(!reason){throw new InvalidArgumentError("need to specify a reason the Duration is invalid");} const invalid=reason instanceof Invalid?reason:new Invalid(reason,explanation);if(Settings.throwOnInvalid){throw new InvalidDurationError(invalid);}else{return new Duration({invalid});}} static normalizeUnit(unit){const normalized={year:"years",years:"years",quarter:"quarters",quarters:"quarters",month:"months",months:"months",week:"weeks",weeks:"weeks",day:"days",days:"days",hour:"hours",hours:"hours",minute:"minutes",minutes:"minutes",second:"seconds",seconds:"seconds",millisecond:"milliseconds",milliseconds:"milliseconds",}[unit?unit.toLowerCase():unit];if(!normalized)throw new InvalidUnitError(unit);return normalized;} static isDuration(o){return(o&&o.isLuxonDuration)||false;} get locale(){return this.isValid?this.loc.locale:null;} get numberingSystem(){return this.isValid?this.loc.numberingSystem:null;} toFormat(fmt,opts={}){const fmtOpts={...opts,floor:opts.round!==false&&opts.floor!==false,};return this.isValid?Formatter.create(this.loc,fmtOpts).formatDurationFromString(this,fmt):INVALID$2;} toHuman(opts={}){if(!this.isValid)return INVALID$2;const l=orderedUnits$1.map((unit)=>{const val=this.values[unit];if(isUndefined(val)){return null;} return this.loc.numberFormatter({style:"unit",unitDisplay:"long",...opts,unit:unit.slice(0,-1)}).format(val);}).filter((n)=>n);return this.loc.listFormatter({type:"conjunction",style:opts.listStyle||"narrow",...opts}).format(l);} toObject(){if(!this.isValid)return{};return{...this.values};} toISO(){if(!this.isValid)return null;let s="P";if(this.years!==0)s+=this.years+"Y";if(this.months!==0||this.quarters!==0)s+=this.months+this.quarters*3+"M";if(this.weeks!==0)s+=this.weeks+"W";if(this.days!==0)s+=this.days+"D";if(this.hours!==0||this.minutes!==0||this.seconds!==0||this.milliseconds!==0) s+="T";if(this.hours!==0)s+=this.hours+"H";if(this.minutes!==0)s+=this.minutes+"M";if(this.seconds!==0||this.milliseconds!==0) s+=roundTo(this.seconds+this.milliseconds/1000,3)+"S";if(s==="P")s+="T0S";return s;} toISOTime(opts={}){if(!this.isValid)return null;const millis=this.toMillis();if(millis<0||millis>=86400000)return null;opts={suppressMilliseconds:false,suppressSeconds:false,includePrefix:false,format:"extended",...opts,includeOffset:false,};const dateTime=DateTime.fromMillis(millis,{zone:"UTC"});return dateTime.toISOTime(opts);} toJSON(){return this.toISO();} toString(){return this.toISO();} [Symbol.for("nodejs.util.inspect.custom")](){if(this.isValid){return`Duration { values: ${JSON.stringify(this.values)} }`;}else{return`Duration { Invalid, reason: ${this.invalidReason} }`;}} toMillis(){if(!this.isValid)return NaN;return durationToMillis(this.matrix,this.values);} valueOf(){return this.toMillis();} plus(duration){if(!this.isValid)return this;const dur=Duration.fromDurationLike(duration),result={};for(const k of orderedUnits$1){if(hasOwnProperty(dur.values,k)||hasOwnProperty(this.values,k)){result[k]=dur.get(k)+this.get(k);}} return clone$1(this,{values:result},true);} minus(duration){if(!this.isValid)return this;const dur=Duration.fromDurationLike(duration);return this.plus(dur.negate());} mapUnits(fn){if(!this.isValid)return this;const result={};for(const k of Object.keys(this.values)){result[k]=asNumber(fn(this.values[k],k));} return clone$1(this,{values:result},true);} get(unit){return this[Duration.normalizeUnit(unit)];} set(values){if(!this.isValid)return this;const mixed={...this.values,...normalizeObject(values,Duration.normalizeUnit)};return clone$1(this,{values:mixed});} reconfigure({locale,numberingSystem,conversionAccuracy,matrix}={}){const loc=this.loc.clone({locale,numberingSystem});const opts={loc,matrix,conversionAccuracy};return clone$1(this,opts);} as(unit){return this.isValid?this.shiftTo(unit).get(unit):NaN;} normalize(){if(!this.isValid)return this;const vals=this.toObject();normalizeValues(this.matrix,vals);return clone$1(this,{values:vals},true);} rescale(){if(!this.isValid)return this;const vals=removeZeroes(this.normalize().shiftToAll().toObject());return clone$1(this,{values:vals},true);} shiftTo(...units){if(!this.isValid)return this;if(units.length===0){return this;} units=units.map((u)=>Duration.normalizeUnit(u));const built={},accumulated={},vals=this.toObject();let lastUnit;for(const k of orderedUnits$1){if(units.indexOf(k)>=0){lastUnit=k;let own=0;for(const ak in accumulated){own+=this.matrix[ak][k]*accumulated[ak];accumulated[ak]=0;} if(isNumber(vals[k])){own+=vals[k];} const i=Math.trunc(own);built[k]=i;accumulated[k]=(own*1000-i*1000)/1000;}else if(isNumber(vals[k])){accumulated[k]=vals[k];}} for(const key in accumulated){if(accumulated[key]!==0){built[lastUnit]+=key===lastUnit?accumulated[key]:accumulated[key]/this.matrix[lastUnit][key];}} normalizeValues(this.matrix,built);return clone$1(this,{values:built},true);} shiftToAll(){if(!this.isValid)return this;return this.shiftTo("years","months","weeks","days","hours","minutes","seconds","milliseconds");} negate(){if(!this.isValid)return this;const negated={};for(const k of Object.keys(this.values)){negated[k]=this.values[k]===0?0:-this.values[k];} return clone$1(this,{values:negated},true);} get years(){return this.isValid?this.values.years||0:NaN;} get quarters(){return this.isValid?this.values.quarters||0:NaN;} get months(){return this.isValid?this.values.months||0:NaN;} get weeks(){return this.isValid?this.values.weeks||0:NaN;} get days(){return this.isValid?this.values.days||0:NaN;} get hours(){return this.isValid?this.values.hours||0:NaN;} get minutes(){return this.isValid?this.values.minutes||0:NaN;} get seconds(){return this.isValid?this.values.seconds||0:NaN;} get milliseconds(){return this.isValid?this.values.milliseconds||0:NaN;} get isValid(){return this.invalid===null;} get invalidReason(){return this.invalid?this.invalid.reason:null;} get invalidExplanation(){return this.invalid?this.invalid.explanation:null;} equals(other){if(!this.isValid||!other.isValid){return false;} if(!this.loc.equals(other.loc)){return false;} function eq(v1,v2){if(v1===undefined||v1===0)return v2===undefined||v2===0;return v1===v2;} for(const u of orderedUnits$1){if(!eq(this.values[u],other.values[u])){return false;}} return true;}} const INVALID$1="Invalid Interval";function validateStartEnd(start,end){if(!start||!start.isValid){return Interval.invalid("missing or invalid start");}else if(!end||!end.isValid){return Interval.invalid("missing or invalid end");}else if(enddateTime;} isBefore(dateTime){if(!this.isValid)return false;return this.e<=dateTime;} contains(dateTime){if(!this.isValid)return false;return this.s<=dateTime&&this.e>dateTime;} set({start,end}={}){if(!this.isValid)return this;return Interval.fromDateTimes(start||this.s,end||this.e);} splitAt(...dateTimes){if(!this.isValid)return[];const sorted=dateTimes.map(friendlyDateTime).filter((d)=>this.contains(d)).sort((a,b)=>a.toMillis()-b.toMillis()),results=[];let{s}=this,i=0;while(s+this.e?this.e:added;results.push(Interval.fromDateTimes(s,next));s=next;i+=1;} return results;} splitBy(duration){const dur=Duration.fromDurationLike(duration);if(!this.isValid||!dur.isValid||dur.as("milliseconds")===0){return[];} let{s}=this,idx=1,next;const results=[];while(sx*idx));next=+added>+this.e?this.e:added;results.push(Interval.fromDateTimes(s,next));s=next;idx+=1;} return results;} divideEqually(numberOfParts){if(!this.isValid)return[];return this.splitBy(this.length()/numberOfParts).slice(0,numberOfParts);} overlaps(other){return this.e>other.s&&this.s=other.e;} equals(other){if(!this.isValid||!other.isValid){return false;} return this.s.equals(other.s)&&this.e.equals(other.e);} intersection(other){if(!this.isValid)return this;const s=this.s>other.s?this.s:other.s,e=this.e=e){return null;}else{return Interval.fromDateTimes(s,e);}} union(other){if(!this.isValid)return this;const s=this.sother.e?this.e:other.e;return Interval.fromDateTimes(s,e);} static merge(intervals){const[found,final]=intervals.sort((a,b)=>a.s-b.s).reduce(([sofar,current],item)=>{if(!current){return[sofar,item];}else if(current.overlaps(item)||current.abutsStart(item)){return[sofar,current.union(item)];}else{return[sofar.concat([current]),item];}},[[],null]);if(final){found.push(final);} return found;} static xor(intervals){let start=null,currentCount=0;const results=[],ends=intervals.map((i)=>[{time:i.s,type:"s"},{time:i.e,type:"e"},]),flattened=Array.prototype.concat(...ends),arr=flattened.sort((a,b)=>a.time-b.time);for(const i of arr){currentCount+=i.type==="s"?1:-1;if(currentCount===1){start=i.time;}else{if(start&&+start!==+i.time){results.push(Interval.fromDateTimes(start,i.time));} start=null;}} return Interval.merge(results);} difference(...intervals){return Interval.xor([this].concat(intervals)).map((i)=>this.intersection(i)).filter((i)=>i&&!i.isEmpty());} toString(){if(!this.isValid)return INVALID$1;return`[${this.s.toISO()} – ${this.e.toISO()})`;} [Symbol.for("nodejs.util.inspect.custom")](){if(this.isValid){return`Interval { start: ${this.s.toISO()}, end: ${this.e.toISO()} }`;}else{return`Interval { Invalid, reason: ${this.invalidReason} }`;}} toLocaleString(formatOpts=DATE_SHORT,opts={}){return this.isValid?Formatter.create(this.s.loc.clone(opts),formatOpts).formatInterval(this):INVALID$1;} toISO(opts){if(!this.isValid)return INVALID$1;return`${this.s.toISO(opts)}/${this.e.toISO(opts)}`;} toISODate(){if(!this.isValid)return INVALID$1;return`${this.s.toISODate()}/${this.e.toISODate()}`;} toISOTime(opts){if(!this.isValid)return INVALID$1;return`${this.s.toISOTime(opts)}/${this.e.toISOTime(opts)}`;} toFormat(dateFormat,{separator=" – "}={}){if(!this.isValid)return INVALID$1;return`${this.s.toFormat(dateFormat)}${separator}${this.e.toFormat(dateFormat)}`;} toDuration(unit,opts){if(!this.isValid){return Duration.invalid(this.invalidReason);} return this.e.diff(this.s,unit,opts);} mapEndpoints(mapFn){return Interval.fromDateTimes(mapFn(this.s),mapFn(this.e));}} class Info{static hasDST(zone=Settings.defaultZone){const proto=DateTime.now().setZone(zone).set({month:12});return!zone.isUniversal&&proto.offset!==proto.set({month:6}).offset;} static isValidIANAZone(zone){return IANAZone.isValidZone(zone);} static normalizeZone(input){return normalizeZone(input,Settings.defaultZone);} static getStartOfWeek({locale=null,locObj=null}={}){return(locObj||Locale.create(locale)).getStartOfWeek();} static getMinimumDaysInFirstWeek({locale=null,locObj=null}={}){return(locObj||Locale.create(locale)).getMinDaysInFirstWeek();} static getWeekendWeekdays({locale=null,locObj=null}={}){return(locObj||Locale.create(locale)).getWeekendDays().slice();} static months(length="long",{locale=null,numberingSystem=null,locObj=null,outputCalendar="gregory"}={}){return(locObj||Locale.create(locale,numberingSystem,outputCalendar)).months(length);} static monthsFormat(length="long",{locale=null,numberingSystem=null,locObj=null,outputCalendar="gregory"}={}){return(locObj||Locale.create(locale,numberingSystem,outputCalendar)).months(length,true);} static weekdays(length="long",{locale=null,numberingSystem=null,locObj=null}={}){return(locObj||Locale.create(locale,numberingSystem,null)).weekdays(length);} static weekdaysFormat(length="long",{locale=null,numberingSystem=null,locObj=null}={}){return(locObj||Locale.create(locale,numberingSystem,null)).weekdays(length,true);} static meridiems({locale=null}={}){return Locale.create(locale).meridiems();} static eras(length="short",{locale=null}={}){return Locale.create(locale,null,"gregory").eras(length);} static features(){return{relative:hasRelative(),localeWeek:hasLocaleWeekInfo()};}} function dayDiff(earlier,later){const utcDayStart=(dt)=>dt.toUTC(0,{keepLocalTime:true}).startOf("day").valueOf(),ms=utcDayStart(later)-utcDayStart(earlier);return Math.floor(Duration.fromMillis(ms).as("days"));} function highOrderDiffs(cursor,later,units){const differs=[["years",(a,b)=>b.year-a.year],["quarters",(a,b)=>b.quarter-a.quarter+(b.year-a.year)*4],["months",(a,b)=>b.month-a.month+(b.year-a.year)*12],["weeks",(a,b)=>{const days=dayDiff(a,b);return(days-(days%7))/7;},],["days",dayDiff],];const results={};const earlier=cursor;let lowestOrder,highWater;for(const[unit,differ]of differs){if(units.indexOf(unit)>=0){lowestOrder=unit;results[unit]=differ(cursor,later);highWater=earlier.plus(results);if(highWater>later){results[unit]--;cursor=earlier.plus(results);if(cursor>later){highWater=cursor;results[unit]--;cursor=earlier.plus(results);}}else{cursor=highWater;}}} return[cursor,results,highWater,lowestOrder];} function diff(earlier,later,units,opts){let[cursor,results,highWater,lowestOrder]=highOrderDiffs(earlier,later,units);const remainingMillis=later-cursor;const lowerOrderUnits=units.filter((u)=>["hours","minutes","seconds","milliseconds"].indexOf(u)>=0);if(lowerOrderUnits.length===0){if(highWater0){return Duration.fromMillis(remainingMillis,opts).shiftTo(...lowerOrderUnits).plus(duration);}else{return duration;}} const numberingSystems={arab:"[\u0660-\u0669]",arabext:"[\u06F0-\u06F9]",bali:"[\u1B50-\u1B59]",beng:"[\u09E6-\u09EF]",deva:"[\u0966-\u096F]",fullwide:"[\uFF10-\uFF19]",gujr:"[\u0AE6-\u0AEF]",hanidec:"[〇|一|二|三|四|五|六|七|八|九]",khmr:"[\u17E0-\u17E9]",knda:"[\u0CE6-\u0CEF]",laoo:"[\u0ED0-\u0ED9]",limb:"[\u1946-\u194F]",mlym:"[\u0D66-\u0D6F]",mong:"[\u1810-\u1819]",mymr:"[\u1040-\u1049]",orya:"[\u0B66-\u0B6F]",tamldec:"[\u0BE6-\u0BEF]",telu:"[\u0C66-\u0C6F]",thai:"[\u0E50-\u0E59]",tibt:"[\u0F20-\u0F29]",latn:"\\d",};const numberingSystemsUTF16={arab:[1632,1641],arabext:[1776,1785],bali:[6992,7001],beng:[2534,2543],deva:[2406,2415],fullwide:[65296,65303],gujr:[2790,2799],khmr:[6112,6121],knda:[3302,3311],laoo:[3792,3801],limb:[6470,6479],mlym:[3430,3439],mong:[6160,6169],mymr:[4160,4169],orya:[2918,2927],tamldec:[3046,3055],telu:[3174,3183],thai:[3664,3673],tibt:[3872,3881],};const hanidecChars=numberingSystems.hanidec.replace(/[\[|\]]/g,"").split("");function parseDigits(str){let value=parseInt(str,10);if(isNaN(value)){value="";for(let i=0;i=min&&code<=max){value+=code-min;}}}} return parseInt(value,10);}else{return value;}} function digitRegex({numberingSystem},append=""){return new RegExp(`${numberingSystems[numberingSystem || "latn"]}${append}`);} const MISSING_FTP="missing Intl.DateTimeFormat.formatToParts support";function intUnit(regex,post=(i)=>i){return{regex,deser:([s])=>post(parseDigits(s))};} const NBSP=String.fromCharCode(160);const spaceOrNBSP=`[ ${NBSP}]`;const spaceOrNBSPRegExp=new RegExp(spaceOrNBSP,"g");function fixListRegex(s){return s.replace(/\./g,"\\.?").replace(spaceOrNBSPRegExp,spaceOrNBSP);} function stripInsensitivities(s){return s.replace(/\./g,"").replace(spaceOrNBSPRegExp," ").toLowerCase();} function oneOf(strings,startIndex){if(strings===null){return null;}else{return{regex:RegExp(strings.map(fixListRegex).join("|")),deser:([s])=>strings.findIndex((i)=>stripInsensitivities(s)===stripInsensitivities(i))+startIndex,};}} function offset(regex,groups){return{regex,deser:([,h,m])=>signedOffset(h,m),groups};} function simple(regex){return{regex,deser:([s])=>s};} function escapeToken(value){return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&");} function unitForToken(token,loc){const one=digitRegex(loc),two=digitRegex(loc,"{2}"),three=digitRegex(loc,"{3}"),four=digitRegex(loc,"{4}"),six=digitRegex(loc,"{6}"),oneOrTwo=digitRegex(loc,"{1,2}"),oneToThree=digitRegex(loc,"{1,3}"),oneToSix=digitRegex(loc,"{1,6}"),oneToNine=digitRegex(loc,"{1,9}"),twoToFour=digitRegex(loc,"{2,4}"),fourToSix=digitRegex(loc,"{4,6}"),literal=(t)=>({regex:RegExp(escapeToken(t.val)),deser:([s])=>s,literal:true}),unitate=(t)=>{if(token.literal){return literal(t);} switch(t.val){case"G":return oneOf(loc.eras("short"),0);case"GG":return oneOf(loc.eras("long"),0);case"y":return intUnit(oneToSix);case"yy":return intUnit(twoToFour,untruncateYear);case"yyyy":return intUnit(four);case"yyyyy":return intUnit(fourToSix);case"yyyyyy":return intUnit(six);case"M":return intUnit(oneOrTwo);case"MM":return intUnit(two);case"MMM":return oneOf(loc.months("short",true),1);case"MMMM":return oneOf(loc.months("long",true),1);case"L":return intUnit(oneOrTwo);case"LL":return intUnit(two);case"LLL":return oneOf(loc.months("short",false),1);case"LLLL":return oneOf(loc.months("long",false),1);case"d":return intUnit(oneOrTwo);case"dd":return intUnit(two);case"o":return intUnit(oneToThree);case"ooo":return intUnit(three);case"HH":return intUnit(two);case"H":return intUnit(oneOrTwo);case"hh":return intUnit(two);case"h":return intUnit(oneOrTwo);case"mm":return intUnit(two);case"m":return intUnit(oneOrTwo);case"q":return intUnit(oneOrTwo);case"qq":return intUnit(two);case"s":return intUnit(oneOrTwo);case"ss":return intUnit(two);case"S":return intUnit(oneToThree);case"SSS":return intUnit(three);case"u":return simple(oneToNine);case"uu":return simple(oneOrTwo);case"uuu":return intUnit(one);case"a":return oneOf(loc.meridiems(),0);case"kkkk":return intUnit(four);case"kk":return intUnit(twoToFour,untruncateYear);case"W":return intUnit(oneOrTwo);case"WW":return intUnit(two);case"E":case"c":return intUnit(one);case"EEE":return oneOf(loc.weekdays("short",false),1);case"EEEE":return oneOf(loc.weekdays("long",false),1);case"ccc":return oneOf(loc.weekdays("short",true),1);case"cccc":return oneOf(loc.weekdays("long",true),1);case"Z":case"ZZ":return offset(new RegExp(`([+-]${oneOrTwo.source})(?::(${two.source}))?`),2);case"ZZZ":return offset(new RegExp(`([+-]${oneOrTwo.source})(${two.source})?`),2);case"z":return simple(/[a-z_+-/]{1,256}?/i);case" ":return simple(/[^\S\n\r]/);default:return literal(t);}};const unit=unitate(token)||{invalidReason:MISSING_FTP,};unit.token=token;return unit;} const partTypeStyleToTokenVal={year:{"2-digit":"yy",numeric:"yyyyy",},month:{numeric:"M","2-digit":"MM",short:"MMM",long:"MMMM",},day:{numeric:"d","2-digit":"dd",},weekday:{short:"EEE",long:"EEEE",},dayperiod:"a",dayPeriod:"a",hour12:{numeric:"h","2-digit":"hh",},hour24:{numeric:"H","2-digit":"HH",},minute:{numeric:"m","2-digit":"mm",},second:{numeric:"s","2-digit":"ss",},timeZoneName:{long:"ZZZZZ",short:"ZZZ",},};function tokenForPart(part,formatOpts,resolvedOpts){const{type,value}=part;if(type==="literal"){const isSpace=/^\s+$/.test(value);return{literal:!isSpace,val:isSpace?" ":value,};} const style=formatOpts[type];let actualType=type;if(type==="hour"){if(formatOpts.hour12!=null){actualType=formatOpts.hour12?"hour12":"hour24";}else if(formatOpts.hourCycle!=null){if(formatOpts.hourCycle==="h11"||formatOpts.hourCycle==="h12"){actualType="hour12";}else{actualType="hour24";}}else{actualType=resolvedOpts.hour12?"hour12":"hour24";}} let val=partTypeStyleToTokenVal[actualType];if(typeof val==="object"){val=val[style];} if(val){return{literal:false,val,};} return undefined;} function buildRegex(units){const re=units.map((u)=>u.regex).reduce((f,r)=>`${f}(${r.source})`,"");return[`^${re}$`,units];} function match(input,regex,handlers){const matches=input.match(regex);if(matches){const all={};let matchIndex=1;for(const i in handlers){if(hasOwnProperty(handlers,i)){const h=handlers[i],groups=h.groups?h.groups+1:1;if(!h.literal&&h.token){all[h.token.val[0]]=h.deser(matches.slice(matchIndex,matchIndex+groups));} matchIndex+=groups;}} return[matches,all];}else{return[matches,{}];}} function dateTimeFromMatches(matches){const toField=(token)=>{switch(token){case"S":return"millisecond";case"s":return"second";case"m":return"minute";case"h":case"H":return"hour";case"d":return"day";case"o":return"ordinal";case"L":case"M":return"month";case"y":return"year";case"E":case"c":return"weekday";case"W":return"weekNumber";case"k":return"weekYear";case"q":return"quarter";default:return null;}};let zone=null;let specificOffset;if(!isUndefined(matches.z)){zone=IANAZone.create(matches.z);} if(!isUndefined(matches.Z)){if(!zone){zone=new FixedOffsetZone(matches.Z);} specificOffset=matches.Z;} if(!isUndefined(matches.q)){matches.M=(matches.q-1)*3+1;} if(!isUndefined(matches.h)){if(matches.h<12&&matches.a===1){matches.h+=12;}else if(matches.h===12&&matches.a===0){matches.h=0;}} if(matches.G===0&&matches.y){matches.y=-matches.y;} if(!isUndefined(matches.u)){matches.S=parseMillis(matches.u);} const vals=Object.keys(matches).reduce((r,k)=>{const f=toField(k);if(f){r[f]=matches[k];} return r;},{});return[vals,zone,specificOffset];} let dummyDateTimeCache=null;function getDummyDateTime(){if(!dummyDateTimeCache){dummyDateTimeCache=DateTime.fromMillis(1555555555555);} return dummyDateTimeCache;} function maybeExpandMacroToken(token,locale){if(token.literal){return token;} const formatOpts=Formatter.macroTokenToFormatOpts(token.val);const tokens=formatOptsToTokens(formatOpts,locale);if(tokens==null||tokens.includes(undefined)){return token;} return tokens;} function expandMacroTokens(tokens,locale){return Array.prototype.concat(...tokens.map((t)=>maybeExpandMacroToken(t,locale)));} function explainFromTokens(locale,input,format){const tokens=expandMacroTokens(Formatter.parseFormat(format),locale),units=tokens.map((t)=>unitForToken(t,locale)),disqualifyingUnit=units.find((t)=>t.invalidReason);if(disqualifyingUnit){return{input,tokens,invalidReason:disqualifyingUnit.invalidReason};}else{const[regexString,handlers]=buildRegex(units),regex=RegExp(regexString,"i"),[rawMatches,matches]=match(input,regex,handlers),[result,zone,specificOffset]=matches?dateTimeFromMatches(matches):[null,null,undefined];if(hasOwnProperty(matches,"a")&&hasOwnProperty(matches,"H")){throw new ConflictingSpecificationError("Can't include meridiem when specifying 24-hour format");} return{input,tokens,regex,rawMatches,matches,result,zone,specificOffset};}} function parseFromTokens(locale,input,format){const{result,zone,specificOffset,invalidReason}=explainFromTokens(locale,input,format);return[result,zone,specificOffset,invalidReason];} function formatOptsToTokens(formatOpts,locale){if(!formatOpts){return null;} const formatter=Formatter.create(locale,formatOpts);const df=formatter.dtFormatter(getDummyDateTime());const parts=df.formatToParts();const resolvedOpts=df.resolvedOptions();return parts.map((p)=>tokenForPart(p,formatOpts,resolvedOpts));} const INVALID="Invalid DateTime";const MAX_DATE=8.64e15;function unsupportedZone(zone){return new Invalid("unsupported zone",`the zone "${zone.name}" is not supported`);} function possiblyCachedWeekData(dt){if(dt.weekData===null){dt.weekData=gregorianToWeek(dt.c);} return dt.weekData;} function possiblyCachedLocalWeekData(dt){if(dt.localWeekData===null){dt.localWeekData=gregorianToWeek(dt.c,dt.loc.getMinDaysInFirstWeek(),dt.loc.getStartOfWeek());} return dt.localWeekData;} function clone(inst,alts){const current={ts:inst.ts,zone:inst.zone,c:inst.c,o:inst.o,loc:inst.loc,invalid:inst.invalid,};return new DateTime({...current,...alts,old:current});} function fixOffset(localTS,o,tz){let utcGuess=localTS-o*60*1000;const o2=tz.offset(utcGuess);if(o===o2){return[utcGuess,o];} utcGuess-=(o2-o)*60*1000;const o3=tz.offset(utcGuess);if(o2===o3){return[utcGuess,o2];} return[localTS-Math.min(o2,o3)*60*1000,Math.max(o2,o3)];} function tsToObj(ts,offset){ts+=offset*60*1000;const d=new Date(ts);return{year:d.getUTCFullYear(),month:d.getUTCMonth()+1,day:d.getUTCDate(),hour:d.getUTCHours(),minute:d.getUTCMinutes(),second:d.getUTCSeconds(),millisecond:d.getUTCMilliseconds(),};} function objToTS(obj,offset,zone){return fixOffset(objToLocalTS(obj),offset,zone);} function adjustTime(inst,dur){const oPre=inst.o,year=inst.c.year+Math.trunc(dur.years),month=inst.c.month+Math.trunc(dur.months)+Math.trunc(dur.quarters)*3,c={...inst.c,year,month,day:Math.min(inst.c.day,daysInMonth(year,month))+ Math.trunc(dur.days)+ Math.trunc(dur.weeks)*7,},millisToAdd=Duration.fromObject({years:dur.years-Math.trunc(dur.years),quarters:dur.quarters-Math.trunc(dur.quarters),months:dur.months-Math.trunc(dur.months),weeks:dur.weeks-Math.trunc(dur.weeks),days:dur.days-Math.trunc(dur.days),hours:dur.hours,minutes:dur.minutes,seconds:dur.seconds,milliseconds:dur.milliseconds,}).as("milliseconds"),localTS=objToLocalTS(c);let[ts,o]=fixOffset(localTS,oPre,inst.zone);if(millisToAdd!==0){ts+=millisToAdd;o=inst.zone.offset(ts);} return{ts,o};} function parseDataToDateTime(parsed,parsedZone,opts,format,text,specificOffset){const{setZone,zone}=opts;if((parsed&&Object.keys(parsed).length!==0)||parsedZone){const interpretationZone=parsedZone||zone,inst=DateTime.fromObject(parsed,{...opts,zone:interpretationZone,specificOffset,});return setZone?inst:inst.setZone(zone);}else{return DateTime.invalid(new Invalid("unparsable",`the input "${text}" can't be parsed as ${format}`));}} function toTechFormat(dt,format,allowZ=true){return dt.isValid?Formatter.create(Locale.create("en-US"),{allowZ,forceSimple:true,}).formatDateTimeFromString(dt,format):null;} function toISODate(o,extended){const longFormat=o.c.year>9999||o.c.year<0;let c="";if(longFormat&&o.c.year>=0)c+="+";c+=padStart(o.c.year,longFormat?6:4);if(extended){c+="-";c+=padStart(o.c.month);c+="-";c+=padStart(o.c.day);}else{c+=padStart(o.c.month);c+=padStart(o.c.day);} return c;} function toISOTime(o,extended,suppressSeconds,suppressMilliseconds,includeOffset,extendedZone){let c=padStart(o.c.hour);if(extended){c+=":";c+=padStart(o.c.minute);if(o.c.millisecond!==0||o.c.second!==0||!suppressSeconds){c+=":";}}else{c+=padStart(o.c.minute);} if(o.c.millisecond!==0||o.c.second!==0||!suppressSeconds){c+=padStart(o.c.second);if(o.c.millisecond!==0||!suppressMilliseconds){c+=".";c+=padStart(o.c.millisecond,3);}} if(includeOffset){if(o.isOffsetFixed&&o.offset===0&&!extendedZone){c+="Z";}else if(o.o<0){c+="-";c+=padStart(Math.trunc(-o.o/60));c+=":";c+=padStart(Math.trunc(-o.o%60));}else{c+="+";c+=padStart(Math.trunc(o.o/60));c+=":";c+=padStart(Math.trunc(o.o%60));}} if(extendedZone){c+="["+o.zone.ianaName+"]";} return c;} const defaultUnitValues={month:1,day:1,hour:0,minute:0,second:0,millisecond:0,},defaultWeekUnitValues={weekNumber:1,weekday:1,hour:0,minute:0,second:0,millisecond:0,},defaultOrdinalUnitValues={ordinal:1,hour:0,minute:0,second:0,millisecond:0,};const orderedUnits=["year","month","day","hour","minute","second","millisecond"],orderedWeekUnits=["weekYear","weekNumber","weekday","hour","minute","second","millisecond",],orderedOrdinalUnits=["year","ordinal","hour","minute","second","millisecond"];function normalizeUnit(unit){const normalized={year:"year",years:"year",month:"month",months:"month",day:"day",days:"day",hour:"hour",hours:"hour",minute:"minute",minutes:"minute",quarter:"quarter",quarters:"quarter",second:"second",seconds:"second",millisecond:"millisecond",milliseconds:"millisecond",weekday:"weekday",weekdays:"weekday",weeknumber:"weekNumber",weeksnumber:"weekNumber",weeknumbers:"weekNumber",weekyear:"weekYear",weekyears:"weekYear",ordinal:"ordinal",}[unit.toLowerCase()];if(!normalized)throw new InvalidUnitError(unit);return normalized;} function normalizeUnitWithLocalWeeks(unit){switch(unit.toLowerCase()){case"localweekday":case"localweekdays":return"localWeekday";case"localweeknumber":case"localweeknumbers":return"localWeekNumber";case"localweekyear":case"localweekyears":return"localWeekYear";default:return normalizeUnit(unit);}} function quickDT(obj,opts){const zone=normalizeZone(opts.zone,Settings.defaultZone),loc=Locale.fromObject(opts),tsNow=Settings.now();let ts,o;if(!isUndefined(obj.year)){for(const u of orderedUnits){if(isUndefined(obj[u])){obj[u]=defaultUnitValues[u];}} const invalid=hasInvalidGregorianData(obj)||hasInvalidTimeData(obj);if(invalid){return DateTime.invalid(invalid);} const offsetProvis=zone.offset(tsNow);[ts,o]=objToTS(obj,offsetProvis,zone);}else{ts=tsNow;} return new DateTime({ts,zone,loc,o});} function diffRelative(start,end,opts){const round=isUndefined(opts.round)?true:opts.round,format=(c,unit)=>{c=roundTo(c,round||opts.calendary?0:2,true);const formatter=end.loc.clone(opts).relFormatter(opts);return formatter.format(c,unit);},differ=(unit)=>{if(opts.calendary){if(!end.hasSame(start,unit)){return end.startOf(unit).diff(start.startOf(unit),unit).get(unit);}else return 0;}else{return end.diff(start,unit).get(unit);}};if(opts.unit){return format(differ(opts.unit),opts.unit);} for(const unit of opts.units){const count=differ(unit);if(Math.abs(count)>=1){return format(count,unit);}} return format(start>end?-0:0,opts.units[opts.units.length-1]);} function lastOpts(argList){let opts={},args;if(argList.length>0&&typeof argList[argList.length-1]==="object"){opts=argList[argList.length-1];args=Array.from(argList).slice(0,argList.length-1);}else{args=Array.from(argList);} return[opts,args];} class DateTime{constructor(config){const zone=config.zone||Settings.defaultZone;let invalid=config.invalid||(Number.isNaN(config.ts)?new Invalid("invalid input"):null)||(!zone.isValid?unsupportedZone(zone):null);this.ts=isUndefined(config.ts)?Settings.now():config.ts;let c=null,o=null;if(!invalid){const unchanged=config.old&&config.old.ts===this.ts&&config.old.zone.equals(zone);if(unchanged){[c,o]=[config.old.c,config.old.o];}else{const ot=zone.offset(this.ts);c=tsToObj(this.ts,ot);invalid=Number.isNaN(c.year)?new Invalid("invalid input"):null;c=invalid?null:c;o=invalid?null:ot;}} this._zone=zone;this.loc=config.loc||Locale.create();this.invalid=invalid;this.weekData=null;this.localWeekData=null;this.c=c;this.o=o;this.isLuxonDateTime=true;} static now(){return new DateTime({});} static local(){const[opts,args]=lastOpts(arguments),[year,month,day,hour,minute,second,millisecond]=args;return quickDT({year,month,day,hour,minute,second,millisecond},opts);} static utc(){const[opts,args]=lastOpts(arguments),[year,month,day,hour,minute,second,millisecond]=args;opts.zone=FixedOffsetZone.utcInstance;return quickDT({year,month,day,hour,minute,second,millisecond},opts);} static fromJSDate(date,options={}){const ts=isDate(date)?date.valueOf():NaN;if(Number.isNaN(ts)){return DateTime.invalid("invalid input");} const zoneToUse=normalizeZone(options.zone,Settings.defaultZone);if(!zoneToUse.isValid){return DateTime.invalid(unsupportedZone(zoneToUse));} return new DateTime({ts:ts,zone:zoneToUse,loc:Locale.fromObject(options),});} static fromMillis(milliseconds,options={}){if(!isNumber(milliseconds)){throw new InvalidArgumentError(`fromMillis requires a numerical input, but received a ${typeof milliseconds} with value ${milliseconds}`);}else if(milliseconds<-MAX_DATE||milliseconds>MAX_DATE){return DateTime.invalid("Timestamp out of range");}else{return new DateTime({ts:milliseconds,zone:normalizeZone(options.zone,Settings.defaultZone),loc:Locale.fromObject(options),});}} static fromSeconds(seconds,options={}){if(!isNumber(seconds)){throw new InvalidArgumentError("fromSeconds requires a numerical input");}else{return new DateTime({ts:seconds*1000,zone:normalizeZone(options.zone,Settings.defaultZone),loc:Locale.fromObject(options),});}} static fromObject(obj,opts={}){obj=obj||{};const zoneToUse=normalizeZone(opts.zone,Settings.defaultZone);if(!zoneToUse.isValid){return DateTime.invalid(unsupportedZone(zoneToUse));} const loc=Locale.fromObject(opts);const normalized=normalizeObject(obj,normalizeUnitWithLocalWeeks);const{minDaysInFirstWeek,startOfWeek}=usesLocalWeekValues(normalized,loc);const tsNow=Settings.now(),offsetProvis=!isUndefined(opts.specificOffset)?opts.specificOffset:zoneToUse.offset(tsNow),containsOrdinal=!isUndefined(normalized.ordinal),containsGregorYear=!isUndefined(normalized.year),containsGregorMD=!isUndefined(normalized.month)||!isUndefined(normalized.day),containsGregor=containsGregorYear||containsGregorMD,definiteWeekDef=normalized.weekYear||normalized.weekNumber;if((containsGregor||containsOrdinal)&&definiteWeekDef){throw new ConflictingSpecificationError("Can't mix weekYear/weekNumber units with year/month/day or ordinals");} if(containsGregorMD&&containsOrdinal){throw new ConflictingSpecificationError("Can't mix ordinal dates with month/day");} const useWeekData=definiteWeekDef||(normalized.weekday&&!containsGregor);let units,defaultValues,objNow=tsToObj(tsNow,offsetProvis);if(useWeekData){units=orderedWeekUnits;defaultValues=defaultWeekUnitValues;objNow=gregorianToWeek(objNow,minDaysInFirstWeek,startOfWeek);}else if(containsOrdinal){units=orderedOrdinalUnits;defaultValues=defaultOrdinalUnitValues;objNow=gregorianToOrdinal(objNow);}else{units=orderedUnits;defaultValues=defaultUnitValues;} let foundFirst=false;for(const u of units){const v=normalized[u];if(!isUndefined(v)){foundFirst=true;}else if(foundFirst){normalized[u]=defaultValues[u];}else{normalized[u]=objNow[u];}} const higherOrderInvalid=useWeekData?hasInvalidWeekData(normalized,minDaysInFirstWeek,startOfWeek):containsOrdinal?hasInvalidOrdinalData(normalized):hasInvalidGregorianData(normalized),invalid=higherOrderInvalid||hasInvalidTimeData(normalized);if(invalid){return DateTime.invalid(invalid);} const gregorian=useWeekData?weekToGregorian(normalized,minDaysInFirstWeek,startOfWeek):containsOrdinal?ordinalToGregorian(normalized):normalized,[tsFinal,offsetFinal]=objToTS(gregorian,offsetProvis,zoneToUse),inst=new DateTime({ts:tsFinal,zone:zoneToUse,o:offsetFinal,loc,});if(normalized.weekday&&containsGregor&&obj.weekday!==inst.weekday){return DateTime.invalid("mismatched weekday",`you can't specify both a weekday of ${normalized.weekday} and a date of ${inst.toISO()}`);} if(!inst.isValid){return DateTime.invalid(inst.invalid);} return inst;} static fromISO(text,opts={}){const[vals,parsedZone]=parseISODate(text);return parseDataToDateTime(vals,parsedZone,opts,"ISO 8601",text);} static fromRFC2822(text,opts={}){const[vals,parsedZone]=parseRFC2822Date(text);return parseDataToDateTime(vals,parsedZone,opts,"RFC 2822",text);} static fromHTTP(text,opts={}){const[vals,parsedZone]=parseHTTPDate(text);return parseDataToDateTime(vals,parsedZone,opts,"HTTP",opts);} static fromFormat(text,fmt,opts={}){if(isUndefined(text)||isUndefined(fmt)){throw new InvalidArgumentError("fromFormat requires an input string and a format");} const{locale=null,numberingSystem=null}=opts,localeToUse=Locale.fromOpts({locale,numberingSystem,defaultToEN:true,}),[vals,parsedZone,specificOffset,invalid]=parseFromTokens(localeToUse,text,fmt);if(invalid){return DateTime.invalid(invalid);}else{return parseDataToDateTime(vals,parsedZone,opts,`format ${fmt}`,text,specificOffset);}} static fromString(text,fmt,opts={}){return DateTime.fromFormat(text,fmt,opts);} static fromSQL(text,opts={}){const[vals,parsedZone]=parseSQL(text);return parseDataToDateTime(vals,parsedZone,opts,"SQL",text);} static invalid(reason,explanation=null){if(!reason){throw new InvalidArgumentError("need to specify a reason the DateTime is invalid");} const invalid=reason instanceof Invalid?reason:new Invalid(reason,explanation);if(Settings.throwOnInvalid){throw new InvalidDateTimeError(invalid);}else{return new DateTime({invalid});}} static isDateTime(o){return(o&&o.isLuxonDateTime)||false;} static parseFormatForOpts(formatOpts,localeOpts={}){const tokenList=formatOptsToTokens(formatOpts,Locale.fromObject(localeOpts));return!tokenList?null:tokenList.map((t)=>(t?t.val:null)).join("");} static expandFormat(fmt,localeOpts={}){const expanded=expandMacroTokens(Formatter.parseFormat(fmt),Locale.fromObject(localeOpts));return expanded.map((t)=>t.val).join("");} get(unit){return this[unit];} get isValid(){return this.invalid===null;} get invalidReason(){return this.invalid?this.invalid.reason:null;} get invalidExplanation(){return this.invalid?this.invalid.explanation:null;} get locale(){return this.isValid?this.loc.locale:null;} get numberingSystem(){return this.isValid?this.loc.numberingSystem:null;} get outputCalendar(){return this.isValid?this.loc.outputCalendar:null;} get zone(){return this._zone;} get zoneName(){return this.isValid?this.zone.name:null;} get year(){return this.isValid?this.c.year:NaN;} get quarter(){return this.isValid?Math.ceil(this.c.month/3):NaN;} get month(){return this.isValid?this.c.month:NaN;} get day(){return this.isValid?this.c.day:NaN;} get hour(){return this.isValid?this.c.hour:NaN;} get minute(){return this.isValid?this.c.minute:NaN;} get second(){return this.isValid?this.c.second:NaN;} get millisecond(){return this.isValid?this.c.millisecond:NaN;} get weekYear(){return this.isValid?possiblyCachedWeekData(this).weekYear:NaN;} get weekNumber(){return this.isValid?possiblyCachedWeekData(this).weekNumber:NaN;} get weekday(){return this.isValid?possiblyCachedWeekData(this).weekday:NaN;} get isWeekend(){return this.isValid&&this.loc.getWeekendDays().includes(this.weekday);} get localWeekday(){return this.isValid?possiblyCachedLocalWeekData(this).weekday:NaN;} get localWeekNumber(){return this.isValid?possiblyCachedLocalWeekData(this).weekNumber:NaN;} get localWeekYear(){return this.isValid?possiblyCachedLocalWeekData(this).weekYear:NaN;} get ordinal(){return this.isValid?gregorianToOrdinal(this.c).ordinal:NaN;} get monthShort(){return this.isValid?Info.months("short",{locObj:this.loc})[this.month-1]:null;} get monthLong(){return this.isValid?Info.months("long",{locObj:this.loc})[this.month-1]:null;} get weekdayShort(){return this.isValid?Info.weekdays("short",{locObj:this.loc})[this.weekday-1]:null;} get weekdayLong(){return this.isValid?Info.weekdays("long",{locObj:this.loc})[this.weekday-1]:null;} get offset(){return this.isValid?+this.o:NaN;} get offsetNameShort(){if(this.isValid){return this.zone.offsetName(this.ts,{format:"short",locale:this.locale,});}else{return null;}} get offsetNameLong(){if(this.isValid){return this.zone.offsetName(this.ts,{format:"long",locale:this.locale,});}else{return null;}} get isOffsetFixed(){return this.isValid?this.zone.isUniversal:null;} get isInDST(){if(this.isOffsetFixed){return false;}else{return(this.offset>this.set({month:1,day:1}).offset||this.offset>this.set({month:5}).offset);}} getPossibleOffsets(){if(!this.isValid||this.isOffsetFixed){return[this];} const dayMs=86400000;const minuteMs=60000;const localTS=objToLocalTS(this.c);const oEarlier=this.zone.offset(localTS-dayMs);const oLater=this.zone.offset(localTS+dayMs);const o1=this.zone.offset(localTS-oEarlier*minuteMs);const o2=this.zone.offset(localTS-oLater*minuteMs);if(o1===o2){return[this];} const ts1=localTS-o1*minuteMs;const ts2=localTS-o2*minuteMs;const c1=tsToObj(ts1,o1);const c2=tsToObj(ts2,o2);if(c1.hour===c2.hour&&c1.minute===c2.minute&&c1.second===c2.second&&c1.millisecond===c2.millisecond){return[clone(this,{ts:ts1}),clone(this,{ts:ts2})];} return[this];} get isInLeapYear(){return isLeapYear(this.year);} get daysInMonth(){return daysInMonth(this.year,this.month);} get daysInYear(){return this.isValid?daysInYear(this.year):NaN;} get weeksInWeekYear(){return this.isValid?weeksInWeekYear(this.weekYear):NaN;} get weeksInLocalWeekYear(){return this.isValid?weeksInWeekYear(this.localWeekYear,this.loc.getMinDaysInFirstWeek(),this.loc.getStartOfWeek()):NaN;} resolvedLocaleOptions(opts={}){const{locale,numberingSystem,calendar}=Formatter.create(this.loc.clone(opts),opts).resolvedOptions(this);return{locale,numberingSystem,outputCalendar:calendar};} toUTC(offset=0,opts={}){return this.setZone(FixedOffsetZone.instance(offset),opts);} toLocal(){return this.setZone(Settings.defaultZone);} setZone(zone,{keepLocalTime=false,keepCalendarTime=false}={}){zone=normalizeZone(zone,Settings.defaultZone);if(zone.equals(this.zone)){return this;}else if(!zone.isValid){return DateTime.invalid(unsupportedZone(zone));}else{let newTS=this.ts;if(keepLocalTime||keepCalendarTime){const offsetGuess=zone.offset(this.ts);const asObj=this.toObject();[newTS]=objToTS(asObj,offsetGuess,zone);} return clone(this,{ts:newTS,zone});}} reconfigure({locale,numberingSystem,outputCalendar}={}){const loc=this.loc.clone({locale,numberingSystem,outputCalendar});return clone(this,{loc});} setLocale(locale){return this.reconfigure({locale});} set(values){if(!this.isValid)return this;const normalized=normalizeObject(values,normalizeUnitWithLocalWeeks);const{minDaysInFirstWeek,startOfWeek}=usesLocalWeekValues(normalized,this.loc);const settingWeekStuff=!isUndefined(normalized.weekYear)||!isUndefined(normalized.weekNumber)||!isUndefined(normalized.weekday),containsOrdinal=!isUndefined(normalized.ordinal),containsGregorYear=!isUndefined(normalized.year),containsGregorMD=!isUndefined(normalized.month)||!isUndefined(normalized.day),containsGregor=containsGregorYear||containsGregorMD,definiteWeekDef=normalized.weekYear||normalized.weekNumber;if((containsGregor||containsOrdinal)&&definiteWeekDef){throw new ConflictingSpecificationError("Can't mix weekYear/weekNumber units with year/month/day or ordinals");} if(containsGregorMD&&containsOrdinal){throw new ConflictingSpecificationError("Can't mix ordinal dates with month/day");} let mixed;if(settingWeekStuff){mixed=weekToGregorian({...gregorianToWeek(this.c,minDaysInFirstWeek,startOfWeek),...normalized},minDaysInFirstWeek,startOfWeek);}else if(!isUndefined(normalized.ordinal)){mixed=ordinalToGregorian({...gregorianToOrdinal(this.c),...normalized});}else{mixed={...this.toObject(),...normalized};if(isUndefined(normalized.day)){mixed.day=Math.min(daysInMonth(mixed.year,mixed.month),mixed.day);}} const[ts,o]=objToTS(mixed,this.o,this.zone);return clone(this,{ts,o});} plus(duration){if(!this.isValid)return this;const dur=Duration.fromDurationLike(duration);return clone(this,adjustTime(this,dur));} minus(duration){if(!this.isValid)return this;const dur=Duration.fromDurationLike(duration).negate();return clone(this,adjustTime(this,dur));} startOf(unit,{useLocaleWeeks=false}={}){if(!this.isValid)return this;const o={},normalizedUnit=Duration.normalizeUnit(unit);switch(normalizedUnit){case"years":o.month=1;case"quarters":case"months":o.day=1;case"weeks":case"days":o.hour=0;case"hours":o.minute=0;case"minutes":o.second=0;case"seconds":o.millisecond=0;break;} if(normalizedUnit==="weeks"){if(useLocaleWeeks){const startOfWeek=this.loc.getStartOfWeek();const{weekday}=this;if(weekdaythis.valueOf(),earlier=otherIsLater?this:otherDateTime,later=otherIsLater?otherDateTime:this,diffed=diff(earlier,later,units,durOpts);return otherIsLater?diffed.negate():diffed;} diffNow(unit="milliseconds",opts={}){return this.diff(DateTime.now(),unit,opts);} until(otherDateTime){return this.isValid?Interval.fromDateTimes(this,otherDateTime):this;} hasSame(otherDateTime,unit,opts){if(!this.isValid)return false;const inputMs=otherDateTime.valueOf();const adjustedToZone=this.setZone(otherDateTime.zone,{keepLocalTime:true});return(adjustedToZone.startOf(unit,opts)<=inputMs&&inputMs<=adjustedToZone.endOf(unit,opts));} equals(other){return(this.isValid&&other.isValid&&this.valueOf()===other.valueOf()&&this.zone.equals(other.zone)&&this.loc.equals(other.loc));} toRelative(options={}){if(!this.isValid)return null;const base=options.base||DateTime.fromObject({},{zone:this.zone}),padding=options.padding?(thisi.valueOf(),Math.min);} static max(...dateTimes){if(!dateTimes.every(DateTime.isDateTime)){throw new InvalidArgumentError("max requires all arguments be DateTimes");} return bestBy(dateTimes,(i)=>i.valueOf(),Math.max);} static fromFormatExplain(text,fmt,options={}){const{locale=null,numberingSystem=null}=options,localeToUse=Locale.fromOpts({locale,numberingSystem,defaultToEN:true,});return explainFromTokens(localeToUse,text,fmt);} static fromStringExplain(text,fmt,options={}){return DateTime.fromFormatExplain(text,fmt,options);} static get DATE_SHORT(){return DATE_SHORT;} static get DATE_MED(){return DATE_MED;} static get DATE_MED_WITH_WEEKDAY(){return DATE_MED_WITH_WEEKDAY;} static get DATE_FULL(){return DATE_FULL;} static get DATE_HUGE(){return DATE_HUGE;} static get TIME_SIMPLE(){return TIME_SIMPLE;} static get TIME_WITH_SECONDS(){return TIME_WITH_SECONDS;} static get TIME_WITH_SHORT_OFFSET(){return TIME_WITH_SHORT_OFFSET;} static get TIME_WITH_LONG_OFFSET(){return TIME_WITH_LONG_OFFSET;} static get TIME_24_SIMPLE(){return TIME_24_SIMPLE;} static get TIME_24_WITH_SECONDS(){return TIME_24_WITH_SECONDS;} static get TIME_24_WITH_SHORT_OFFSET(){return TIME_24_WITH_SHORT_OFFSET;} static get TIME_24_WITH_LONG_OFFSET(){return TIME_24_WITH_LONG_OFFSET;} static get DATETIME_SHORT(){return DATETIME_SHORT;} static get DATETIME_SHORT_WITH_SECONDS(){return DATETIME_SHORT_WITH_SECONDS;} static get DATETIME_MED(){return DATETIME_MED;} static get DATETIME_MED_WITH_SECONDS(){return DATETIME_MED_WITH_SECONDS;} static get DATETIME_MED_WITH_WEEKDAY(){return DATETIME_MED_WITH_WEEKDAY;} static get DATETIME_FULL(){return DATETIME_FULL;} static get DATETIME_FULL_WITH_SECONDS(){return DATETIME_FULL_WITH_SECONDS;} static get DATETIME_HUGE(){return DATETIME_HUGE;} static get DATETIME_HUGE_WITH_SECONDS(){return DATETIME_HUGE_WITH_SECONDS;}} function friendlyDateTime(dateTimeish){if(DateTime.isDateTime(dateTimeish)){return dateTimeish;}else if(dateTimeish&&dateTimeish.valueOf&&isNumber(dateTimeish.valueOf())){return DateTime.fromJSDate(dateTimeish);}else if(dateTimeish&&typeof dateTimeish==="object"){return DateTime.fromObject(dateTimeish);}else{throw new InvalidArgumentError(`Unknown datetime argument: ${dateTimeish}, of type ${typeof dateTimeish}`);}} const VERSION="3.4.4";exports.DateTime=DateTime;exports.Duration=Duration;exports.FixedOffsetZone=FixedOffsetZone;exports.IANAZone=IANAZone;exports.Info=Info;exports.Interval=Interval;exports.InvalidZone=InvalidZone;exports.Settings=Settings;exports.SystemZone=SystemZone;exports.VERSION=VERSION;exports.Zone=Zone;Object.defineProperty(exports,'__esModule',{value:true});return exports;})({});luxon.DateTime.prototype[Symbol.toStringTag]="LuxonDateTime";luxon.Duration.prototype[Symbol.toStringTag]="LuxonDuration";luxon.Interval.prototype[Symbol.toStringTag]="LuxonInterval";luxon.Settings.prototype[Symbol.toStringTag]="LuxonSettings";luxon.Info.prototype[Symbol.toStringTag]="LuxonInfo";luxon.Zone.prototype[Symbol.toStringTag]="LuxonZone";; /* /web/static/src/polyfills/object.js */ if(!Object.hasOwn){Object.hasOwn=(obj,key)=>Object.prototype.hasOwnProperty.call(obj,key);}; /* /web/static/src/polyfills/array.js */ if(!Array.prototype.at){Object.defineProperty(Array.prototype,"at",{enumerable:false,value:function(index){if(index>=0){return this[index];} return this[this.length+index];}});}; /* /web_editor/static/src/js/frontend/loader_loading.js */ (function(){'use strict';document.addEventListener('DOMContentLoaded',()=>{var textareaEls=document.querySelectorAll('textarea.o_wysiwyg_loader');for(var i=0;i{if(typeof data==="function"){data(ev);} else if(Array.isArray(data)){data=filterOutModifiersFromData(data).data;data[0](data[1],ev);} return false;},};class VToggler{constructor(key,child){this.key=key;this.child=child;} mount(parent,afterNode){this.parentEl=parent;this.child.mount(parent,afterNode);} moveBeforeDOMNode(node,parent){this.child.moveBeforeDOMNode(node,parent);} moveBeforeVNode(other,afterNode){this.moveBeforeDOMNode((other&&other.firstNode())||afterNode);} patch(other,withBeforeRemove){if(this===other){return;} let child1=this.child;let child2=other.child;if(this.key===other.key){child1.patch(child2,withBeforeRemove);} else{child2.mount(this.parentEl,child1.firstNode());if(withBeforeRemove){child1.beforeRemove();} child1.remove();this.child=child2;this.key=other.key;}} beforeRemove(){this.child.beforeRemove();} remove(){this.child.remove();} firstNode(){return this.child.firstNode();} toString(){return this.child.toString();}} function toggler(key,child){return new VToggler(key,child);} class OwlError extends Error{} const{setAttribute:elemSetAttribute,removeAttribute}=Element.prototype;const tokenList=DOMTokenList.prototype;const tokenListAdd=tokenList.add;const tokenListRemove=tokenList.remove;const isArray=Array.isArray;const{split,trim}=String.prototype;const wordRegexp=/\s+/;function setAttribute(key,value){switch(value){case false:case undefined:removeAttribute.call(this,key);break;case true:elemSetAttribute.call(this,key,"");break;default:elemSetAttribute.call(this,key,value);}} function createAttrUpdater(attr){return function(value){setAttribute.call(this,attr,value);};} function attrsSetter(attrs){if(isArray(attrs)){if(attrs[0]==="class"){setClass.call(this,attrs[1]);} else{setAttribute.call(this,attrs[0],attrs[1]);}} else{for(let k in attrs){if(k==="class"){setClass.call(this,attrs[k]);} else{setAttribute.call(this,k,attrs[k]);}}}} function attrsUpdater(attrs,oldAttrs){if(isArray(attrs)){const name=attrs[0];const val=attrs[1];if(name===oldAttrs[0]){if(val===oldAttrs[1]){return;} if(name==="class"){updateClass.call(this,val,oldAttrs[1]);} else{setAttribute.call(this,name,val);}} else{removeAttribute.call(this,oldAttrs[0]);setAttribute.call(this,name,val);}} else{for(let k in oldAttrs){if(!(k in attrs)){if(k==="class"){updateClass.call(this,"",oldAttrs[k]);} else{removeAttribute.call(this,k);}}} for(let k in attrs){const val=attrs[k];if(val!==oldAttrs[k]){if(k==="class"){updateClass.call(this,val,oldAttrs[k]);} else{setAttribute.call(this,k,val);}}}}} function toClassObj(expr){const result={};switch(typeof expr){case"string":const str=trim.call(expr);if(!str){return{};} let words=split.call(str,wordRegexp);for(let i=0,l=words.length;i{if(!scheduled){scheduled=true;await Promise.resolve();scheduled=false;callback(...args);}};} function inOwnerDocument(el){if(!el){return false;} if(el.ownerDocument.contains(el)){return true;} const rootNode=el.getRootNode();return rootNode instanceof ShadowRoot&&el.ownerDocument.contains(rootNode.host);} function validateTarget(target){const document=target&&target.ownerDocument;if(document){const HTMLElement=document.defaultView.HTMLElement;if(target instanceof HTMLElement||target instanceof ShadowRoot){if(!document.body.contains(target instanceof HTMLElement?target:target.host)){throw new OwlError("Cannot mount a component on a detached dom node");} return;}} throw new OwlError("Cannot mount component: the target is not a valid DOM element");} class EventBus extends EventTarget{trigger(name,payload){this.dispatchEvent(new CustomEvent(name,{detail:payload}));}} function whenReady(fn){return new Promise(function(resolve){if(document.readyState!=="loading"){resolve(true);} else{document.addEventListener("DOMContentLoaded",resolve,false);}}).then(fn||function(){});} async function loadFile(url){const result=await fetch(url);if(!result.ok){throw new OwlError("Error while fetching xml templates");} return await result.text();} class Markup extends String{} function markup(value){return new Markup(value);} function createEventHandler(rawEvent){const eventName=rawEvent.split(".")[0];const capture=rawEvent.includes(".capture");if(rawEvent.includes(".synthetic")){return createSyntheticHandler(eventName,capture);} else{return createElementHandler(eventName,capture);}} let nextNativeEventId=1;function createElementHandler(evName,capture=false){let eventKey=`__event__${evName}_${nextNativeEventId++}`;if(capture){eventKey=`${eventKey}_capture`;} function listener(ev){const currentTarget=ev.currentTarget;if(!currentTarget||!inOwnerDocument(currentTarget)) return;const data=currentTarget[eventKey];if(!data) return;config.mainEventHandler(data,ev,currentTarget);} function setup(data){this[eventKey]=data;this.addEventListener(evName,listener,{capture});} function remove(){delete this[eventKey];this.removeEventListener(evName,listener,{capture});} function update(data){this[eventKey]=data;} return{setup,update,remove};} let nextSyntheticEventId=1;function createSyntheticHandler(evName,capture=false){let eventKey=`__event__synthetic_${evName}`;if(capture){eventKey=`${eventKey}_capture`;} setupSyntheticEvent(evName,eventKey,capture);const currentId=nextSyntheticEventId++;function setup(data){const _data=this[eventKey]||{};_data[currentId]=data;this[eventKey]=_data;} function remove(){delete this[eventKey];} return{setup,update:setup,remove};} function nativeToSyntheticEvent(eventKey,event){let dom=event.target;while(dom!==null){const _data=dom[eventKey];if(_data){for(const data of Object.values(_data)){const stopped=config.mainEventHandler(data,event,dom);if(stopped) return;}} dom=dom.parentNode;}} const CONFIGURED_SYNTHETIC_EVENTS={};function setupSyntheticEvent(evName,eventKey,capture=false){if(CONFIGURED_SYNTHETIC_EVENTS[eventKey]){return;} document.addEventListener(evName,(event)=>nativeToSyntheticEvent(eventKey,event),{capture,});CONFIGURED_SYNTHETIC_EVENTS[eventKey]=true;} const getDescriptor$3=(o,p)=>Object.getOwnPropertyDescriptor(o,p);const nodeProto$4=Node.prototype;const nodeInsertBefore$3=nodeProto$4.insertBefore;const nodeSetTextContent$1=getDescriptor$3(nodeProto$4,"textContent").set;const nodeRemoveChild$3=nodeProto$4.removeChild;class VMulti{constructor(children){this.children=children;} mount(parent,afterNode){const children=this.children;const l=children.length;const anchors=new Array(l);for(let i=0;i(c?c.toString():"")).join("");}} function multi(children){return new VMulti(children);} const getDescriptor$2=(o,p)=>Object.getOwnPropertyDescriptor(o,p);const nodeProto$3=Node.prototype;const characterDataProto$1=CharacterData.prototype;const nodeInsertBefore$2=nodeProto$3.insertBefore;const characterDataSetData$1=getDescriptor$2(characterDataProto$1,"data").set;const nodeRemoveChild$2=nodeProto$3.removeChild;class VSimpleNode{constructor(text){this.text=text;} mountNode(node,parent,afterNode){this.parentEl=parent;nodeInsertBefore$2.call(parent,node,afterNode);this.el=node;} moveBeforeDOMNode(node,parent=this.parentEl){this.parentEl=parent;nodeInsertBefore$2.call(parent,this.el,node);} moveBeforeVNode(other,afterNode){nodeInsertBefore$2.call(this.parentEl,this.el,other?other.el:afterNode);} beforeRemove(){} remove(){nodeRemoveChild$2.call(this.parentEl,this.el);} firstNode(){return this.el;} toString(){return this.text;}} class VText$1 extends VSimpleNode{mount(parent,afterNode){this.mountNode(document.createTextNode(toText(this.text)),parent,afterNode);} patch(other){const text2=other.text;if(this.text!==text2){characterDataSetData$1.call(this.el,toText(text2));this.text=text2;}}} class VComment extends VSimpleNode{mount(parent,afterNode){this.mountNode(document.createComment(toText(this.text)),parent,afterNode);} patch(){}} function text(str){return new VText$1(str);} function comment(str){return new VComment(str);} function toText(value){switch(typeof value){case"string":return value;case"number":return String(value);case"boolean":return value?"true":"false";default:return value||"";}} const getDescriptor$1=(o,p)=>Object.getOwnPropertyDescriptor(o,p);const nodeProto$2=Node.prototype;const elementProto=Element.prototype;const characterDataProto=CharacterData.prototype;const characterDataSetData=getDescriptor$1(characterDataProto,"data").set;const nodeGetFirstChild=getDescriptor$1(nodeProto$2,"firstChild").get;const nodeGetNextSibling=getDescriptor$1(nodeProto$2,"nextSibling").get;const NO_OP=()=>{};function makePropSetter(name){return function setProp(value){this[name]=value===0?0:value?value.valueOf():"";};} const cache$1={};function createBlock(str){if(str in cache$1){return cache$1[str];} const doc=new DOMParser().parseFromString(`${str}`,"text/xml");const node=doc.firstChild.firstChild;if(config.shouldNormalizeDom){normalizeNode(node);} const tree=buildTree(node);const context=buildContext(tree);const template=tree.el;const Block=buildBlock(template,context);cache$1[str]=Block;return Block;} function normalizeNode(node){if(node.nodeType===Node.TEXT_NODE){if(!/\S/.test(node.textContent)){node.remove();return;}} if(node.nodeType===Node.ELEMENT_NODE){if(node.tagName==="pre"){return;}} for(let i=node.childNodes.length-1;i>=0;--i){normalizeNode(node.childNodes.item(i));}} function buildTree(node,parent=null,domParentTree=null){switch(node.nodeType){case Node.ELEMENT_NODE:{let currentNS=domParentTree&&domParentTree.currentNS;const tagName=node.tagName;let el=undefined;const info=[];if(tagName.startsWith("block-text-")){const index=parseInt(tagName.slice(11),10);info.push({type:"text",idx:index});el=document.createTextNode("");} if(tagName.startsWith("block-child-")){if(!domParentTree.isRef){addRef(domParentTree);} const index=parseInt(tagName.slice(12),10);info.push({type:"child",idx:index});el=document.createTextNode("");} currentNS||(currentNS=node.namespaceURI);if(!el){el=currentNS?document.createElementNS(currentNS,tagName):document.createElement(tagName);} if(el instanceof Element){if(!domParentTree){const fragment=document.createElement("template").content;fragment.appendChild(el);} const attrs=node.attributes;for(let i=0;iv.type==="child").length);ctx={collectors:[],locations:[],children,cbRefs:[],refN:tree.refN,refList:[]};fromIdx=0;} if(tree.refN){const initialIdx=fromIdx;const isRef=tree.isRef;const firstChild=tree.firstChild?tree.firstChild.refN:0;const nextSibling=tree.nextSibling?tree.nextSibling.refN:0;if(isRef){for(let info of tree.info){info.refIdx=initialIdx;} tree.refIdx=initialIdx;updateCtx(ctx,tree);fromIdx++;} if(nextSibling){const idx=fromIdx+firstChild;ctx.collectors.push({idx,prevIdx:initialIdx,getVal:nodeGetNextSibling});buildContext(tree.nextSibling,ctx,idx);} if(firstChild){ctx.collectors.push({idx:fromIdx,prevIdx:initialIdx,getVal:nodeGetFirstChild});buildContext(tree.firstChild,ctx,fromIdx);}} return ctx;} function updateCtx(ctx,tree){for(let info of tree.info){switch(info.type){case"text":ctx.locations.push({idx:info.idx,refIdx:info.refIdx,setData:setText,updateData:setText,});break;case"child":if(info.isOnlyChild){ctx.children[info.idx]={parentRefIdx:info.refIdx,isOnlyChild:true,};} else{ctx.children[info.idx]={parentRefIdx:parentTree(tree).refIdx,afterRefIdx:info.refIdx,};} break;case"property":{const refIdx=info.refIdx;const setProp=makePropSetter(info.name);ctx.locations.push({idx:info.idx,refIdx,setData:setProp,updateData:setProp,});break;} case"attribute":{const refIdx=info.refIdx;let updater;let setter;if(info.name==="class"){setter=setClass;updater=updateClass;} else{setter=createAttrUpdater(info.name);updater=setter;} ctx.locations.push({idx:info.idx,refIdx,setData:setter,updateData:updater,});break;} case"attributes":ctx.locations.push({idx:info.idx,refIdx:info.refIdx,setData:attrsSetter,updateData:attrsUpdater,});break;case"handler":{const{setup,update}=createEventHandler(info.event);ctx.locations.push({idx:info.idx,refIdx:info.refIdx,setData:setup,updateData:update,});break;} case"ref":const index=ctx.cbRefs.push(info.idx)-1;ctx.locations.push({idx:info.idx,refIdx:info.refIdx,setData:makeRefSetter(index,ctx.refList),updateData:NO_OP,});}}} function buildBlock(template,ctx){let B=createBlockClass(template,ctx);if(ctx.cbRefs.length){const cbRefs=ctx.cbRefs;const refList=ctx.refList;let cbRefsNumber=cbRefs.length;B=class extends B{mount(parent,afterNode){refList.push(new Array(cbRefsNumber));super.mount(parent,afterNode);for(let cbRef of refList.pop()){cbRef();}} remove(){super.remove();for(let cbRef of cbRefs){let fn=this.data[cbRef];fn(null);}}};} if(ctx.children.length){B=class extends B{constructor(data,children){super(data);this.children=children;}};B.prototype.beforeRemove=VMulti.prototype.beforeRemove;return(data,children=[])=>new B(data,children);} return(data)=>new B(data);} function createBlockClass(template,ctx){const{refN,collectors,children}=ctx;const colN=collectors.length;ctx.locations.sort((a,b)=>a.idx-b.idx);const locations=ctx.locations.map((loc)=>({refIdx:loc.refIdx,setData:loc.setData,updateData:loc.updateData,}));const locN=locations.length;const childN=children.length;const childrenLocs=children;const isDynamic=refN>0;const nodeCloneNode=nodeProto$2.cloneNode;const nodeInsertBefore=nodeProto$2.insertBefore;const elementRemove=elementProto.remove;class Block{constructor(data){this.data=data;} beforeRemove(){} remove(){elementRemove.call(this.el);} firstNode(){return this.el;} moveBeforeDOMNode(node,parent=this.parentEl){this.parentEl=parent;nodeInsertBefore.call(parent,this.el,node);} moveBeforeVNode(other,afterNode){nodeInsertBefore.call(this.parentEl,this.el,other?other.el:afterNode);} toString(){const div=document.createElement("div");this.mount(div,null);return div.innerHTML;} mount(parent,afterNode){const el=nodeCloneNode.call(template,true);nodeInsertBefore.call(parent,el,afterNode);this.el=el;this.parentEl=parent;} patch(other,withBeforeRemove){}} if(isDynamic){Block.prototype.mount=function mount(parent,afterNode){const el=nodeCloneNode.call(template,true);const refs=new Array(refN);this.refs=refs;refs[0]=el;for(let i=0;ifn(this);};} const getDescriptor=(o,p)=>Object.getOwnPropertyDescriptor(o,p);const nodeProto$1=Node.prototype;const nodeInsertBefore$1=nodeProto$1.insertBefore;const nodeAppendChild=nodeProto$1.appendChild;const nodeRemoveChild$1=nodeProto$1.removeChild;const nodeSetTextContent=getDescriptor(nodeProto$1,"textContent").set;class VList{constructor(children){this.children=children;} mount(parent,afterNode){const children=this.children;const _anchor=document.createTextNode("");this.anchor=_anchor;nodeInsertBefore$1.call(parent,_anchor,afterNode);const l=children.length;if(l){const mount=children[0].mount;for(let i=0;iendIdx1){const nextChild=ch2[endIdx2+1];const anchor=nextChild?cFirstNode.call(nextChild)||null:_anchor;for(let i=startIdx2;i<=endIdx2;i++){cMount.call(ch2[i],parent,anchor);}} else{for(let i=startIdx1;i<=endIdx1;i++){let ch=ch1[i];if(ch){if(withBeforeRemove){beforeRemove.call(ch);} cRemove.call(ch);}}}}} beforeRemove(){const children=this.children;const l=children.length;if(l){const beforeRemove=children[0].beforeRemove;for(let i=0;ic.toString()).join("");}} function list(children){return new VList(children);} function createMapping(ch1,startIdx1,endIdx2){let mapping={};for(let i=startIdx1;i<=endIdx2;i++){mapping[ch1[i].key]=i;} return mapping;} const nodeProto=Node.prototype;const nodeInsertBefore=nodeProto.insertBefore;const nodeRemoveChild=nodeProto.removeChild;class VHtml{constructor(html){this.content=[];this.html=html;} mount(parent,afterNode){this.parentEl=parent;const template=document.createElement("template");template.innerHTML=this.html;this.content=[...template.content.childNodes];for(let elem of this.content){nodeInsertBefore.call(parent,elem,afterNode);} if(!this.content.length){const textNode=document.createTextNode("");this.content.push(textNode);nodeInsertBefore.call(parent,textNode,afterNode);}} moveBeforeDOMNode(node,parent=this.parentEl){this.parentEl=parent;for(let elem of this.content){nodeInsertBefore.call(parent,elem,node);}} moveBeforeVNode(other,afterNode){const target=other?other.content[0]:afterNode;this.moveBeforeDOMNode(target);} patch(other){if(this===other){return;} const html2=other.html;if(this.html!==html2){const parent=this.parentEl;const afterNode=this.content[0];const template=document.createElement("template");template.innerHTML=html2;const content=[...template.content.childNodes];for(let elem of content){nodeInsertBefore.call(parent,elem,afterNode);} if(!content.length){const textNode=document.createTextNode("");content.push(textNode);nodeInsertBefore.call(parent,textNode,afterNode);} this.remove();this.content=content;this.html=other.html;}} beforeRemove(){} remove(){const parent=this.parentEl;for(let elem of this.content){nodeRemoveChild.call(parent,elem);}} firstNode(){return this.content[0];} toString(){return this.html;}} function html(str){return new VHtml(str);} function createCatcher(eventsSpec){const n=Object.keys(eventsSpec).length;class VCatcher{constructor(child,handlers){this.handlerFns=[];this.afterNode=null;this.child=child;this.handlerData=handlers;} mount(parent,afterNode){this.parentEl=parent;this.child.mount(parent,afterNode);this.afterNode=document.createTextNode("");parent.insertBefore(this.afterNode,afterNode);this.wrapHandlerData();for(let name in eventsSpec){const index=eventsSpec[name];const handler=createEventHandler(name);this.handlerFns[index]=handler;handler.setup.call(parent,this.handlerData[index]);}} wrapHandlerData(){for(let i=0;i=0;i--){try{errorHandlers[i](error);handled=true;break;} catch(e){error=e;}} if(handled){return true;}} return _handleError(node.parent,error);} function handleError(params){let{error}=params;if(!(error instanceof OwlError)){error=Object.assign(new OwlError(`An error occured in the owl lifecycle (see this Error's "cause" property)`),{cause:error});} const node="node"in params?params.node:params.fiber.node;const fiber="fiber"in params?params.fiber:node.fiber;if(fiber){let current=fiber;do{current.node.fiber=current;current=current.parent;}while(current);fibersInError.set(fiber.root,error);} const handled=_handleError(node,error);if(!handled){console.warn(`[Owl] Unhandled error. Destroying the root component`);try{node.app.destroy();} catch(e){console.error(e);} throw error;}} function makeChildFiber(node,parent){let current=node.fiber;if(current){cancelFibers(current.children);current.root=null;} return new Fiber(node,parent);} function makeRootFiber(node){let current=node.fiber;if(current){let root=current.root;root.locked=true;root.setCounter(root.counter+1-cancelFibers(current.children));root.locked=false;current.children=[];current.childrenMap={};current.bdom=null;if(fibersInError.has(current)){fibersInError.delete(current);fibersInError.delete(root);current.appliedToDom=false;if(current instanceof RootFiber){current.mounted=current instanceof MountFiber?[current]:[];}} return current;} const fiber=new RootFiber(node,null);if(node.willPatch.length){fiber.willPatch.push(fiber);} if(node.patched.length){fiber.patched.push(fiber);} return fiber;} function throwOnRender(){throw new OwlError("Attempted to render cancelled fiber");} function cancelFibers(fibers){let result=0;for(let fiber of fibers){let node=fiber.node;fiber.render=throwOnRender;if(node.status===0){node.cancel();} node.fiber=null;if(fiber.bdom){node.forceNextRender=true;} else{result++;} result+=cancelFibers(fiber.children);} return result;} class Fiber{constructor(node,parent){this.bdom=null;this.children=[];this.appliedToDom=false;this.deep=false;this.childrenMap={};this.node=node;this.parent=parent;if(parent){this.deep=parent.deep;const root=parent.root;root.setCounter(root.counter+1);this.root=root;parent.children.push(this);} else{this.root=this;}} render(){let prev=this.root.node;let scheduler=prev.app.scheduler;let current=prev.parent;while(current){if(current.fiber){let root=current.fiber.root;if(root.counter===0&&prev.parentKey in current.fiber.childrenMap){current=root.node;} else{scheduler.delayedRenders.push(this);return;}} prev=current;current=current.parent;} this._render();} _render(){const node=this.node;const root=this.root;if(root){try{this.bdom=true;this.bdom=node.renderFn();} catch(e){node.app.handleError({node,error:e});} root.setCounter(root.counter-1);}}} class RootFiber extends Fiber{constructor(){super(...arguments);this.counter=1;this.willPatch=[];this.patched=[];this.mounted=[];this.locked=false;} complete(){const node=this.node;this.locked=true;let current=undefined;let mountedFibers=this.mounted;try{for(current of this.willPatch){let node=current.node;if(node.fiber===current){const component=node.component;for(let cb of node.willPatch){cb.call(component);}}} current=undefined;node._patch();this.locked=false;while((current=mountedFibers.pop())){current=current;if(current.appliedToDom){for(let cb of current.node.mounted){cb();}}} let patchedFibers=this.patched;while((current=patchedFibers.pop())){current=current;if(current.appliedToDom){for(let cb of current.node.patched){cb();}}}} catch(e){for(let fiber of mountedFibers){fiber.node.willUnmount=[];} this.locked=false;node.app.handleError({fiber:current||this,error:e});}} setCounter(newValue){this.counter=newValue;if(newValue===0){this.node.app.scheduler.flush();}}} class MountFiber extends RootFiber{constructor(node,target,options={}){super(node,null);this.target=target;this.position=options.position||"last-child";} complete(){let current=this;try{const node=this.node;node.children=this.childrenMap;node.app.constructor.validateTarget(this.target);if(node.bdom){node.updateDom();} else{node.bdom=this.bdom;if(this.position==="last-child"||this.target.childNodes.length===0){mount$1(node.bdom,this.target);} else{const firstChild=this.target.childNodes[0];mount$1(node.bdom,this.target,firstChild);}} node.fiber=null;node.status=1;this.appliedToDom=true;let mountedFibers=this.mounted;while((current=mountedFibers.pop())){if(current.appliedToDom){for(let cb of current.node.mounted){cb();}}}} catch(e){this.node.app.handleError({fiber:current,error:e});}}} const KEYCHANGES=Symbol("Key changes");const NO_CALLBACK=()=>{throw new Error("Called NO_CALLBACK. Owl is broken, please report this to the maintainers.");};const objectToString=Object.prototype.toString;const objectHasOwnProperty=Object.prototype.hasOwnProperty;const SUPPORTED_RAW_TYPES=["Object","Array","Set","Map","WeakMap"];const COLLECTION_RAW_TYPES=["Set","Map","WeakMap"];function rawType(obj){return objectToString.call(toRaw(obj)).slice(8,-1);} function canBeMadeReactive(value){if(typeof value!=="object"){return false;} return SUPPORTED_RAW_TYPES.includes(rawType(value));} function possiblyReactive(val,cb){return canBeMadeReactive(val)?reactive(val,cb):val;} const skipped=new WeakSet();function markRaw(value){skipped.add(value);return value;} function toRaw(value){return targets.has(value)?targets.get(value):value;} const targetToKeysToCallbacks=new WeakMap();function observeTargetKey(target,key,callback){if(callback===NO_CALLBACK){return;} if(!targetToKeysToCallbacks.get(target)){targetToKeysToCallbacks.set(target,new Map());} const keyToCallbacks=targetToKeysToCallbacks.get(target);if(!keyToCallbacks.get(key)){keyToCallbacks.set(key,new Set());} keyToCallbacks.get(key).add(callback);if(!callbacksToTargets.has(callback)){callbacksToTargets.set(callback,new Set());} callbacksToTargets.get(callback).add(target);} function notifyReactives(target,key){const keyToCallbacks=targetToKeysToCallbacks.get(target);if(!keyToCallbacks){return;} const callbacks=keyToCallbacks.get(key);if(!callbacks){return;} for(const callback of[...callbacks]){clearReactivesForCallback(callback);callback();}} const callbacksToTargets=new WeakMap();function clearReactivesForCallback(callback){const targetsToClear=callbacksToTargets.get(callback);if(!targetsToClear){return;} for(const target of targetsToClear){const observedKeys=targetToKeysToCallbacks.get(target);if(!observedKeys){continue;} for(const[key,callbacks]of observedKeys.entries()){callbacks.delete(callback);if(!callbacks.size){observedKeys.delete(key);}}} targetsToClear.clear();} function getSubscriptions(callback){const targets=callbacksToTargets.get(callback)||[];return[...targets].map((target)=>{const keysToCallbacks=targetToKeysToCallbacks.get(target);let keys=[];if(keysToCallbacks){for(const[key,cbs]of keysToCallbacks){if(cbs.has(callback)){keys.push(key);}}} return{target,keys};});} const targets=new WeakMap();const reactiveCache=new WeakMap();function reactive(target,callback=NO_CALLBACK){if(!canBeMadeReactive(target)){throw new OwlError(`Cannot make the given value reactive`);} if(skipped.has(target)){return target;} if(targets.has(target)){return reactive(targets.get(target),callback);} if(!reactiveCache.has(target)){reactiveCache.set(target,new WeakMap());} const reactivesForTarget=reactiveCache.get(target);if(!reactivesForTarget.has(callback)){const targetRawType=rawType(target);const handler=COLLECTION_RAW_TYPES.includes(targetRawType)?collectionsProxyHandler(target,callback,targetRawType):basicProxyHandler(callback);const proxy=new Proxy(target,handler);reactivesForTarget.set(callback,proxy);targets.set(proxy,target);} return reactivesForTarget.get(callback);} function basicProxyHandler(callback){return{get(target,key,receiver){const desc=Object.getOwnPropertyDescriptor(target,key);if(desc&&!desc.writable&&!desc.configurable){return Reflect.get(target,key,receiver);} observeTargetKey(target,key,callback);return possiblyReactive(Reflect.get(target,key,receiver),callback);},set(target,key,value,receiver){const hadKey=objectHasOwnProperty.call(target,key);const originalValue=Reflect.get(target,key,receiver);const ret=Reflect.set(target,key,toRaw(value),receiver);if(!hadKey&&objectHasOwnProperty.call(target,key)){notifyReactives(target,KEYCHANGES);} if(originalValue!==Reflect.get(target,key,receiver)||(key==="length"&&Array.isArray(target))){notifyReactives(target,key);} return ret;},deleteProperty(target,key){const ret=Reflect.deleteProperty(target,key);notifyReactives(target,KEYCHANGES);notifyReactives(target,key);return ret;},ownKeys(target){observeTargetKey(target,KEYCHANGES,callback);return Reflect.ownKeys(target);},has(target,key){observeTargetKey(target,KEYCHANGES,callback);return Reflect.has(target,key);},};} function makeKeyObserver(methodName,target,callback){return(key)=>{key=toRaw(key);observeTargetKey(target,key,callback);return possiblyReactive(target[methodName](key),callback);};} function makeIteratorObserver(methodName,target,callback){return function*(){observeTargetKey(target,KEYCHANGES,callback);const keys=target.keys();for(const item of target[methodName]()){const key=keys.next().value;observeTargetKey(target,key,callback);yield possiblyReactive(item,callback);}};} function makeForEachObserver(target,callback){return function forEach(forEachCb,thisArg){observeTargetKey(target,KEYCHANGES,callback);target.forEach(function(val,key,targetObj){observeTargetKey(target,key,callback);forEachCb.call(thisArg,possiblyReactive(val,callback),possiblyReactive(key,callback),possiblyReactive(targetObj,callback));},thisArg);};} function delegateAndNotify(setterName,getterName,target){return(key,value)=>{key=toRaw(key);const hadKey=target.has(key);const originalValue=target[getterName](key);const ret=target[setterName](key,value);const hasKey=target.has(key);if(hadKey!==hasKey){notifyReactives(target,KEYCHANGES);} if(originalValue!==target[getterName](key)){notifyReactives(target,key);} return ret;};} function makeClearNotifier(target){return()=>{const allKeys=[...target.keys()];target.clear();notifyReactives(target,KEYCHANGES);for(const key of allKeys){notifyReactives(target,key);}};} const rawTypeToFuncHandlers={Set:(target,callback)=>({has:makeKeyObserver("has",target,callback),add:delegateAndNotify("add","has",target),delete:delegateAndNotify("delete","has",target),keys:makeIteratorObserver("keys",target,callback),values:makeIteratorObserver("values",target,callback),entries:makeIteratorObserver("entries",target,callback),[Symbol.iterator]:makeIteratorObserver(Symbol.iterator,target,callback),forEach:makeForEachObserver(target,callback),clear:makeClearNotifier(target),get size(){observeTargetKey(target,KEYCHANGES,callback);return target.size;},}),Map:(target,callback)=>({has:makeKeyObserver("has",target,callback),get:makeKeyObserver("get",target,callback),set:delegateAndNotify("set","get",target),delete:delegateAndNotify("delete","has",target),keys:makeIteratorObserver("keys",target,callback),values:makeIteratorObserver("values",target,callback),entries:makeIteratorObserver("entries",target,callback),[Symbol.iterator]:makeIteratorObserver(Symbol.iterator,target,callback),forEach:makeForEachObserver(target,callback),clear:makeClearNotifier(target),get size(){observeTargetKey(target,KEYCHANGES,callback);return target.size;},}),WeakMap:(target,callback)=>({has:makeKeyObserver("has",target,callback),get:makeKeyObserver("get",target,callback),set:delegateAndNotify("set","get",target),delete:delegateAndNotify("delete","has",target),}),};function collectionsProxyHandler(target,callback,targetRawType){const specialHandlers=rawTypeToFuncHandlers[targetRawType](target,callback);return Object.assign(basicProxyHandler(callback),{get(target,key){if(objectHasOwnProperty.call(specialHandlers,key)){return specialHandlers[key];} observeTargetKey(target,key,callback);return possiblyReactive(target[key],callback);},});} let currentNode=null;function saveCurrent(){let n=currentNode;return()=>{currentNode=n;};} function getCurrent(){if(!currentNode){throw new OwlError("No active component (a hook function should only be called in 'setup')");} return currentNode;} function useComponent(){return currentNode.component;} function applyDefaultProps(props,defaultProps){for(let propName in defaultProps){if(props[propName]===undefined){props[propName]=defaultProps[propName];}}} const batchedRenderFunctions=new WeakMap();function useState(state){const node=getCurrent();let render=batchedRenderFunctions.get(node);if(!render){render=batched(node.render.bind(node,false));batchedRenderFunctions.set(node,render);node.willDestroy.push(clearReactivesForCallback.bind(null,render));} return reactive(state,render);} class ComponentNode{constructor(C,props,app,parent,parentKey){this.fiber=null;this.bdom=null;this.status=0;this.forceNextRender=false;this.nextProps=null;this.children=Object.create(null);this.refs={};this.willStart=[];this.willUpdateProps=[];this.willUnmount=[];this.mounted=[];this.willPatch=[];this.patched=[];this.willDestroy=[];currentNode=this;this.app=app;this.parent=parent;this.props=props;this.parentKey=parentKey;const defaultProps=C.defaultProps;props=Object.assign({},props);if(defaultProps){applyDefaultProps(props,defaultProps);} const env=(parent&&parent.childEnv)||app.env;this.childEnv=env;for(const key in props){const prop=props[key];if(prop&&typeof prop==="object"&&targets.has(prop)){props[key]=useState(prop);}} this.component=new C(props,env,this);const ctx=Object.assign(Object.create(this.component),{this:this.component});this.renderFn=app.getTemplate(C.template).bind(this.component,ctx,this);this.component.setup();currentNode=null;} mountComponent(target,options){const fiber=new MountFiber(this,target,options);this.app.scheduler.addFiber(fiber);this.initiateRender(fiber);} async initiateRender(fiber){this.fiber=fiber;if(this.mounted.length){fiber.root.mounted.push(fiber);} const component=this.component;try{await Promise.all(this.willStart.map((f)=>f.call(component)));} catch(e){this.app.handleError({node:this,error:e});return;} if(this.status===0&&this.fiber===fiber){fiber.render();}} async render(deep){if(this.status>=2){return;} let current=this.fiber;if(current&&(current.root.locked||current.bdom===true)){await Promise.resolve();current=this.fiber;} if(current){if(!current.bdom&&!fibersInError.has(current)){if(deep){current.deep=deep;} return;} deep=deep||current.deep;} else if(!this.bdom){return;} const fiber=makeRootFiber(this);fiber.deep=deep;this.fiber=fiber;this.app.scheduler.addFiber(fiber);await Promise.resolve();if(this.status>=2){return;} if(this.fiber===fiber&&(current||!fiber.parent)){fiber.render();}} cancel(){this._cancel();delete this.parent.children[this.parentKey];this.app.scheduler.scheduleDestroy(this);} _cancel(){this.status=2;const children=this.children;for(let childKey in children){children[childKey]._cancel();}} destroy(){let shouldRemove=this.status===1;this._destroy();if(shouldRemove){this.bdom.remove();}} _destroy(){const component=this.component;if(this.status===1){for(let cb of this.willUnmount){cb.call(component);}} for(let child of Object.values(this.children)){child._destroy();} if(this.willDestroy.length){try{for(let cb of this.willDestroy){cb.call(component);}} catch(e){this.app.handleError({error:e,node:this});}} this.status=3;} async updateAndRender(props,parentFiber){this.nextProps=props;props=Object.assign({},props);const fiber=makeChildFiber(this,parentFiber);this.fiber=fiber;const component=this.component;const defaultProps=component.constructor.defaultProps;if(defaultProps){applyDefaultProps(props,defaultProps);} currentNode=this;for(const key in props){const prop=props[key];if(prop&&typeof prop==="object"&&targets.has(prop)){props[key]=useState(prop);}} currentNode=null;const prom=Promise.all(this.willUpdateProps.map((f)=>f.call(component,props)));await prom;if(fiber!==this.fiber){return;} component.props=props;fiber.render();const parentRoot=parentFiber.root;if(this.willPatch.length){parentRoot.willPatch.push(fiber);} if(this.patched.length){parentRoot.patched.push(fiber);}} updateDom(){if(!this.fiber){return;} if(this.bdom===this.fiber.bdom){for(let k in this.children){const child=this.children[k];child.updateDom();}} else{this.bdom.patch(this.fiber.bdom,false);this.fiber.appliedToDom=true;this.fiber=null;}} setRef(name,el){if(el){this.refs[name]=el;}} firstNode(){const bdom=this.bdom;return bdom?bdom.firstNode():undefined;} mount(parent,anchor){const bdom=this.fiber.bdom;this.bdom=bdom;bdom.mount(parent,anchor);this.status=1;this.fiber.appliedToDom=true;this.children=this.fiber.childrenMap;this.fiber=null;} moveBeforeDOMNode(node,parent){this.bdom.moveBeforeDOMNode(node,parent);} moveBeforeVNode(other,afterNode){this.bdom.moveBeforeVNode(other?other.bdom:null,afterNode);} patch(){if(this.fiber&&this.fiber.parent){this._patch();this.props=this.nextProps;}} _patch(){let hasChildren=false;for(let _k in this.children){hasChildren=true;break;} const fiber=this.fiber;this.children=fiber.childrenMap;this.bdom.patch(fiber.bdom,hasChildren);fiber.appliedToDom=true;this.fiber=null;} beforeRemove(){this._destroy();} remove(){this.bdom.remove();} get name(){return this.component.constructor.name;} get subscriptions(){const render=batchedRenderFunctions.get(this);return render?getSubscriptions(render):[];}} const TIMEOUT=Symbol("timeout");const HOOK_TIMEOUT={onWillStart:3000,onWillUpdateProps:3000,};function wrapError(fn,hookName){const error=new OwlError();const timeoutError=new OwlError();const node=getCurrent();return(...args)=>{const onError=(cause)=>{error.cause=cause;error.message=cause instanceof Error?`The following error occurred in ${hookName}: "${cause.message}"`:`Something that is not an Error was thrown in ${hookName} (see this Error's "cause" property)`;throw error;};let result;try{result=fn(...args);} catch(cause){onError(cause);} if(!(result instanceof Promise)){return result;} const timeout=HOOK_TIMEOUT[hookName];if(timeout){const fiber=node.fiber;Promise.race([result.catch(()=>{}),new Promise((resolve)=>setTimeout(()=>resolve(TIMEOUT),timeout)),]).then((res)=>{if(res===TIMEOUT&&node.fiber===fiber&&node.status<=2){timeoutError.message=`${hookName}'s promise hasn't resolved after ${timeout / 1000} seconds`;console.log(timeoutError);}});} return result.catch(onError);};} function onWillStart(fn){const node=getCurrent();const decorate=node.app.dev?wrapError:(fn)=>fn;node.willStart.push(decorate(fn.bind(node.component),"onWillStart"));} function onWillUpdateProps(fn){const node=getCurrent();const decorate=node.app.dev?wrapError:(fn)=>fn;node.willUpdateProps.push(decorate(fn.bind(node.component),"onWillUpdateProps"));} function onMounted(fn){const node=getCurrent();const decorate=node.app.dev?wrapError:(fn)=>fn;node.mounted.push(decorate(fn.bind(node.component),"onMounted"));} function onWillPatch(fn){const node=getCurrent();const decorate=node.app.dev?wrapError:(fn)=>fn;node.willPatch.unshift(decorate(fn.bind(node.component),"onWillPatch"));} function onPatched(fn){const node=getCurrent();const decorate=node.app.dev?wrapError:(fn)=>fn;node.patched.push(decorate(fn.bind(node.component),"onPatched"));} function onWillUnmount(fn){const node=getCurrent();const decorate=node.app.dev?wrapError:(fn)=>fn;node.willUnmount.unshift(decorate(fn.bind(node.component),"onWillUnmount"));} function onWillDestroy(fn){const node=getCurrent();const decorate=node.app.dev?wrapError:(fn)=>fn;node.willDestroy.push(decorate(fn.bind(node.component),"onWillDestroy"));} function onWillRender(fn){const node=getCurrent();const renderFn=node.renderFn;const decorate=node.app.dev?wrapError:(fn)=>fn;fn=decorate(fn.bind(node.component),"onWillRender");node.renderFn=()=>{fn();return renderFn();};} function onRendered(fn){const node=getCurrent();const renderFn=node.renderFn;const decorate=node.app.dev?wrapError:(fn)=>fn;fn=decorate(fn.bind(node.component),"onRendered");node.renderFn=()=>{const result=renderFn();fn();return result;};} function onError(callback){const node=getCurrent();let handlers=nodeErrorHandlers.get(node);if(!handlers){handlers=[];nodeErrorHandlers.set(node,handlers);} handlers.push(callback.bind(node.component));} class Component{constructor(props,env,node){this.props=props;this.env=env;this.__owl__=node;} setup(){} render(deep=false){this.__owl__.render(deep===true);}} Component.template="";const VText=text("").constructor;class VPortal extends VText{constructor(selector,content){super("");this.target=null;this.selector=selector;this.content=content;} mount(parent,anchor){super.mount(parent,anchor);this.target=document.querySelector(this.selector);if(this.target){this.content.mount(this.target,null);} else{this.content.mount(parent,anchor);}} beforeRemove(){this.content.beforeRemove();} remove(){if(this.content){super.remove();this.content.remove();this.content=null;}} patch(other){super.patch(other);if(this.content){this.content.patch(other.content,true);} else{this.content=other.content;this.content.mount(this.target,null);}}} function portalTemplate(app,bdom,helpers){let{callSlot}=helpers;return function template(ctx,node,key=""){return new VPortal(ctx.props.target,callSlot(ctx,node,key,"default",false,null));};} class Portal extends Component{setup(){const node=this.__owl__;onMounted(()=>{const portal=node.bdom;if(!portal.target){const target=document.querySelector(this.props.target);if(target){portal.content.moveBeforeDOMNode(target.firstChild,target);} else{throw new OwlError("invalid portal target");}}});onWillUnmount(()=>{const portal=node.bdom;portal.remove();});}} Portal.template="__portal__";Portal.props={target:{type:String,},slots:true,};const isUnionType=(t)=>Array.isArray(t);const isBaseType=(t)=>typeof t!=="object";const isValueType=(t)=>typeof t==="object"&&t&&"value"in t;function isOptional(t){return typeof t==="object"&&"optional"in t?t.optional||false:false;} function describeType(type){return type==="*"||type===true?"value":type.name.toLowerCase();} function describe(info){if(isBaseType(info)){return describeType(info);} else if(isUnionType(info)){return info.map(describe).join(" or ");} else if(isValueType(info)){return String(info.value);} if("element"in info){return`list of ${describe({ type: info.element, optional: false })}s`;} if("shape"in info){return`object`;} return describe(info.type||"*");} function toSchema(spec){return Object.fromEntries(spec.map((e)=>e.endsWith("?")?[e.slice(0,-1),{optional:true}]:[e,{type:"*",optional:false}]));} function validate(obj,spec){let errors=validateSchema(obj,spec);if(errors.length){throw new OwlError("Invalid object: "+errors.join(", "));}} function validateSchema(obj,schema){if(Array.isArray(schema)){schema=toSchema(schema);} obj=toRaw(obj);let errors=[];for(let key in obj){if(key in schema){let result=validateType(key,obj[key],schema[key]);if(result){errors.push(result);}} else if(!("*"in schema)){errors.push(`unknown key '${key}'`);}} for(let key in schema){const spec=schema[key];if(key!=="*"&&!isOptional(spec)&&!(key in obj)){const isObj=typeof spec==="object"&&!Array.isArray(spec);const isAny=spec==="*"||(isObj&&"type"in spec?spec.type==="*":isObj);let detail=isAny?"":` (should be a ${describe(spec)})`;errors.push(`'${key}' is missing${detail}`);}} return errors;} function validateBaseType(key,value,type){if(typeof type==="function"){if(typeof value==="object"){if(!(value instanceof type)){return`'${key}' is not a ${describeType(type)}`;}} else if(typeof value!==type.name.toLowerCase()){return`'${key}' is not a ${describeType(type)}`;}} return null;} function validateArrayType(key,value,descr){if(!Array.isArray(value)){return`'${key}' is not a list of ${describe(descr)}s`;} for(let i=0;i!validateType(key,value,p));return validDescr?null:`'${key}' is not a ${describe(descr)}`;} let result=null;if("element"in descr){result=validateArrayType(key,value,descr.element);} else if("shape"in descr){if(typeof value!=="object"||Array.isArray(value)){result=`'${key}' is not an object`;} else{const errors=validateSchema(value,descr.shape);if(errors.length){result=`'${key}' doesn't have the correct shape (${errors.join(", ")})`;}}} else if("values"in descr){if(typeof value!=="object"||Array.isArray(value)){result=`'${key}' is not an object`;} else{const errors=Object.entries(value).map(([key,value])=>validateType(key,value,descr.values)).filter(Boolean);if(errors.length){result=`some of the values in '${key}' are invalid (${errors.join(", ")})`;}}} if("type"in descr&&!result){result=validateType(key,value,descr.type);} if("validate"in descr&&!result){result=!descr.validate(value)?`'${key}' is not valid`:null;} return result;} const ObjectCreate=Object.create;function withDefault(value,defaultValue){return value===undefined||value===null||value===false?defaultValue:value;} function callSlot(ctx,parent,key,name,dynamic,extra,defaultContent){key=key+"__slot_"+name;const slots=ctx.props.slots||{};const{__render,__ctx,__scope}=slots[name]||{};const slotScope=ObjectCreate(__ctx||{});if(__scope){slotScope[__scope]=extra;} const slotBDom=__render?__render(slotScope,parent,key):null;if(defaultContent){let child1=undefined;let child2=undefined;if(slotBDom){child1=dynamic?toggler(name,slotBDom):slotBDom;} else{child2=defaultContent(ctx,parent,key);} return multi([child1,child2]);} return slotBDom||text("");} function capture(ctx){const result=ObjectCreate(ctx);for(let k in ctx){result[k]=ctx[k];} return result;} function withKey(elem,k){elem.key=k;return elem;} function prepareList(collection){let keys;let values;if(Array.isArray(collection)){keys=collection;values=collection;} else if(collection instanceof Map){keys=[...collection.keys()];values=[...collection.values()];} else if(Symbol.iterator in Object(collection)){keys=[...collection];values=keys;} else if(collection&&typeof collection==="object"){values=Object.values(collection);keys=Object.keys(collection);} else{throw new OwlError(`Invalid loop expression: "${collection}" is not iterable`);} const n=values.length;return[keys,values,n,new Array(n)];} const isBoundary=Symbol("isBoundary");function setContextValue(ctx,key,value){const ctx0=ctx;while(!ctx.hasOwnProperty(key)&&!ctx.hasOwnProperty(isBoundary)){const newCtx=ctx.__proto__;if(!newCtx){ctx=ctx0;break;} ctx=newCtx;} ctx[key]=value;} function toNumber(val){const n=parseFloat(val);return isNaN(n)?val:n;} function shallowEqual(l1,l2){for(let i=0,l=l1.length;iArray.isArray(schema)?schema.includes(name):name in schema&&!("*"in schema)&&!isOptional(schema[name]);for(let p in defaultProps){if(isMandatory(p)){throw new OwlError(`A default value cannot be defined for a mandatory prop (name: '${p}', component: ${ComponentClass.name})`);}}} const errors=validateSchema(props,schema);if(errors.length){throw new OwlError(`Invalid props for component '${ComponentClass.name}': `+errors.join(", "));}} function makeRefWrapper(node){let refNames=new Set();return(name,fn)=>{if(refNames.has(name)){throw new OwlError(`Cannot set the same ref more than once in the same component, ref "${name}" was set multiple times in ${node.name}`);} refNames.add(name);return fn;};} const helpers={withDefault,zero:Symbol("zero"),isBoundary,callSlot,capture,withKey,prepareList,setContextValue,shallowEqual,toNumber,validateProps,LazyValue,safeOutput,createCatcher,markRaw,OwlError,makeRefWrapper,};function parseXML(xml){const parser=new DOMParser();const doc=parser.parseFromString(xml,"text/xml");if(doc.getElementsByTagName("parsererror").length){let msg="Invalid XML in template.";const parsererrorText=doc.getElementsByTagName("parsererror")[0].textContent;if(parsererrorText){msg+="\nThe parser has produced the following error message:\n"+parsererrorText;const re=/\d+/g;const firstMatch=re.exec(parsererrorText);if(firstMatch){const lineNumber=Number(firstMatch[0]);const line=xml.split("\n")[lineNumber-1];const secondMatch=re.exec(parsererrorText);if(line&&secondMatch){const columnIndex=Number(secondMatch[0])-1;if(line[columnIndex]){msg+=`\nThe error might be located at xml line ${lineNumber} column ${columnIndex}\n`+`${line}\n${"-".repeat(columnIndex - 1)}^`;}}}} throw new OwlError(msg);} return doc;} const bdom={text,createBlock,list,multi,html,toggler,comment};class TemplateSet{constructor(config={}){this.rawTemplates=Object.create(globalTemplates);this.templates={};this.Portal=Portal;this.dev=config.dev||false;this.translateFn=config.translateFn;this.translatableAttributes=config.translatableAttributes;if(config.templates){if(config.templates instanceof Document||typeof config.templates==="string"){this.addTemplates(config.templates);} else{for(const name in config.templates){this.addTemplate(name,config.templates[name]);}}} this.getRawTemplate=config.getTemplate;this.customDirectives=config.customDirectives||{};this.runtimeUtils={...helpers,__globals__:config.globalValues||{}};this.hasGlobalValues=Boolean(config.globalValues&&Object.keys(config.globalValues).length);} static registerTemplate(name,fn){globalTemplates[name]=fn;} addTemplate(name,template){if(name in this.rawTemplates){if(!this.dev){return;} const rawTemplate=this.rawTemplates[name];const currentAsString=typeof rawTemplate==="string"?rawTemplate:rawTemplate instanceof Element?rawTemplate.outerHTML:rawTemplate.toString();const newAsString=typeof template==="string"?template:template.outerHTML;if(currentAsString===newAsString){return;} throw new OwlError(`Template ${name} already defined with different content`);} this.rawTemplates[name]=template;} addTemplates(xml){if(!xml){return;} xml=xml instanceof Document?xml:parseXML(xml);for(const template of xml.querySelectorAll("[t-name]")){const name=template.getAttribute("t-name");this.addTemplate(name,template);}} getTemplate(name){var _a;if(!(name in this.templates)){const rawTemplate=((_a=this.getRawTemplate)===null||_a===void 0?void 0:_a.call(this,name))||this.rawTemplates[name];if(rawTemplate===undefined){let extraInfo="";try{const componentName=getCurrent().component.constructor.name;extraInfo=` (for component "${componentName}")`;} catch{} throw new OwlError(`Missing template: "${name}"${extraInfo}`);} const isFn=typeof rawTemplate==="function"&&!(rawTemplate instanceof Element);const templateFn=isFn?rawTemplate:this._compileTemplate(name,rawTemplate);const templates=this.templates;this.templates[name]=function(context,parent){return templates[name].call(this,context,parent);};const template=templateFn(this,bdom,this.runtimeUtils);this.templates[name]=template;} return this.templates[name];} _compileTemplate(name,template){throw new OwlError(`Unable to compile a template. Please use owl full build instead`);} callTemplate(owner,subTemplate,ctx,parent,key){const template=this.getTemplate(subTemplate);return toggler(subTemplate,template.call(owner,ctx,parent,key+subTemplate));}} const globalTemplates={};function xml(...args){const name=`__template__${xml.nextId++}`;const value=String.raw(...args);globalTemplates[name]=value;return name;} xml.nextId=1;TemplateSet.registerTemplate("__portal__",portalTemplate);const RESERVED_WORDS="true,false,NaN,null,undefined,debugger,console,window,in,instanceof,new,function,return,eval,void,Math,RegExp,Array,Object,Date,__globals__".split(",");const WORD_REPLACEMENT=Object.assign(Object.create(null),{and:"&&",or:"||",gt:">",gte:">=",lt:"<",lte:"<=",});const STATIC_TOKEN_MAP=Object.assign(Object.create(null),{"{":"LEFT_BRACE","}":"RIGHT_BRACE","[":"LEFT_BRACKET","]":"RIGHT_BRACKET",":":"COLON",",":"COMMA","(":"LEFT_PAREN",")":"RIGHT_PAREN",});const OPERATORS="...,.,===,==,+,!==,!=,!,||,&&,>=,>,<=,<,?,-,*,/,%,typeof ,=>,=,;,in ,new ,|,&,^,~".split(",");let tokenizeString=function(expr){let s=expr[0];let start=s;if(s!=="'"&&s!=='"'&&s!=="`"){return false;} let i=1;let cur;while(expr[i]&&expr[i]!==start){cur=expr[i];s+=cur;if(cur==="\\"){i++;cur=expr[i];if(!cur){throw new OwlError("Invalid expression");} s+=cur;} i++;} if(expr[i]!==start){throw new OwlError("Invalid expression");} s+=start;if(start==="`"){return{type:"TEMPLATE_STRING",value:s,replace(replacer){return s.replace(/\$\{(.*?)\}/g,(match,group)=>{return"${"+replacer(group)+"}";});},};} return{type:"VALUE",value:s};};let tokenizeNumber=function(expr){let s=expr[0];if(s&&s.match(/[0-9]/)){let i=1;while(expr[i]&&expr[i].match(/[0-9]|\./)){s+=expr[i];i++;} return{type:"VALUE",value:s};} else{return false;}};let tokenizeSymbol=function(expr){let s=expr[0];if(s&&s.match(/[a-zA-Z_\$]/)){let i=1;while(expr[i]&&expr[i].match(/\w/)){s+=expr[i];i++;} if(s in WORD_REPLACEMENT){return{type:"OPERATOR",value:WORD_REPLACEMENT[s],size:s.length};} return{type:"SYMBOL",value:s};} else{return false;}};const tokenizeStatic=function(expr){const char=expr[0];if(char&&char in STATIC_TOKEN_MAP){return{type:STATIC_TOKEN_MAP[char],value:char};} return false;};const tokenizeOperator=function(expr){for(let op of OPERATORS){if(expr.startsWith(op)){return{type:"OPERATOR",value:op};}} return false;};const TOKENIZERS=[tokenizeString,tokenizeNumber,tokenizeOperator,tokenizeSymbol,tokenizeStatic,];function tokenize(expr){const result=[];let token=true;let error;let current=expr;try{while(token){current=current.trim();if(current){for(let tokenizer of TOKENIZERS){token=tokenizer(current);if(token){result.push(token);current=current.slice(token.size||token.value.length);break;}}} else{token=false;}}} catch(e){error=e;} if(current.length||error){throw new OwlError(`Tokenizer error: could not tokenize \`${expr}\``);} return result;} const isLeftSeparator=(token)=>token&&(token.type==="LEFT_BRACE"||token.type==="COMMA");const isRightSeparator=(token)=>token&&(token.type==="RIGHT_BRACE"||token.type==="COMMA");function compileExprToArray(expr){const localVars=new Set();const tokens=tokenize(expr);let i=0;let stack=[];while(icompileExpr(expr));} if(nextToken&&nextToken.type==="OPERATOR"&&nextToken.value==="=>"){if(token.type==="RIGHT_PAREN"){let j=i-1;while(j>0&&tokens[j].type!=="LEFT_PAREN"){if(tokens[j].type==="SYMBOL"&&tokens[j].originalValue){tokens[j].value=tokens[j].originalValue;localVars.add(tokens[j].value);} j--;}} else{localVars.add(token.value);}} if(isVar){token.varName=token.value;if(!localVars.has(token.value)){token.originalValue=token.value;token.value=`ctx['${token.value}']`;}} i++;} for(const token of tokens){if(token.type==="SYMBOL"&&token.varName&&localVars.has(token.value)){token.originalValue=token.value;token.value=`_${token.value}`;token.isLocal=true;}} return tokens;} const paddedValues=new Map([["in "," in "]]);function compileExpr(expr){return compileExprToArray(expr).map((t)=>paddedValues.get(t.value)||t.value).join("");} const INTERP_REGEXP=/\{\{.*?\}\}|\#\{.*?\}/g;function replaceDynamicParts(s,replacer){let matches=s.match(INTERP_REGEXP);if(matches&&matches[0].length===s.length){return`(${replacer(s.slice(2, matches[0][0] === "{" ? -2 : -1))})`;} let r=s.replace(INTERP_REGEXP,(s)=>"${"+replacer(s.slice(2,s[0]==="{"?-2:-1))+"}");return"`"+r+"`";} function interpolate(s){return replaceDynamicParts(s,compileExpr);} const whitespaceRE=/\s+/g;const xmlDoc=document.implementation.createDocument(null,null,null);const MODS=new Set(["stop","capture","prevent","self","synthetic"]);let nextDataIds={};function generateId(prefix=""){nextDataIds[prefix]=(nextDataIds[prefix]||0)+1;return prefix+nextDataIds[prefix];} function isProp(tag,key){switch(tag){case"input":return(key==="checked"||key==="indeterminate"||key==="value"||key==="readonly"||key==="readOnly"||key==="disabled");case"option":return key==="selected"||key==="disabled";case"textarea":return key==="value"||key==="readonly"||key==="readOnly"||key==="disabled";case"select":return key==="value"||key==="disabled";case"button":case"optgroup":return key==="disabled";} return false;} function toStringExpression(str){return`\`${str.replace(/\\/g, "\\\\").replace(/`/g,"\\`").replace(/\$\{/,"\\${")}\``;} class BlockDescription{constructor(target,type){this.dynamicTagName=null;this.isRoot=false;this.hasDynamicChildren=false;this.children=[];this.data=[];this.childNumber=0;this.parentVar="";this.id=BlockDescription.nextBlockId++;this.varName="b"+this.id;this.blockName="block"+this.id;this.target=target;this.type=type;} insertData(str,prefix="d"){const id=generateId(prefix);this.target.addLine(`let ${id} = ${str};`);return this.data.push(id)-1;} insert(dom){if(this.currentDom){this.currentDom.appendChild(dom);} else{this.dom=dom;}} generateExpr(expr){if(this.type==="block"){const hasChildren=this.children.length;let params=this.data.length?`[${this.data.join(", ")}]`:hasChildren?"[]":"";if(hasChildren){params+=", ["+this.children.map((c)=>c.varName).join(", ")+"]";} if(this.dynamicTagName){return`toggler(${this.dynamicTagName}, ${this.blockName}(${this.dynamicTagName})(${params}))`;} return`${this.blockName}(${params})`;} else if(this.type==="list"){return`list(c_block${this.id})`;} return expr;} asXmlString(){const t=xmlDoc.createElement("t");t.appendChild(this.dom);return t.innerHTML;}} BlockDescription.nextBlockId=1;function createContext(parentCtx,params){return Object.assign({block:null,index:0,forceNewBlock:true,translate:parentCtx.translate,translationCtx:parentCtx.translationCtx,tKeyExpr:null,nameSpace:parentCtx.nameSpace,tModelSelectedExpr:parentCtx.tModelSelectedExpr,},params);} class CodeTarget{constructor(name,on){this.indentLevel=0;this.loopLevel=0;this.code=[];this.hasRoot=false;this.hasCache=false;this.shouldProtectScope=false;this.hasRefWrapper=false;this.name=name;this.on=on||null;} addLine(line,idx){const prefix=new Array(this.indentLevel+2).join(" ");if(idx===undefined){this.code.push(prefix+line);} else{this.code.splice(idx,0,prefix+line);}} generateCode(){let result=[];result.push(`function ${this.name}(ctx, node, key = "") {`);if(this.shouldProtectScope){result.push(` ctx = Object.create(ctx);`);result.push(` ctx[isBoundary] = 1`);} if(this.hasRefWrapper){result.push(` let refWrapper = makeRefWrapper(this.__owl__);`);} if(this.hasCache){result.push(` let cache = ctx.cache || {};`);result.push(` let nextCache = ctx.cache = {};`);} for(let line of this.code){result.push(line);} if(!this.hasRoot){result.push(`return text('');`);} result.push(`}`);return result.join("\n ");} currentKey(ctx){let key=this.loopLevel?`key${this.loopLevel}`:"key";if(ctx.tKeyExpr){key=`${ctx.tKeyExpr} + ${key}`;} return key;}} const TRANSLATABLE_ATTRS=["label","title","placeholder","alt"];const translationRE=/^(\s*)([\s\S]+?)(\s*)$/;class CodeGenerator{constructor(ast,options){this.blocks=[];this.nextBlockId=1;this.isDebug=false;this.targets=[];this.target=new CodeTarget("template");this.translatableAttributes=TRANSLATABLE_ATTRS;this.staticDefs=[];this.slotNames=new Set();this.helpers=new Set();this.translateFn=options.translateFn||((s)=>s);if(options.translatableAttributes){const attrs=new Set(TRANSLATABLE_ATTRS);for(let attr of options.translatableAttributes){if(attr.startsWith("-")){attrs.delete(attr.slice(1));} else{attrs.add(attr);}} this.translatableAttributes=[...attrs];} this.hasSafeContext=options.hasSafeContext||false;this.dev=options.dev||false;this.ast=ast;this.templateName=options.name;if(options.hasGlobalValues){this.helpers.add("__globals__");}} generateCode(){const ast=this.ast;this.isDebug=ast.type===12;BlockDescription.nextBlockId=1;nextDataIds={};this.compileAST(ast,{block:null,index:0,forceNewBlock:false,isLast:true,translate:true,translationCtx:"",tKeyExpr:null,});let mainCode=[` let { text, createBlock, list, multi, html, toggler, comment } = bdom;`];if(this.helpers.size){mainCode.push(`let { ${[...this.helpers].join(", ")} } = helpers;`);} if(this.templateName){mainCode.push(`// Template name: "${this.templateName}"`);} for(let{id,expr}of this.staticDefs){mainCode.push(`const ${id} = ${expr};`);} if(this.blocks.length){mainCode.push(``);for(let block of this.blocks){if(block.dom){let xmlString=toStringExpression(block.asXmlString());if(block.dynamicTagName){xmlString=xmlString.replace(/^`<\w+/,`\`<\${tag || '${block.dom.nodeName}'}`);xmlString=xmlString.replace(/\w+>`$/,`\${tag || '${block.dom.nodeName}'}>\``);mainCode.push(`let ${block.blockName} = tag => createBlock(${xmlString});`);} else{mainCode.push(`let ${block.blockName} = createBlock(${xmlString});`);}}}} if(this.targets.length){for(let fn of this.targets){mainCode.push("");mainCode=mainCode.concat(fn.generateCode());}} mainCode.push("");mainCode=mainCode.concat("return "+this.target.generateCode());const code=mainCode.join("\n ");if(this.isDebug){const msg=`[Owl Debug]\n${code}`;console.log(msg);} return code;} compileInNewTarget(prefix,ast,ctx,on){const name=generateId(prefix);const initialTarget=this.target;const target=new CodeTarget(name,on);this.targets.push(target);this.target=target;this.compileAST(ast,createContext(ctx));this.target=initialTarget;return name;} addLine(line,idx){this.target.addLine(line,idx);} define(varName,expr){this.addLine(`const ${varName} = ${expr};`);} insertAnchor(block,index=block.children.length){const tag=`block-child-${index}`;const anchor=xmlDoc.createElement(tag);block.insert(anchor);} createBlock(parentBlock,type,ctx){const hasRoot=this.target.hasRoot;const block=new BlockDescription(this.target,type);if(!hasRoot){this.target.hasRoot=true;block.isRoot=true;} if(parentBlock){parentBlock.children.push(block);if(parentBlock.type==="list"){block.parentVar=`c_block${parentBlock.id}`;}} return block;} insertBlock(expression,block,ctx){let blockExpr=block.generateExpr(expression);if(block.parentVar){let key=this.target.currentKey(ctx);this.helpers.add("withKey");this.addLine(`${block.parentVar}[${ctx.index}] = withKey(${blockExpr}, ${key});`);return;} if(ctx.tKeyExpr){blockExpr=`toggler(${ctx.tKeyExpr}, ${blockExpr})`;} if(block.isRoot){if(this.target.on){blockExpr=this.wrapWithEventCatcher(blockExpr,this.target.on);} this.addLine(`return ${blockExpr};`);} else{this.define(block.varName,blockExpr);}} captureExpression(expr,forceCapture=false){if(!forceCapture&&!expr.includes("=>")){return compileExpr(expr);} const tokens=compileExprToArray(expr);const mapping=new Map();return tokens.map((tok)=>{if(tok.varName&&!tok.isLocal){if(!mapping.has(tok.varName)){const varId=generateId("v");mapping.set(tok.varName,varId);this.define(varId,tok.value);} tok.value=mapping.get(tok.varName);} return tok.value;}).join("");} translate(str,translationCtx){const match=translationRE.exec(str);return match[1]+this.translateFn(match[2],translationCtx)+match[3];} compileAST(ast,ctx){switch(ast.type){case 1:return this.compileComment(ast,ctx);case 0:return this.compileText(ast,ctx);case 2:return this.compileTDomNode(ast,ctx);case 4:return this.compileTEsc(ast,ctx);case 8:return this.compileTOut(ast,ctx);case 5:return this.compileTIf(ast,ctx);case 9:return this.compileTForeach(ast,ctx);case 10:return this.compileTKey(ast,ctx);case 3:return this.compileMulti(ast,ctx);case 7:return this.compileTCall(ast,ctx);case 15:return this.compileTCallBlock(ast,ctx);case 6:return this.compileTSet(ast,ctx);case 11:return this.compileComponent(ast,ctx);case 12:return this.compileDebug(ast,ctx);case 13:return this.compileLog(ast,ctx);case 14:return this.compileTSlot(ast,ctx);case 16:return this.compileTTranslation(ast,ctx);case 17:return this.compileTTranslationContext(ast,ctx);case 18:return this.compileTPortal(ast,ctx);}} compileDebug(ast,ctx){this.addLine(`debugger;`);if(ast.content){return this.compileAST(ast.content,ctx);} return null;} compileLog(ast,ctx){this.addLine(`console.log(${compileExpr(ast.expr)});`);if(ast.content){return this.compileAST(ast.content,ctx);} return null;} compileComment(ast,ctx){let{block,forceNewBlock}=ctx;const isNewBlock=!block||forceNewBlock;if(isNewBlock){block=this.createBlock(block,"comment",ctx);this.insertBlock(`comment(${toStringExpression(ast.value)})`,block,{...ctx,forceNewBlock:forceNewBlock&&!block,});} else{const text=xmlDoc.createComment(ast.value);block.insert(text);} return block.varName;} compileText(ast,ctx){let{block,forceNewBlock}=ctx;let value=ast.value;if(value&&ctx.translate!==false){value=this.translate(value,ctx.translationCtx);} if(!ctx.inPreTag){value=value.replace(whitespaceRE," ");} if(!block||forceNewBlock){block=this.createBlock(block,"text",ctx);this.insertBlock(`text(${toStringExpression(value)})`,block,{...ctx,forceNewBlock:forceNewBlock&&!block,});} else{const createFn=ast.type===0?xmlDoc.createTextNode:xmlDoc.createComment;block.insert(createFn.call(xmlDoc,value));} return block.varName;} generateHandlerCode(rawEvent,handler){const modifiers=rawEvent.split(".").slice(1).map((m)=>{if(!MODS.has(m)){throw new OwlError(`Unknown event modifier: '${m}'`);} return`"${m}"`;});let modifiersCode="";if(modifiers.length){modifiersCode=`${modifiers.join(",")}, `;} return`[${modifiersCode}${this.captureExpression(handler)}, ctx]`;} compileTDomNode(ast,ctx){var _a;let{block,forceNewBlock}=ctx;const isNewBlock=!block||forceNewBlock||ast.dynamicTag!==null||ast.ns;let codeIdx=this.target.code.length;if(isNewBlock){if((ast.dynamicTag||ctx.tKeyExpr||ast.ns)&&ctx.block){this.insertAnchor(ctx.block);} block=this.createBlock(block,"block",ctx);this.blocks.push(block);if(ast.dynamicTag){const tagExpr=generateId("tag");this.define(tagExpr,compileExpr(ast.dynamicTag));block.dynamicTagName=tagExpr;}} const attrs={};for(let key in ast.attrs){let expr,attrName;if(key.startsWith("t-attf")){expr=interpolate(ast.attrs[key]);const idx=block.insertData(expr,"attr");attrName=key.slice(7);attrs["block-attribute-"+idx]=attrName;} else if(key.startsWith("t-att")){attrName=key==="t-att"?null:key.slice(6);expr=compileExpr(ast.attrs[key]);if(attrName&&isProp(ast.tag,attrName)){if(attrName==="readonly"){attrName="readOnly";} if(attrName==="value"){expr=`new String((${expr}) === 0 ? 0 : ((${expr}) || ""))`;} else{expr=`new Boolean(${expr})`;} const idx=block.insertData(expr,"prop");attrs[`block-property-${idx}`]=attrName;} else{const idx=block.insertData(expr,"attr");if(key==="t-att"){attrs[`block-attributes`]=String(idx);} else{attrs[`block-attribute-${idx}`]=attrName;}}} else if(this.translatableAttributes.includes(key)){const attrTranslationCtx=((_a=ast.attrsTranslationCtx)===null||_a===void 0?void 0:_a[key])||ctx.translationCtx;attrs[key]=this.translateFn(ast.attrs[key],attrTranslationCtx);} else{expr=`"${ast.attrs[key]}"`;attrName=key;attrs[key]=ast.attrs[key];} if(attrName==="value"&&ctx.tModelSelectedExpr){let selectedId=block.insertData(`${ctx.tModelSelectedExpr} === ${expr}`,"attr");attrs[`block-attribute-${selectedId}`]="selected";}} let tModelSelectedExpr;if(ast.model){const{hasDynamicChildren,baseExpr,expr,eventType,shouldNumberize,shouldTrim,targetAttr,specialInitTargetAttr,}=ast.model;const baseExpression=compileExpr(baseExpr);const bExprId=generateId("bExpr");this.define(bExprId,baseExpression);const expression=compileExpr(expr);const exprId=generateId("expr");this.define(exprId,expression);const fullExpression=`${bExprId}[${exprId}]`;let idx;if(specialInitTargetAttr){let targetExpr=targetAttr in attrs&&`'${attrs[targetAttr]}'`;if(!targetExpr&&ast.attrs){const dynamicTgExpr=ast.attrs[`t-att-${targetAttr}`];if(dynamicTgExpr){targetExpr=compileExpr(dynamicTgExpr);}} idx=block.insertData(`${fullExpression} === ${targetExpr}`,"prop");attrs[`block-property-${idx}`]=specialInitTargetAttr;} else if(hasDynamicChildren){const bValueId=generateId("bValue");tModelSelectedExpr=`${bValueId}`;this.define(tModelSelectedExpr,fullExpression);} else{idx=block.insertData(`${fullExpression}`,"prop");attrs[`block-property-${idx}`]=targetAttr;} this.helpers.add("toNumber");let valueCode=`ev.target.${targetAttr}`;valueCode=shouldTrim?`${valueCode}.trim()`:valueCode;valueCode=shouldNumberize?`toNumber(${valueCode})`:valueCode;const handler=`[(ev) => { ${fullExpression} = ${valueCode}; }]`;idx=block.insertData(handler,"hdlr");attrs[`block-handler-${idx}`]=eventType;} for(let ev in ast.on){const name=this.generateHandlerCode(ev,ast.on[ev]);const idx=block.insertData(name,"hdlr");attrs[`block-handler-${idx}`]=ev;} if(ast.ref){if(this.dev){this.helpers.add("makeRefWrapper");this.target.hasRefWrapper=true;} const isDynamic=INTERP_REGEXP.test(ast.ref);let name=`\`${ast.ref}\``;if(isDynamic){name=replaceDynamicParts(ast.ref,(expr)=>this.captureExpression(expr,true));} let setRefStr=`(el) => this.__owl__.setRef((${name}), el)`;if(this.dev){setRefStr=`refWrapper(${name}, ${setRefStr})`;} const idx=block.insertData(setRefStr,"ref");attrs["block-ref"]=String(idx);} const nameSpace=ast.ns||ctx.nameSpace;const dom=nameSpace?xmlDoc.createElementNS(nameSpace,ast.tag):xmlDoc.createElement(ast.tag);for(const[attr,val]of Object.entries(attrs)){if(!(attr==="class"&&val==="")){dom.setAttribute(attr,val);}} block.insert(dom);if(ast.content.length){const initialDom=block.currentDom;block.currentDom=dom;const children=ast.content;for(let i=0;i c.varName).join(", ")};`,codeIdx);}} return block.varName;} compileTEsc(ast,ctx){let{block,forceNewBlock}=ctx;let expr;if(ast.expr==="0"){this.helpers.add("zero");expr=`ctx[zero]`;} else{expr=compileExpr(ast.expr);if(ast.defaultValue){this.helpers.add("withDefault");expr=`withDefault(${expr}, ${toStringExpression(ast.defaultValue)})`;}} if(!block||forceNewBlock){block=this.createBlock(block,"text",ctx);this.insertBlock(`text(${expr})`,block,{...ctx,forceNewBlock:forceNewBlock&&!block});} else{const idx=block.insertData(expr,"txt");const text=xmlDoc.createElement(`block-text-${idx}`);block.insert(text);} return block.varName;} compileTOut(ast,ctx){let{block}=ctx;if(block){this.insertAnchor(block);} block=this.createBlock(block,"html",ctx);let blockStr;if(ast.expr==="0"){this.helpers.add("zero");blockStr=`ctx[zero]`;} else if(ast.body){let bodyValue=null;bodyValue=BlockDescription.nextBlockId;const subCtx=createContext(ctx);this.compileAST({type:3,content:ast.body},subCtx);this.helpers.add("safeOutput");blockStr=`safeOutput(${compileExpr(ast.expr)}, b${bodyValue})`;} else{this.helpers.add("safeOutput");blockStr=`safeOutput(${compileExpr(ast.expr)})`;} this.insertBlock(blockStr,block,ctx);return block.varName;} compileTIfBranch(content,block,ctx){this.target.indentLevel++;let childN=block.children.length;this.compileAST(content,createContext(ctx,{block,index:ctx.index}));if(block.children.length>childN){this.insertAnchor(block,childN);} this.target.indentLevel--;} compileTIf(ast,ctx,nextNode){let{block,forceNewBlock}=ctx;const codeIdx=this.target.code.length;const isNewBlock=!block||(block.type!=="multi"&&forceNewBlock);if(block){block.hasDynamicChildren=true;} if(!block||(block.type!=="multi"&&forceNewBlock)){block=this.createBlock(block,"multi",ctx);} this.addLine(`if (${compileExpr(ast.condition)}) {`);this.compileTIfBranch(ast.content,block,ctx);if(ast.tElif){for(let clause of ast.tElif){this.addLine(`} else if (${compileExpr(clause.condition)}) {`);this.compileTIfBranch(clause.content,block,ctx);}} if(ast.tElse){this.addLine(`} else {`);this.compileTIfBranch(ast.tElse,block,ctx);} this.addLine("}");if(isNewBlock){if(block.children.length){const code=this.target.code;const children=block.children.slice();let current=children.shift();for(let i=codeIdx;i c.varName).join(", ")};`,codeIdx);} const args=block.children.map((c)=>c.varName).join(", ");this.insertBlock(`multi([${args}])`,block,ctx);} return block.varName;} compileTForeach(ast,ctx){let{block}=ctx;if(block){this.insertAnchor(block);} block=this.createBlock(block,"list",ctx);this.target.loopLevel++;const loopVar=`i${this.target.loopLevel}`;this.addLine(`ctx = Object.create(ctx);`);const vals=`v_block${block.id}`;const keys=`k_block${block.id}`;const l=`l_block${block.id}`;const c=`c_block${block.id}`;this.helpers.add("prepareList");this.define(`[${keys}, ${vals}, ${l}, ${c}]`,`prepareList(${compileExpr(ast.collection)});`);if(this.dev){this.define(`keys${block.id}`,`new Set()`);} this.addLine(`for (let ${loopVar} = 0; ${loopVar} < ${l}; ${loopVar}++) {`);this.target.indentLevel++;this.addLine(`ctx[\`${ast.elem}\`] = ${keys}[${loopVar}];`);if(!ast.hasNoFirst){this.addLine(`ctx[\`${ast.elem}_first\`] = ${loopVar} === 0;`);} if(!ast.hasNoLast){this.addLine(`ctx[\`${ast.elem}_last\`] = ${loopVar} === ${keys}.length - 1;`);} if(!ast.hasNoIndex){this.addLine(`ctx[\`${ast.elem}_index\`] = ${loopVar};`);} if(!ast.hasNoValue){this.addLine(`ctx[\`${ast.elem}_value\`] = ${vals}[${loopVar}];`);} this.define(`key${this.target.loopLevel}`,ast.key?compileExpr(ast.key):loopVar);if(this.dev){this.helpers.add("OwlError");this.addLine(`if (keys${block.id}.has(String(key${this.target.loopLevel}))) { throw new OwlError(\`Got duplicate key in t-foreach: \${key${this.target.loopLevel}}\`)}`);this.addLine(`keys${block.id}.add(String(key${this.target.loopLevel}));`);} let id;if(ast.memo){this.target.hasCache=true;id=generateId();this.define(`memo${id}`,compileExpr(ast.memo));this.define(`vnode${id}`,`cache[key${this.target.loopLevel}];`);this.addLine(`if (vnode${id}) {`);this.target.indentLevel++;this.addLine(`if (shallowEqual(vnode${id}.memo, memo${id})) {`);this.target.indentLevel++;this.addLine(`${c}[${loopVar}] = vnode${id};`);this.addLine(`nextCache[key${this.target.loopLevel}] = vnode${id};`);this.addLine(`continue;`);this.target.indentLevel--;this.addLine("}");this.target.indentLevel--;this.addLine("}");} const subCtx=createContext(ctx,{block,index:loopVar});this.compileAST(ast.body,subCtx);if(ast.memo){this.addLine(`nextCache[key${this.target.loopLevel}] = Object.assign(${c}[${loopVar}], {memo: memo${id}});`);} this.target.indentLevel--;this.target.loopLevel--;this.addLine(`}`);if(!ctx.isLast){this.addLine(`ctx = ctx.__proto__;`);} this.insertBlock("l",block,ctx);return block.varName;} compileTKey(ast,ctx){const tKeyExpr=generateId("tKey_");this.define(tKeyExpr,compileExpr(ast.expr));ctx=createContext(ctx,{tKeyExpr,block:ctx.block,index:ctx.index,});return this.compileAST(ast.content,ctx);} compileMulti(ast,ctx){let{block,forceNewBlock}=ctx;const isNewBlock=!block||forceNewBlock;let codeIdx=this.target.code.length;if(isNewBlock){const n=ast.content.filter((c)=>c.type!==6).length;let result=null;if(n<=1){for(let child of ast.content){const blockName=this.compileAST(child,ctx);result=result||blockName;} return result;} block=this.createBlock(block,"multi",ctx);} let index=0;for(let i=0,l=ast.content.length;i c.varName).join(", ")};`,codeIdx);} const args=block.children.map((c)=>c.varName).join(", ");this.insertBlock(`multi([${args}])`,block,ctx);} return block.varName;} compileTCall(ast,ctx){let{block,forceNewBlock}=ctx;let ctxVar=ctx.ctxVar||"ctx";if(ast.context){ctxVar=generateId("ctx");this.addLine(`let ${ctxVar} = ${compileExpr(ast.context)};`);} const isDynamic=INTERP_REGEXP.test(ast.name);const subTemplate=isDynamic?interpolate(ast.name):"`"+ast.name+"`";if(block&&!forceNewBlock){this.insertAnchor(block);} block=this.createBlock(block,"multi",ctx);if(ast.body){this.addLine(`${ctxVar} = Object.create(${ctxVar});`);this.addLine(`${ctxVar}[isBoundary] = 1;`);this.helpers.add("isBoundary");const subCtx=createContext(ctx,{ctxVar});const bl=this.compileMulti({type:3,content:ast.body},subCtx);if(bl){this.helpers.add("zero");this.addLine(`${ctxVar}[zero] = ${bl};`);}} const key=this.generateComponentKey();if(isDynamic){const templateVar=generateId("template");if(!this.staticDefs.find((d)=>d.id==="call")){this.staticDefs.push({id:"call",expr:`app.callTemplate.bind(app)`});} this.define(templateVar,subTemplate);this.insertBlock(`call(this, ${templateVar}, ${ctxVar}, node, ${key})`,block,{...ctx,forceNewBlock:!block,});} else{const id=generateId(`callTemplate_`);this.staticDefs.push({id,expr:`app.getTemplate(${subTemplate})`});this.insertBlock(`${id}.call(this, ${ctxVar}, node, ${key})`,block,{...ctx,forceNewBlock:!block,});} if(ast.body&&!ctx.isLast){this.addLine(`${ctxVar} = ${ctxVar}.__proto__;`);} return block.varName;} compileTCallBlock(ast,ctx){let{block,forceNewBlock}=ctx;if(block){if(!forceNewBlock){this.insertAnchor(block);}} block=this.createBlock(block,"multi",ctx);this.insertBlock(compileExpr(ast.name),block,{...ctx,forceNewBlock:!block});return block.varName;} compileTSet(ast,ctx){this.target.shouldProtectScope=true;this.helpers.add("isBoundary").add("withDefault");const expr=ast.value?compileExpr(ast.value||""):"null";if(ast.body){this.helpers.add("LazyValue");const bodyAst={type:3,content:ast.body};const name=this.compileInNewTarget("value",bodyAst,ctx);let key=this.target.currentKey(ctx);let value=`new LazyValue(${name}, ctx, this, node, ${key})`;value=ast.value?(value?`withDefault(${expr}, ${value})`:expr):value;this.addLine(`ctx[\`${ast.name}\`] = ${value};`);} else{let value;if(ast.defaultValue){const defaultValue=toStringExpression(ctx.translate?this.translate(ast.defaultValue,ctx.translationCtx):ast.defaultValue);if(ast.value){value=`withDefault(${expr}, ${defaultValue})`;} else{value=defaultValue;}} else{value=expr;} this.helpers.add("setContextValue");this.addLine(`setContextValue(${ctx.ctxVar || "ctx"}, "${ast.name}", ${value});`);} return null;} generateComponentKey(currentKey="key"){const parts=[generateId("__")];for(let i=0;ithis.formatProp(k,v,attrsTranslationCtx,translationCtx));} getPropString(props,dynProps){let propString=`{${props.join(",")}}`;if(dynProps){propString=`Object.assign({}, ${compileExpr(dynProps)}${props.length ? ", " + propString : ""})`;} return propString;} compileComponent(ast,ctx){let{block}=ctx;const hasSlotsProp="slots"in(ast.props||{});const props=ast.props?this.formatPropObject(ast.props,ast.propsTranslationCtx,ctx.translationCtx):[];let slotDef="";if(ast.slots){let ctxStr="ctx";if(this.target.loopLevel||!this.hasSafeContext){ctxStr=generateId("ctx");this.helpers.add("capture");this.define(ctxStr,`capture(ctx)`);} let slotStr=[];for(let slotName in ast.slots){const slotAst=ast.slots[slotName];const params=[];if(slotAst.content){const name=this.compileInNewTarget("slot",slotAst.content,ctx,slotAst.on);params.push(`__render: ${name}.bind(this), __ctx: ${ctxStr}`);} const scope=ast.slots[slotName].scope;if(scope){params.push(`__scope: "${scope}"`);} if(ast.slots[slotName].attrs){params.push(...this.formatPropObject(ast.slots[slotName].attrs,ast.slots[slotName].attrsTranslationCtx,ctx.translationCtx));} const slotInfo=`{${params.join(", ")}}`;slotStr.push(`'${slotName}': ${slotInfo}`);} slotDef=`{${slotStr.join(", ")}}`;} if(slotDef&&!(ast.dynamicProps||hasSlotsProp)){this.helpers.add("markRaw");props.push(`slots: markRaw(${slotDef})`);} let propString=this.getPropString(props,ast.dynamicProps);let propVar;if((slotDef&&(ast.dynamicProps||hasSlotsProp))||this.dev){propVar=generateId("props");this.define(propVar,propString);propString=propVar;} if(slotDef&&(ast.dynamicProps||hasSlotsProp)){this.helpers.add("markRaw");this.addLine(`${propVar}.slots = markRaw(Object.assign(${slotDef}, ${propVar}.slots))`);} let expr;if(ast.isDynamic){expr=generateId("Comp");this.define(expr,compileExpr(ast.name));} else{expr=`\`${ast.name}\``;} if(this.dev){this.addLine(`helpers.validateProps(${expr}, ${propVar}, this);`);} if(block&&(ctx.forceNewBlock===false||ctx.tKeyExpr)){this.insertAnchor(block);} let keyArg=this.generateComponentKey();if(ctx.tKeyExpr){keyArg=`${ctx.tKeyExpr} + ${keyArg}`;} let id=generateId("comp");const propList=[];for(let p in ast.props||{}){let[name,suffix]=p.split(".");if(!suffix){propList.push(`"${name}"`);}} this.staticDefs.push({id,expr:`app.createComponent(${ast.isDynamic ? null : expr}, ${!ast.isDynamic}, ${!!ast.slots}, ${!!ast.dynamicProps}, [${propList}])`,});if(ast.isDynamic){keyArg=`(${expr}).name + ${keyArg}`;} let blockExpr=`${id}(${propString}, ${keyArg}, node, this, ${ast.isDynamic ? expr : null})`;if(ast.isDynamic){blockExpr=`toggler(${expr}, ${blockExpr})`;} if(ast.on){blockExpr=this.wrapWithEventCatcher(blockExpr,ast.on);} block=this.createBlock(block,"multi",ctx);this.insertBlock(blockExpr,block,ctx);return block.varName;} wrapWithEventCatcher(expr,on){this.helpers.add("createCatcher");let name=generateId("catcher");let spec={};let handlers=[];for(let ev in on){let handlerId=generateId("hdlr");let idx=handlers.push(handlerId)-1;spec[ev]=idx;const handler=this.generateHandlerCode(ev,on[ev]);this.define(handlerId,handler);} this.staticDefs.push({id:name,expr:`createCatcher(${JSON.stringify(spec)})`});return`${name}(${expr}, [${handlers.join(",")}])`;} compileTSlot(ast,ctx){this.helpers.add("callSlot");let{block}=ctx;let blockString;let slotName;let dynamic=false;let isMultiple=false;if(ast.name.match(INTERP_REGEXP)){dynamic=true;isMultiple=true;slotName=interpolate(ast.name);} else{slotName="'"+ast.name+"'";isMultiple=isMultiple||this.slotNames.has(ast.name);this.slotNames.add(ast.name);} const attrs={...ast.attrs};const dynProps=attrs["t-props"];delete attrs["t-props"];let key=this.target.loopLevel?`key${this.target.loopLevel}`:"key";if(isMultiple){key=this.generateComponentKey(key);} const props=ast.attrs?this.formatPropObject(attrs,ast.attrsTranslationCtx,ctx.translationCtx):[];const scope=this.getPropString(props,dynProps);if(ast.defaultContent){const name=this.compileInNewTarget("defaultContent",ast.defaultContent,ctx);blockString=`callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope}, ${name}.bind(this))`;} else{if(dynamic){let name=generateId("slot");this.define(name,slotName);blockString=`toggler(${name}, callSlot(ctx, node, ${key}, ${name}, ${dynamic}, ${scope}))`;} else{blockString=`callSlot(ctx, node, ${key}, ${slotName}, ${dynamic}, ${scope})`;}} if(ast.on){blockString=this.wrapWithEventCatcher(blockString,ast.on);} if(block){this.insertAnchor(block);} block=this.createBlock(block,"multi",ctx);this.insertBlock(blockString,block,{...ctx,forceNewBlock:false});return block.varName;} compileTTranslation(ast,ctx){if(ast.content){return this.compileAST(ast.content,Object.assign({},ctx,{translate:false}));} return null;} compileTTranslationContext(ast,ctx){if(ast.content){return this.compileAST(ast.content,Object.assign({},ctx,{translationCtx:ast.translationCtx}));} return null;} compileTPortal(ast,ctx){if(!this.staticDefs.find((d)=>d.id==="Portal")){this.staticDefs.push({id:"Portal",expr:`app.Portal`});} let{block}=ctx;const name=this.compileInNewTarget("slot",ast.content,ctx);let ctxStr="ctx";if(this.target.loopLevel||!this.hasSafeContext){ctxStr=generateId("ctx");this.helpers.add("capture");this.define(ctxStr,`capture(ctx)`);} let id=generateId("comp");this.staticDefs.push({id,expr:`app.createComponent(null, false, true, false, false)`,});const target=compileExpr(ast.target);const key=this.generateComponentKey();const blockString=`${id}({target: ${target},slots: {'default': {__render: ${name}.bind(this), __ctx: ${ctxStr}}}}, ${key}, node, ctx, Portal)`;if(block){this.insertAnchor(block);} block=this.createBlock(block,"multi",ctx);this.insertBlock(blockString,block,{...ctx,forceNewBlock:false});return block.varName;}} const cache=new WeakMap();function parse(xml,customDir){const ctx={inPreTag:false,customDirectives:customDir,};if(typeof xml==="string"){const elem=parseXML(`${xml}`).firstChild;return _parse(elem,ctx);} let ast=cache.get(xml);if(!ast){ast=_parse(xml.cloneNode(true),ctx);cache.set(xml,ast);} return ast;} function _parse(xml,ctx){normalizeXML(xml);return parseNode(xml,ctx)||{type:0,value:""};} function parseNode(node,ctx){if(!(node instanceof Element)){return parseTextCommentNode(node,ctx);} return(parseTCustom(node,ctx)||parseTDebugLog(node,ctx)||parseTForEach(node,ctx)||parseTIf(node,ctx)||parseTPortal(node,ctx)||parseTCall(node,ctx)||parseTCallBlock(node)||parseTEscNode(node,ctx)||parseTOutNode(node,ctx)||parseTKey(node,ctx)||parseTTranslation(node,ctx)||parseTTranslationContext(node,ctx)||parseTSlot(node,ctx)||parseComponent(node,ctx)||parseDOMNode(node,ctx)||parseTSetNode(node,ctx)||parseTNode(node,ctx));} function parseTNode(node,ctx){if(node.tagName!=="t"){return null;} return parseChildNodes(node,ctx);} const lineBreakRE=/[\r\n]/;function parseTextCommentNode(node,ctx){if(node.nodeType===Node.TEXT_NODE){let value=node.textContent||"";if(!ctx.inPreTag&&lineBreakRE.test(value)&&!value.trim()){return null;} return{type:0,value};} else if(node.nodeType===Node.COMMENT_NODE){return{type:1,value:node.textContent||""};} return null;} function parseTCustom(node,ctx){if(!ctx.customDirectives){return null;} const nodeAttrsNames=node.getAttributeNames();for(let attr of nodeAttrsNames){if(attr==="t-custom"||attr==="t-custom-"){throw new OwlError("Missing custom directive name with t-custom directive");} if(attr.startsWith("t-custom-")){const directiveName=attr.split(".")[0].slice(9);const customDirective=ctx.customDirectives[directiveName];if(!customDirective){throw new OwlError(`Custom directive "${directiveName}" is not defined`);} const value=node.getAttribute(attr);const modifiers=attr.split(".").slice(1);node.removeAttribute(attr);try{customDirective(node,value,modifiers);} catch(error){throw new OwlError(`Custom directive "${directiveName}" throw the following error: ${error}`);} return parseNode(node,ctx);}} return null;} function parseTDebugLog(node,ctx){if(node.hasAttribute("t-debug")){node.removeAttribute("t-debug");return{type:12,content:parseNode(node,ctx),};} if(node.hasAttribute("t-log")){const expr=node.getAttribute("t-log");node.removeAttribute("t-log");return{type:13,expr,content:parseNode(node,ctx),};} return null;} const hasDotAtTheEnd=/\.[\w_]+\s*$/;const hasBracketsAtTheEnd=/\[[^\[]+\]\s*$/;const ROOT_SVG_TAGS=new Set(["svg","g","path"]);function parseDOMNode(node,ctx){const{tagName}=node;const dynamicTag=node.getAttribute("t-tag");node.removeAttribute("t-tag");if(tagName==="t"&&!dynamicTag){return null;} if(tagName.startsWith("block-")){throw new OwlError(`Invalid tag name: '${tagName}'`);} ctx=Object.assign({},ctx);if(tagName==="pre"){ctx.inPreTag=true;} let ns=!ctx.nameSpace&&ROOT_SVG_TAGS.has(tagName)?"http://www.w3.org/2000/svg":null;const ref=node.getAttribute("t-ref");node.removeAttribute("t-ref");const nodeAttrsNames=node.getAttributeNames();let attrs=null;let attrsTranslationCtx=null;let on=null;let model=null;for(let attr of nodeAttrsNames){const value=node.getAttribute(attr);if(attr==="t-on"||attr==="t-on-"){throw new OwlError("Missing event name with t-on directive");} if(attr.startsWith("t-on-")){on=on||{};on[attr.slice(5)]=value;} else if(attr.startsWith("t-model")){if(!["input","select","textarea"].includes(tagName)){throw new OwlError("The t-model directive only works with , ";support.noCloneChecked=!!div.cloneNode(true).lastChild.defaultValue;div.innerHTML="";support.option=!!div.lastChild;})();var wrapMap={thead:[1,"","
"],col:[2,"","
"],tr:[2,"","
"],td:[3,"","
"],_default:[0,"",""]};wrapMap.tbody=wrapMap.tfoot=wrapMap.colgroup=wrapMap.caption=wrapMap.thead;wrapMap.th=wrapMap.td;if(!support.option){wrapMap.optgroup=wrapMap.option=[1,""];} function getAll(context,tag){var ret;if(typeof context.getElementsByTagName!=="undefined"){ret=context.getElementsByTagName(tag||"*");}else if(typeof context.querySelectorAll!=="undefined"){ret=context.querySelectorAll(tag||"*");}else{ret=[];} if(tag===undefined||tag&&nodeName(context,tag)){return jQuery.merge([context],ret);} return ret;} function setGlobalEval(elems,refElements){var i=0,l=elems.length;for(;i-1){if(ignored){ignored.push(elem);} continue;} attached=isAttached(elem);tmp=getAll(fragment.appendChild(elem),"script");if(attached){setGlobalEval(tmp);} if(scripts){j=0;while((elem=tmp[j++])){if(rscriptType.test(elem.type||"")){scripts.push(elem);}}}} return fragment;} var rtypenamespace=/^([^.]*)(?:\.(.+)|)/;function returnTrue(){return true;} function returnFalse(){return false;} function expectSync(elem,type){return(elem===safeActiveElement())===(type==="focus");} function safeActiveElement(){try{return document.activeElement;}catch(err){}} function on(elem,types,selector,data,fn,one){var origFn,type;if(typeof types==="object"){if(typeof selector!=="string"){data=data||selector;selector=undefined;} for(type in types){on(elem,type,selector,data,types[type],one);} return elem;} if(data==null&&fn==null){fn=selector;data=selector=undefined;}else if(fn==null){if(typeof selector==="string"){fn=data;data=undefined;}else{fn=data;data=selector;selector=undefined;}} if(fn===false){fn=returnFalse;}else if(!fn){return elem;} if(one===1){origFn=fn;fn=function(event){jQuery().off(event);return origFn.apply(this,arguments);};fn.guid=origFn.guid||(origFn.guid=jQuery.guid++);} return elem.each(function(){jQuery.event.add(this,types,fn,data,selector);});} jQuery.event={global:{},add:function(elem,types,handler,data,selector){var handleObjIn,eventHandle,tmp,events,t,handleObj,special,handlers,type,namespaces,origType,elemData=dataPriv.get(elem);if(!acceptData(elem)){return;} if(handler.handler){handleObjIn=handler;handler=handleObjIn.handler;selector=handleObjIn.selector;} if(selector){jQuery.find.matchesSelector(documentElement,selector);} if(!handler.guid){handler.guid=jQuery.guid++;} if(!(events=elemData.events)){events=elemData.events=Object.create(null);} if(!(eventHandle=elemData.handle)){eventHandle=elemData.handle=function(e){return typeof jQuery!=="undefined"&&jQuery.event.triggered!==e.type?jQuery.event.dispatch.apply(elem,arguments):undefined;};} types=(types||"").match(rnothtmlwhite)||[""];t=types.length;while(t--){tmp=rtypenamespace.exec(types[t])||[];type=origType=tmp[1];namespaces=(tmp[2]||"").split(".").sort();if(!type){continue;} special=jQuery.event.special[type]||{};type=(selector?special.delegateType:special.bindType)||type;special=jQuery.event.special[type]||{};handleObj=jQuery.extend({type:type,origType:origType,data:data,handler:handler,guid:handler.guid,selector:selector,needsContext:selector&&jQuery.expr.match.needsContext.test(selector),namespace:namespaces.join(".")},handleObjIn);if(!(handlers=events[type])){handlers=events[type]=[];handlers.delegateCount=0;if(!special.setup||special.setup.call(elem,data,namespaces,eventHandle)===false){if(elem.addEventListener){elem.addEventListener(type,eventHandle);}}} if(special.add){special.add.call(elem,handleObj);if(!handleObj.handler.guid){handleObj.handler.guid=handler.guid;}} if(selector){handlers.splice(handlers.delegateCount++,0,handleObj);}else{handlers.push(handleObj);} jQuery.event.global[type]=true;}},remove:function(elem,types,handler,selector,mappedTypes){var j,origCount,tmp,events,t,handleObj,special,handlers,type,namespaces,origType,elemData=dataPriv.hasData(elem)&&dataPriv.get(elem);if(!elemData||!(events=elemData.events)){return;} types=(types||"").match(rnothtmlwhite)||[""];t=types.length;while(t--){tmp=rtypenamespace.exec(types[t])||[];type=origType=tmp[1];namespaces=(tmp[2]||"").split(".").sort();if(!type){for(type in events){jQuery.event.remove(elem,type+types[t],handler,selector,true);} continue;} special=jQuery.event.special[type]||{};type=(selector?special.delegateType:special.bindType)||type;handlers=events[type]||[];tmp=tmp[2]&&new RegExp("(^|\\.)"+namespaces.join("\\.(?:.*\\.|)")+"(\\.|$)");origCount=j=handlers.length;while(j--){handleObj=handlers[j];if((mappedTypes||origType===handleObj.origType)&&(!handler||handler.guid===handleObj.guid)&&(!tmp||tmp.test(handleObj.namespace))&&(!selector||selector===handleObj.selector||selector==="**"&&handleObj.selector)){handlers.splice(j,1);if(handleObj.selector){handlers.delegateCount--;} if(special.remove){special.remove.call(elem,handleObj);}}} if(origCount&&!handlers.length){if(!special.teardown||special.teardown.call(elem,namespaces,elemData.handle)===false){jQuery.removeEvent(elem,type,elemData.handle);} delete events[type];}} if(jQuery.isEmptyObject(events)){dataPriv.remove(elem,"handle events");}},dispatch:function(nativeEvent){var i,j,ret,matched,handleObj,handlerQueue,args=new Array(arguments.length),event=jQuery.event.fix(nativeEvent),handlers=(dataPriv.get(this,"events")||Object.create(null))[event.type]||[],special=jQuery.event.special[event.type]||{};args[0]=event;for(i=1;i=1)){for(;cur!==this;cur=cur.parentNode||this){if(cur.nodeType===1&&!(event.type==="click"&&cur.disabled===true)){matchedHandlers=[];matchedSelectors={};for(i=0;i-1:jQuery.find(sel,this,null,[cur]).length;} if(matchedSelectors[sel]){matchedHandlers.push(handleObj);}} if(matchedHandlers.length){handlerQueue.push({elem:cur,handlers:matchedHandlers});}}}} cur=this;if(delegateCount\s*$/g;function manipulationTarget(elem,content){if(nodeName(elem,"table")&&nodeName(content.nodeType!==11?content:content.firstChild,"tr")){return jQuery(elem).children("tbody")[0]||elem;} return elem;} function disableScript(elem){elem.type=(elem.getAttribute("type")!==null)+"/"+elem.type;return elem;} function restoreScript(elem){if((elem.type||"").slice(0,5)==="true/"){elem.type=elem.type.slice(5);}else{elem.removeAttribute("type");} return elem;} function cloneCopyEvent(src,dest){var i,l,type,pdataOld,udataOld,udataCur,events;if(dest.nodeType!==1){return;} if(dataPriv.hasData(src)){pdataOld=dataPriv.get(src);events=pdataOld.events;if(events){dataPriv.remove(dest,"handle events");for(type in events){for(i=0,l=events[type].length;i1&&typeof value==="string"&&!support.checkClone&&rchecked.test(value))){return collection.each(function(index){var self=collection.eq(index);if(valueIsFunction){args[0]=value.call(this,index,self.html());} domManip(self,args,callback,ignored);});} if(l){fragment=buildFragment(args,collection[0].ownerDocument,false,collection,ignored);first=fragment.firstChild;if(fragment.childNodes.length===1){fragment=first;} if(first||ignored){scripts=jQuery.map(getAll(fragment,"script"),disableScript);hasScripts=scripts.length;for(;i0){setGlobalEval(destElements,!inPage&&getAll(elem,"script"));} return clone;},cleanData:function(elems){var data,elem,type,special=jQuery.event.special,i=0;for(;(elem=elems[i])!==undefined;i++){if(acceptData(elem)){if((data=elem[dataPriv.expando])){if(data.events){for(type in data.events){if(special[type]){jQuery.event.remove(elem,type);}else{jQuery.removeEvent(elem,type,data.handle);}}} elem[dataPriv.expando]=undefined;} if(elem[dataUser.expando]){elem[dataUser.expando]=undefined;}}}}});jQuery.fn.extend({detach:function(selector){return remove(this,selector,true);},remove:function(selector){return remove(this,selector);},text:function(value){return access(this,function(value){return value===undefined?jQuery.text(this):this.empty().each(function(){if(this.nodeType===1||this.nodeType===11||this.nodeType===9){this.textContent=value;}});},null,value,arguments.length);},append:function(){return domManip(this,arguments,function(elem){if(this.nodeType===1||this.nodeType===11||this.nodeType===9){var target=manipulationTarget(this,elem);target.appendChild(elem);}});},prepend:function(){return domManip(this,arguments,function(elem){if(this.nodeType===1||this.nodeType===11||this.nodeType===9){var target=manipulationTarget(this,elem);target.insertBefore(elem,target.firstChild);}});},before:function(){return domManip(this,arguments,function(elem){if(this.parentNode){this.parentNode.insertBefore(elem,this);}});},after:function(){return domManip(this,arguments,function(elem){if(this.parentNode){this.parentNode.insertBefore(elem,this.nextSibling);}});},empty:function(){var elem,i=0;for(;(elem=this[i])!=null;i++){if(elem.nodeType===1){jQuery.cleanData(getAll(elem,false));elem.textContent="";}} return this;},clone:function(dataAndEvents,deepDataAndEvents){dataAndEvents=dataAndEvents==null?false:dataAndEvents;deepDataAndEvents=deepDataAndEvents==null?dataAndEvents:deepDataAndEvents;return this.map(function(){return jQuery.clone(this,dataAndEvents,deepDataAndEvents);});},html:function(value){return access(this,function(value){var elem=this[0]||{},i=0,l=this.length;if(value===undefined&&elem.nodeType===1){return elem.innerHTML;} if(typeof value==="string"&&!rnoInnerhtml.test(value)&&!wrapMap[(rtagName.exec(value)||["",""])[1].toLowerCase()]){value=jQuery.htmlPrefilter(value);try{for(;i=0){delta+=Math.max(0,Math.ceil(elem["offset"+dimension[0].toUpperCase()+dimension.slice(1)]- computedVal- delta- extra- 0.5))||0;} return delta;} function getWidthOrHeight(elem,dimension,extra){var styles=getStyles(elem),boxSizingNeeded=!support.boxSizingReliable()||extra,isBorderBox=boxSizingNeeded&&jQuery.css(elem,"boxSizing",false,styles)==="border-box",valueIsBorderBox=isBorderBox,val=curCSS(elem,dimension,styles),offsetProp="offset"+dimension[0].toUpperCase()+dimension.slice(1);if(rnumnonpx.test(val)){if(!extra){return val;} val="auto";} if((!support.boxSizingReliable()&&isBorderBox||!support.reliableTrDimensions()&&nodeName(elem,"tr")||val==="auto"||!parseFloat(val)&&jQuery.css(elem,"display",false,styles)==="inline")&&elem.getClientRects().length){isBorderBox=jQuery.css(elem,"boxSizing",false,styles)==="border-box";valueIsBorderBox=offsetProp in elem;if(valueIsBorderBox){val=elem[offsetProp];}} val=parseFloat(val)||0;return(val+ boxModelAdjustment(elem,dimension,extra||(isBorderBox?"border":"content"),valueIsBorderBox,styles,val))+"px";} jQuery.extend({cssHooks:{opacity:{get:function(elem,computed){if(computed){var ret=curCSS(elem,"opacity");return ret===""?"1":ret;}}}},cssNumber:{"animationIterationCount":true,"columnCount":true,"fillOpacity":true,"flexGrow":true,"flexShrink":true,"fontWeight":true,"gridArea":true,"gridColumn":true,"gridColumnEnd":true,"gridColumnStart":true,"gridRow":true,"gridRowEnd":true,"gridRowStart":true,"lineHeight":true,"opacity":true,"order":true,"orphans":true,"widows":true,"zIndex":true,"zoom":true},cssProps:{},style:function(elem,name,value,extra){if(!elem||elem.nodeType===3||elem.nodeType===8||!elem.style){return;} var ret,type,hooks,origName=camelCase(name),isCustomProp=rcustomProp.test(name),style=elem.style;if(!isCustomProp){name=finalPropName(origName);} hooks=jQuery.cssHooks[name]||jQuery.cssHooks[origName];if(value!==undefined){type=typeof value;if(type==="string"&&(ret=rcssNum.exec(value))&&ret[1]){value=adjustCSS(elem,name,ret);type="number";} if(value==null||value!==value){return;} if(type==="number"&&!isCustomProp){value+=ret&&ret[3]||(jQuery.cssNumber[origName]?"":"px");} if(!support.clearCloneStyle&&value===""&&name.indexOf("background")===0){style[name]="inherit";} if(!hooks||!("set"in hooks)||(value=hooks.set(elem,value,extra))!==undefined){if(isCustomProp){style.setProperty(name,value);}else{style[name]=value;}}}else{if(hooks&&"get"in hooks&&(ret=hooks.get(elem,false,extra))!==undefined){return ret;} return style[name];}},css:function(elem,name,extra,styles){var val,num,hooks,origName=camelCase(name),isCustomProp=rcustomProp.test(name);if(!isCustomProp){name=finalPropName(origName);} hooks=jQuery.cssHooks[name]||jQuery.cssHooks[origName];if(hooks&&"get"in hooks){val=hooks.get(elem,true,extra);} if(val===undefined){val=curCSS(elem,name,styles);} if(val==="normal"&&name in cssNormalTransform){val=cssNormalTransform[name];} if(extra===""||extra){num=parseFloat(val);return extra===true||isFinite(num)?num||0:val;} return val;}});jQuery.each(["height","width"],function(_i,dimension){jQuery.cssHooks[dimension]={get:function(elem,computed,extra){if(computed){return rdisplayswap.test(jQuery.css(elem,"display"))&&(!elem.getClientRects().length||!elem.getBoundingClientRect().width)?swap(elem,cssShow,function(){return getWidthOrHeight(elem,dimension,extra);}):getWidthOrHeight(elem,dimension,extra);}},set:function(elem,value,extra){var matches,styles=getStyles(elem),scrollboxSizeBuggy=!support.scrollboxSize()&&styles.position==="absolute",boxSizingNeeded=scrollboxSizeBuggy||extra,isBorderBox=boxSizingNeeded&&jQuery.css(elem,"boxSizing",false,styles)==="border-box",subtract=extra?boxModelAdjustment(elem,dimension,extra,isBorderBox,styles):0;if(isBorderBox&&scrollboxSizeBuggy){subtract-=Math.ceil(elem["offset"+dimension[0].toUpperCase()+dimension.slice(1)]- parseFloat(styles[dimension])- boxModelAdjustment(elem,dimension,"border",false,styles)- 0.5);} if(subtract&&(matches=rcssNum.exec(value))&&(matches[3]||"px")!=="px"){elem.style[dimension]=value;value=jQuery.css(elem,dimension);} return setPositiveNumber(elem,value,subtract);}};});jQuery.cssHooks.marginLeft=addGetHookIf(support.reliableMarginLeft,function(elem,computed){if(computed){return(parseFloat(curCSS(elem,"marginLeft"))||elem.getBoundingClientRect().left- swap(elem,{marginLeft:0},function(){return elem.getBoundingClientRect().left;}))+"px";}});jQuery.each({margin:"",padding:"",border:"Width"},function(prefix,suffix){jQuery.cssHooks[prefix+suffix]={expand:function(value){var i=0,expanded={},parts=typeof value==="string"?value.split(" "):[value];for(;i<4;i++){expanded[prefix+cssExpand[i]+suffix]=parts[i]||parts[i-2]||parts[0];} return expanded;}};if(prefix!=="margin"){jQuery.cssHooks[prefix+suffix].set=setPositiveNumber;}});jQuery.fn.extend({css:function(name,value){return access(this,function(elem,name,value){var styles,len,map={},i=0;if(Array.isArray(name)){styles=getStyles(elem);len=name.length;for(;i1);}});function Tween(elem,options,prop,end,easing){return new Tween.prototype.init(elem,options,prop,end,easing);} jQuery.Tween=Tween;Tween.prototype={constructor:Tween,init:function(elem,options,prop,end,easing,unit){this.elem=elem;this.prop=prop;this.easing=easing||jQuery.easing._default;this.options=options;this.start=this.now=this.cur();this.end=end;this.unit=unit||(jQuery.cssNumber[prop]?"":"px");},cur:function(){var hooks=Tween.propHooks[this.prop];return hooks&&hooks.get?hooks.get(this):Tween.propHooks._default.get(this);},run:function(percent){var eased,hooks=Tween.propHooks[this.prop];if(this.options.duration){this.pos=eased=jQuery.easing[this.easing](percent,this.options.duration*percent,0,1,this.options.duration);}else{this.pos=eased=percent;} this.now=(this.end-this.start)*eased+this.start;if(this.options.step){this.options.step.call(this.elem,this.now,this);} if(hooks&&hooks.set){hooks.set(this);}else{Tween.propHooks._default.set(this);} return this;}};Tween.prototype.init.prototype=Tween.prototype;Tween.propHooks={_default:{get:function(tween){var result;if(tween.elem.nodeType!==1||tween.elem[tween.prop]!=null&&tween.elem.style[tween.prop]==null){return tween.elem[tween.prop];} result=jQuery.css(tween.elem,tween.prop,"");return!result||result==="auto"?0:result;},set:function(tween){if(jQuery.fx.step[tween.prop]){jQuery.fx.step[tween.prop](tween);}else if(tween.elem.nodeType===1&&(jQuery.cssHooks[tween.prop]||tween.elem.style[finalPropName(tween.prop)]!=null)){jQuery.style(tween.elem,tween.prop,tween.now+tween.unit);}else{tween.elem[tween.prop]=tween.now;}}}};Tween.propHooks.scrollTop=Tween.propHooks.scrollLeft={set:function(tween){if(tween.elem.nodeType&&tween.elem.parentNode){tween.elem[tween.prop]=tween.now;}}};jQuery.easing={linear:function(p){return p;},swing:function(p){return 0.5-Math.cos(p*Math.PI)/2;},_default:"swing"};jQuery.fx=Tween.prototype.init;jQuery.fx.step={};var fxNow,inProgress,rfxtypes=/^(?:toggle|show|hide)$/,rrun=/queueHooks$/;function schedule(){if(inProgress){if(document.hidden===false&&window.requestAnimationFrame){window.requestAnimationFrame(schedule);}else{window.setTimeout(schedule,jQuery.fx.interval);} jQuery.fx.tick();}} function createFxNow(){window.setTimeout(function(){fxNow=undefined;});return(fxNow=Date.now());} function genFx(type,includeWidth){var which,i=0,attrs={height:type};includeWidth=includeWidth?1:0;for(;i<4;i+=2-includeWidth){which=cssExpand[i];attrs["margin"+which]=attrs["padding"+which]=type;} if(includeWidth){attrs.opacity=attrs.width=type;} return attrs;} function createTween(value,prop,animation){var tween,collection=(Animation.tweeners[prop]||[]).concat(Animation.tweeners["*"]),index=0,length=collection.length;for(;index1);},removeAttr:function(name){return this.each(function(){jQuery.removeAttr(this,name);});}});jQuery.extend({attr:function(elem,name,value){var ret,hooks,nType=elem.nodeType;if(nType===3||nType===8||nType===2){return;} if(typeof elem.getAttribute==="undefined"){return jQuery.prop(elem,name,value);} if(nType!==1||!jQuery.isXMLDoc(elem)){hooks=jQuery.attrHooks[name.toLowerCase()]||(jQuery.expr.match.bool.test(name)?boolHook:undefined);} if(value!==undefined){if(value===null){jQuery.removeAttr(elem,name);return;} if(hooks&&"set"in hooks&&(ret=hooks.set(elem,value,name))!==undefined){return ret;} elem.setAttribute(name,value+"");return value;} if(hooks&&"get"in hooks&&(ret=hooks.get(elem,name))!==null){return ret;} ret=jQuery.find.attr(elem,name);return ret==null?undefined:ret;},attrHooks:{type:{set:function(elem,value){if(!support.radioValue&&value==="radio"&&nodeName(elem,"input")){var val=elem.value;elem.setAttribute("type",value);if(val){elem.value=val;} return value;}}}},removeAttr:function(elem,value){var name,i=0,attrNames=value&&value.match(rnothtmlwhite);if(attrNames&&elem.nodeType===1){while((name=attrNames[i++])){elem.removeAttribute(name);}}}});boolHook={set:function(elem,value,name){if(value===false){jQuery.removeAttr(elem,name);}else{elem.setAttribute(name,name);} return name;}};jQuery.each(jQuery.expr.match.bool.source.match(/\w+/g),function(_i,name){var getter=attrHandle[name]||jQuery.find.attr;attrHandle[name]=function(elem,name,isXML){var ret,handle,lowercaseName=name.toLowerCase();if(!isXML){handle=attrHandle[lowercaseName];attrHandle[lowercaseName]=ret;ret=getter(elem,name,isXML)!=null?lowercaseName:null;attrHandle[lowercaseName]=handle;} return ret;};});var rfocusable=/^(?:input|select|textarea|button)$/i,rclickable=/^(?:a|area)$/i;jQuery.fn.extend({prop:function(name,value){return access(this,jQuery.prop,name,value,arguments.length>1);},removeProp:function(name){return this.each(function(){delete this[jQuery.propFix[name]||name];});}});jQuery.extend({prop:function(elem,name,value){var ret,hooks,nType=elem.nodeType;if(nType===3||nType===8||nType===2){return;} if(nType!==1||!jQuery.isXMLDoc(elem)){name=jQuery.propFix[name]||name;hooks=jQuery.propHooks[name];} if(value!==undefined){if(hooks&&"set"in hooks&&(ret=hooks.set(elem,value,name))!==undefined){return ret;} return(elem[name]=value);} if(hooks&&"get"in hooks&&(ret=hooks.get(elem,name))!==null){return ret;} return elem[name];},propHooks:{tabIndex:{get:function(elem){var tabindex=jQuery.find.attr(elem,"tabindex");if(tabindex){return parseInt(tabindex,10);} if(rfocusable.test(elem.nodeName)||rclickable.test(elem.nodeName)&&elem.href){return 0;} return-1;}}},propFix:{"for":"htmlFor","class":"className"}});if(!support.optSelected){jQuery.propHooks.selected={get:function(elem){var parent=elem.parentNode;if(parent&&parent.parentNode){parent.parentNode.selectedIndex;} return null;},set:function(elem){var parent=elem.parentNode;if(parent){parent.selectedIndex;if(parent.parentNode){parent.parentNode.selectedIndex;}}}};} jQuery.each(["tabIndex","readOnly","maxLength","cellSpacing","cellPadding","rowSpan","colSpan","useMap","frameBorder","contentEditable"],function(){jQuery.propFix[this.toLowerCase()]=this;});function stripAndCollapse(value){var tokens=value.match(rnothtmlwhite)||[];return tokens.join(" ");} function getClass(elem){return elem.getAttribute&&elem.getAttribute("class")||"";} function classesToArray(value){if(Array.isArray(value)){return value;} if(typeof value==="string"){return value.match(rnothtmlwhite)||[];} return[];} jQuery.fn.extend({addClass:function(value){var classNames,cur,curValue,className,i,finalValue;if(isFunction(value)){return this.each(function(j){jQuery(this).addClass(value.call(this,j,getClass(this)));});} classNames=classesToArray(value);if(classNames.length){return this.each(function(){curValue=getClass(this);cur=this.nodeType===1&&(" "+stripAndCollapse(curValue)+" ");if(cur){for(i=0;i-1){cur=cur.replace(" "+className+" "," ");}} finalValue=stripAndCollapse(cur);if(curValue!==finalValue){this.setAttribute("class",finalValue);}}});} return this;},toggleClass:function(value,stateVal){var classNames,className,i,self,type=typeof value,isValidValue=type==="string"||Array.isArray(value);if(isFunction(value)){return this.each(function(i){jQuery(this).toggleClass(value.call(this,i,getClass(this),stateVal),stateVal);});} if(typeof stateVal==="boolean"&&isValidValue){return stateVal?this.addClass(value):this.removeClass(value);} classNames=classesToArray(value);return this.each(function(){if(isValidValue){self=jQuery(this);for(i=0;i-1){return true;}} return false;}});var rreturn=/\r/g;jQuery.fn.extend({val:function(value){var hooks,ret,valueIsFunction,elem=this[0];if(!arguments.length){if(elem){hooks=jQuery.valHooks[elem.type]||jQuery.valHooks[elem.nodeName.toLowerCase()];if(hooks&&"get"in hooks&&(ret=hooks.get(elem,"value"))!==undefined){return ret;} ret=elem.value;if(typeof ret==="string"){return ret.replace(rreturn,"");} return ret==null?"":ret;} return;} valueIsFunction=isFunction(value);return this.each(function(i){var val;if(this.nodeType!==1){return;} if(valueIsFunction){val=value.call(this,i,jQuery(this).val());}else{val=value;} if(val==null){val="";}else if(typeof val==="number"){val+="";}else if(Array.isArray(val)){val=jQuery.map(val,function(value){return value==null?"":value+"";});} hooks=jQuery.valHooks[this.type]||jQuery.valHooks[this.nodeName.toLowerCase()];if(!hooks||!("set"in hooks)||hooks.set(this,val,"value")===undefined){this.value=val;}});}});jQuery.extend({valHooks:{option:{get:function(elem){var val=jQuery.find.attr(elem,"value");return val!=null?val:stripAndCollapse(jQuery.text(elem));}},select:{get:function(elem){var value,option,i,options=elem.options,index=elem.selectedIndex,one=elem.type==="select-one",values=one?null:[],max=one?index+1:options.length;if(index<0){i=max;}else{i=one?index:0;} for(;i-1){optionSet=true;}} if(!optionSet){elem.selectedIndex=-1;} return values;}}}});jQuery.each(["radio","checkbox"],function(){jQuery.valHooks[this]={set:function(elem,value){if(Array.isArray(value)){return(elem.checked=jQuery.inArray(jQuery(elem).val(),value)>-1);}}};if(!support.checkOn){jQuery.valHooks[this].get=function(elem){return elem.getAttribute("value")===null?"on":elem.value;};}});support.focusin="onfocusin"in window;var rfocusMorph=/^(?:focusinfocus|focusoutblur)$/,stopPropagationCallback=function(e){e.stopPropagation();};jQuery.extend(jQuery.event,{trigger:function(event,data,elem,onlyHandlers){var i,cur,tmp,bubbleType,ontype,handle,special,lastElement,eventPath=[elem||document],type=hasOwn.call(event,"type")?event.type:event,namespaces=hasOwn.call(event,"namespace")?event.namespace.split("."):[];cur=lastElement=tmp=elem=elem||document;if(elem.nodeType===3||elem.nodeType===8){return;} if(rfocusMorph.test(type+jQuery.event.triggered)){return;} if(type.indexOf(".")>-1){namespaces=type.split(".");type=namespaces.shift();namespaces.sort();} ontype=type.indexOf(":")<0&&"on"+type;event=event[jQuery.expando]?event:new jQuery.Event(type,typeof event==="object"&&event);event.isTrigger=onlyHandlers?2:3;event.namespace=namespaces.join(".");event.rnamespace=event.namespace?new RegExp("(^|\\.)"+namespaces.join("\\.(?:.*\\.|)")+"(\\.|$)"):null;event.result=undefined;if(!event.target){event.target=elem;} data=data==null?[event]:jQuery.makeArray(data,[event]);special=jQuery.event.special[type]||{};if(!onlyHandlers&&special.trigger&&special.trigger.apply(elem,data)===false){return;} if(!onlyHandlers&&!special.noBubble&&!isWindow(elem)){bubbleType=special.delegateType||type;if(!rfocusMorph.test(bubbleType+type)){cur=cur.parentNode;} for(;cur;cur=cur.parentNode){eventPath.push(cur);tmp=cur;} if(tmp===(elem.ownerDocument||document)){eventPath.push(tmp.defaultView||tmp.parentWindow||window);}} i=0;while((cur=eventPath[i++])&&!event.isPropagationStopped()){lastElement=cur;event.type=i>1?bubbleType:special.bindType||type;handle=(dataPriv.get(cur,"events")||Object.create(null))[event.type]&&dataPriv.get(cur,"handle");if(handle){handle.apply(cur,data);} handle=ontype&&cur[ontype];if(handle&&handle.apply&&acceptData(cur)){event.result=handle.apply(cur,data);if(event.result===false){event.preventDefault();}}} event.type=type;if(!onlyHandlers&&!event.isDefaultPrevented()){if((!special._default||special._default.apply(eventPath.pop(),data)===false)&&acceptData(elem)){if(ontype&&isFunction(elem[type])&&!isWindow(elem)){tmp=elem[ontype];if(tmp){elem[ontype]=null;} jQuery.event.triggered=type;if(event.isPropagationStopped()){lastElement.addEventListener(type,stopPropagationCallback);} elem[type]();if(event.isPropagationStopped()){lastElement.removeEventListener(type,stopPropagationCallback);} jQuery.event.triggered=undefined;if(tmp){elem[ontype]=tmp;}}}} return event.result;},simulate:function(type,elem,event){var e=jQuery.extend(new jQuery.Event(),event,{type:type,isSimulated:true});jQuery.event.trigger(e,null,elem);}});jQuery.fn.extend({trigger:function(type,data){return this.each(function(){jQuery.event.trigger(type,data,this);});},triggerHandler:function(type,data){var elem=this[0];if(elem){return jQuery.event.trigger(type,data,elem,true);}}});if(!support.focusin){jQuery.each({focus:"focusin",blur:"focusout"},function(orig,fix){var handler=function(event){jQuery.event.simulate(fix,event.target,jQuery.event.fix(event));};jQuery.event.special[fix]={setup:function(){var doc=this.ownerDocument||this.document||this,attaches=dataPriv.access(doc,fix);if(!attaches){doc.addEventListener(orig,handler,true);} dataPriv.access(doc,fix,(attaches||0)+1);},teardown:function(){var doc=this.ownerDocument||this.document||this,attaches=dataPriv.access(doc,fix)-1;if(!attaches){doc.removeEventListener(orig,handler,true);dataPriv.remove(doc,fix);}else{dataPriv.access(doc,fix,attaches);}}};});} var location=window.location;var nonce={guid:Date.now()};var rquery=(/\?/);jQuery.parseXML=function(data){var xml,parserErrorElem;if(!data||typeof data!=="string"){return null;} try{xml=(new window.DOMParser()).parseFromString(data,"text/xml");}catch(e){} parserErrorElem=xml&&xml.getElementsByTagName("parsererror")[0];if(!xml||parserErrorElem){jQuery.error("Invalid XML: "+(parserErrorElem?jQuery.map(parserErrorElem.childNodes,function(el){return el.textContent;}).join("\n"):data));} return xml;};var rbracket=/\[\]$/,rCRLF=/\r?\n/g,rsubmitterTypes=/^(?:submit|button|image|reset|file)$/i,rsubmittable=/^(?:input|select|textarea|keygen)/i;function buildParams(prefix,obj,traditional,add){var name;if(Array.isArray(obj)){jQuery.each(obj,function(i,v){if(traditional||rbracket.test(prefix)){add(prefix,v);}else{buildParams(prefix+"["+(typeof v==="object"&&v!=null?i:"")+"]",v,traditional,add);}});}else if(!traditional&&toType(obj)==="object"){for(name in obj){buildParams(prefix+"["+name+"]",obj[name],traditional,add);}}else{add(prefix,obj);}} jQuery.param=function(a,traditional){var prefix,s=[],add=function(key,valueOrFunction){var value=isFunction(valueOrFunction)?valueOrFunction():valueOrFunction;s[s.length]=encodeURIComponent(key)+"="+ encodeURIComponent(value==null?"":value);};if(a==null){return"";} if(Array.isArray(a)||(a.jquery&&!jQuery.isPlainObject(a))){jQuery.each(a,function(){add(this.name,this.value);});}else{for(prefix in a){buildParams(prefix,a[prefix],traditional,add);}} return s.join("&");};jQuery.fn.extend({serialize:function(){return jQuery.param(this.serializeArray());},serializeArray:function(){return this.map(function(){var elements=jQuery.prop(this,"elements");return elements?jQuery.makeArray(elements):this;}).filter(function(){var type=this.type;return this.name&&!jQuery(this).is(":disabled")&&rsubmittable.test(this.nodeName)&&!rsubmitterTypes.test(type)&&(this.checked||!rcheckableType.test(type));}).map(function(_i,elem){var val=jQuery(this).val();if(val==null){return null;} if(Array.isArray(val)){return jQuery.map(val,function(val){return{name:elem.name,value:val.replace(rCRLF,"\r\n")};});} return{name:elem.name,value:val.replace(rCRLF,"\r\n")};}).get();}});var r20=/%20/g,rhash=/#.*$/,rantiCache=/([?&])_=[^&]*/,rheaders=/^(.*?):[ \t]*([^\r\n]*)$/mg,rlocalProtocol=/^(?:about|app|app-storage|.+-extension|file|res|widget):$/,rnoContent=/^(?:GET|HEAD)$/,rprotocol=/^\/\//,prefilters={},transports={},allTypes="*/".concat("*"),originAnchor=document.createElement("a");originAnchor.href=location.href;function addToPrefiltersOrTransports(structure){return function(dataTypeExpression,func){if(typeof dataTypeExpression!=="string"){func=dataTypeExpression;dataTypeExpression="*";} var dataType,i=0,dataTypes=dataTypeExpression.toLowerCase().match(rnothtmlwhite)||[];if(isFunction(func)){while((dataType=dataTypes[i++])){if(dataType[0]==="+"){dataType=dataType.slice(1)||"*";(structure[dataType]=structure[dataType]||[]).unshift(func);}else{(structure[dataType]=structure[dataType]||[]).push(func);}}}};} function inspectPrefiltersOrTransports(structure,options,originalOptions,jqXHR){var inspected={},seekingTransport=(structure===transports);function inspect(dataType){var selected;inspected[dataType]=true;jQuery.each(structure[dataType]||[],function(_,prefilterOrFactory){var dataTypeOrTransport=prefilterOrFactory(options,originalOptions,jqXHR);if(typeof dataTypeOrTransport==="string"&&!seekingTransport&&!inspected[dataTypeOrTransport]){options.dataTypes.unshift(dataTypeOrTransport);inspect(dataTypeOrTransport);return false;}else if(seekingTransport){return!(selected=dataTypeOrTransport);}});return selected;} return inspect(options.dataTypes[0])||!inspected["*"]&&inspect("*");} function ajaxExtend(target,src){var key,deep,flatOptions=jQuery.ajaxSettings.flatOptions||{};for(key in src){if(src[key]!==undefined){(flatOptions[key]?target:(deep||(deep={})))[key]=src[key];}} if(deep){jQuery.extend(true,target,deep);} return target;} function ajaxHandleResponses(s,jqXHR,responses){var ct,type,finalDataType,firstDataType,contents=s.contents,dataTypes=s.dataTypes;while(dataTypes[0]==="*"){dataTypes.shift();if(ct===undefined){ct=s.mimeType||jqXHR.getResponseHeader("Content-Type");}} if(ct){for(type in contents){if(contents[type]&&contents[type].test(ct)){dataTypes.unshift(type);break;}}} if(dataTypes[0]in responses){finalDataType=dataTypes[0];}else{for(type in responses){if(!dataTypes[0]||s.converters[type+" "+dataTypes[0]]){finalDataType=type;break;} if(!firstDataType){firstDataType=type;}} finalDataType=finalDataType||firstDataType;} if(finalDataType){if(finalDataType!==dataTypes[0]){dataTypes.unshift(finalDataType);} return responses[finalDataType];}} function ajaxConvert(s,response,jqXHR,isSuccess){var conv2,current,conv,tmp,prev,converters={},dataTypes=s.dataTypes.slice();if(dataTypes[1]){for(conv in s.converters){converters[conv.toLowerCase()]=s.converters[conv];}} current=dataTypes.shift();while(current){if(s.responseFields[current]){jqXHR[s.responseFields[current]]=response;} if(!prev&&isSuccess&&s.dataFilter){response=s.dataFilter(response,s.dataType);} prev=current;current=dataTypes.shift();if(current){if(current==="*"){current=prev;}else if(prev!=="*"&&prev!==current){conv=converters[prev+" "+current]||converters["* "+current];if(!conv){for(conv2 in converters){tmp=conv2.split(" ");if(tmp[1]===current){conv=converters[prev+" "+tmp[0]]||converters["* "+tmp[0]];if(conv){if(conv===true){conv=converters[conv2];}else if(converters[conv2]!==true){current=tmp[0];dataTypes.unshift(tmp[1]);} break;}}}} if(conv!==true){if(conv&&s.throws){response=conv(response);}else{try{response=conv(response);}catch(e){return{state:"parsererror",error:conv?e:"No conversion from "+prev+" to "+current};}}}}}} return{state:"success",data:response};} jQuery.extend({active:0,lastModified:{},etag:{},ajaxSettings:{url:location.href,type:"GET",isLocal:rlocalProtocol.test(location.protocol),global:true,processData:true,async:true,contentType:"application/x-www-form-urlencoded; charset=UTF-8",accepts:{"*":allTypes,text:"text/plain",html:"text/html",xml:"application/xml, text/xml",json:"application/json, text/javascript"},contents:{xml:/\bxml\b/,html:/\bhtml/,json:/\bjson\b/},responseFields:{xml:"responseXML",text:"responseText",json:"responseJSON"},converters:{"* text":String,"text html":true,"text json":JSON.parse,"text xml":jQuery.parseXML},flatOptions:{url:true,context:true}},ajaxSetup:function(target,settings){return settings?ajaxExtend(ajaxExtend(target,jQuery.ajaxSettings),settings):ajaxExtend(jQuery.ajaxSettings,target);},ajaxPrefilter:addToPrefiltersOrTransports(prefilters),ajaxTransport:addToPrefiltersOrTransports(transports),ajax:function(url,options){if(typeof url==="object"){options=url;url=undefined;} options=options||{};var transport,cacheURL,responseHeadersString,responseHeaders,timeoutTimer,urlAnchor,completed,fireGlobals,i,uncached,s=jQuery.ajaxSetup({},options),callbackContext=s.context||s,globalEventContext=s.context&&(callbackContext.nodeType||callbackContext.jquery)?jQuery(callbackContext):jQuery.event,deferred=jQuery.Deferred(),completeDeferred=jQuery.Callbacks("once memory"),statusCode=s.statusCode||{},requestHeaders={},requestHeadersNames={},strAbort="canceled",jqXHR={readyState:0,getResponseHeader:function(key){var match;if(completed){if(!responseHeaders){responseHeaders={};while((match=rheaders.exec(responseHeadersString))){responseHeaders[match[1].toLowerCase()+" "]=(responseHeaders[match[1].toLowerCase()+" "]||[]).concat(match[2]);}} match=responseHeaders[key.toLowerCase()+" "];} return match==null?null:match.join(", ");},getAllResponseHeaders:function(){return completed?responseHeadersString:null;},setRequestHeader:function(name,value){if(completed==null){name=requestHeadersNames[name.toLowerCase()]=requestHeadersNames[name.toLowerCase()]||name;requestHeaders[name]=value;} return this;},overrideMimeType:function(type){if(completed==null){s.mimeType=type;} return this;},statusCode:function(map){var code;if(map){if(completed){jqXHR.always(map[jqXHR.status]);}else{for(code in map){statusCode[code]=[statusCode[code],map[code]];}}} return this;},abort:function(statusText){var finalText=statusText||strAbort;if(transport){transport.abort(finalText);} done(0,finalText);return this;}};deferred.promise(jqXHR);s.url=((url||s.url||location.href)+"").replace(rprotocol,location.protocol+"//");s.type=options.method||options.type||s.method||s.type;s.dataTypes=(s.dataType||"*").toLowerCase().match(rnothtmlwhite)||[""];if(s.crossDomain==null){urlAnchor=document.createElement("a");try{urlAnchor.href=s.url;urlAnchor.href=urlAnchor.href;s.crossDomain=originAnchor.protocol+"//"+originAnchor.host!==urlAnchor.protocol+"//"+urlAnchor.host;}catch(e){s.crossDomain=true;}} if(s.data&&s.processData&&typeof s.data!=="string"){s.data=jQuery.param(s.data,s.traditional);} inspectPrefiltersOrTransports(prefilters,s,options,jqXHR);if(completed){return jqXHR;} fireGlobals=jQuery.event&&s.global;if(fireGlobals&&jQuery.active++===0){jQuery.event.trigger("ajaxStart");} s.type=s.type.toUpperCase();s.hasContent=!rnoContent.test(s.type);cacheURL=s.url.replace(rhash,"");if(!s.hasContent){uncached=s.url.slice(cacheURL.length);if(s.data&&(s.processData||typeof s.data==="string")){cacheURL+=(rquery.test(cacheURL)?"&":"?")+s.data;delete s.data;} if(s.cache===false){cacheURL=cacheURL.replace(rantiCache,"$1");uncached=(rquery.test(cacheURL)?"&":"?")+"_="+(nonce.guid++)+ uncached;} s.url=cacheURL+uncached;}else if(s.data&&s.processData&&(s.contentType||"").indexOf("application/x-www-form-urlencoded")===0){s.data=s.data.replace(r20,"+");} if(s.ifModified){if(jQuery.lastModified[cacheURL]){jqXHR.setRequestHeader("If-Modified-Since",jQuery.lastModified[cacheURL]);} if(jQuery.etag[cacheURL]){jqXHR.setRequestHeader("If-None-Match",jQuery.etag[cacheURL]);}} if(s.data&&s.hasContent&&s.contentType!==false||options.contentType){jqXHR.setRequestHeader("Content-Type",s.contentType);} jqXHR.setRequestHeader("Accept",s.dataTypes[0]&&s.accepts[s.dataTypes[0]]?s.accepts[s.dataTypes[0]]+ (s.dataTypes[0]!=="*"?", "+allTypes+"; q=0.01":""):s.accepts["*"]);for(i in s.headers){jqXHR.setRequestHeader(i,s.headers[i]);} if(s.beforeSend&&(s.beforeSend.call(callbackContext,jqXHR,s)===false||completed)){return jqXHR.abort();} strAbort="abort";completeDeferred.add(s.complete);jqXHR.done(s.success);jqXHR.fail(s.error);transport=inspectPrefiltersOrTransports(transports,s,options,jqXHR);if(!transport){done(-1,"No Transport");}else{jqXHR.readyState=1;if(fireGlobals){globalEventContext.trigger("ajaxSend",[jqXHR,s]);} if(completed){return jqXHR;} if(s.async&&s.timeout>0){timeoutTimer=window.setTimeout(function(){jqXHR.abort("timeout");},s.timeout);} try{completed=false;transport.send(requestHeaders,done);}catch(e){if(completed){throw e;} done(-1,e);}} function done(status,nativeStatusText,responses,headers){var isSuccess,success,error,response,modified,statusText=nativeStatusText;if(completed){return;} completed=true;if(timeoutTimer){window.clearTimeout(timeoutTimer);} transport=undefined;responseHeadersString=headers||"";jqXHR.readyState=status>0?4:0;isSuccess=status>=200&&status<300||status===304;if(responses){response=ajaxHandleResponses(s,jqXHR,responses);} if(!isSuccess&&jQuery.inArray("script",s.dataTypes)>-1&&jQuery.inArray("json",s.dataTypes)<0){s.converters["text script"]=function(){};} response=ajaxConvert(s,response,jqXHR,isSuccess);if(isSuccess){if(s.ifModified){modified=jqXHR.getResponseHeader("Last-Modified");if(modified){jQuery.lastModified[cacheURL]=modified;} modified=jqXHR.getResponseHeader("etag");if(modified){jQuery.etag[cacheURL]=modified;}} if(status===204||s.type==="HEAD"){statusText="nocontent";}else if(status===304){statusText="notmodified";}else{statusText=response.state;success=response.data;error=response.error;isSuccess=!error;}}else{error=statusText;if(status||!statusText){statusText="error";if(status<0){status=0;}}} jqXHR.status=status;jqXHR.statusText=(nativeStatusText||statusText)+"";if(isSuccess){deferred.resolveWith(callbackContext,[success,statusText,jqXHR]);}else{deferred.rejectWith(callbackContext,[jqXHR,statusText,error]);} jqXHR.statusCode(statusCode);statusCode=undefined;if(fireGlobals){globalEventContext.trigger(isSuccess?"ajaxSuccess":"ajaxError",[jqXHR,s,isSuccess?success:error]);} completeDeferred.fireWith(callbackContext,[jqXHR,statusText]);if(fireGlobals){globalEventContext.trigger("ajaxComplete",[jqXHR,s]);if(!(--jQuery.active)){jQuery.event.trigger("ajaxStop");}}} return jqXHR;},getJSON:function(url,data,callback){return jQuery.get(url,data,callback,"json");},getScript:function(url,callback){return jQuery.get(url,undefined,callback,"script");}});jQuery.each(["get","post"],function(_i,method){jQuery[method]=function(url,data,callback,type){if(isFunction(data)){type=type||callback;callback=data;data=undefined;} return jQuery.ajax(jQuery.extend({url:url,type:method,dataType:type,data:data,success:callback},jQuery.isPlainObject(url)&&url));};});jQuery.ajaxPrefilter(function(s){var i;for(i in s.headers){if(i.toLowerCase()==="content-type"){s.contentType=s.headers[i]||"";}}});jQuery._evalUrl=function(url,options,doc){return jQuery.ajax({url:url,type:"GET",dataType:"script",cache:true,async:false,global:false,converters:{"text script":function(){}},dataFilter:function(response){jQuery.globalEval(response,options,doc);}});};jQuery.fn.extend({wrapAll:function(html){var wrap;if(this[0]){if(isFunction(html)){html=html.call(this[0]);} wrap=jQuery(html,this[0].ownerDocument).eq(0).clone(true);if(this[0].parentNode){wrap.insertBefore(this[0]);} wrap.map(function(){var elem=this;while(elem.firstElementChild){elem=elem.firstElementChild;} return elem;}).append(this);} return this;},wrapInner:function(html){if(isFunction(html)){return this.each(function(i){jQuery(this).wrapInner(html.call(this,i));});} return this.each(function(){var self=jQuery(this),contents=self.contents();if(contents.length){contents.wrapAll(html);}else{self.append(html);}});},wrap:function(html){var htmlIsFunction=isFunction(html);return this.each(function(i){jQuery(this).wrapAll(htmlIsFunction?html.call(this,i):html);});},unwrap:function(selector){this.parent(selector).not("body").each(function(){jQuery(this).replaceWith(this.childNodes);});return this;}});jQuery.expr.pseudos.hidden=function(elem){return!jQuery.expr.pseudos.visible(elem);};jQuery.expr.pseudos.visible=function(elem){return!!(elem.offsetWidth||elem.offsetHeight||elem.getClientRects().length);};jQuery.ajaxSettings.xhr=function(){try{return new window.XMLHttpRequest();}catch(e){}};var xhrSuccessStatus={0:200,1223:204},xhrSupported=jQuery.ajaxSettings.xhr();support.cors=!!xhrSupported&&("withCredentials"in xhrSupported);support.ajax=xhrSupported=!!xhrSupported;jQuery.ajaxTransport(function(options){var callback,errorCallback;if(support.cors||xhrSupported&&!options.crossDomain){return{send:function(headers,complete){var i,xhr=options.xhr();xhr.open(options.type,options.url,options.async,options.username,options.password);if(options.xhrFields){for(i in options.xhrFields){xhr[i]=options.xhrFields[i];}} if(options.mimeType&&xhr.overrideMimeType){xhr.overrideMimeType(options.mimeType);} if(!options.crossDomain&&!headers["X-Requested-With"]){headers["X-Requested-With"]="XMLHttpRequest";} for(i in headers){xhr.setRequestHeader(i,headers[i]);} callback=function(type){return function(){if(callback){callback=errorCallback=xhr.onload=xhr.onerror=xhr.onabort=xhr.ontimeout=xhr.onreadystatechange=null;if(type==="abort"){xhr.abort();}else if(type==="error"){if(typeof xhr.status!=="number"){complete(0,"error");}else{complete(xhr.status,xhr.statusText);}}else{complete(xhrSuccessStatus[xhr.status]||xhr.status,xhr.statusText,(xhr.responseType||"text")!=="text"||typeof xhr.responseText!=="string"?{binary:xhr.response}:{text:xhr.responseText},xhr.getAllResponseHeaders());}}};};xhr.onload=callback();errorCallback=xhr.onerror=xhr.ontimeout=callback("error");if(xhr.onabort!==undefined){xhr.onabort=errorCallback;}else{xhr.onreadystatechange=function(){if(xhr.readyState===4){window.setTimeout(function(){if(callback){errorCallback();}});}};} callback=callback("abort");try{xhr.send(options.hasContent&&options.data||null);}catch(e){if(callback){throw e;}}},abort:function(){if(callback){callback();}}};}});jQuery.ajaxPrefilter(function(s){if(s.crossDomain){s.contents.script=false;}});jQuery.ajaxSetup({accepts:{script:"text/javascript, application/javascript, "+"application/ecmascript, application/x-ecmascript"},contents:{script:/\b(?:java|ecma)script\b/},converters:{"text script":function(text){jQuery.globalEval(text);return text;}}});jQuery.ajaxPrefilter("script",function(s){if(s.cache===undefined){s.cache=false;} if(s.crossDomain){s.type="GET";}});jQuery.ajaxTransport("script",function(s){if(s.crossDomain||s.scriptAttrs){var script,callback;return{send:function(_,complete){script=jQuery(" `);printWindow.document.close();}} return __exports;});; /* /web/static/src/core/file_viewer/file_viewer_hook.js */ odoo.define('@web/core/file_viewer/file_viewer_hook',['@odoo/owl','@web/core/registry','@web/core/file_viewer/file_viewer'],function(require){'use strict';let __exports={};const{onWillDestroy}=require("@odoo/owl");const{registry}=require("@web/core/registry");const{FileViewer}=require("@web/core/file_viewer/file_viewer");let id=1;__exports.createFileViewer=createFileViewer;function createFileViewer(){const fileViewerId=`web.file_viewer${id++}`;function open(file,files=[file]){if(!file.isViewable){return;} if(files.length>0){const viewableFiles=files.filter((file)=>file.isViewable);const index=viewableFiles.indexOf(file);registry.category("main_components").add(fileViewerId,{Component:FileViewer,props:{files:viewableFiles,startIndex:index,close},});}} function close(){registry.category("main_components").remove(fileViewerId);} return{open,close};} __exports.useFileViewer=useFileViewer;function useFileViewer(){const{open,close}=createFileViewer();onWillDestroy(close);return{open,close};} return __exports;});; /* /web/static/src/core/hotkeys/hotkey_hook.js */ odoo.define('@web/core/hotkeys/hotkey_hook',['@web/core/utils/hooks','@odoo/owl'],function(require){'use strict';let __exports={};const{useService}=require("@web/core/utils/hooks");const{useEffect}=require("@odoo/owl");__exports.useHotkey=useHotkey;function useHotkey(hotkey,callback,options={}){const hotkeyService=useService("hotkey");useEffect(()=>hotkeyService.add(hotkey,callback,options),()=>[]);} return __exports;});; /* /web/static/src/core/hotkeys/hotkey_service.js */ odoo.define('@web/core/hotkeys/hotkey_service',['@web/core/browser/feature_detection','@web/core/registry','@web/core/browser/browser','@web/core/utils/ui'],function(require){'use strict';let __exports={};const{isMacOS}=require("@web/core/browser/feature_detection");const{registry}=require("@web/core/registry");const{browser}=require("@web/core/browser/browser");const{getVisibleElements}=require("@web/core/utils/ui");const ALPHANUM_KEYS="abcdefghijklmnopqrstuvwxyz0123456789".split("");const NAV_KEYS=["arrowleft","arrowright","arrowup","arrowdown","pageup","pagedown","home","end","backspace","enter","tab","delete","space",];const MODIFIERS=["alt","control","shift"];const AUTHORIZED_KEYS=[...ALPHANUM_KEYS,...NAV_KEYS,"escape"];__exports.getActiveHotkey=getActiveHotkey;function getActiveHotkey(ev){if(!ev.key){return"";} if(ev.isComposing){return"";} const hotkey=[];if(isMacOS()?ev.ctrlKey:ev.altKey){hotkey.push("alt");} if(isMacOS()?ev.metaKey:ev.ctrlKey){hotkey.push("control");} if(ev.shiftKey){hotkey.push("shift");} let key=ev.key.toLowerCase();if(key===" "){key="space";} if(ev.code&&ev.code.indexOf("Digit")===0){key=ev.code.slice(-1);} if(!AUTHORIZED_KEYS.includes(key)&&ev.code&&ev.code.indexOf("Key")===0){key=ev.code.slice(-1).toLowerCase();} if(!MODIFIERS.includes(key)){hotkey.push(key);} return hotkey.join("+");} const hotkeyService=__exports.hotkeyService={dependencies:["ui"],overlayModifier:"alt",start(env,{ui}){const registrations=new Map();let nextToken=0;let overlaysVisible=false;addListeners(browser);function addListeners(target){target.addEventListener("keydown",onKeydown);target.addEventListener("keyup",removeHotkeyOverlays);target.addEventListener("blur",removeHotkeyOverlays);target.addEventListener("click",removeHotkeyOverlays);} function onKeydown(event){if(event.code&&event.code.indexOf("Numpad")===0&&/^\d$/.test(event.key)){return;} const hotkey=getActiveHotkey(event);if(!hotkey){return;} const{activeElement,isBlocked}=ui;if(isBlocked){return;} const elementsWithAccessKey=document.querySelectorAll("[accesskey]");for(const el of elementsWithAccessKey){if(el instanceof HTMLElement){el.dataset.hotkey=el.accessKey;el.removeAttribute("accesskey");}} if(!overlaysVisible&&hotkey===hotkeyService.overlayModifier){addHotkeyOverlays(activeElement);event.preventDefault();return;} const singleKey=hotkey.split("+").pop();if(!AUTHORIZED_KEYS.includes(singleKey)){return;} const targetIsEditable=event.target instanceof HTMLElement&&(/input|textarea/i.test(event.target.tagName)||event.target.isContentEditable)&&!event.target.matches("input[type=checkbox], input[type=radio]");const shouldProtectEditable=targetIsEditable&&!event.target.dataset.allowHotkeys&&singleKey!=="escape";const infos={activeElement,hotkey,isRepeated:event.repeat,target:event.target,shouldProtectEditable,};const dispatched=dispatch(infos);if(dispatched){event.preventDefault();event.stopImmediatePropagation();} if(overlaysVisible){removeHotkeyOverlays();event.preventDefault();}} function dispatch(infos){const{activeElement,hotkey,isRepeated,target,shouldProtectEditable}=infos;const reversedRegistrations=Array.from(registrations.values()).reverse();const domRegistrations=getDomRegistrations(hotkey,activeElement);const allRegistrations=reversedRegistrations.concat(domRegistrations);const candidates=allRegistrations.filter((reg)=>reg.hotkey===hotkey&&(reg.allowRepeat||!isRepeated)&&(reg.bypassEditableProtection||!shouldProtectEditable)&&(reg.global||reg.activeElement===activeElement)&&(!reg.isAvailable||reg.isAvailable())&&(!reg.area||(target&®.area()&®.area().contains(target))));let winner=candidates.shift();if(winner&&winner.area){for(const candidate of candidates.filter((c)=>Boolean(c.area))){if(candidate.area()&&winner.area().contains(candidate.area())){winner=candidate;}}} if(winner){winner.callback({area:winner.area&&winner.area(),target,});return true;} return false;} function getDomRegistrations(hotkey,activeElement){const overlayModParts=hotkeyService.overlayModifier.split("+");if(!overlayModParts.every((el)=>hotkey.includes(el))){return[];} const cleanHotkey=hotkey.split("+").filter((key)=>!overlayModParts.includes(key)).join("+");const elems=getVisibleElements(activeElement,`[data-hotkey='${cleanHotkey}' i]`);return elems.map((el)=>({hotkey,activeElement,bypassEditableProtection:true,callback:()=>{if(document.activeElement){document.activeElement.blur();} el.focus();setTimeout(()=>el.click());},}));} function addHotkeyOverlays(activeElement){const hotkeysFromHookToHighlight=[];for(const[,registration]of registrations){const overlayElement=registration.withOverlay?.();if(overlayElement){hotkeysFromHookToHighlight.push({hotkey:registration.hotkey.replace(`${hotkeyService.overlayModifier}+`,""),el:overlayElement,});}} const hotkeysFromDomToHighlight=getVisibleElements(activeElement,"[data-hotkey]:not(:disabled)").map((el)=>({hotkey:el.dataset.hotkey,el}));const items=[...hotkeysFromDomToHighlight,...hotkeysFromHookToHighlight];for(const item of items){const hotkey=item.hotkey;const overlay=document.createElement("div");overlay.classList.add("o_web_hotkey_overlay","position-absolute","top-0","bottom-0","start-0","end-0","d-flex","justify-content-center","align-items-center","m-0","bg-black-50","h6");overlay.style.zIndex=1;const overlayKbd=document.createElement("kbd");overlayKbd.className="small";overlayKbd.appendChild(document.createTextNode(hotkey.toUpperCase()));overlay.appendChild(overlayKbd);let overlayParent;if(item.el.tagName.toUpperCase()==="INPUT"){overlayParent=item.el.parentElement;}else{overlayParent=item.el;} if(overlayParent.style.position!=="absolute"){overlayParent.style.position="relative";} overlayParent.appendChild(overlay);} overlaysVisible=true;} function removeHotkeyOverlays(){for(const overlay of document.querySelectorAll(".o_web_hotkey_overlay")){overlay.remove();} overlaysVisible=false;} function registerHotkey(hotkey,callback,options={}){if(!hotkey||hotkey.length===0){throw new Error("You must specify an hotkey when registering a registration.");} if(!callback||typeof callback!=="function"){throw new Error("You must specify a callback function when registering a registration.");} const keys=hotkey.toLowerCase().split("+").filter((k)=>!MODIFIERS.includes(k));if(keys.some((k)=>!AUTHORIZED_KEYS.includes(k))){throw new Error(`You are trying to subscribe for an hotkey ('${hotkey}') that contains parts not whitelisted: ${keys.join(", ")}`);}else if(keys.length>1){throw new Error(`You are trying to subscribe for an hotkey ('${hotkey}') that contains more than one single key part: ${keys.join("+")}`);} const token=nextToken++;const registration={hotkey:hotkey.toLowerCase(),callback,activeElement:null,allowRepeat:options&&options.allowRepeat,bypassEditableProtection:options&&options.bypassEditableProtection,global:options&&options.global,area:options&&options.area,isAvailable:options&&options.isAvailable,withOverlay:options&&options.withOverlay,};Promise.resolve().then(()=>{registration.activeElement=ui.activeElement;});registrations.set(token,registration);return token;} function unregisterHotkey(token){registrations.delete(token);} return{add(hotkey,callback,options={}){const token=registerHotkey(hotkey,callback,options);return()=>{unregisterHotkey(token);};},registerIframe(iframe){addListeners(iframe.contentWindow);},};},};registry.category("services").add("hotkey",hotkeyService);return __exports;});; /* /web/static/src/core/install_scoped_app/install_scoped_app.js */ odoo.define('@web/core/install_scoped_app/install_scoped_app',['@web/core/browser/browser','@web/core/registry','@odoo/owl','@web/core/browser/feature_detection','@web/core/utils/hooks','@web/core/dropdown/dropdown'],function(require){'use strict';let __exports={};const{browser}=require("@web/core/browser/browser");const{registry}=require("@web/core/registry");const{Component,onMounted,useState}=require("@odoo/owl");const{isDisplayStandalone}=require("@web/core/browser/feature_detection");const{useService}=require("@web/core/utils/hooks");const{Dropdown}=require("@web/core/dropdown/dropdown");const InstallScopedApp=__exports.InstallScopedApp=class InstallScopedApp extends Component{static props={};static template="web.InstallScopedApp";static components={Dropdown};setup(){this.pwa=useState(useService("pwa"));this.state=useState({manifest:{},showInstallUI:false});this.isDisplayStandalone=isDisplayStandalone();this.isInstallationPossible=browser.BeforeInstallPromptEvent!==undefined;onMounted(async()=>{this.state.manifest=await this.pwa.getManifest();this.state.showInstallUI=true;});} onChangeName(ev){const value=ev.target.value;if(value!==this.state.manifest.name){const url=new URL(document.location.href);url.searchParams.set("app_name",encodeURIComponent(value));browser.location.replace(url);}} onInstall(){this.state.showInstallUI=false;this.pwa.show({onDone:(res)=>{if(res.outcome==="accepted"){browser.location.replace(this.state.manifest.start_url);}else{this.state.showInstallUI=true;}},});}} registry.category("public_components").add("web.install_scoped_app",InstallScopedApp);return __exports;});; /* /web/static/src/core/l10n/dates.js */ odoo.define('@web/core/l10n/dates',['@web/core/l10n/localization','@web/core/l10n/translation','@web/core/utils/functions','@web/core/utils/arrays'],function(require){'use strict';let __exports={};const{localization}=require("@web/core/l10n/localization");const{_t}=require("@web/core/l10n/translation");const{memoize}=require("@web/core/utils/functions");const{ensureArray}=require("@web/core/utils/arrays");const{DateTime,Settings}=luxon;const MIN_VALID_DATE=__exports.MIN_VALID_DATE=DateTime.fromObject({year:1000});const MAX_VALID_DATE=__exports.MAX_VALID_DATE=DateTime.fromObject({year:9999}).endOf("year");const SERVER_DATE_FORMAT="yyyy-MM-dd";const SERVER_TIME_FORMAT="HH:mm:ss";const SERVER_DATETIME_FORMAT=`${SERVER_DATE_FORMAT} ${SERVER_TIME_FORMAT}`;const nonAlphaRegex=/[^a-z]/gi;const nonDigitRegex=/[^\d]/g;const normalizeFormatTable={a:"ccc",A:"cccc",b:"MMM",B:"MMMM",d:"dd",H:"HH",I:"hh",j:"o",m:"MM",M:"mm",p:"a",S:"ss",W:"WW",w:"c",y:"yy",Y:"yyyy",c:"ccc MMM d HH:mm:ss yyyy",x:"MM/dd/yy",X:"HH:mm:ss",};const smartDateUnits={d:"days",m:"months",w:"weeks",y:"years",};const smartDateRegex=new RegExp(["^","([+-])","(\\d+)",`([${Object.keys(smartDateUnits).join("")}]?)`,"$"].join("\\s*"),"i");const dateCache=new WeakMap();const dateTimeCache=new WeakMap();const ConversionError=__exports.ConversionError=class ConversionError extends Error{name="ConversionError";} __exports.areDatesEqual=areDatesEqual;function areDatesEqual(d1,d2){if(Array.isArray(d1)||Array.isArray(d2)){d1=ensureArray(d1);d2=ensureArray(d2);return d1.length===d2.length&&d1.every((d1Val,i)=>areDatesEqual(d1Val,d2[i]));} if(d1 instanceof DateTime&&d2 instanceof DateTime&&d1!==d2){return d1.equals(d2);}else{return d1===d2;}} __exports.clampDate=clampDate;function clampDate(desired,minDate,maxDate){if(maxDatedesired){return minDate;} return desired;} __exports.getLocalWeekNumber=getLocalWeekNumber;function getLocalWeekNumber(date){return getLocalYearAndWeek(date).week;} __exports.getLocalYearAndWeek=getLocalYearAndWeek;function getLocalYearAndWeek(date){if(!date.isLuxonDateTime){date=DateTime.fromJSDate(date);} const{weekStart}=localization;date=date.minus({days:(date.weekday+7-weekStart)%7});date=weekStart>1&&weekStart<5?date.minus({days:(date.weekday+6)%7}):date.plus({days:(8-date.weekday)%7});date=date.plus({days:6});const jan4=DateTime.local(date.year,1,4);const diffDays=dateletter===str[index-1]?"":letter);});const strftimeToLuxonFormat=__exports.strftimeToLuxonFormat=memoize(function strftimeToLuxonFormat(format){const output=[];let inToken=false;for(let index=0;indexduration.get(key)));const durationSplit=duration.toHuman({unitDisplay:displayStyle}).split(",");if(!showFullDuration&&duration.loc.locale.includes("en")&&duration.months>0){durationSplit[0]=durationSplit[0].replace("m","M");} return durationSplit.slice(0,numberOfValuesToDisplay).join(",");} __exports.serializeDate=serializeDate;function serializeDate(value){if(!dateCache.has(value)){dateCache.set(value,value.toFormat(SERVER_DATE_FORMAT,{numberingSystem:"latn"}));} return dateCache.get(value);} __exports.serializeDateTime=serializeDateTime;function serializeDateTime(value){if(!dateTimeCache.has(value)){dateTimeCache.set(value,value.setZone("utc").toFormat(SERVER_DATETIME_FORMAT,{numberingSystem:"latn"}));} return dateTimeCache.get(value);} __exports.parseDate=parseDate;function parseDate(value,options={}){const parsed=parseDateTime(value,{...options,format:options.format||localization.dateFormat,});return parsed&&parsed.startOf("day");} __exports.parseDateTime=parseDateTime;function parseDateTime(value,options={}){if(!value){return false;} const fmt=options.format||localization.dateTimeFormat;const parseOpts={setZone:true,zone:options.tz||"default",};const switchToLatin=Settings.defaultNumberingSystem!=="latn"&&/[0-9]/.test(value);if(switchToLatin){parseOpts.numberingSystem="latn";} let result=DateTime.fromFormat(value,fmt,parseOpts);if(!isValidDate(result)){result=parseSmartDateInput(value);} if(!isValidDate(result)){const fmtWoZero=stripAlphaDupes(fmt);result=DateTime.fromFormat(value,fmtWoZero,parseOpts);} if(!isValidDate(result)){const digitList=value.split(nonDigitRegex).filter(Boolean);const fmtList=fmt.split(nonAlphaRegex).filter(Boolean);const valWoSeps=digitList.join("");let carry=0;const fmtWoSeps=fmtList.map((part,i)=>{const digitLength=(digitList[i]||"").length;const actualPart=part.slice(0,digitLength+carry);carry+=digitLength-actualPart.length;return actualPart;}).join("");result=DateTime.fromFormat(valWoSeps,fmtWoSeps,parseOpts);} if(!isValidDate(result)){const valueDigits=value.replace(nonDigitRegex,"");if(valueDigits.length>4){result=DateTime.fromISO(value,parseOpts);if(!isValidDate(result)){result=DateTime.fromSQL(value,parseOpts);}}} if(!isValidDate(result)){throw new ConversionError(_t("'%s' is not a correct date or datetime",value));} if(switchToLatin){result=result.reconfigure({numberingSystem:Settings.defaultNumberingSystem,});} return result.setZone(options.tz||"default");} __exports.deserializeDate=deserializeDate;function deserializeDate(value,options={}){options={numberingSystem:"latn",zone:"default",...options};return DateTime.fromSQL(value,options).reconfigure({numberingSystem:Settings.defaultNumberingSystem,});} __exports.deserializeDateTime=deserializeDateTime;function deserializeDateTime(value,options={}){return DateTime.fromSQL(value,{numberingSystem:"latn",zone:"utc"}).setZone(options?.tz||"default").reconfigure({numberingSystem:Settings.defaultNumberingSystem,});} return __exports;});; /* /web/static/src/core/l10n/localization.js */ odoo.define('@web/core/l10n/localization',[],function(require){'use strict';let __exports={};const localization=__exports.localization=new Proxy({},{get:(target,p)=>{if(p in target||p==="then"){return Reflect.get(target,p);} throw new Error(`could not access localization parameter "${p}": parameters are not ready yet. Maybe add 'localization' to your dependencies?`);},});return __exports;});; /* /web/static/src/core/l10n/localization_service.js */ odoo.define('@web/core/l10n/localization_service',['@web/session','@web/core/l10n/utils','@web/core/user','@web/core/browser/browser','@web/core/registry','@web/core/l10n/dates','@web/core/l10n/localization','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{session}=require("@web/session");const{jsToPyLocale}=require("@web/core/l10n/utils");const{user}=require("@web/core/user");const{browser}=require("@web/core/browser/browser");const{registry}=require("@web/core/registry");const{strftimeToLuxonFormat}=require("@web/core/l10n/dates");const{localization}=require("@web/core/l10n/localization");const{translatedTerms,translationLoaded,translationIsReady}=require("@web/core/l10n/translation");const{Settings}=luxon;const NUMBERING_SYSTEMS=[[/^ar-(sa|sy|001)$/i,"arab"],[/^bn/i,"beng"],[/^bo/i,"tibt"],[/^pa-in/i,"guru"],[/^ta/i,"tamldec"],[/.*/i,"latn"],];const localizationService=__exports.localizationService={start:async()=>{const cacheHashes=session.cache_hashes||{};const translationsHash=cacheHashes.translations||new Date().getTime().toString();const lang=jsToPyLocale(user.lang||document.documentElement.getAttribute("lang"));const translationURL=session.translationURL||"/web/webclient/translations";let url=`${translationURL}/${translationsHash}`;if(lang){url+=`?lang=${lang}`;} const response=await browser.fetch(url);if(!response.ok){throw new Error("Error while fetching translations");} const{lang_parameters:userLocalization,modules:modules,multi_lang:multiLang,}=await response.json();const terms={};for(const addon of Object.keys(modules)){for(const message of modules[addon].messages){terms[message.id]=message.string;}} Object.assign(translatedTerms,terms);translatedTerms[translationLoaded]=true;translationIsReady.resolve(true);const locale=user.lang||browser.navigator.language;Settings.defaultLocale=locale;for(const[re,numberingSystem]of NUMBERING_SYSTEMS){if(re.test(locale)){Settings.defaultNumberingSystem=numberingSystem;break;}} const dateFormat=strftimeToLuxonFormat(userLocalization.date_format);const timeFormat=strftimeToLuxonFormat(userLocalization.time_format);const shortTimeFormat=strftimeToLuxonFormat(userLocalization.short_time_format);const dateTimeFormat=`${dateFormat} ${timeFormat}`;const grouping=JSON.parse(userLocalization.grouping);Object.assign(localization,{dateFormat,timeFormat,shortTimeFormat,dateTimeFormat,decimalPoint:userLocalization.decimal_point,direction:userLocalization.direction,grouping,multiLang,thousandsSep:userLocalization.thousands_sep,weekStart:userLocalization.week_start,code:jsToPyLocale(locale),});return localization;},};registry.category("services").add("localization",localizationService);return __exports;});; /* /web/static/src/core/l10n/translation.js */ odoo.define('@web/core/l10n/translation',['@odoo/owl','@web/core/utils/concurrency','@web/core/utils/strings'],function(require){'use strict';let __exports={};const{markup}=require("@odoo/owl");const{Deferred}=require("@web/core/utils/concurrency");const{escape,sprintf}=require("@web/core/utils/strings");const translationLoaded=__exports.translationLoaded=Symbol("translationLoaded");const translatedTerms=__exports.translatedTerms={[translationLoaded]:false,};const translationIsReady=__exports.translationIsReady=new Deferred();const Markup=markup().constructor;__exports._t=_t;function _t(term,...values){if(translatedTerms[translationLoaded]){const translation=translatedTerms[term]??term;if(values.length===0){return translation;} return _safeSprintf(translation,...values);}else{return new LazyTranslatedString(term,values);}} class LazyTranslatedString extends String{constructor(term,values){super(term);this.values=values;} valueOf(){const term=super.valueOf();if(translatedTerms[translationLoaded]){const translation=translatedTerms[term]??term;if(this.values.length===0){return translation;} return _safeSprintf(translation,...this.values);}else{throw new Error(`translation error`);}} toString(){return this.valueOf();}} _t("less than a minute ago");_t("about a minute ago");_t("%d minutes ago");_t("about an hour ago");_t("%d hours ago");_t("a day ago");_t("%d days ago");_t("about a month ago");_t("%d months ago");_t("about a year ago");_t("%d years ago");__exports.loadLanguages=loadLanguages;async function loadLanguages(orm){if(!loadLanguages.installedLanguages){loadLanguages.installedLanguages=await orm.call("res.lang","get_installed");} return loadLanguages.installedLanguages;} function _safeSprintf(str,...values){let hasMarkup;if(values.length===1&&Object.prototype.toString.call(values[0])==="[object Object]"){hasMarkup=Object.values(values[0]).some((v)=>v instanceof Markup);}else{hasMarkup=values.some((v)=>v instanceof Markup);} if(hasMarkup){return markup(sprintf(escape(str),..._escapeNonMarkup(values)));} return sprintf(str,...values);} function _escapeNonMarkup(values){if(Object.prototype.toString.call(values[0])==="[object Object]"){const sanitized={};for(const[key,value]of Object.entries(values[0])){sanitized[key]=value instanceof Markup?value:escape(value);} return[sanitized];} return values.map((x)=>(x instanceof Markup?x:escape(x)));} return __exports;});; /* /web/static/src/core/l10n/utils.js */ odoo.define('@web/core/l10n/utils',['@web/core/l10n/utils/format_list','@web/core/l10n/utils/locales'],function(require){'use strict';let __exports={};Object.assign(__exports,require("@web/core/l10n/utils/format_list"));Object.assign(__exports,require("@web/core/l10n/utils/locales"));return __exports;});; /* /web/static/src/core/l10n/utils/format_list.js */ odoo.define('@web/core/l10n/utils/format_list',['@web/core/user'],function(require){'use strict';let __exports={};const{user}=require("@web/core/user");const LIST_STYLES={standard:{type:"conjunction",style:"long",},"standard-short":{type:"conjunction",style:"short",},or:{type:"disjunction",style:"long",},"or-short":{type:"disjunction",style:"short",},unit:{type:"unit",style:"long",},"unit-short":{type:"unit",style:"short",},"unit-narrow":{type:"unit",style:"narrow",},};__exports.formatList=formatList;function formatList(list,{localeCode="",style="standard"}={}){const locale=localeCode||user.lang||"en-US";const formatter=new Intl.ListFormat(locale,LIST_STYLES[style]);return formatter.format(list);} return __exports;});; /* /web/static/src/core/l10n/utils/locales.js */ odoo.define('@web/core/l10n/utils/locales',[],function(require){'use strict';let __exports={};__exports.jsToPyLocale=jsToPyLocale;function jsToPyLocale(locale){if(!locale){return"";} try{var{language,script,region}=new Intl.Locale(locale);if(language==="fil"){language="tl";}}catch{return locale;} let xpgLocale=language;if(region){xpgLocale+=`_${region}`;} switch(script){case"Cyrl":xpgLocale+="@Cyrl";break;case"Latn":xpgLocale+="@latin";break;} return xpgLocale;} __exports.pyToJsLocale=pyToJsLocale;function pyToJsLocale(locale){if(!locale){return"";} const regex=/^([a-z]+)(_[A-Z\d]+)?(@.+)?$/;const match=locale.match(regex);if(!match){return locale;} const[,language,territory,modifier]=match;const subtags=[language];switch(modifier){case"@Cyrl":subtags.push("Cyrl");break;case"@latin":subtags.push("Latn");break;} if(territory){subtags.push(territory.slice(1));} return subtags.join("-");} return __exports;});; /* /web/static/src/core/macro.js */ odoo.define('@web/core/macro',['@web/core/browser/browser','@web/core/utils/ui','@web/core/utils/concurrency','@odoo/owl'],function(require){'use strict';let __exports={};const{browser}=require("@web/core/browser/browser");const{isVisible}=require("@web/core/utils/ui");const{delay,Mutex}=require("@web/core/utils/concurrency");const{validate}=require("@odoo/owl");const macroSchema={name:{type:String,optional:true},checkDelay:{type:Number,optional:true},stepDelay:{type:Number,optional:true},timeout:{type:Number,optional:true},steps:{type:Array,element:{type:Object,shape:{action:{type:[Function,String],optional:true},initialDelay:{type:Function,optional:true},timeout:{type:Number,optional:true},trigger:{type:[Function,String],optional:true},value:{type:[String,Number],optional:true},},validate:(step)=>{return step.action||step.trigger;},},},onComplete:{type:Function,optional:true},onStep:{type:Function,optional:true},onError:{type:Function,optional:true},};const mutex=new Mutex();class MacroError extends Error{constructor(type,message,options){super(message,options);this.type=type;}} __exports.waitForStable=waitForStable;async function waitForStable(target=document,timeout=1000/16){return new Promise((resolve)=>{let observer;let timer;const mutationList=[];function onMutation(mutations){mutationList.push(...(mutations||[]));clearTimeout(timer);timer=setTimeout(()=>{observer.disconnect();resolve(mutationList);},timeout);} observer=new MacroMutationObserver(onMutation);observer.observe(target);onMutation([]);});} const Macro=__exports.Macro=class Macro{currentIndex=0;isComplete=false;calledBack=false;constructor(descr){try{validate(descr,macroSchema);}catch(error){throw new Error(`Error in schema for Macro ${JSON.stringify(descr, null, 4)}\n${error.message}`);} Object.assign(this,descr);this.name=this.name||"anonymous";this.onComplete=this.onComplete||(()=>{});this.onStep=this.onStep||(()=>{});this.onError=this.onError||((e)=>{console.error(e);});this.stepElFound=new Array(this.steps.length).fill(false);this.stepHasStarted=new Array(this.steps.length).fill(false);this.observer=new MacroMutationObserver(()=>this.debounceAdvance("mutation"));} async start(target=document){this.observer.observe(target);this.debounceAdvance("next");} getDebounceDelay(){let delay=Math.max(this.checkDelay??750,50);if(!this.stepHasStarted[this.currentIndex]){delay=this.currentIndex===0?0:50;this.stepHasStarted[this.currentIndex]=true;if(this.currentStep?.initialDelay){const initialDelay=parseFloat(this.currentStep.initialDelay());delay=initialDelay>=0?initialDelay:delay;}} return delay;} async advance(){if(this.isComplete){return;} if(this.currentStep.trigger){this.setTimer();} let proceedToAction=true;if(this.currentStep.trigger){proceedToAction=this.findTrigger();} if(proceedToAction){this.onStep(this.currentElement,this.currentStep,this.currentIndex);this.clearTimer();const actionResult=await this.stepAction(this.currentElement);if(!actionResult){this.currentIndex++;if(this.currentIndex>=this.steps.length){this.stop();} this.debounceAdvance("next");}}} findTrigger(){const{trigger}=this.currentStep;if(this.isComplete){return;} try{if(typeof trigger==="function"){this.currentElement=trigger();}else if(typeof trigger==="string"){const triggerEl=document.querySelector(trigger);this.currentElement=isVisible(triggerEl)&&triggerEl;}else{throw new Error(`Trigger can only be string or function.`);}}catch(error){this.stop(new MacroError("Trigger",`ERROR during find trigger:\n${error.message}`,{cause:error,}));} return!!this.currentElement;} async stepAction(element){const{action}=this.currentStep;if(this.isComplete||!action){return;} try{return await action(element);}catch(error){this.stop(new MacroError("Action",`ERROR during perform action:\n${error.message}`,{cause:error,}));}} get currentStep(){return this.steps[this.currentIndex];} get currentElement(){return this.stepElFound[this.currentIndex];} set currentElement(value){this.stepElFound[this.currentIndex]=value;} setTimer(){this.clearTimer();const timeout=this.currentStep.timeout||this.timeout;if(timeout>0){this.timer=browser.setTimeout(()=>{this.stop(new MacroError("Timeout",`TIMEOUT step failed to complete within ${timeout} ms.`));},timeout);}} clearTimer(){this.resetDebounce();if(this.timer){browser.clearTimeout(this.timer);}} resetDebounce(){if(this.debouncedAdvance){browser.clearTimeout(this.debouncedAdvance);}} async debounceAdvance(from){this.resetDebounce();if(this.isComplete||(from==="next"&&this.stepHasStarted[this.currentIndex])||(from==="mutation"&&!this.stepHasStarted[this.currentIndex])||(from==="mutation"&&this.currentElement)){return;} if(!this.currentStep&&this.currentIndex===0){await delay(300);this.stop();}else if(from==="next"&&!this.currentStep.trigger){this.advance();}else{this.debouncedAdvance=browser.setTimeout(()=>mutex.exec(()=>this.advance()),this.getDebounceDelay());}} stop(error){this.clearTimer();this.isComplete=true;this.observer.disconnect();if(!this.calledBack){this.calledBack=true;if(error){this.onError(error,this.currentStep,this.currentIndex);}else if(this.currentIndex===this.steps.length){mutex.getUnlockedDef().then(()=>{this.onComplete();});}} return;}} const MacroMutationObserver=__exports.MacroMutationObserver=class MacroMutationObserver{observerOptions={attributes:true,childList:true,subtree:true,characterData:true,};constructor(callback){this.callback=callback;this.observer=new MutationObserver((mutationList,observer)=>{callback(mutationList);mutationList.forEach((mutationRecord)=>Array.from(mutationRecord.addedNodes).forEach((node)=>{let iframes=[];if(String(node.tagName).toLowerCase()==="iframe"){iframes=[node];}else if(node instanceof HTMLElement){iframes=Array.from(node.querySelectorAll("iframe"));} iframes.forEach((iframeEl)=>this.observeIframe(iframeEl,observer,()=>callback()));this.findAllShadowRoots(node).forEach((shadowRoot)=>observer.observe(shadowRoot,this.observerOptions));}));});} disconnect(){this.observer.disconnect();} findAllShadowRoots(node,shadowRoots=[]){if(node.shadowRoot){shadowRoots.push(node.shadowRoot);this.findAllShadowRoots(node.shadowRoot,shadowRoots);} node.childNodes.forEach((child)=>{this.findAllShadowRoots(child,shadowRoots);});return shadowRoots;} observe(target){this.observer.observe(target,this.observerOptions);target.querySelectorAll("iframe").forEach((el)=>this.observeIframe(el,this.observer,()=>this.callback()));this.findAllShadowRoots(target).forEach((shadowRoot)=>{this.observer.observe(shadowRoot,this.observerOptions);});} observeIframe(iframeEl,observer,callback){const observerOptions={attributes:true,childList:true,subtree:true,characterData:true,};const observeIframeContent=()=>{if(iframeEl.contentDocument){iframeEl.contentDocument.addEventListener("load",(event)=>{callback();observer.observe(event.target,observerOptions);});if(!iframeEl.src||iframeEl.contentDocument.readyState==="complete"){callback();observer.observe(iframeEl.contentDocument,observerOptions);}}};observeIframeContent();iframeEl.addEventListener("load",observeIframeContent);}} return __exports;});; /* /web/static/src/core/main_components_container.js */ odoo.define('@web/core/main_components_container',['@odoo/owl','@web/core/registry','@web/core/registry_hook','@web/core/utils/components'],function(require){'use strict';let __exports={};const{Component,xml}=require("@odoo/owl");const{registry}=require("@web/core/registry");const{useRegistry}=require("@web/core/registry_hook");const{ErrorHandler}=require("@web/core/utils/components");const mainComponents=registry.category("main_components");mainComponents.addValidation({Component:{validate:(c)=>c.prototype instanceof Component},props:{type:Object,optional:true}});const MainComponentsContainer=__exports.MainComponentsContainer=class MainComponentsContainer extends Component{static components={ErrorHandler};static props={};static template=xml`
`;setup(){this.Components=useRegistry(mainComponents);} handleComponentError(error,C){this.Components.entries.splice(this.Components.entries.indexOf(C),1);this.render();Promise.resolve().then(()=>{throw error;});}} return __exports;});; /* /web/static/src/core/model_field_selector/model_field_selector.js */ odoo.define('@web/core/model_field_selector/model_field_selector',['@odoo/owl','@web/core/utils/concurrency','@web/core/model_field_selector/model_field_selector_popover','@web/core/model_field_selector/utils','@web/core/popover/popover_hook'],function(require){'use strict';let __exports={};const{Component,onWillStart,onWillUpdateProps,useState}=require("@odoo/owl");const{KeepLast}=require("@web/core/utils/concurrency");const{ModelFieldSelectorPopover}=require("@web/core/model_field_selector/model_field_selector_popover");const{useLoadFieldInfo,useLoadPathDescription}=require("@web/core/model_field_selector/utils");const{usePopover}=require("@web/core/popover/popover_hook");const ModelFieldSelector=__exports.ModelFieldSelector=class ModelFieldSelector extends Component{static template="web._ModelFieldSelector";static components={Popover:ModelFieldSelectorPopover,};static props={resModel:String,path:{optional:true},allowEmpty:{type:Boolean,optional:true},readonly:{type:Boolean,optional:true},showSearchInput:{type:Boolean,optional:true},isDebugMode:{type:Boolean,optional:true},update:{type:Function,optional:true},filter:{type:Function,optional:true},followRelations:{type:Boolean,optional:true},showDebugInput:{type:Boolean,optional:true},};static defaultProps={readonly:true,allowEmpty:false,isDebugMode:false,showSearchInput:true,update:()=>{},followRelations:true,};setup(){this.loadPathDescription=useLoadPathDescription();const loadFieldInfo=useLoadFieldInfo();this.popover=usePopover(this.constructor.components.Popover,{popoverClass:"o_popover_field_selector",onClose:async()=>{if(this.newPath!==null){const fieldInfo=await loadFieldInfo(this.props.resModel,this.newPath);this.props.update(this.newPath,fieldInfo);}},});this.keepLast=new KeepLast();this.state=useState({isInvalid:false,displayNames:[]});onWillStart(()=>this.updateState(this.props));onWillUpdateProps((nextProps)=>this.updateState(nextProps));} openPopover(currentTarget){if(this.props.readonly){return;} this.newPath=null;this.popover.open(currentTarget,{resModel:this.props.resModel,path:this.props.path,update:(path,_fieldInfo,debug=false)=>{this.newPath=path;if(!debug){this.updateState({...this.props,path},true);}},showSearchInput:this.props.showSearchInput,isDebugMode:this.props.isDebugMode,filter:this.props.filter,followRelations:this.props.followRelations,showDebugInput:this.props.showDebugInput,});} async updateState(params,isConcurrent){const{resModel,path,allowEmpty}=params;let prom=this.loadPathDescription(resModel,path,allowEmpty);if(isConcurrent){prom=this.keepLast.add(prom);} const state=await prom;Object.assign(this.state,state);} clear(){if(this.popover.isOpen){this.newPath="";this.popover.close();return;} this.props.update("",{resModel:this.props.resModel,fieldDef:null});}} return __exports;});; /* /web/static/src/core/model_field_selector/model_field_selector_popover.js */ odoo.define('@web/core/model_field_selector/model_field_selector_popover',['@odoo/owl','@web/core/utils/timing','@web/core/l10n/translation','@web/core/utils/search','@web/core/utils/concurrency','@web/core/utils/arrays','@web/core/utils/hooks'],function(require){'use strict';let __exports={};const{Component,onWillStart,useEffect,useRef,useState}=require("@odoo/owl");const{debounce}=require("@web/core/utils/timing");const{_t}=require("@web/core/l10n/translation");const{fuzzyLookup}=require("@web/core/utils/search");const{KeepLast}=require("@web/core/utils/concurrency");const{sortBy}=require("@web/core/utils/arrays");const{useService}=require("@web/core/utils/hooks");class Page{constructor(resModel,fieldDefs,options={}){this.resModel=resModel;this.fieldDefs=fieldDefs;const{previousPage=null,selectedName=null,isDebugMode}=options;this.previousPage=previousPage;this.selectedName=selectedName;this.isDebugMode=isDebugMode;this.sortedFieldNames=sortBy(Object.keys(fieldDefs),(key)=>fieldDefs[key].string);this.fieldNames=this.sortedFieldNames;this.query="";this.focusedFieldName=null;this.resetFocusedFieldName();} get path(){const previousPath=this.previousPage?.path||"";if(this.selectedName){if(previousPath){return`${previousPath}.${this.selectedName}`;}else{return this.selectedName;}} return previousPath;} get selectedField(){return this.fieldDefs[this.selectedName];} get title(){const prefix=this.previousPage?.previousPage?"... > ":"";const title=this.previousPage?.selectedField?.string||"";if(prefix.length||title.length){return`${prefix}${title}`;} return _t("Select a field");} focus(direction){if(!this.fieldNames.length){return;} const index=this.fieldNames.indexOf(this.focusedFieldName);if(direction==="previous"){if(index===0){this.focusedFieldName=this.fieldNames[this.fieldNames.length-1];}else{this.focusedFieldName=this.fieldNames[index-1];}}else{if(index===this.fieldNames.length-1){this.focusedFieldName=this.fieldNames[0];}else{this.focusedFieldName=this.fieldNames[index+1];}}} resetFocusedFieldName(){if(this.selectedName&&this.fieldNames.includes(this.selectedName)){this.focusedFieldName=this.selectedName;}else{this.focusedFieldName=this.fieldNames.length?this.fieldNames[0]:null;}} searchFields(query=""){this.query=query;this.fieldNames=this.sortedFieldNames;if(query){this.fieldNames=fuzzyLookup(query,this.fieldNames,(key)=>{const vals=[this.fieldDefs[key].string];if(this.isDebugMode){vals.push(key);} return vals;});} this.resetFocusedFieldName();}} const ModelFieldSelectorPopover=__exports.ModelFieldSelectorPopover=class ModelFieldSelectorPopover extends Component{static template="web.ModelFieldSelectorPopover";static props={close:Function,filter:{type:Function,optional:true},followRelations:{type:Boolean,optional:true},showDebugInput:{type:Boolean,optional:true},isDebugMode:{type:Boolean,optional:true},path:{optional:true},resModel:String,showSearchInput:{type:Boolean,optional:true},update:Function,};static defaultProps={filter:(value)=>value.searchable&&value.type!="json",isDebugMode:false,followRelations:true,};setup(){this.fieldService=useService("field");this.state=useState({page:null});this.keepLast=new KeepLast();this.debouncedSearchFields=debounce(this.searchFields.bind(this),250);onWillStart(async()=>{this.state.page=await this.loadPages(this.props.resModel,this.props.path);});const rootRef=useRef("root");useEffect(()=>{const focusedElement=rootRef.el.querySelector(".o_model_field_selector_popover_item.active");if(focusedElement){focusedElement.scrollIntoView({block:"center"});}});useEffect(()=>{if(this.props.showSearchInput){const searchInput=rootRef.el.querySelector(".o_model_field_selector_popover_search .o_input");searchInput.focus();}},()=>[this.state.page]);} get showDebugInput(){return this.props.showDebugInput??this.props.isDebugMode;} filter(fieldDefs,path){const filteredKeys=Object.keys(fieldDefs).filter((k)=>this.props.filter(fieldDefs[k],path));return Object.fromEntries(filteredKeys.map((k)=>[k,fieldDefs[k]]));} async followRelation(fieldDef){const{modelsInfo}=await this.keepLast.add(this.fieldService.loadPath(this.state.page.resModel,`${fieldDef.name}.*`));this.state.page.selectedName=fieldDef.name;const{resModel,fieldDefs}=modelsInfo.at(-1);this.openPage(new Page(resModel,this.filter(fieldDefs,this.state.page.path),{previousPage:this.state.page,isDebugMode:this.props.isDebugMode,}));} goToPreviousPage(){this.keepLast.add(Promise.resolve());this.openPage(this.state.page.previousPage);} async loadNewPath(path){const newPage=await this.keepLast.add(this.loadPages(this.props.resModel,path));this.openPage(newPage);} async loadPages(resModel,path){if(typeof path!=="string"||!path.length){const fieldDefs=await this.fieldService.loadFields(resModel);return new Page(resModel,this.filter(fieldDefs,path),{isDebugMode:this.props.isDebugMode,});} const{isInvalid,modelsInfo,names}=await this.fieldService.loadPath(resModel,path);switch(isInvalid){case"model":throw new Error(`Invalid model name: ${resModel}`);case"path":{const{resModel,fieldDefs}=modelsInfo[0];return new Page(resModel,this.filter(fieldDefs,path),{selectedName:path,isDebugMode:this.props.isDebugMode,});} default:{let page=null;for(let index=0;index{if(typeof path!=="string"||!path){return{resModel,fieldDef:null};} const{isInvalid,names,modelsInfo}=await fieldService.loadPath(resModel,path);if(isInvalid){return{resModel,fieldDef:null};} const name=names.at(-1);const modelInfo=modelsInfo.at(-1);return{resModel:modelInfo.resModel,fieldDef:modelInfo.fieldDefs[name]};};} __exports.useLoadPathDescription=useLoadPathDescription;function useLoadPathDescription(fieldService){fieldService||=useService("field");return async(resModel,path,allowEmpty)=>{if([0,1].includes(path)){return{isInvalid:false,displayNames:[makeString(path)]};} if(allowEmpty&&!path){return{isInvalid:false,displayNames:[]};} if(typeof path!=="string"||!path){return{isInvalid:true,displayNames:[makeString()]};} const{isInvalid,modelsInfo,names}=await fieldService.loadPath(resModel,path);const result={isInvalid:!!isInvalid,displayNames:[]};if(!isInvalid){const lastName=names.at(-1);const lastFieldDef=modelsInfo.at(-1).fieldDefs[lastName];if(["properties","properties_definition"].includes(lastFieldDef.type)){result.isInvalid=true;}} for(let index=0;index{if(!this.props.models){this.models=await this._fetchAvailableModels();}else{this.models=await this.orm.call("ir.model","display_name_for",[this.props.models,]);} this.models=this.models.map((record)=>({label:record.display_name,technical:record.model,classList:{[`o_model_selector_${record.model}`]:1,},}));});} get sources(){return[this.optionsSource];} get optionsSource(){return{placeholder:_t("Loading..."),options:this.loadOptionsSource.bind(this),};} onSelect(option){this.props.onModelSelected({label:option.label,technical:option.technical,});} filterModels(name){if(!name){const visibleModels=this.models.slice(0,8);if(this.models.length-visibleModels.length>0){visibleModels.push({label:_t("Start typing..."),unselectable:true,classList:"o_m2o_start_typing",});} return visibleModels;} return fuzzyLookup(name,this.models,(model)=>model.technical+model.label);} loadOptionsSource(request){const options=this.filterModels(request);if(!options.length){options.push({label:_t("No records"),classList:"o_m2o_no_result",unselectable:true,});} return options;} async _fetchAvailableModels(){const result=await this.orm.call("ir.model","get_available_models");return result||[];}} return __exports;});; /* /web/static/src/core/name_service.js */ odoo.define('@web/core/name_service',['@web/core/registry','@web/core/utils/arrays','@web/core/utils/concurrency'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{unique,zip}=require("@web/core/utils/arrays");const{Deferred}=require("@web/core/utils/concurrency");const ERROR_INACCESSIBLE_OR_MISSING=__exports.ERROR_INACCESSIBLE_OR_MISSING=Symbol("INACCESSIBLE OR MISSING RECORD ID");function isId(val){return Number.isInteger(val)&&val>=1;} const nameService=__exports.nameService={dependencies:["orm"],async:["loadDisplayNames"],start(env,{orm}){let cache={};const batches={};function clearCache(){cache={};} env.bus.addEventListener("ACTION_MANAGER:UPDATE",clearCache);function getMapping(resModel){if(!cache[resModel]){cache[resModel]={};} return cache[resModel];} function addDisplayNames(resModel,displayNames){const mapping=getMapping(resModel);for(const resId in displayNames){mapping[resId]=new Deferred();mapping[resId].resolve(displayNames[resId]);}} async function loadDisplayNames(resModel,resIds){const mapping=getMapping(resModel);const proms=[];const resIdsToFetch=[];for(const resId of unique(resIds)){if(!isId(resId)){throw new Error(`Invalid ID: ${resId}`);} if(!(resId in mapping)){mapping[resId]=new Deferred();resIdsToFetch.push(resId);} proms.push(mapping[resId]);} if(resIdsToFetch.length){if(batches[resModel]){batches[resModel].push(...resIdsToFetch);}else{batches[resModel]=resIdsToFetch;await Promise.resolve();const idsInBatch=unique(batches[resModel]);delete batches[resModel];const specification={display_name:{}};orm.silent.webSearchRead(resModel,[["id","in",idsInBatch]],{specification}).then(({records})=>{const displayNames=Object.fromEntries(records.map((rec)=>[rec.id,rec.display_name]));for(const resId of idsInBatch){mapping[resId].resolve(resId in displayNames?displayNames[resId]:ERROR_INACCESSIBLE_OR_MISSING);}});}} const names=await Promise.all(proms);return Object.fromEntries(zip(resIds,names));} return{addDisplayNames,clearCache,loadDisplayNames};},};registry.category("services").add("name",nameService);return __exports;});; /* /web/static/src/core/navigation/navigation.js */ odoo.define('@web/core/navigation/navigation',['@odoo/owl','@web/core/utils/hooks','@web/core/utils/scrolling','@web/core/utils/timing'],function(require){'use strict';let __exports={};const{useEffect,useRef}=require("@odoo/owl");const{useService}=require("@web/core/utils/hooks");const{scrollTo}=require("@web/core/utils/scrolling");const{debounce,throttleForAnimation}=require("@web/core/utils/timing");const ACTIVE_ELEMENT_CLASS="focus";const throttledElementFocus=throttleForAnimation((el)=>el?.focus());function focusElement(el){throttledElementFocus.cancel();throttledElementFocus(el);} class NavigationItem{constructor({index,el,setActiveItem,options}){this.index=index;this.options=options;this.setActiveItem=setActiveItem;this.el=el;if(options.shouldFocusChildInput){const subInput=el.querySelector(":scope input, :scope button, :scope textarea");this.target=subInput||el;}else{this.target=el;} const focus=()=>this.focus(true);const onMouseEnter=(ev)=>this.onMouseEnter(ev);this.target.addEventListener("focus",focus);this.target.addEventListener("mouseenter",onMouseEnter);this.removeListeners=()=>{this.target.removeEventListener("focus",focus);this.target.removeEventListener("mouseenter",onMouseEnter);};} select(){this.focus();this.target.click();} focus(skipRealFocus=false){scrollTo(this.target);this.setActiveItem(this.index,this);this.target.classList.add(ACTIVE_ELEMENT_CLASS);if(!skipRealFocus&&!this.options.virtualFocus){focusElement(this.target);}} defocus(){this.target.classList.remove(ACTIVE_ELEMENT_CLASS);} onMouseEnter(){this.focus(true);this.options.onMouseEnter?.(this);}} class Navigator{constructor(containerRef,options,hotkeyService){this.enabled=false;this.containerRef=containerRef;const focusAt=(increment)=>{const isFocused=this.activeItem?.el.isConnected;const index=this.currentActiveIndex+increment;if(isFocused&&index>=0){return this.items[index%this.items.length]?.focus();}else if(!isFocused&&increment>=0){return this.items[0]?.focus();}else{return this.items.at(-1)?.focus();}};this.options={shouldFocusChildInput:true,virtualFocus:false,itemsSelector:":scope .o-navigable",focusInitialElementOnDisabled:()=>true,...options,hotkeys:{home:(index,items)=>items[0]?.focus(),end:(index,items)=>items.at(-1)?.focus(),tab:()=>focusAt(+1),"shift+tab":()=>focusAt(-1),arrowdown:()=>focusAt(+1),arrowup:()=>focusAt(-1),enter:(index,items)=>{const item=items[index]||items[0];item?.select();},...(options?.hotkeys||{}),},};this.items=[];this.activeItem=undefined;this.currentActiveIndex=-1;this.initialFocusElement=undefined;this.debouncedUpdate=debounce(()=>this.update(),100);this.hotkeyRemoves=[];this.hotkeyService=hotkeyService;this.allowedInEditableHotkeys=["arrowup","arrowdown","enter","tab","shift+tab"];} enable(){if(!this.containerRef.el||this.targetObserver){return;} for(const[hotkey,callback]of Object.entries(this.options.hotkeys)){if(!callback){continue;} this.hotkeyRemoves.push(this.hotkeyService.add(hotkey,()=>callback(this.currentActiveIndex,this.items),{allowRepeat:true,bypassEditableProtection:this.allowedInEditableHotkeys.includes(hotkey),}));} this.targetObserver=new MutationObserver(()=>this.debouncedUpdate());this.targetObserver.observe(this.containerRef.el,{childList:true,subtree:true,});this.initialFocusElement=document.activeElement;this.currentActiveIndex=-1;this.update();if(this.options.onEnabled){this.options.onEnabled(this.items);}else if(this.items.length>0){this.items[0]?.focus();} this.enabled=true;} disable(){if(!this.enabled){return;} if(this.targetObserver){this.targetObserver.disconnect();this.targetObserver=undefined;} this.clearItems();for(const removeHotkey of this.hotkeyRemoves){removeHotkey();} this.hotkeyRemoves=[];if(this.options.focusInitialElementOnDisabled()){focusElement(this.initialFocusElement);} this.enabled=false;} update(){if(!this.containerRef.el){return;} const oldItemsLength=this.items.length;this.clearItems();const elements=[...this.containerRef.el.querySelectorAll(this.options.itemsSelector)];this.items=elements.map((el,index)=>{return new NavigationItem({index,el,options:this.options,setActiveItem:(index,el)=>this.setActiveItem(index,el),});});if(oldItemsLength!=this.items.length&&this.currentActiveIndex>=this.items.length){this.items.at(-1)?.focus();}} setActiveItem(index,item){if(this.activeItem){this.activeItem.el.classList.remove(ACTIVE_ELEMENT_CLASS);} this.activeItem=item;this.currentActiveIndex=index;} clearItems(){for(const item of this.items){item.removeListeners();} this.items=[];}} __exports.useNavigation=useNavigation;function useNavigation(containerRef,options={}){const hotkeyService=useService("hotkey");containerRef=typeof containerRef==="string"?useRef(containerRef):containerRef;const navigator=new Navigator(containerRef,options,hotkeyService);useEffect((container)=>{if(container){navigator.enable();}else if(navigator){navigator.disable();}},()=>[containerRef.el]);return{enable:()=>navigator.enable(),disable:()=>navigator.disable(),};} return __exports;});; /* /web/static/src/core/network/download.js */ odoo.define('@web/core/network/download',['@web/core/l10n/translation','@web/core/network/rpc','@web/core/browser/browser'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{makeErrorFromResponse,ConnectionLostError}=require("@web/core/network/rpc");const{browser}=require("@web/core/browser/browser");const HEX_ESCAPE_REPLACE_REGEXP=/%([0-9A-Fa-f]{2})/g;const NON_LATIN1_REGEXP=/[^\x20-\x7e\xa0-\xff]/g;const QESC_REGEXP=/\\([\u0000-\u007f])/g;const PARAM_REGEXP=/;[\x09\x20]*([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*=[\x09\x20]*("(?:[\x20!\x23-\x5b\x5d-\x7e\x80-\xff]|\\[\x20-\x7e])*"|[!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*/g;const EXT_VALUE_REGEXP=/^([A-Za-z0-9!#$%&+\-^_`{}~]+)'(?:[A-Za-z]{2,3}(?:-[A-Za-z]{3}){0,3}|[A-Za-z]{4,8}|)'((?:%[0-9A-Fa-f]{2}|[A-Za-z0-9!#$&+.^_`|~-])+)$/;const DISPOSITION_TYPE_REGEXP=/^([!#$%&'*+.0-9A-Z^_`a-z|~-]+)[\x09\x20]*(?:$|;)/;function decodefield(str){const match=EXT_VALUE_REGEXP.exec(str);if(!match){throw new TypeError("invalid extended field value");} const charset=match[1].toLowerCase();const encoded=match[2];switch(charset){case"iso-8859-1":return encoded.replace(HEX_ESCAPE_REPLACE_REGEXP,pdecode).replace(NON_LATIN1_REGEXP,"?");case"utf-8":return decodeURIComponent(encoded);default:throw new TypeError("unsupported charset in extended field");}} function parse(string){if(!string||typeof string!=="string"){throw new TypeError("argument string is required");} let match=DISPOSITION_TYPE_REGEXP.exec(string);if(!match){throw new TypeError("invalid type format");} let index=match[0].length;const type=match[1].toLowerCase();let key;const names=[];const params={};let value;index=PARAM_REGEXP.lastIndex=match[0].substr(-1)===";"?index-1:index;while((match=PARAM_REGEXP.exec(string))){if(match.index!==index){throw new TypeError("invalid parameter format");} index+=match[0].length;key=match[1].toLowerCase();value=match[2];if(names.indexOf(key)!==-1){throw new TypeError("invalid duplicate parameter");} names.push(key);if(key.indexOf("*")+1===key.length){key=key.slice(0,-1);value=decodefield(value);params[key]=value;continue;} if(typeof params[key]==="string"){continue;} if(value[0]==='"'){value=value.substr(1,value.length-2).replace(QESC_REGEXP,"$1");} params[key]=value;} if(index!==-1&&index!==string.length){throw new TypeError("invalid parameter format");} return new ContentDisposition(type,params);} function pdecode(str,hex){return String.fromCharCode(parseInt(hex,16));} function ContentDisposition(type,parameters){this.type=type;this.parameters=parameters;} function _download(data,filename,mimetype){let self=window,defaultMime="application/octet-stream",mimeType=mimetype||defaultMime,payload=data,url=!filename&&!mimetype&&payload,anchor=document.createElement("a"),toString=function(a){return String(a);},myBlob=self.Blob||self.MozBlob||self.WebKitBlob||toString,fileName=filename||"download",blob,reader;myBlob=myBlob.call?myBlob.bind(self):Blob;if(String(this)==="true"){payload=[payload,mimeType];mimeType=payload[0];payload=payload[1];} if(url&&url.length<2048){fileName=url.split("/").pop().split("?")[0];anchor.href=url;if(anchor.href.indexOf(url)!==-1){return new Promise((resolve,reject)=>{let xhr=new browser.XMLHttpRequest();xhr.open("GET",url,true);configureBlobDownloadXHR(xhr,{onSuccess:resolve,onFailure:reject,url});xhr.send();});}} if(/^data:[\w+\-]+\/[\w+\-]+[,;]/.test(payload)){if(payload.length>1024*1024*1.999&&myBlob!==toString){payload=dataUrlToBlob(payload);mimeType=payload.type||defaultMime;}else{return navigator.msSaveBlob?navigator.msSaveBlob(dataUrlToBlob(payload),fileName):saver(payload);}} blob=payload instanceof myBlob?payload:new myBlob([payload],{type:mimeType});function dataUrlToBlob(strUrl){let parts=strUrl.split(/[:;,]/),type=parts[1],decoder=parts[2]==="base64"?atob:decodeURIComponent,binData=decoder(parts.pop()),mx=binData.length,i=0,uiArr=new Uint8Array(mx);for(i;i{anchor.click();document.body.removeChild(anchor);if(winMode===true){setTimeout(()=>{self.URL.revokeObjectURL(anchor.href);},250);}},66);return true;} if(/(Version)\/(\d+)\.(\d+)(?:\.(\d+))?.*Safari\//.test(navigator.userAgent)){url=url.replace(/^data:([\w\/\-+]+)/,defaultMime);if(!window.open(url)){if(confirm("Displaying New Document\n\nUse Save As... to download, then click back to return to this page.")){location.href=url;}} return true;} let f=document.createElement("iframe");document.body.appendChild(f);if(!winMode){url=`data:${url.replace(/^data:([\w\/\-+]+)/, defaultMime)}`;} f.src=url;setTimeout(()=>{document.body.removeChild(f);},333);} if(navigator.msSaveBlob){return navigator.msSaveBlob(blob,fileName);} if(self.URL){saver(self.URL.createObjectURL(blob),true);}else{if(typeof blob==="string"||blob.constructor===toString){try{return saver(`data:${mimeType};base64,${self.btoa(blob)}`);}catch{return saver(`data:${mimeType},${encodeURIComponent(blob)}`);}} reader=new FileReader();reader.onload=function(){saver(this.result);};reader.readAsDataURL(blob);} return true;} __exports.downloadFile=downloadFile;function downloadFile(data,filename,mimetype){return downloadFile._download(data,filename,mimetype);} downloadFile._download=_download;__exports.download=download;function download(options){return download._download(options);} download._download=(options)=>{return new Promise((resolve,reject)=>{const xhr=new browser.XMLHttpRequest();let data;if(Object.prototype.hasOwnProperty.call(options,"form")){xhr.open(options.form.method,options.form.action);data=new FormData(options.form);}else{xhr.open("POST",options.url);data=new FormData();Object.entries(options.data).forEach((entry)=>{const[key,value]=entry;data.append(key,value);});} data.append("token","dummy-because-api-expects-one");if(odoo.csrf_token){data.append("csrf_token",odoo.csrf_token);} configureBlobDownloadXHR(xhr,{onSuccess:resolve,onFailure:reject,url:options.url,});xhr.send(data);});};__exports.configureBlobDownloadXHR=configureBlobDownloadXHR;function configureBlobDownloadXHR(xhr,{onSuccess=()=>{},onFailure=()=>{},url}={}){xhr.responseType="blob";xhr.onload=()=>{const mimetype=xhr.response.type;const header=(xhr.getResponseHeader("Content-Disposition")||"").replace(/;$/,"");const filename=header?parse(header).parameters.filename:null;if(xhr.status===200&&(mimetype!=="text/html"||filename)){_download(xhr.response,filename,mimetype);onSuccess(filename);}else if(xhr.status===502){onFailure(new ConnectionLostError(url));}else{const decoder=new FileReader();decoder.onload=()=>{const contents=decoder.result;const doc=new DOMParser().parseFromString(contents,"text/html");const nodes=doc.body.children.length===0?[doc.body]:doc.body.children;let error;try{const node=nodes[1]||nodes[0];error=JSON.parse(node.textContent);}catch{error={message:"Arbitrary Uncaught Python Exception",data:{debug:`${xhr.status}`+`\n`+`${nodes.length > 0 ? nodes[0].textContent : ""} ${nodes.length > 1 ? nodes[1].textContent : ""}`,},};} error=makeErrorFromResponse(error);onFailure(error);};decoder.readAsText(xhr.response);}};xhr.onerror=()=>{onFailure(new ConnectionLostError(url));};} return __exports;});; /* /web/static/src/core/network/http_service.js */ odoo.define('@web/core/network/http_service',['@web/core/browser/browser','@web/core/registry'],function(require){'use strict';let __exports={};const{browser}=require("@web/core/browser/browser");const{registry}=require("@web/core/registry");function checkResponseStatus(response){if(response.status===502){throw new Error("Failed to fetch");}} __exports.get=get;async function get(route,readMethod="json"){const response=await browser.fetch(route,{method:"GET"});checkResponseStatus(response);return response[readMethod]();} __exports.post=post;async function post(route,params={},readMethod="json"){let formData=params;if(!(formData instanceof FormData)){formData=new FormData();for(const key in params){const value=params[key];if(Array.isArray(value)&&value.length){for(const val of value){formData.append(key,val);}}else{formData.append(key,value);}}} const response=await browser.fetch(route,{body:formData,method:"POST",});checkResponseStatus(response);return response[readMethod]();} const httpService=__exports.httpService={start(){return{get,post};},};registry.category("services").add("http",httpService);return __exports;});; /* /web/static/src/core/network/rpc.js */ odoo.define('@web/core/network/rpc',['@odoo/owl','@web/core/browser/browser'],function(require){'use strict';let __exports={};const{EventBus}=require("@odoo/owl");const{browser}=require("@web/core/browser/browser");const rpcBus=__exports.rpcBus=new EventBus();const RPCError=__exports.RPCError=class RPCError extends Error{constructor(){super(...arguments);this.name="RPC_ERROR";this.type="server";this.code=null;this.data=null;this.exceptionName=null;this.subType=null;}} const ConnectionLostError=__exports.ConnectionLostError=class ConnectionLostError extends Error{constructor(url,...args){super(`Connection to "${url}" couldn't be established or was interrupted`,...args);this.url=url;}} const ConnectionAbortedError=__exports.ConnectionAbortedError=class ConnectionAbortedError extends Error{} __exports.makeErrorFromResponse=makeErrorFromResponse;function makeErrorFromResponse(reponse){const{code,data:errorData,message,type:subType}=reponse;const error=new RPCError();error.exceptionName=errorData.name;error.subType=subType;error.data=errorData;error.message=message;error.code=code;return error;} let rpcId=0;__exports.rpc=rpc;function rpc(url,params={},settings={}){return rpc._rpc(url,params,settings);} rpc._rpc=function(url,params,settings){const XHR=browser.XMLHttpRequest;const data={id:rpcId++,jsonrpc:"2.0",method:"call",params:params,};const request=settings.xhr||new XHR();let rejectFn;const promise=new Promise((resolve,reject)=>{rejectFn=reject;rpcBus.trigger("RPC:REQUEST",{data,url,settings});request.addEventListener("load",()=>{if(request.status===502){const error=new ConnectionLostError(url);rpcBus.trigger("RPC:RESPONSE",{data,settings,error});reject(error);return;} let params;try{params=JSON.parse(request.response);}catch{const error=new ConnectionLostError(url);rpcBus.trigger("RPC:RESPONSE",{data,settings,error});return reject(error);} const{error:responseError,result:responseResult}=params;if(!params.error){rpcBus.trigger("RPC:RESPONSE",{data,settings,result:params.result});return resolve(responseResult);} const error=makeErrorFromResponse(responseError);error.id=data.id;error.model=data.params.model;rpcBus.trigger("RPC:RESPONSE",{data,settings,error});reject(error);});request.addEventListener("error",()=>{const error=new ConnectionLostError(url);rpcBus.trigger("RPC:RESPONSE",{data,settings,error});reject(error);});request.open("POST",url);const headers=settings.headers||{};headers["Content-Type"]="application/json";for(let[header,value]of Object.entries(headers)){request.setRequestHeader(header,value);} request.send(JSON.stringify(data));});promise.abort=function(rejectError=true){if(request.abort){request.abort();} const error=new ConnectionAbortedError("XmlHttpRequestError abort");rpcBus.trigger("RPC:RESPONSE",{data,settings,error});if(rejectError){rejectFn(error);}};return promise;};return __exports;});; /* /web/static/src/core/notebook/notebook.js */ odoo.define('@web/core/notebook/notebook',['@web/core/utils/scrolling','@odoo/owl','@web/core/browser/browser'],function(require){'use strict';let __exports={};const{scrollTo}=require("@web/core/utils/scrolling");const{Component,onWillUpdateProps,useEffect,useExternalListener,useRef,useState,}=require("@odoo/owl");const{browser}=require("@web/core/browser/browser");const Notebook=__exports.Notebook=class Notebook extends Component{static template="web.Notebook";static defaultProps={className:"",orientation:"horizontal",onPageUpdate:()=>{},};static props={slots:{type:Object,optional:true},pages:{type:Object,optional:true},class:{optional:true},className:{type:String,optional:true},anchors:{type:Object,optional:true},defaultPage:{type:String,optional:true},orientation:{type:String,optional:true},icons:{type:Object,optional:true},onPageUpdate:{type:Function,optional:true},};setup(){this.activePane=useRef("activePane");this.anchorTarget=null;this.pages=this.computePages(this.props);this.state=useState({currentPage:null});this.state.currentPage=this.computeActivePage(this.props.defaultPage,true);useExternalListener(browser,"click",this.onAnchorClicked);useEffect(()=>{this.props.onPageUpdate(this.state.currentPage);if(this.anchorTarget){const matchingEl=this.activePane.el.querySelector(`#${this.anchorTarget}`);scrollTo(matchingEl,{isAnchor:true});this.anchorTarget=null;} this.activePane.el?.classList.add("show");},()=>[this.state.currentPage]);onWillUpdateProps((nextProps)=>{const activateDefault=this.props.defaultPage!==nextProps.defaultPage||!this.defaultVisible;this.pages=this.computePages(nextProps);this.state.currentPage=this.computeActivePage(nextProps.defaultPage,activateDefault);});} get navItems(){return this.pages.filter((e)=>e[1].isVisible);} get page(){const page=this.pages.find((e)=>e[0]===this.state.currentPage)[1];return page.Component&&page;} onAnchorClicked(ev){if(!this.props.anchors){return;} const href=ev.target.closest("a")?.getAttribute("href");if(!href){return;} const id=href.substring(1);if(this.props.anchors[id]){if(this.state.currentPage!==this.props.anchors[id].target){ev.preventDefault();this.anchorTarget=id;this.state.currentPage=this.props.anchors[id].target;}}} activatePage(pageIndex){if(!this.disabledPages.includes(pageIndex)&&this.state.currentPage!==pageIndex){this.activePane.el?.classList.remove("show");this.state.currentPage=pageIndex;}} computePages(props){if(!props.slots&&!props.pages){return[];} if(props.pages){for(const page of props.pages){page.isVisible=true;}} this.disabledPages=[];const pages=[];const pagesWithIndex=[];for(const[k,v]of Object.entries({...props.slots,...props.pages})){const id=v.id||k;if(v.index){pagesWithIndex.push([id,v]);}else{pages.push([id,v]);} if(v.isDisabled){this.disabledPages.push(k);}} for(const page of pagesWithIndex){pages.splice(page[1].index,0,page);} return pages;} computeActivePage(defaultPage,activateDefault){if(!this.pages.length){return null;} const pages=this.pages.filter((e)=>e[1].isVisible).map((e)=>e[0]);if(defaultPage){if(!pages.includes(defaultPage)){this.defaultVisible=false;}else{this.defaultVisible=true;if(activateDefault){return defaultPage;}}} const current=this.state.currentPage;if(!current||(current&&!pages.includes(current))){return pages[0];} return current;}} return __exports;});; /* /web/static/src/core/notifications/notification.js */ odoo.define('@web/core/notifications/notification',['@odoo/owl'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const Notification=__exports.Notification=class Notification extends Component{static template="web.NotificationWowl";static props={message:{validate:(m)=>{return(typeof m==="string"||(typeof m==="object"&&typeof m.toString==="function"));},},title:{type:[String,Boolean,{toString:Function}],optional:true},type:{type:String,optional:true,validate:(t)=>["warning","danger","success","info"].includes(t),},className:{type:String,optional:true},buttons:{type:Array,element:{type:Object,shape:{name:{type:String},icon:{type:String,optional:true},primary:{type:Boolean,optional:true},onClick:Function,},},optional:true,},close:{type:Function},refresh:{type:Function},freeze:{type:Function},};static defaultProps={buttons:[],className:"",type:"warning",};} return __exports;});; /* /web/static/src/core/notifications/notification_container.js */ odoo.define('@web/core/notifications/notification_container',['@web/core/notifications/notification','@web/core/transition','@odoo/owl'],function(require){'use strict';let __exports={};const{Notification}=require("@web/core/notifications/notification");const{Transition}=require("@web/core/transition");const{Component,xml,useState}=require("@odoo/owl");const NotificationContainer=__exports.NotificationContainer=class NotificationContainer extends Component{static props={notifications:Object,};static template=xml`
`;static components={Notification,Transition};setup(){this.notifications=useState(this.props.notifications);}} return __exports;});; /* /web/static/src/core/notifications/notification_service.js */ odoo.define('@web/core/notifications/notification_service',['@web/core/browser/browser','@web/core/registry','@web/core/notifications/notification_container','@odoo/owl'],function(require){'use strict';let __exports={};const{browser}=require("@web/core/browser/browser");const{registry}=require("@web/core/registry");const{NotificationContainer}=require("@web/core/notifications/notification_container");const{reactive}=require("@odoo/owl");const AUTOCLOSE_DELAY=4000;const notificationService=__exports.notificationService={notificationContainer:NotificationContainer,start(){let notifId=0;const notifications=reactive({});registry.category("main_components").add(this.notificationContainer.name,{Component:this.notificationContainer,props:{notifications},},{sequence:100});function add(message,options={}){const id=++notifId;const closeFn=()=>close(id);const props=Object.assign({},options,{message,close:closeFn});const autocloseDelay=options.autocloseDelay??AUTOCLOSE_DELAY;const sticky=props.sticky;delete props.sticky;delete props.onClose;delete props.autocloseDelay;let closeTimeout;const refresh=sticky?()=>{}:()=>{closeTimeout=browser.setTimeout(closeFn,autocloseDelay);};const freeze=sticky?()=>{}:()=>{browser.clearTimeout(closeTimeout);};props.refresh=refreshAll;props.freeze=freezeAll;const notification={id,props,onClose:options.onClose,refresh,freeze,};notifications[id]=notification;if(!sticky){closeTimeout=browser.setTimeout(closeFn,autocloseDelay);} return closeFn;} function refreshAll(){for(const id in notifications){notifications[id].refresh();}} function freezeAll(){for(const id in notifications){notifications[id].freeze();}} function close(id){if(notifications[id]){const notification=notifications[id];if(notification.onClose){notification.onClose();} delete notifications[id];}} return{add};},};registry.category("services").add("notification",notificationService);return __exports;});; /* /web/static/src/core/orm_service.js */ odoo.define('@web/core/orm_service',['@web/core/registry','@web/core/network/rpc','@web/core/user'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{rpc}=require("@web/core/network/rpc");const{user}=require("@web/core/user");const x2ManyCommands=__exports.x2ManyCommands={CREATE:0,create(virtualID,values){delete values.id;return[x2ManyCommands.CREATE,virtualID||false,values];},UPDATE:1,update(id,values){delete values.id;return[x2ManyCommands.UPDATE,id,values];},DELETE:2,delete(id){return[x2ManyCommands.DELETE,id,false];},UNLINK:3,unlink(id){return[x2ManyCommands.UNLINK,id,false];},LINK:4,link(id){return[x2ManyCommands.LINK,id,false];},CLEAR:5,clear(){return[x2ManyCommands.CLEAR,false,false];},SET:6,set(ids){return[x2ManyCommands.SET,false,ids];},};function validateModel(value){if(typeof value!=="string"||value.length===0){throw new Error(`Invalid model name: ${value}`);}} function validatePrimitiveList(name,type,value){if(!Array.isArray(value)||value.some((val)=>typeof val!==type)){throw new Error(`Invalid ${name} list: ${value}`);}} function validateObject(name,obj){if(typeof obj!=="object"||obj===null||Array.isArray(obj)){throw new Error(`${name} should be an object`);}} function validateArray(name,array){if(!Array.isArray(array)){throw new Error(`${name} should be an array`);}} const UPDATE_METHODS=__exports.UPDATE_METHODS=["unlink","create","write","web_save","action_archive","action_unarchive",];const ORM=__exports.ORM=class ORM{constructor(){this.rpc=rpc;this._silent=false;} get silent(){return Object.assign(Object.create(this),{_silent:true});} call(model,method,args=[],kwargs={}){validateModel(model);const url=`/web/dataset/call_kw/${model}/${method}`;const fullContext=Object.assign({},user.context,kwargs.context||{});const fullKwargs=Object.assign({},kwargs,{context:fullContext});const params={model,method,args,kwargs:fullKwargs,};return this.rpc(url,params,{silent:this._silent});} create(model,records,kwargs={}){validateArray("records",records);for(const record of records){validateObject("record",record);} return this.call(model,"create",[records],kwargs);} read(model,ids,fields,kwargs={}){validatePrimitiveList("ids","number",ids);if(fields){validatePrimitiveList("fields","string",fields);} if(!ids.length){return Promise.resolve([]);} return this.call(model,"read",[ids,fields],kwargs);} readGroup(model,domain,fields,groupby,kwargs={}){validateArray("domain",domain);validatePrimitiveList("fields","string",fields);validatePrimitiveList("groupby","string",groupby);groupby=[...new Set(groupby)];return this.call(model,"read_group",[],{...kwargs,domain,fields,groupby});} search(model,domain,kwargs={}){validateArray("domain",domain);return this.call(model,"search",[domain],kwargs);} searchRead(model,domain,fields,kwargs={}){validateArray("domain",domain);if(fields){validatePrimitiveList("fields","string",fields);} return this.call(model,"search_read",[],{...kwargs,domain,fields});} searchCount(model,domain,kwargs={}){validateArray("domain",domain);return this.call(model,"search_count",[domain],kwargs);} unlink(model,ids,kwargs={}){validatePrimitiveList("ids","number",ids);if(!ids.length){return Promise.resolve(true);} return this.call(model,"unlink",[ids],kwargs);} webReadGroup(model,domain,fields,groupby,kwargs={}){validateArray("domain",domain);validatePrimitiveList("fields","string",fields);validatePrimitiveList("groupby","string",groupby);return this.call(model,"web_read_group",[],{...kwargs,groupby,domain,fields,});} webRead(model,ids,kwargs={}){validatePrimitiveList("ids","number",ids);return this.call(model,"web_read",[ids],kwargs);} webSearchRead(model,domain,kwargs={}){validateArray("domain",domain);return this.call(model,"web_search_read",[],{...kwargs,domain});} write(model,ids,data,kwargs={}){validatePrimitiveList("ids","number",ids);validateObject("data",data);return this.call(model,"write",[ids,data],kwargs);} webSave(model,ids,data,kwargs={}){validatePrimitiveList("ids","number",ids);validateObject("data",data);return this.call(model,"web_save",[ids,data],kwargs);}} const ormService=__exports.ormService={async:["call","create","nameGet","read","readGroup","search","searchRead","unlink","webSearchRead","write",],start(){return new ORM();},};registry.category("services").add("orm",ormService);return __exports;});; /* /web/static/src/core/overlay/overlay_container.js */ odoo.define('@web/core/overlay/overlay_container',['@odoo/owl','@web/core/utils/arrays','@web/core/utils/components'],function(require){'use strict';let __exports={};const{Component,onWillDestroy,useChildSubEnv,useEffect,useRef,useState}=require("@odoo/owl");const{sortBy}=require("@web/core/utils/arrays");const{ErrorHandler}=require("@web/core/utils/components");const OVERLAY_ITEMS=[];const OVERLAY_SYMBOL=__exports.OVERLAY_SYMBOL=Symbol("Overlay");class OverlayItem extends Component{static template="web.OverlayContainer.Item";static components={};static props={component:{type:Function},props:{type:Object},env:{type:Object,optional:true},};setup(){this.rootRef=useRef("rootRef");OVERLAY_ITEMS.push(this);onWillDestroy(()=>{const index=OVERLAY_ITEMS.indexOf(this);OVERLAY_ITEMS.splice(index,1);});if(this.props.env){this.__owl__.childEnv=this.props.env;} useChildSubEnv({[OVERLAY_SYMBOL]:{contains:(target)=>this.contains(target),},});} get subOverlays(){return OVERLAY_ITEMS.slice(OVERLAY_ITEMS.indexOf(this));} contains(target){return(this.rootRef.el?.contains(target)||this.subOverlays.some((oi)=>oi.rootRef.el?.contains(target)));}} const OverlayContainer=__exports.OverlayContainer=class OverlayContainer extends Component{static template="web.OverlayContainer";static components={ErrorHandler,OverlayItem};static props={overlays:Object};setup(){this.root=useRef("root");this.state=useState({rootEl:null});useEffect(()=>{this.state.rootEl=this.root.el;},()=>[this.root.el]);} get sortedOverlays(){return sortBy(Object.values(this.props.overlays),(overlay)=>overlay.sequence);} isVisible(overlay){return overlay.rootId===this.state.rootEl?.getRootNode()?.host?.id;} handleError(overlay,error){overlay.remove();Promise.resolve().then(()=>{throw error;});}} return __exports;});; /* /web/static/src/core/overlay/overlay_service.js */ odoo.define('@web/core/overlay/overlay_service',['@odoo/owl','@web/core/registry','@web/core/overlay/overlay_container'],function(require){'use strict';let __exports={};const{markRaw,reactive}=require("@odoo/owl");const{registry}=require("@web/core/registry");const{OverlayContainer}=require("@web/core/overlay/overlay_container");const mainComponents=registry.category("main_components");const services=registry.category("services");const overlayService=__exports.overlayService={start(){let nextId=0;const overlays=reactive({});mainComponents.add("OverlayContainer",{Component:OverlayContainer,props:{overlays},});const remove=(id,onRemove=()=>{})=>{if(id in overlays){onRemove();delete overlays[id];}};const add=(component,props,options={})=>{const id=++nextId;const removeCurrentOverlay=()=>remove(id,options.onRemove);overlays[id]={id,component,env:options.env&&markRaw(options.env),props,remove:removeCurrentOverlay,sequence:options.sequence??50,rootId:options.rootId,};return removeCurrentOverlay;};return{add,overlays};},};services.add("overlay",overlayService);return __exports;});; /* /web/static/src/core/pager/pager.js */ odoo.define('@web/core/pager/pager',['@web/core/utils/hooks','@web/core/utils/numbers','@odoo/owl'],function(require){'use strict';let __exports={};const{useAutofocus}=require("@web/core/utils/hooks");const{clamp}=require("@web/core/utils/numbers");const{Component,useExternalListener,useState,EventBus}=require("@odoo/owl");const PAGER_UPDATED_EVENT=__exports.PAGER_UPDATED_EVENT="PAGER:UPDATED";const pagerBus=__exports.pagerBus=new EventBus();const Pager=__exports.Pager=class Pager extends Component{static template="web.Pager";static defaultProps={isEditable:true,withAccessKey:true,};static props={offset:Number,limit:Number,total:Number,onUpdate:Function,isEditable:{type:Boolean,optional:true},withAccessKey:{type:Boolean,optional:true},updateTotal:{type:Function,optional:true},};setup(){this.state=useState({isEditing:false,isDisabled:false,});this.inputRef=useAutofocus();useExternalListener(document,"mousedown",this.onClickAway,{capture:true});} get minimum(){return this.props.offset+1;} get maximum(){return Math.min(this.props.offset+this.props.limit,this.props.total);} get value(){const parts=[this.minimum];if(this.props.limit>1){parts.push(this.maximum);} return parts.join("-");} get isSinglePage(){return!this.props.updateTotal&&this.minimum===1&&this.maximum===this.props.total;} async navigate(direction){let minimum=this.props.offset+this.props.limit*direction;let total=this.props.total;if(this.props.updateTotal&&minimum<0){total=await this.props.updateTotal();} if(minimum>=total){if(!this.props.updateTotal){minimum=0;}}else if(minimum<0&&this.props.limit===1){minimum=total-1;}else if(minimum<0&&this.props.limit>1){minimum=total-(total%this.props.limit||this.props.limit);} this.update(minimum,this.props.limit,true);} async parse(value){let[minimum,maximum]=value.trim().split(/\s*[-\s,;]\s*/);minimum=parseInt(minimum,10);maximum=maximum?parseInt(maximum,10):minimum;if(this.props.updateTotal){return{minimum:minimum-1,maximum};} return{minimum:clamp(minimum,1,this.props.total)-1,maximum:clamp(maximum,1,this.props.total),};} async setValue(value){const{minimum,maximum}=await this.parse(value);if(!isNaN(minimum)&&!isNaN(maximum)&&minimum{this.state.show=false;},1400);}} registry.category("main_components").add("PagerIndicator",{Component:PagerIndicator,});return __exports;});; /* /web/static/src/core/popover/popover.js */ odoo.define('@web/core/popover/popover',['@odoo/owl','@web/core/hotkeys/hotkey_hook','@web/core/overlay/overlay_container','@web/core/position/position_hook','@web/core/ui/ui_service','@web/core/utils/classname','@web/core/utils/hooks'],function(require){'use strict';let __exports={};const{Component,onMounted,onWillDestroy,useComponent,useRef}=require("@odoo/owl");const{useHotkey}=require("@web/core/hotkeys/hotkey_hook");const{OVERLAY_SYMBOL}=require("@web/core/overlay/overlay_container");const{usePosition}=require("@web/core/position/position_hook");const{useActiveElement}=require("@web/core/ui/ui_service");const{addClassesToElement,mergeClasses}=require("@web/core/utils/classname");const{useForwardRefToParent}=require("@web/core/utils/hooks");function useEarlyExternalListener(target,eventName,handler,eventParams){const component=useComponent();const boundHandler=handler.bind(component);target.addEventListener(eventName,boundHandler,eventParams);onWillDestroy(()=>target.removeEventListener(eventName,boundHandler,eventParams));} function useClickAway(callback){const pointerDownHandler=(event)=>{callback(event.composedPath()[0]);};const blurHandler=(ev)=>{const target=ev.relatedTarget||document.activeElement;if(target?.tagName==="IFRAME"){callback(target);}};useEarlyExternalListener(window,"pointerdown",pointerDownHandler,{capture:true});useEarlyExternalListener(window,"blur",blurHandler,{capture:true});} const POPOVERS=new WeakMap();__exports.getPopoverForTarget=getPopoverForTarget;function getPopoverForTarget(target){return POPOVERS.get(target);} const Popover=__exports.Popover=class Popover extends Component{static template="web.Popover";static defaultProps={animation:true,arrow:true,class:"",closeOnClickAway:()=>true,closeOnEscape:true,componentProps:{},fixedPosition:false,position:"bottom",setActiveElement:false,};static props={component:{type:Function},componentProps:{optional:true,type:Object},target:{validate:(target)=>{const Element=target?.ownerDocument?.defaultView?.Element;return((Boolean(Element)&&(target instanceof Element||target instanceof window.Element))||(typeof target==="object"&&target?.constructor?.name?.endsWith("Element")));},},animation:{optional:true,type:Boolean},arrow:{optional:true,type:Boolean},class:{optional:true},role:{optional:true,type:String},fixedPosition:{optional:true,type:Boolean},holdOnHover:{optional:true,type:Boolean},onPositioned:{optional:true,type:Function},position:{optional:true,type:String,validate:(p)=>{const[d,v="middle"]=p.split("-");return(["top","bottom","left","right"].includes(d)&&["start","middle","end","fit"].includes(v));},},close:{optional:true,type:Function},closeOnClickAway:{optional:true,type:Function},closeOnEscape:{optional:true,type:Boolean},setActiveElement:{optional:true,type:Boolean},ref:{optional:true,type:Function},slots:{optional:true,type:Object},};static animationTime=200;setup(){if(this.props.setActiveElement){useActiveElement("ref");} useForwardRefToParent("ref");this.popoverRef=useRef("ref");let shouldAnimate=this.props.animation;this.position=usePosition("ref",()=>this.props.target,{onPositioned:(el,solution)=>{(this.props.onPositioned||this.onPositioned.bind(this))(el,solution);if(this.props.arrow&&this.props.onPositioned){this.onPositioned.bind(this)(el,solution);} if(shouldAnimate){shouldAnimate=false;const transform={top:["translateY(-5%)","translateY(0)"],right:["translateX(5%)","translateX(0)"],bottom:["translateY(5%)","translateY(0)"],left:["translateX(-5%)","translateX(0)"],}[solution.direction];this.position.lock();const animation=el.animate({opacity:[0,1],transform},this.constructor.animationTime);animation.finished.then(this.position.unlock);} if(this.props.fixedPosition){this.position.lock();}},position:this.props.position,});onMounted(()=>POPOVERS.set(this.props.target,this.popoverRef.el));onWillDestroy(()=>POPOVERS.delete(this.props.target));if(!this.props.close){return;} if(this.props.target.isConnected){useClickAway((target)=>this.onClickAway(target));if(this.props.closeOnEscape){useHotkey("escape",()=>this.props.close());} const targetObserver=new MutationObserver(this.onTargetMutate.bind(this));targetObserver.observe(this.props.target.parentElement,{childList:true});onWillDestroy(()=>targetObserver.disconnect());}else{this.props.close();}} get defaultClassObj(){return mergeClasses("o_popover popover mw-100",{"o-popover--with-arrow":this.props.arrow},this.props.class);} isInside(target){return(this.props.target?.contains(target)||this.popoverRef?.el?.contains(target)||this.env[OVERLAY_SYMBOL]?.contains(target));} onClickAway(target){if(this.props.closeOnClickAway(target)&&!this.isInside(target)){this.props.close();}} onTargetMutate(){if(!this.props.target.isConnected){this.props.close();}} onPositioned(el,{direction,variant}){const position=`${direction[0]}${variant[0]}`;el.classList=[];const directionMap={top:"top",bottom:"bottom",left:"start",right:"end",};addClassesToElement(el,this.defaultClassObj,`bs-popover-${directionMap[direction]}`,`o-popover-${direction}`,`o-popover--${position}`);if(this.props.arrow){const arrowEl=el.querySelector(":scope > .popover-arrow");arrowEl.className="popover-arrow";switch(position){case"tm":case"bm":case"tf":case"bf":arrowEl.classList.add("start-0","end-0","mx-auto");break;case"lm":case"rm":case"lf":case"rf":arrowEl.classList.add("top-0","bottom-0","my-auto");break;case"ts":case"bs":arrowEl.classList.add("end-auto");break;case"te":case"be":arrowEl.classList.add("start-auto");break;case"ls":case"rs":arrowEl.classList.add("bottom-auto");break;case"le":case"re":arrowEl.classList.add("top-auto");break;}}}} return __exports;});; /* /web/static/src/core/popover/popover_hook.js */ odoo.define('@web/core/popover/popover_hook',['@odoo/owl','@web/core/utils/hooks'],function(require){'use strict';let __exports={};const{onWillUnmount,status,useComponent}=require("@odoo/owl");const{useService}=require("@web/core/utils/hooks");__exports.makePopover=makePopover;function makePopover(addFn,component,options){let removeFn=null;function close(){removeFn?.();} return{open(target,props){close();const newOptions=Object.create(options);newOptions.onClose=()=>{removeFn=null;options.onClose?.();};removeFn=addFn(target,component,props,newOptions);},close,get isOpen(){return Boolean(removeFn);},};} __exports.usePopover=usePopover;function usePopover(component,options={}){const popoverService=useService("popover");const owner=useComponent();const newOptions=Object.create(options);newOptions.onClose=()=>{if(status(owner)!=="destroyed"){options.onClose?.();}};const popover=makePopover(popoverService.add,component,newOptions);onWillUnmount(popover.close);return popover;} return __exports;});; /* /web/static/src/core/popover/popover_service.js */ odoo.define('@web/core/popover/popover_service',['@odoo/owl','@web/core/popover/popover','@web/core/registry'],function(require){'use strict';let __exports={};const{markRaw}=require("@odoo/owl");const{Popover}=require("@web/core/popover/popover");const{registry}=require("@web/core/registry");const popoverService=__exports.popoverService={dependencies:["overlay"],start(_,{overlay}){const add=(target,component,props={},options={})=>{const closeOnClickAway=typeof options.closeOnClickAway==="function"?options.closeOnClickAway:()=>options.closeOnClickAway??true;const remove=overlay.add(Popover,{target,close:()=>remove(),closeOnClickAway,closeOnEscape:options.closeOnEscape,component,componentProps:markRaw(props),ref:options.ref,class:options.popoverClass,animation:options.animation,arrow:options.arrow,role:options.popoverRole,position:options.position,onPositioned:options.onPositioned,fixedPosition:options.fixedPosition,holdOnHover:options.holdOnHover,setActiveElement:options.setActiveElement??true,},{env:options.env,onRemove:options.onClose,rootId:target.getRootNode()?.host?.id,});return remove;};return{add};},};registry.category("services").add("popover",popoverService);return __exports;});; /* /web/static/src/core/position/position_hook.js */ odoo.define('@web/core/position/position_hook',['@web/core/position/utils','@web/core/utils/objects','@web/core/utils/timing','@odoo/owl'],function(require){'use strict';let __exports={};const{reposition}=require("@web/core/position/utils");const{omit}=require("@web/core/utils/objects");const{useThrottleForAnimation}=require("@web/core/utils/timing");const{EventBus,onWillDestroy,useChildSubEnv,useComponent,useEffect,useRef,}=require("@odoo/owl");const DEFAULTS={margin:0,position:"bottom",};const POSITION_BUS=Symbol("position-bus");__exports.usePosition=usePosition;function usePosition(refName,getTarget,options={}){const ref=useRef(refName);let lock=false;const update=()=>{const targetEl=getTarget();if(!ref.el||!targetEl?.isConnected||lock){return;} const repositionOptions={...DEFAULTS,...omit(options,"onPositioned")};const solution=reposition(ref.el,targetEl,repositionOptions);options.onPositioned?.(ref.el,solution);};const component=useComponent();const bus=component.env[POSITION_BUS]||new EventBus();let executingUpdate=false;const batchedUpdate=async()=>{if(!executingUpdate){executingUpdate=true;update();await Promise.resolve();executingUpdate=false;}};bus.addEventListener("update",batchedUpdate);onWillDestroy(()=>bus.removeEventListener("update",batchedUpdate));const isTopmost=!(POSITION_BUS in component.env);if(isTopmost){useChildSubEnv({[POSITION_BUS]:bus});} const throttledUpdate=useThrottleForAnimation(()=>bus.trigger("update"));useEffect(()=>{bus.trigger("update");if(isTopmost){const scrollListener=(e)=>{if(ref.el?.contains(e.target)){return;} throttledUpdate();};const targetDocument=getTarget()?.ownerDocument;targetDocument?.addEventListener("scroll",scrollListener,{capture:true});targetDocument?.addEventListener("load",throttledUpdate,{capture:true});window.addEventListener("resize",throttledUpdate);return()=>{targetDocument?.removeEventListener("scroll",scrollListener,{capture:true});targetDocument?.removeEventListener("load",throttledUpdate,{capture:true});window.removeEventListener("resize",throttledUpdate);};}});return{lock:()=>{lock=true;},unlock:()=>{lock=false;bus.trigger("update");},};} return __exports;});; /* /web/static/src/core/position/utils.js */ odoo.define('@web/core/position/utils',['@web/core/l10n/localization'],function(require){'use strict';let __exports={};const{localization}=require("@web/core/l10n/localization");const DIRECTIONS={t:"top",r:"right",b:"bottom",l:"left"};const VARIANTS={s:"start",m:"middle",e:"end",f:"fit"};const DIRECTION_FLIP_ORDER={top:"tbrl",right:"rltb",bottom:"btrl",left:"lrbt"};const VARIANT_FLIP_ORDER={start:"sme",middle:"mse",end:"ems",fit:"f"};const FIT_FLIP_ORDER={top:"tb",right:"rl",bottom:"bt",left:"lr"};function getIFrame(popperEl,targetEl){return[...popperEl.ownerDocument.getElementsByTagName("iframe")].find((iframe)=>iframe.contentDocument?.contains(targetEl));} function computePosition(popper,target,{container,margin,position}){let[direction,variant="middle"]=position.split("-");if(localization.direction==="rtl"){if(["left","right"].includes(direction)){direction=direction==="left"?"right":"left";}else if(["start","end"].includes(variant)){variant=variant==="start"?"end":"start";}} const directions=variant==="fit"?FIT_FLIP_ORDER[direction]:DIRECTION_FLIP_ORDER[direction];const variants=VARIANT_FLIP_ORDER[variant];if(!container){container=popper.ownerDocument.documentElement;}else if(typeof container==="function"){container=container();} const popperStyle=getComputedStyle(popper);const{marginTop,marginLeft,marginRight,marginBottom}=popperStyle;const popMargins={top:parseFloat(marginTop),left:parseFloat(marginLeft),right:parseFloat(marginRight),bottom:parseFloat(marginBottom),};const shouldAccountForIFrame=popper.ownerDocument!==target.ownerDocument;const iframe=shouldAccountForIFrame?getIFrame(popper,target):null;const popBox=popper.getBoundingClientRect();const targetBox=target.getBoundingClientRect();const contBox=container.getBoundingClientRect();const iframeBox=iframe?.getBoundingClientRect()??{top:0,left:0};const containerIsHTMLNode=container===container.ownerDocument.firstElementChild;const directionsData={t:iframeBox.top+targetBox.top-popMargins.bottom-margin-popBox.height,b:iframeBox.top+targetBox.bottom+popMargins.top+margin,r:iframeBox.left+targetBox.right+popMargins.left+margin,l:iframeBox.left+targetBox.left-popMargins.right-margin-popBox.width,};const variantsData={vf:iframeBox.left+targetBox.left,vs:iframeBox.left+targetBox.left+popMargins.left,vm:iframeBox.left+targetBox.left+targetBox.width/2-popBox.width/2,ve:iframeBox.left+targetBox.right-popMargins.right-popBox.width,hf:iframeBox.top+targetBox.top,hs:iframeBox.top+targetBox.top+popMargins.top,hm:iframeBox.top+targetBox.top+targetBox.height/2-popBox.height/2,he:iframeBox.top+targetBox.bottom-popMargins.bottom-popBox.height,};function getPositioningData(d=directions[0],v=variants[0],containerRestricted=false){const vertical=["t","b"].includes(d);const variantPrefix=vertical?"v":"h";const directionValue=directionsData[d];const variantValue=variantsData[variantPrefix+v];if(containerRestricted){const[directionSize,variantSize]=vertical?[popBox.height,popBox.width]:[popBox.width,popBox.height];let[directionMin,directionMax]=vertical?[contBox.top,contBox.bottom]:[contBox.left,contBox.right];let[variantMin,variantMax]=vertical?[contBox.left,contBox.right]:[contBox.top,contBox.bottom];if(containerIsHTMLNode){if(vertical){directionMin+=container.scrollTop;directionMax+=container.scrollTop;}else{variantMin+=container.scrollTop;variantMax+=container.scrollTop;}} const directionOverflow=Math.ceil(directionValue)Math.ceil(directionMax);const variantOverflow=Math.ceil(variantValue)Math.ceil(variantMax);if(directionOverflow||variantOverflow){return null;}} const positioning=vertical?{top:directionValue,left:variantValue}:{top:variantValue,left:directionValue};return{top:positioning.top-popBox.top,left:positioning.left-popBox.left,direction:DIRECTIONS[d],variant:VARIANTS[v],};} for(const d of directions){for(const v of variants){const match=getPositioningData(d,v,true);if(match){return match;}}} return getPositioningData();} __exports.reposition=reposition;function reposition(popper,target,options){popper.style.position="fixed";popper.style.top="0px";popper.style.left="0px";const solution=computePosition(popper,target,options);const{top,left,direction,variant}=solution;popper.style.top=`${top}px`;popper.style.left=`${left}px`;if(variant==="fit"){const styleProperty=["top","bottom"].includes(direction)?"width":"height";popper.style[styleProperty]=target.getBoundingClientRect()[styleProperty]+"px";} return solution;} return __exports;});; /* /web/static/src/core/pwa/install_prompt.js */ odoo.define('@web/core/pwa/install_prompt',['@odoo/owl','@web/core/dialog/dialog','@web/core/browser/feature_detection'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const{Dialog}=require("@web/core/dialog/dialog");const{isIOS}=require("@web/core/browser/feature_detection");const InstallPrompt=__exports.InstallPrompt=class InstallPrompt extends Component{static props={close:true,onClose:{type:Function},};static components={Dialog,};static template="web.InstallPrompt";get isMobileSafari(){return isIOS();} onClose(){this.props.close();this.props.onClose();}} return __exports;});; /* /web/static/src/core/pwa/pwa_service.js */ odoo.define('@web/core/pwa/pwa_service',['@odoo/owl','@web/core/browser/browser','@web/core/browser/feature_detection','@web/core/network/http_service','@web/core/registry','@web/core/pwa/install_prompt'],function(require){'use strict';let __exports={};const{reactive}=require("@odoo/owl");const{browser}=require("@web/core/browser/browser");const{isDisplayStandalone,isIOS,isMacOS,isBrowserSafari,}=require("@web/core/browser/feature_detection");const{get}=require("@web/core/network/http_service");const{registry}=require("@web/core/registry");const{InstallPrompt}=require("@web/core/pwa/install_prompt");const serviceRegistry=registry.category("services");let BEFOREINSTALLPROMPT_EVENT;let REGISTER_BEFOREINSTALLPROMPT_EVENT;browser.addEventListener("beforeinstallprompt",(ev)=>{if(REGISTER_BEFOREINSTALLPROMPT_EVENT){return REGISTER_BEFOREINSTALLPROMPT_EVENT(ev);}else{BEFOREINSTALLPROMPT_EVENT=ev;}});const pwaService={dependencies:["dialog"],start(env,{dialog}){let _manifest;let nativePrompt;const state=reactive({canPromptToInstall:false,isAvailable:false,isScopedApp:browser.location.href.includes("/scoped_app"),isSupportedOnBrowser:false,startUrl:"/odoo",decline,getManifest,hasScopeBeenInstalled,show,});function _getInstallationState(scope=state.startUrl){const installationState=browser.localStorage.getItem("pwaService.installationState");return installationState?JSON.parse(installationState)[scope]:"";} function _setInstallationState(value){const ls=JSON.parse(browser.localStorage.getItem("pwaService.installationState")||"{}");ls[state.startUrl]=value;browser.localStorage.setItem("pwaService.installationState",JSON.stringify(ls));} function _removeInstallationState(){const ls=JSON.parse(browser.localStorage.getItem("pwaService.installationState"));delete ls[state.startUrl];browser.localStorage.setItem("pwaService.installationState",JSON.stringify(ls));} if(state.isScopedApp){if(browser.location.pathname==="/scoped_app"){state.startUrl="/"+new URL(browser.location.href).searchParams.get("path");}else{state.startUrl=browser.location.pathname;}} state.isSupportedOnBrowser=browser.BeforeInstallPromptEvent!==undefined||(isBrowserSafari()&&!isDisplayStandalone()&&(isIOS()||(isMacOS()&&browser.navigator.userAgent.match(/Version\/(\d+)/)[1]>=17)));const installationState=_getInstallationState();if(state.isSupportedOnBrowser){if(BEFOREINSTALLPROMPT_EVENT){_handleBeforeInstallPrompt(BEFOREINSTALLPROMPT_EVENT,installationState);BEFOREINSTALLPROMPT_EVENT=null;} REGISTER_BEFOREINSTALLPROMPT_EVENT=(ev)=>{_handleBeforeInstallPrompt(ev,installationState);};if(isBrowserSafari()){state.canPromptToInstall=installationState!=="dismissed";state.isAvailable=true;}} function _handleBeforeInstallPrompt(ev,installationState){nativePrompt=ev;if(installationState==="accepted"){if(!isDisplayStandalone()){_removeInstallationState();}} state.canPromptToInstall=installationState!=="dismissed";state.isAvailable=true;} async function getManifest(){if(!_manifest){const manifest=await get(document.querySelector("link[rel=manifest")?.getAttribute("href"),"text");_manifest=JSON.parse(manifest);} return _manifest;} function hasScopeBeenInstalled(scope){return _getInstallationState(scope)==="accepted";} async function show({onDone}={}){if(!state.isAvailable){return;} if(nativePrompt){const res=await nativePrompt.prompt();_setInstallationState(res.outcome);state.canPromptToInstall=false;if(onDone){onDone(res);}}else if(isBrowserSafari()){dialog.add(InstallPrompt,{onClose:()=>{if(onDone){onDone({});} this.decline();},});}} function decline(){_setInstallationState("dismissed");state.canPromptToInstall=false;} return state;},};serviceRegistry.add("pwa",pwaService);return __exports;});; /* /web/static/src/core/py_js/py.js */ odoo.define('@web/core/py_js/py',['@web/core/py_js/py_interpreter','@web/core/py_js/py_parser','@web/core/py_js/py_tokenizer','@web/core/py_js/py_utils'],function(require){'use strict';let __exports={};const{evaluate}=require("@web/core/py_js/py_interpreter");const{parse}=require("@web/core/py_js/py_parser");const{tokenize}=require("@web/core/py_js/py_tokenizer");{const{evaluate}=require("@web/core/py_js/py_interpreter");Object.assign(__exports,{evaluate})};{const{parse}=require("@web/core/py_js/py_parser");Object.assign(__exports,{parse})};{const{tokenize}=require("@web/core/py_js/py_tokenizer");Object.assign(__exports,{tokenize})};{const{formatAST}=require("@web/core/py_js/py_utils");Object.assign(__exports,{formatAST})};__exports.parseExpr=parseExpr;function parseExpr(expr){const tokens=tokenize(expr);return parse(tokens);} __exports.evaluateExpr=evaluateExpr;function evaluateExpr(expr,context={}){let ast;try{ast=parseExpr(expr);}catch(error){throw new EvalError(`Can not parse python expression: (${expr})\nError: ${error.message}`);} try{return evaluate(ast,context);}catch(error){throw new EvalError(`Can not evaluate python expression: (${expr})\nError: ${error.message}`);}} __exports.evaluateBooleanExpr=evaluateBooleanExpr;function evaluateBooleanExpr(expr,context={}){if(!expr||expr==='False'||expr==='0'){return false;} if(expr==='True'||expr==='1'){return true;} return evaluateExpr(`bool(${expr})`,context);} return __exports;});; /* /web/static/src/core/py_js/py_builtin.js */ odoo.define('@web/core/py_js/py_builtin',['@web/core/py_js/py_date'],function(require){'use strict';let __exports={};const{PyDate,PyDateTime,PyRelativeDelta,PyTime,PyTimeDelta}=require("@web/core/py_js/py_date");const EvaluationError=__exports.EvaluationError=class EvaluationError extends Error{} __exports.execOnIterable=execOnIterable;function execOnIterable(iterable,func){if(iterable===null){throw new EvaluationError(`value not iterable`);} if(typeof iterable==="object"&&!Array.isArray(iterable)&&!(iterable instanceof Set)){iterable=Object.keys(iterable);} if(typeof iterable?.[Symbol.iterator]!=="function"){throw new EvaluationError(`value not iterable`);} return func(iterable);} const BUILTINS=__exports.BUILTINS={bool(value){switch(typeof value){case"number":return value!==0;case"string":return value!=="";case"boolean":return value;case"object":if(value===null||value===undefined){return false;} if(value.isTrue){return value.isTrue();} if(value instanceof Array){return!!value.length;} if(value instanceof Set){return!!value.size;} return Object.keys(value).length!==0;} return true;},set(iterable){if(arguments.length>2){throw new EvaluationError(`set expected at most 1 argument, got (${arguments.length - 1}`);} return execOnIterable(iterable,(iterable)=>{return new Set(iterable);});},max(...args){return Math.max(...args.slice(0,-1));},min(...args){return Math.min(...args.slice(0,-1));},time:{strftime(format){return PyDateTime.now().strftime(format);},},context_today(){return PyDate.today();},get current_date(){return this.today;},get today(){return PyDate.today().strftime("%Y-%m-%d");},get now(){return PyDateTime.now().strftime("%Y-%m-%d %H:%M:%S");},datetime:{time:PyTime,timedelta:PyTimeDelta,datetime:PyDateTime,date:PyDate,},relativedelta:PyRelativeDelta,true:true,false:false,};return __exports;});; /* /web/static/src/core/py_js/py_date.js */ odoo.define('@web/core/py_js/py_date',['@web/core/py_js/py_parser'],function(require){'use strict';let __exports={};const{parseArgs}=require("@web/core/py_js/py_parser");const AssertionError=__exports.AssertionError=class AssertionError extends Error{} const ValueError=__exports.ValueError=class ValueError extends Error{} const NotSupportedError=__exports.NotSupportedError=class NotSupportedError extends Error{} function fmt2(n){return String(n).padStart(2,"0");} function fmt4(n){return String(n).padStart(4,"0");} function divmod(a,b,fn){let mod=a%b;if((mod>0&&b<0)||(mod<0&&b>0)){mod+=b;} return fn(Math.floor(a/b),mod);} function assert(bool,message="AssertionError"){if(!bool){throw new AssertionError(message);}} const DAYS_IN_MONTH=[null,31,28,31,30,31,30,31,31,30,31,30,31];const DAYS_BEFORE_MONTH=[null];for(let dbm=0,i=1;i2&&isLeap(year);return DAYS_BEFORE_MONTH[month]+(postLeapFeb?1:0);} function ymd2ord(year,month,day){const dim=daysInMonth(year,month);if(!(1<=day&&day<=dim)){throw new ValueError(`day must be in 1..${dim}`);} return daysBeforeYear(year)+daysBeforeMonth(year,month)+day;} const DI400Y=daysBeforeYear(401);const DI100Y=daysBeforeYear(101);const DI4Y=daysBeforeYear(5);function ord2ymd(n){--n;let n400,n100,n4,n1,n0;divmod(n,DI400Y,function(_n400,n){n400=_n400;divmod(n,DI100Y,function(_n100,n){n100=_n100;divmod(n,DI4Y,function(_n4,n){n4=_n4;divmod(n,365,function(_n1,n){n1=_n1;n0=n;});});});});n=n0;const year=n400*400+1+n100*100+n4*4+n1;if(n1==4||n100==100){assert(n0===0);return{year:year-1,month:12,day:31,};} const leapyear=n1===3&&(n4!==24||n100==3);assert(leapyear==isLeap(year));let month=(n+50)>>5;let preceding=DAYS_BEFORE_MONTH[month]+(month>2&&leapyear?1:0);if(preceding>n){--month;preceding-=DAYS_IN_MONTH[month]+(month===2&&leapyear?1:0);} n-=preceding;return{year:year,month:month,day:n+1,};} function tmxxx(year,month,day,hour,minute,second,microsecond){hour=hour||0;minute=minute||0;second=second||0;microsecond=microsecond||0;if(microsecond<0||microsecond>999999){divmod(microsecond,1000000,function(carry,ms){microsecond=ms;second+=carry;});} if(second<0||second>59){divmod(second,60,function(carry,s){second=s;minute+=carry;});} if(minute<0||minute>59){divmod(minute,60,function(carry,m){minute=m;hour+=carry;});} if(hour<0||hour>23){divmod(hour,24,function(carry,h){hour=h;day+=carry;});} if(month<1||month>12){divmod(month-1,12,function(carry,m){month=m+1;year+=carry;});} const dim=daysInMonth(year,month);if(day<1||day>dim){if(day===0){--month;if(month>0){day=daysInMonth(year,month);}else{--year;month=12;day=31;}}else if(day==dim+1){++month;day=1;if(month>12){month=1;++year;}}else{const r=ord2ymd(ymd2ord(year,month,1)+(day-1));year=r.year;month=r.month;day=r.day;}} return{year:year,month:month,day:day,hour:hour,minute:minute,second:second,microsecond:microsecond,};} const PyDate=__exports.PyDate=class PyDate{static today(){return this.convertDate(new Date());} static convertDate(date){const year=date.getFullYear();const month=date.getMonth()+1;const day=date.getDate();return new PyDate(year,month,day);} constructor(year,month,day){this.year=year;this.month=month;this.day=day;} static create(...args){const{year,month,day}=parseArgs(args,["year","month","day"]);return new PyDate(year,month,day);} add(timedelta){const s=tmxxx(this.year,this.month,this.day+timedelta.days);return new PyDate(s.year,s.month,s.day);} isEqual(other){if(!(other instanceof PyDate)){return false;} return this.year===other.year&&this.month===other.month&&this.day===other.day;} strftime(format){return format.replace(/%([A-Za-z])/g,(m,c)=>{switch(c){case"Y":return fmt4(this.year);case"m":return fmt2(this.month);case"d":return fmt2(this.day);} throw new ValueError(`No known conversion for ${m}`);});} substract(other){if(other instanceof PyTimeDelta){return this.add(other.negate());} if(other instanceof PyDate){return PyTimeDelta.create(this.toordinal()-other.toordinal());} throw NotSupportedError();} toJSON(){return this.strftime("%Y-%m-%d");} toordinal(){return ymd2ord(this.year,this.month,this.day);}} const PyDateTime=__exports.PyDateTime=class PyDateTime{static now(){return this.convertDate(new Date());} static convertDate(date){const year=date.getFullYear();const month=date.getMonth()+1;const day=date.getDate();const hour=date.getHours();const minute=date.getMinutes();const second=date.getSeconds();return new PyDateTime(year,month,day,hour,minute,second,0);} static create(...args){const namedArgs=parseArgs(args,["year","month","day","hour","minute","second","microsecond",]);const year=namedArgs.year;const month=namedArgs.month;const day=namedArgs.day;const hour=namedArgs.hour||0;const minute=namedArgs.minute||0;const second=namedArgs.second||0;const ms=namedArgs.micro/1000||0;return new PyDateTime(year,month,day,hour,minute,second,ms);} static combine(...args){const{date,time}=parseArgs(args,["date","time"]);return PyDateTime.create(date.year,date.month,date.day,time.hour,time.minute,time.second);} constructor(year,month,day,hour,minute,second,microsecond){this.year=year;this.month=month;this.day=day;this.hour=hour;this.minute=minute;this.second=second;this.microsecond=microsecond;} add(timedelta){const s=tmxxx(this.year,this.month,this.day+timedelta.days,this.hour,this.minute,this.second+timedelta.seconds,this.microsecond+timedelta.microseconds);return new PyDateTime(s.year,s.month,s.day,s.hour,s.minute,s.second,s.microsecond);} isEqual(other){if(!(other instanceof PyDateTime)){return false;} return(this.year===other.year&&this.month===other.month&&this.day===other.day&&this.hour===other.hour&&this.minute===other.minute&&this.second===other.second&&this.microsecond===other.microsecond);} strftime(format){return format.replace(/%([A-Za-z])/g,(m,c)=>{switch(c){case"Y":return fmt4(this.year);case"m":return fmt2(this.month);case"d":return fmt2(this.day);case"H":return fmt2(this.hour);case"M":return fmt2(this.minute);case"S":return fmt2(this.second);} throw new ValueError(`No known conversion for ${m}`);});} substract(timedelta){return this.add(timedelta.negate());} toJSON(){return this.strftime("%Y-%m-%d %H:%M:%S");} to_utc(){const d=new Date(this.year,this.month-1,this.day,this.hour,this.minute,this.second);const timedelta=PyTimeDelta.create({minutes:d.getTimezoneOffset()});return this.add(timedelta);}} const PyTime=__exports.PyTime=class PyTime extends PyDate{static create(...args){const namedArgs=parseArgs(args,["hour","minute","second"]);const hour=namedArgs.hour||0;const minute=namedArgs.minute||0;const second=namedArgs.second||0;return new PyTime(hour,minute,second);} constructor(hour,minute,second){const now=new Date();const year=now.getFullYear();const month=now.getMonth();const day=now.getDate();super(year,month,day);this.hour=hour;this.minute=minute;this.second=second;} strftime(format){return format.replace(/%([A-Za-z])/g,(m,c)=>{switch(c){case"Y":return fmt4(this.year);case"m":return fmt2(this.month+1);case"d":return fmt2(this.day);case"H":return fmt2(this.hour);case"M":return fmt2(this.minute);case"S":return fmt2(this.second);} throw new ValueError(`No known conversion for ${m}`);});} toJSON(){return this.strftime("%H:%M:%S");}} const DAYS_IN_YEAR=[31,59,90,120,151,181,212,243,273,304,334,366];const TIME_PERIODS=["hour","minute","second"];const PERIODS=["year","month","day",...TIME_PERIODS];const RELATIVE_KEYS="years months weeks days hours minutes seconds microseconds leapdays".split(" ");const ABSOLUTE_KEYS="year month day hour minute second microsecond weekday nlyearday yearday".split(" ");const argsSpec=["dt1","dt2"];const PyRelativeDelta=__exports.PyRelativeDelta=class PyRelativeDelta{static create(...args){const params=parseArgs(args,argsSpec);if("dt1"in params){throw new Error("relativedelta(dt1, dt2) is not supported for now");} for(const period of PERIODS){if(period in params){const val=params[period];assert(val>=0,`${period} ${val} is out of range`);}} for(const key of RELATIVE_KEYS){params[key]=params[key]||0;} for(const key of ABSOLUTE_KEYS){params[key]=key in params?params[key]:null;} params.days+=7*params.weeks;let yearDay=0;if(params.nlyearday){yearDay=params.nlyearday;}else if(params.yearday){yearDay=params.yearday;if(yearDay>59){params.leapDays=-1;}} if(yearDay){for(let monthIndex=0;monthIndex2&&isLeap(newDateTime.year)){leapDays=delta.leapDays;} const temp=newDateTime.add(PyTimeDelta.create({days:delta.days+leapDays,hours:delta.hours,minutes:delta.minutes,seconds:delta.seconds,microseconds:delta.microseconds,}));const hasTime=Boolean(temp.hour||temp.minute||temp.second||temp.microsecond);const returnDate=!hasTime&&date instanceof PyDate?new PyDate(temp.year,temp.month,temp.day):temp;if(delta.weekday!==null){const wantedDow=delta.weekday+1;const _date=new Date(returnDate.year,returnDate.month-1,returnDate.day);const days=(7-_date.getDay()+wantedDow)%7;return returnDate.add(new PyTimeDelta(days,0,0));} return returnDate;} static substract(date,delta){return PyRelativeDelta.add(date,delta.negate());} constructor(params={},sign=+1){this.years=sign*params.years;this.months=sign*params.months;this.days=sign*params.days;this.hours=sign*params.hours;this.minutes=sign*params.minutes;this.seconds=sign*params.seconds;this.microseconds=sign*params.microseconds;this.leapDays=params.leapDays;this.year=params.year;this.month=params.month;this.day=params.day;this.hour=params.hour;this.minute=params.minute;this.second=params.second;this.microsecond=params.microsecond;this.weekday=params.weekday;} negate(){return new PyRelativeDelta(this,-1);} isEqual(other){throw new NotSupportedError();}} const TIME_DELTA_KEYS="weeks days hours minutes seconds milliseconds microseconds".split(" ");function modf(x){const mod=x%1;return[mod<0?mod+1:mod,Math.floor(x)];} const PyTimeDelta=__exports.PyTimeDelta=class PyTimeDelta{static create(...args){const namedArgs=parseArgs(args,["days","seconds","microseconds"]);for(const key of TIME_DELTA_KEYS){namedArgs[key]=namedArgs[key]||0;} let d=0;let s=0;let us=0;const days=namedArgs.days+namedArgs.weeks*7;let seconds=namedArgs.seconds+60*namedArgs.minutes+3600*namedArgs.hours;let microseconds=namedArgs.microseconds+1000*namedArgs.milliseconds;const[dFrac,dInt]=modf(days);d=dInt;let daysecondsfrac=0;if(dFrac){const[dsFrac,dsInt]=modf(dFrac*24*3600);s=dsInt;daysecondsfrac=dsFrac;} const[sFrac,sInt]=modf(seconds);seconds=sInt;const secondsfrac=sFrac+daysecondsfrac;divmod(seconds,24*3600,(days,seconds)=>{d+=days;s+=seconds;});microseconds+=secondsfrac*1e6;divmod(microseconds,1000000,(seconds,microseconds)=>{divmod(seconds,24*3600,(days,seconds)=>{d+=days;s+=seconds;us+=Math.round(microseconds);});});return new PyTimeDelta(d,s,us);} constructor(days,seconds,microseconds){this.days=days;this.seconds=seconds;this.microseconds=microseconds;} add(other){return PyTimeDelta.create({days:this.days+other.days,seconds:this.seconds+other.seconds,microseconds:this.microseconds+other.microseconds,});} divide(n){const us=(this.days*24*3600+this.seconds)*1e6+this.microseconds;return PyTimeDelta.create({microseconds:Math.floor(us/n)});} isEqual(other){if(!(other instanceof PyTimeDelta)){return false;} return(this.days===other.days&&this.seconds===other.seconds&&this.microseconds===other.microseconds);} isTrue(){return this.days!==0||this.seconds!==0||this.microseconds!==0;} multiply(n){return PyTimeDelta.create({days:n*this.days,seconds:n*this.seconds,microseconds:n*this.microseconds,});} negate(){return PyTimeDelta.create({days:-this.days,seconds:-this.seconds,microseconds:-this.microseconds,});} substract(other){return PyTimeDelta.create({days:this.days-other.days,seconds:this.seconds-other.seconds,microseconds:this.microseconds-other.microseconds,});} total_seconds(){return this.days*86400+this.seconds+this.microseconds/1000000;}} return __exports;});; /* /web/static/src/core/py_js/py_interpreter.js */ odoo.define('@web/core/py_js/py_interpreter',['@web/core/py_js/py_builtin','@web/core/py_js/py_date','@web/core/py_js/py_utils','@web/core/py_js/py_parser'],function(require){'use strict';let __exports={};const{BUILTINS,EvaluationError,execOnIterable}=require("@web/core/py_js/py_builtin");const{NotSupportedError,PyDate,PyDateTime,PyRelativeDelta,PyTime,PyTimeDelta,}=require("@web/core/py_js/py_date");const{PY_DICT,toPyDict}=require("@web/core/py_js/py_utils");const{parseArgs}=require("@web/core/py_js/py_parser");const isTrue=BUILTINS.bool;function applyUnaryOp(ast,context){const value=evaluate(ast.right,context);switch(ast.op){case"-":if(value instanceof Object&&value.negate){return value.negate();} return-value;case"+":return value;case"not":return!isTrue(value);} throw new EvaluationError(`Unknown unary operator: ${ast.op}`);} function pytypeIndex(val){switch(typeof val){case"object":return val===null?1:Array.isArray(val)?5:3;case"number":return 2;case"string":return 4;} throw new EvaluationError(`Unknown type: ${typeof val}`);} function isConstructor(obj){return!!obj.prototype&&!!obj.prototype.constructor.name;} function isLess(left,right){if(typeof left==="number"&&typeof right==="number"){return left":case"!=":return!isEqual(left,right);case"<":return isLess(left,right);case">":return isLess(right,left);case">=":return isEqual(left,right)||isLess(right,left);case"<=":return isEqual(left,right)||isLess(left,right);case"in":return isIn(left,right);case"not in":return!isIn(left,right);} throw new EvaluationError(`Unknown binary operator: ${ast.op}`);} const DICT={get(...args){const{key,defValue}=parseArgs(args,["key","defValue"]);if(key in this){return this[key];}else if(defValue){return defValue;} return null;},};const STRING={lower(){return this.toLowerCase();},upper(){return this.toUpperCase();},};function applyFunc(key,func,set,...args){if(args.length===1){return new Set(set);} if(args.length>2){throw new EvaluationError(`${key}: py_js supports at most 1 argument, got (${args.length - 1})`);} return execOnIterable(args[0],func);} const SET={intersection(...args){return applyFunc("intersection",(iterable)=>{const intersection=new Set();for(const i of iterable){if(this.has(i)){intersection.add(i);}} return intersection;},this,...args);},difference(...args){return applyFunc("difference",(iterable)=>{iterable=new Set(iterable);const difference=new Set();for(const e of this){if(!iterable.has(e)){difference.add(e);}} return difference;},this,...args);},union(...args){return applyFunc("union",(iterable)=>{return new Set([...this,...iterable]);},this,...args);},};function methods(_class){return Object.getOwnPropertyNames(_class.prototype).map((prop)=>_class.prototype[prop]);} const allowedFns=new Set([BUILTINS.time.strftime,BUILTINS.set,BUILTINS.bool,BUILTINS.min,BUILTINS.max,BUILTINS.context_today,BUILTINS.datetime.datetime.now,BUILTINS.datetime.datetime.combine,BUILTINS.datetime.date.today,...methods(BUILTINS.relativedelta),...Object.values(BUILTINS.datetime).flatMap((obj)=>methods(obj)),...Object.values(SET),...Object.values(DICT),...Object.values(STRING),]);const unboundFn=Symbol("unbound function");__exports.evaluate=evaluate;function evaluate(ast,context={}){const dicts=new Set();let pyContext;const evalContext=Object.create(context);if(!evalContext.context){Object.defineProperty(evalContext,"context",{get(){if(!pyContext){pyContext=toPyDict(context);} return pyContext;},});} function _innerEvaluate(ast){switch(ast.type){case 0:case 1:return ast.value;case 5:if(ast.value in evalContext){return evalContext[ast.value];}else if(ast.value in BUILTINS){return BUILTINS[ast.value];}else{throw new EvaluationError(`Name '${ast.value}' is not defined`);} case 3:return null;case 2:return ast.value;case 6:return applyUnaryOp(ast,evalContext);case 7:return applyBinaryOp(ast,evalContext);case 14:{const left=_evaluate(ast.left);if(ast.op==="and"){return isTrue(left)?_evaluate(ast.right):left;}else{return isTrue(left)?left:_evaluate(ast.right);}} case 4:case 10:return ast.value.map(_evaluate);case 11:{const dict={};for(const key in ast.value){dict[key]=_evaluate(ast.value[key]);} dicts.add(dict);return dict;} case 8:{const fnValue=_evaluate(ast.fn);const args=ast.args.map(_evaluate);const kwargs={};for(const kwarg in ast.kwargs){kwargs[kwarg]=_evaluate(ast.kwargs[kwarg]);} if(fnValue===PyDate||fnValue===PyDateTime||fnValue===PyTime||fnValue===PyRelativeDelta||fnValue===PyTimeDelta){return fnValue.create(...args,kwargs);} return fnValue(...args,kwargs);} case 12:{const dict=_evaluate(ast.target);const key=_evaluate(ast.key);return dict[key];} case 13:{if(isTrue(_evaluate(ast.condition))){return _evaluate(ast.ifTrue);}else{return _evaluate(ast.ifFalse);}} case 15:{let left=_evaluate(ast.obj);let result;if(dicts.has(left)||Object.isPrototypeOf.call(PY_DICT,left)){result=DICT[ast.key];}else if(typeof left==="string"){result=STRING[ast.key];}else if(left instanceof Set){result=SET[ast.key];}else if(ast.key=="get"&&typeof left==="object"){result=DICT[ast.key];left=toPyDict(left);}else{result=left[ast.key];} if(typeof result==="function"){if(!isConstructor(result)){const bound=result.bind(left);bound[unboundFn]=result;return bound;}} return result;}} throw new EvaluationError(`AST of type ${ast.type} cannot be evaluated`);} function _evaluate(ast){const val=_innerEvaluate(ast);if(typeof val==="function"&&!allowedFns.has(val)&&!allowedFns.has(val[unboundFn])){throw new Error("Invalid Function Call");} return val;} return _evaluate(ast);} return __exports;});; /* /web/static/src/core/py_js/py_parser.js */ odoo.define('@web/core/py_js/py_parser',['@web/core/py_js/py_tokenizer'],function(require){'use strict';let __exports={};const{binaryOperators,comparators}=require("@web/core/py_js/py_tokenizer");const ParserError=__exports.ParserError=class ParserError extends Error{} const chainedOperators=new Set(comparators);const infixOperators=new Set(binaryOperators.concat(comparators));__exports.bp=bp;function bp(symbol){switch(symbol){case"=":return 10;case"if":return 20;case"in":case"not in":case"is":case"is not":case"<":case"<=":case">":case">=":case"<>":case"==":case"!=":return 60;case"or":return 30;case"and":return 40;case"not":return 50;case"|":return 70;case"^":return 80;case"&":return 90;case"<<":case">>":return 100;case"+":case"-":return 110;case"*":case"/":case"//":case"%":return 120;case"**":return 140;case".":case"(":case"[":return 150;} return 0;} function bindingPower(token){return token.type===2?bp(token.value):0;} function isSymbol(token,value){return token.type===2&&token.value===value;} function parsePrefix(current,tokens){switch(current.type){case 0:return{type:0,value:current.value};case 1:return{type:1,value:current.value};case 4:if(current.value==="None"){return{type:3};}else{return{type:2,value:current.value==="True"};} case 3:return{type:5,value:current.value};case 2:switch(current.value){case"-":case"+":case"~":return{type:6,op:current.value,right:_parse(tokens,130),};case"not":return{type:6,op:current.value,right:_parse(tokens,50),};case"(":{const content=[];let isTuple=false;while(tokens[0]&&!isSymbol(tokens[0],")")){content.push(_parse(tokens,0));if(tokens[0]){if(tokens[0]&&isSymbol(tokens[0],",")){isTuple=true;tokens.shift();}else if(!isSymbol(tokens[0],")")){throw new ParserError("parsing error");}}else{throw new ParserError("parsing error");}} if(!tokens[0]||!isSymbol(tokens[0],")")){throw new ParserError("parsing error");} tokens.shift();isTuple=isTuple||content.length===0;return isTuple?{type:10,value:content}:content[0];} case"[":{const value=[];while(tokens[0]&&!isSymbol(tokens[0],"]")){value.push(_parse(tokens,0));if(tokens[0]){if(isSymbol(tokens[0],",")){tokens.shift();}else if(!isSymbol(tokens[0],"]")){throw new ParserError("parsing error");}}} if(!tokens[0]||!isSymbol(tokens[0],"]")){throw new ParserError("parsing error");} tokens.shift();return{type:4,value};} case"{":{const dict={};while(tokens[0]&&!isSymbol(tokens[0],"}")){const key=_parse(tokens,0);if((key.type!==1&&key.type!==0)||!tokens[0]||!isSymbol(tokens[0],":")){throw new ParserError("parsing error");} tokens.shift();const value=_parse(tokens,0);dict[key.value]=value;if(isSymbol(tokens[0],",")){tokens.shift();}} if(!tokens.shift()){throw new ParserError("parsing error");} return{type:11,value:dict};}}} throw new ParserError("Token cannot be parsed");} function parseInfix(left,current,tokens){switch(current.type){case 2:if(infixOperators.has(current.value)){let right=_parse(tokens,bindingPower(current));if(current.value==="and"||current.value==="or"){return{type:14,op:current.value,left,right,};}else if(current.value==="."){if(right.type===5){return{type:15,obj:left,key:right.value,};}else{throw new ParserError("invalid obj lookup");}} let op={type:7,op:current.value,left,right,};while(chainedOperators.has(current.value)&&tokens[0]&&tokens[0].type===2&&chainedOperators.has(tokens[0].value)){const nextToken=tokens.shift();op={type:14,op:"and",left:op,right:{type:7,op:nextToken.value,left:right,right:_parse(tokens,bindingPower(nextToken)),},};right=op.right.right;} return op;} switch(current.value){case"(":{const args=[];const kwargs={};while(tokens[0]&&!isSymbol(tokens[0],")")){const arg=_parse(tokens,0);if(arg.type===9){kwargs[arg.name.value]=arg.value;}else{args.push(arg);} if(tokens[0]&&isSymbol(tokens[0],",")){tokens.shift();}} if(!tokens[0]||!isSymbol(tokens[0],")")){throw new ParserError("parsing error");} tokens.shift();return{type:8,fn:left,args,kwargs};} case"=":if(left.type===5){return{type:9,name:left,value:_parse(tokens,10),};} break;case"[":{const key=_parse(tokens);if(!tokens[0]||!isSymbol(tokens[0],"]")){throw new ParserError("parsing error");} tokens.shift();return{type:12,target:left,key:key,};} case"if":{const condition=_parse(tokens);if(!tokens[0]||!isSymbol(tokens[0],"else")){throw new ParserError("parsing error");} tokens.shift();const ifFalse=_parse(tokens);return{type:13,condition,ifTrue:left,ifFalse,};}}} throw new ParserError("Token cannot be parsed");} function _parse(tokens,bp=0){const token=tokens.shift();let expr=parsePrefix(token,tokens);while(tokens[0]&&bindingPower(tokens[0])>bp){expr=parseInfix(expr,tokens.shift(),tokens);} return expr;} __exports.parse=parse;function parse(tokens){if(tokens.length){const ast=_parse(tokens,0);if(tokens.length){throw new ParserError("Token(s) unused");} return ast;} throw new ParserError("Missing token");} __exports.parseArgs=parseArgs;function parseArgs(args,spec){const last=args[args.length-1];const unnamedArgs=typeof last==="object"?args.slice(0,-1):args;const kwargs=typeof last==="object"?last:{};for(const[index,val]of unnamedArgs.entries()){kwargs[spec[index]]=val;} return kwargs;} return __exports;});; /* /web/static/src/core/py_js/py_tokenizer.js */ odoo.define('@web/core/py_js/py_tokenizer',[],function(require){'use strict';let __exports={};const TokenizerError=__exports.TokenizerError=class TokenizerError extends Error{} const directMap={"\\":"\\",'"':'"',"'":"'",a:"\x07",b:"\x08",f:"\x0c",n:"\n",r:"\r",t:"\t",v:"\v",};function decodeStringLiteral(str,unicode){const out=[];let code;for(var i=0;i",">=","<>","!=","==",];const binaryOperators=__exports.binaryOperators=["or","and","|","^","&","<<",">>","+","-","*","/","//","%","~","**",".",];const unaryOperators=__exports.unaryOperators=["-"];const symbols=new Set([...["(",")","[","]","{","}",":",","],...["if","else","lambda","="],...comparators,...binaryOperators,...unaryOperators,]);function group(...args){return"("+args.join("|")+")";} const Name="[a-zA-Z_]\\w*";const Whitespace="[ \\f\\t]*";const DecNumber="\\d+(L|l)?";const IntNumber=DecNumber;const Exponent="[eE][+-]?\\d+";const PointFloat=group(`\\d+\\.\\d*(${Exponent})?`,`\\.\\d+(${Exponent})?`);const FloatNumber=group(PointFloat,`\\d+${Exponent}`);const Number=group(FloatNumber,IntNumber);const Operator=group("\\*\\*=?",">>=?","<<=?","<>","!=","//=?","[+\\-*/%&|^=<>]=?","~");const Bracket="[\\[\\]\\(\\)\\{\\}]";const Special="[:;.,`@]";const Funny=group(Operator,Bracket,Special);const ContStr=group("([uU])?'([^\n'\\\\]*(?:\\\\.[^\n'\\\\]*)*)'",'([uU])?"([^\n"\\\\]*(?:\\\\.[^\n"\\\\]*)*)"');const PseudoToken=Whitespace+group(Number,Funny,ContStr,Name);const NumberPattern=new RegExp("^"+Number+"$");const StringPattern=new RegExp("^"+ContStr+"$");const NamePattern=new RegExp("^"+Name+"$");const strip=new RegExp("^"+Whitespace);__exports.tokenize=tokenize;function tokenize(str){const tokens=[];const max=str.length;let start=0;let end=0;const pseudoprog=new RegExp(PseudoToken,"g");while(pseudoprog.lastIndex> at index "+ (end||0)+"; parsed so far: "+ tokens);} if(pseudomatch.index>end){if(str.slice(end,pseudomatch.index).trim()){throw new TokenizerError("Invalid expression");}} start=pseudomatch.index;end=pseudoprog.lastIndex;let token=str.slice(start,end).replace(strip,"");if(NumberPattern.test(token)){tokens.push({type:0,value:parseFloat(token),});}else if(StringPattern.test(token)){var m=StringPattern.exec(token);tokens.push({type:1,value:decodeStringLiteral(m[3]!==undefined?m[3]:m[5],!!(m[2]||m[4])),});}else if(symbols.has(token)){if(token==="in"&&tokens.length>0&&tokens[tokens.length-1].value==="not"){token="not in";tokens.pop();}else if(token==="not"&&tokens.length>0&&tokens[tokens.length-1].value==="is"){token="is not";tokens.pop();} tokens.push({type:2,value:token,});}else if(constants.has(token)){tokens.push({type:4,value:token,});}else if(NamePattern.test(token)){tokens.push({type:3,value:token,});}else{throw new TokenizerError("Invalid expression");}} return tokens;} return __exports;});; /* /web/static/src/core/py_js/py_utils.js */ odoo.define('@web/core/py_js/py_utils',['@web/core/py_js/py_parser','@web/core/py_js/py_date'],function(require){'use strict';let __exports={};const{bp}=require("@web/core/py_js/py_parser");const{PyDate,PyDateTime}=require("@web/core/py_js/py_date");__exports.toPyValue=toPyValue;function toPyValue(value){switch(typeof value){case"string":return{type:1,value};case"number":return{type:0,value};case"boolean":return{type:2,value};case"object":if(Array.isArray(value)){return{type:4,value:value.map(toPyValue)};}else if(value===null){return{type:3};}else if(value instanceof Date){return{type:1,value:PyDateTime.convertDate(value)};}else if(value instanceof PyDate||value instanceof PyDateTime){return{type:1,value};}else{const content={};for(const key in value){content[key]=toPyValue(value[key]);} return{type:11,value:content};} default:throw new Error("Invalid type");}} __exports.formatAST=formatAST;function formatAST(ast,lbp=0){switch(ast.type){case 3:return"None";case 1:return JSON.stringify(ast.value);case 0:return String(ast.value);case 2:return ast.value?"True":"False";case 4:return`[${ast.value.map(formatAST).join(", ")}]`;case 6:if(ast.op==="not"){return`not `+formatAST(ast.right,50);} return ast.op+formatAST(ast.right,130);case 7:{const abp=bp(ast.op);const str=`${formatAST(ast.left, abp)} ${ast.op} ${formatAST(ast.right, abp)}`;return abpthis.computeDerivedParams());onWillUpdateProps((nextProps)=>this.computeDerivedParams(nextProps));} async computeDerivedParams(props=this.props){const displayNames=await this.getDisplayNames(props);this.tags=this.getTags(props,displayNames);} async getDisplayNames(props){const ids=this.getIds(props);return this.nameService.loadDisplayNames(props.resModel,ids);} get placeholder(){return this.getIds().length?"":this.props.placeholder;} getIds(props=this.props){return props.resIds;} getTags(props,displayNames){return props.resIds.map((id,index)=>{const text=typeof displayNames[id]==="string"?displayNames[id]:_t("Inaccessible/missing record ID: %s",id);return{text,onDelete:()=>{this.deleteTag(index);},onKeydown:this.onTagKeydown,};});} deleteTag(index){this.props.update([...this.props.resIds.slice(0,index),...this.props.resIds.slice(index+1),]);} update(resIds){this.props.update([...this.props.resIds,...resIds]);}} return __exports;});; /* /web/static/src/core/record_selectors/record_autocomplete.js */ odoo.define('@web/core/record_selectors/record_autocomplete',['@odoo/owl','@web/core/autocomplete/autocomplete','@web/core/l10n/translation','@web/core/domain','@web/core/registry','@web/core/utils/hooks'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const{AutoComplete}=require("@web/core/autocomplete/autocomplete");const{_t}=require("@web/core/l10n/translation");const{Domain}=require("@web/core/domain");const{registry}=require("@web/core/registry");const{useOwnedDialogs,useService}=require("@web/core/utils/hooks");const SEARCH_LIMIT=7;const SEARCH_MORE_LIMIT=320;const RecordAutocomplete=__exports.RecordAutocomplete=class RecordAutocomplete extends Component{static props={resModel:String,update:Function,multiSelect:Boolean,getIds:Function,value:String,domain:{type:Array,optional:true},context:{type:Object,optional:true},className:{type:String,optional:true},fieldString:{type:String,optional:true},placeholder:{type:String,optional:true},};static components={AutoComplete};static template="web.RecordAutocomplete";setup(){this.orm=useService("orm");this.nameService=useService("name");this.addDialog=useOwnedDialogs();this.sources=[{placeholder:_t("Loading..."),options:this.loadOptionsSource.bind(this),},];} addNames(options){const displayNames=Object.fromEntries(options);this.nameService.addDisplayNames(this.props.resModel,displayNames);} getIds(){return this.props.getIds();} async loadOptionsSource(name){if(this.lastProm){this.lastProm.abort(false);} this.lastProm=this.search(name,SEARCH_LIMIT+1);const nameGets=(await this.lastProm).map(([id,label])=>([id,label?label.split("\n")[0]:_t("Unnamed")]));this.addNames(nameGets);const options=nameGets.map(([value,label])=>({value,label}));if(SEARCH_LIMITnameGet[0]));}else{operator="not in";ids.push(...this.getIds());} const dynamicFilters=ids.length?[{description:_t("Quick search: %s",name),domain:[["id",operator,ids]],},]:undefined;const SelectCreateDialog=registry.category("dialogs").get("select_create");this.addDialog(SelectCreateDialog,{title:_t("Search: %s",fieldString),dynamicFilters,domain:this.getDomain(),resModel,noCreate:true,multiSelect,context:this.props.context||{},onSelected:(resId)=>{const resIds=Array.isArray(resId)?resId:[resId];this.props.update([...resIds]);},});} getDomain(){const domainIds=Domain.not([["id","in",this.getIds()]]);if(this.props.domain){return Domain.and([this.props.domain,domainIds]).toList();} return domainIds.toList();} onSelect({value:resId,action},params){if(action){return action(params);} this.props.update([resId]);} search(name,limit){const domain=this.getDomain();return this.orm.call(this.props.resModel,"name_search",[],{name,args:domain,limit,context:this.props.context||{},});} onChange({inputValue}){if(!inputValue.length){this.props.update([]);}}} return __exports;});; /* /web/static/src/core/record_selectors/record_selector.js */ odoo.define('@web/core/record_selectors/record_selector',['@odoo/owl','@web/core/utils/hooks','@web/core/record_selectors/record_autocomplete','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{Component,onWillStart,onWillUpdateProps}=require("@odoo/owl");const{useService}=require("@web/core/utils/hooks");const{RecordAutocomplete}=require("@web/core/record_selectors/record_autocomplete");const{_t}=require("@web/core/l10n/translation");const RecordSelector=__exports.RecordSelector=class RecordSelector extends Component{static props={resId:[Number,{value:false}],resModel:String,update:Function,domain:{type:Array,optional:true},context:{type:Object,optional:true},fieldString:{type:String,optional:true},placeholder:{type:String,optional:true},};static components={RecordAutocomplete};static template="web.RecordSelector";setup(){this.nameService=useService("name");onWillStart(()=>this.computeDerivedParams());onWillUpdateProps((nextProps)=>this.computeDerivedParams(nextProps));} async computeDerivedParams(props=this.props){const displayNames=await this.getDisplayNames(props);this.displayName=this.getDisplayName(props,displayNames);} async getDisplayNames(props){const ids=this.getIds(props);return this.nameService.loadDisplayNames(props.resModel,ids);} getDisplayName(props=this.props,displayNames){const{resId}=props;if(resId===false){return"";} return typeof displayNames[resId]==="string"?displayNames[resId]:_t("Inaccessible/missing record ID: %s",resId);} getIds(props=this.props){if(props.resId){return[props.resId];} return[];} update(resIds){this.props.update(resIds[0]||false);this.render(true);}} return __exports;});; /* /web/static/src/core/record_selectors/tag_navigation_hook.js */ odoo.define('@web/core/record_selectors/tag_navigation_hook',['@web/core/hotkeys/hotkey_service','@odoo/owl'],function(require){'use strict';let __exports={};const{getActiveHotkey}=require("@web/core/hotkeys/hotkey_service");const{useEffect,useRef}=require("@odoo/owl");__exports.useTagNavigation=useTagNavigation;function useTagNavigation(refName,deleteTag){const ref=useRef(refName);useEffect((autocomplete)=>{if(!autocomplete){return;} autocomplete.addEventListener("keydown",onAutoCompleteKeydown);return()=>{autocomplete.removeEventListener("keydown",onAutoCompleteKeydown);};},()=>[ref.el?.querySelector(".o-autocomplete")]);function focusTag(index){const tags=ref.el.getElementsByClassName("o_tag");if(tags.length){if(index===undefined){tags[tags.length-1].focus();}else{tags[index].focus();}}} function onAutoCompleteKeydown(ev){if(ev.isComposing){return;} const hotkey=getActiveHotkey(ev);const input=ev.target.closest(".o-autocomplete--input");const autoCompleteMenuOpened=!!ref.el.querySelector(".o-autocomplete--dropdown-menu");switch(hotkey){case"arrowleft":{if(input.selectionStart||autoCompleteMenuOpened){return;} focusTag();break;} case"arrowright":{if(input.selectionStart!==input.value.length||autoCompleteMenuOpened){return;} focusTag(0);break;} case"backspace":{if(input.value){return;} const tags=ref.el.getElementsByClassName("o_tag");if(tags.length){deleteTag(tags.length-1);} break;} default:return;} ev.preventDefault();ev.stopPropagation();} function onTagKeydown(ev){const hotkey=getActiveHotkey(ev);const tags=[...ref.el.getElementsByClassName("o_tag")];const closestTag=ev.target.closest(".o_tag");const tagIndex=tags.indexOf(closestTag);const input=ref.el.querySelector(".o-autocomplete--input");switch(hotkey){case"arrowleft":{if(tagIndex===0){input.focus();}else{focusTag(tagIndex-1);} break;} case"arrowright":{if(tagIndex===tags.length-1){input.focus();}else{focusTag(tagIndex+1);} break;} case"backspace":{input.focus();deleteTag(tagIndex);break;} default:return;} ev.preventDefault();ev.stopPropagation();} return onTagKeydown;} return __exports;});; /* /web/static/src/core/registry.js */ odoo.define('@web/core/registry',['@odoo/owl'],function(require){'use strict';let __exports={};const{EventBus,validate}=require("@odoo/owl");const KeyNotFoundError=__exports.KeyNotFoundError=class KeyNotFoundError extends Error{} const DuplicatedKeyError=__exports.DuplicatedKeyError=class DuplicatedKeyError extends Error{} const validateSchema=(value,schema)=>{if(!odoo.debug){return;} validate(value,schema);} const Registry=__exports.Registry=class Registry extends EventBus{constructor(name){super();this.content={};this.subRegistries={};this.elements=null;this.entries=null;this.name=name;this.validationSchema=null;this.addEventListener("UPDATE",()=>{this.elements=null;this.entries=null;});} add(key,value,{force,sequence}={}){if(this.validationSchema){validateSchema(value,this.validationSchema);} if(!force&&key in this.content){throw new DuplicatedKeyError(`Cannot add key "${key}" in the "${this.name}" registry: it already exists`);} let previousSequence;if(force){const elem=this.content[key];previousSequence=elem&&elem[0];} sequence=sequence===undefined?previousSequence||50:sequence;this.content[key]=[sequence,value];const payload={operation:"add",key,value};this.trigger("UPDATE",payload);return this;} get(key,defaultValue){if(arguments.length<2&&!(key in this.content)){throw new KeyNotFoundError(`Cannot find key "${key}" in the "${this.name}" registry`);} const info=this.content[key];return info?info[1]:defaultValue;} contains(key){return key in this.content;} getAll(){if(!this.elements){const content=Object.values(this.content).sort((el1,el2)=>el1[0]-el2[0]);this.elements=content.map((elem)=>elem[1]);} return this.elements.slice();} getEntries(){if(!this.entries){const entries=Object.entries(this.content).sort((el1,el2)=>el1[1][0]-el2[1][0]);this.entries=entries.map(([str,elem])=>[str,elem[1]]);} return this.entries.slice();} remove(key){const value=this.content[key];delete this.content[key];const payload={operation:"delete",key,value};this.trigger("UPDATE",payload);} category(subcategory){if(!(subcategory in this.subRegistries)){this.subRegistries[subcategory]=new Registry(subcategory);} return this.subRegistries[subcategory];} addValidation(schema){if(this.validationSchema){throw new Error("Validation schema already set on this registry");} this.validationSchema=schema;for(const value of this.getAll()){validateSchema(value,schema);}}} const registry=__exports.registry=new Registry();return __exports;});; /* /web/static/src/core/registry_hook.js */ odoo.define('@web/core/registry_hook',['@odoo/owl'],function(require){'use strict';let __exports={};const{useState,onWillStart,onWillDestroy}=require("@odoo/owl");__exports.useRegistry=useRegistry;function useRegistry(registry){const state=useState({entries:registry.getEntries()});const listener=({detail})=>{const index=state.entries.findIndex(([k])=>k===detail.key);if(detail.operation==="add"&&index===-1){const newEntries=registry.getEntries();const newEntry=newEntries.find(([k])=>k===detail.key);const newIndex=newEntries.indexOf(newEntry);if(newIndex===newEntries.length-1){state.entries.push(newEntry);}else{state.entries.splice(newIndex,0,newEntry);}}else if(detail.operation==="delete"&&index>=0){state.entries.splice(index,1);}};onWillStart(()=>registry.addEventListener("UPDATE",listener));onWillDestroy(()=>registry.removeEventListener("UPDATE",listener));return state;} return __exports;});; /* /web/static/src/core/resizable_panel/resizable_panel.js */ odoo.define('@web/core/resizable_panel/resizable_panel',['@odoo/owl'],function(require){'use strict';let __exports={};const{Component,onMounted,onWillUpdateProps,onWillUnmount,useEffect,useExternalListener,useRef,useComponent,}=require("@odoo/owl");function useResizable({containerRef,handleRef,initialWidth=400,getMinWidth=()=>400,onResize=()=>{},getResizeSide=()=>"end",}){containerRef=typeof containerRef=="string"?useRef(containerRef):containerRef;handleRef=typeof handleRef=="string"?useRef(handleRef):handleRef;const props=useComponent().props;let minWidth=getMinWidth(props);let resizeSide=getResizeSide(props);let isChangingSize=false;useExternalListener(document,"mouseup",()=>onMouseUp());useExternalListener(document,"mousemove",(ev)=>onMouseMove(ev));useExternalListener(window,"resize",()=>{const limit=getLimitWidth();if(getContainerRect().width>=limit){resize(computeFinalWidth(limit));}});let docDirection;useEffect((container)=>{if(container){docDirection=getComputedStyle(container).direction;}},()=>[containerRef.el]);onMounted(()=>{if(handleRef.el){resize(initialWidth);handleRef.el.addEventListener("mousedown",onMouseDown);}});onWillUpdateProps((nextProps)=>{minWidth=getMinWidth(nextProps);resizeSide=getResizeSide(nextProps);});onWillUnmount(()=>{if(handleRef.el){handleRef.el.removeEventListener("mousedown",onMouseDown);}});function onMouseDown(){isChangingSize=true;document.body.classList.add("pe-none","user-select-none");} function onMouseUp(){isChangingSize=false;document.body.classList.remove("pe-none","user-select-none");} function onMouseMove(ev){if(!isChangingSize||!containerRef.el){return;} const direction=(docDirection==="ltr"&&resizeSide==="end")||(docDirection==="rtl"&&resizeSide==="start")?1:-1;const fixedSide=direction===1?"left":"right";const containerRect=getContainerRect();const newWidth=(ev.clientX-containerRect[fixedSide])*direction;resize(computeFinalWidth(newWidth));} function computeFinalWidth(targetContainerWidth){const handlerSpacing=handleRef.el?handleRef.el.offsetWidth/2:10;const w=Math.max(minWidth,targetContainerWidth+handlerSpacing);const limit=getLimitWidth();return Math.min(w,limit-handlerSpacing);} function getContainerRect(){const container=containerRef.el;const offsetParent=container.offsetParent;let containerRect={};if(!offsetParent){containerRect=container.getBoundingClientRect();}else{containerRect.left=container.offsetLeft;containerRect.right=container.offsetLeft+container.offsetWidth;containerRect.width=container.offsetWidth;} return containerRect;} function getLimitWidth(){const offsetParent=containerRef.el.offsetParent;return offsetParent?offsetParent.offsetWidth:window.innerWidth;} function resize(width){containerRef.el.style.setProperty("width",`${width}px`);onResize(width);}} const ResizablePanel=__exports.ResizablePanel=class ResizablePanel extends Component{static template="web_studio.ResizablePanel";static components={};static props={onResize:{type:Function,optional:true},initialWidth:{type:Number,optional:true},minWidth:{type:Number,optional:true},class:{type:String,optional:true},slots:{type:Object},handleSide:{validate:(val)=>["start","end"].includes(val),optional:true,},};static defaultProps={onResize:()=>{},width:400,minWidth:400,class:"",handleSide:"end",};setup(){useResizable({containerRef:"containerRef",handleRef:"handleRef",onResize:this.props.onResize,initialWidth:this.props.initialWidth,getMinWidth:(props)=>props.minWidth,getResizeSide:(props)=>props.handleSide,});} get class(){const classes=this.props.class.split(" ");if(!classes.some((cls)=>cls.startsWith("position-"))){classes.push("position-relative");} return classes.join(" ");}} return __exports;});; /* /web/static/src/core/select_menu/select_menu.js */ odoo.define('@web/core/select_menu/select_menu',['@odoo/owl','@web/core/dropdown/dropdown','@web/core/dropdown/dropdown_item','@web/core/l10n/translation','@web/core/tags_list/tags_list','@web/core/utils/classname','@web/core/utils/hooks','@web/core/utils/scrolling','@web/core/utils/search','@web/core/utils/timing'],function(require){'use strict';let __exports={};const{Component,onWillUpdateProps,useEffect,useRef,useState}=require("@odoo/owl");const{Dropdown}=require("@web/core/dropdown/dropdown");const{DropdownItem}=require("@web/core/dropdown/dropdown_item");const{_t}=require("@web/core/l10n/translation");const{TagsList}=require("@web/core/tags_list/tags_list");const{mergeClasses}=require("@web/core/utils/classname");const{useAutofocus,useChildRef}=require("@web/core/utils/hooks");const{scrollTo}=require("@web/core/utils/scrolling");const{fuzzyLookup}=require("@web/core/utils/search");const{useDebounced}=require("@web/core/utils/timing");const SelectMenu=__exports.SelectMenu=class SelectMenu extends Component{static template="web.SelectMenu";static choiceItemTemplate="web.SelectMenu.ChoiceItem";static components={Dropdown,DropdownItem,TagsList};static defaultProps={value:undefined,class:"",togglerClass:"",multiSelect:false,onSelect:()=>{},required:false,searchable:true,autoSort:true,searchPlaceholder:_t("Search..."),choices:[],groups:[],disabled:false,};static props={choices:{optional:true,type:Array,element:{type:Object,shape:{value:true,label:{type:String},"*":true,},},},groups:{type:Array,optional:true,element:{type:Object,shape:{label:{type:String,optional:true},choices:{type:Array,element:{type:Object,shape:{value:true,label:{type:String},"*":true,},},},},},},class:{type:String,optional:true},menuClass:{type:String,optional:true},togglerClass:{type:String,optional:true},required:{type:Boolean,optional:true},searchable:{type:Boolean,optional:true},autoSort:{type:Boolean,optional:true},placeholder:{type:String,optional:true},searchPlaceholder:{type:String,optional:true},value:{optional:true},multiSelect:{type:Boolean,optional:true},onInput:{type:Function,optional:true},onSelect:{type:Function,optional:true},slots:{type:Object,optional:true},disabled:{type:Boolean,optional:true},};static SCROLL_SETTINGS={defaultCount:500,increaseAmount:300,distanceBeforeReload:500,};setup(){this.state=useState({choices:[],displayedOptions:[],searchValue:"",});this.inputRef=useRef("inputRef");this.menuRef=useChildRef();this.debouncedOnInput=useDebounced(()=>this.onInput(this.inputRef.el?this.inputRef.el.value.trim():""),250);this.isOpen=false;this.selectedChoice=this.getSelectedChoice(this.props);onWillUpdateProps((nextProps)=>{if(this.state.choices!==nextProps.choices){this.state.choices=nextProps.choices;} if(this.props.value!==nextProps.value){this.selectedChoice=this.getSelectedChoice(nextProps);}});useEffect(()=>{if(this.isOpen){const groups=[{choices:this.props.choices},...this.props.groups];this.filterOptions(this.state.searchValue,groups);}},()=>[this.props.choices,this.props.groups]);useAutofocus({refName:"inputRef"});} get displayValue(){return this.selectedChoice?this.selectedChoice.label:"";} get canDeselect(){return!this.props.required&&this.selectedChoice!==undefined;} get multiSelectChoices(){return this.selectedChoice.map((c)=>{return{id:c.value,text:c.label,onDelete:()=>{const values=[...this.props.value];values.splice(values.indexOf(c.value),1);this.props.onSelect(values);},};});} get menuClass(){return mergeClasses({"o_select_menu_menu border bg-light":true,"py-0":this.props.searchable,o_select_menu_multi_select:this.props.multiSelect,},this.props.menuClass);} async onBeforeOpen(){if(this.state.searchValue.length){this.state.searchValue="";if(this.props.onInput){await this.executeOnInput("");}} this.filterOptions();} onStateChanged(open){this.isOpen=open;if(open){this.menuRef.el?.addEventListener("scroll",(ev)=>this.onScroll(ev));const selectedElement=this.menuRef.el?.querySelectorAll(".o_select_active")[0];if(selectedElement){scrollTo(selectedElement);}}} isOptionSelected(choice){if(this.props.multiSelect){return this.props.value.includes(choice.value);} return this.props.value===choice.value;} getItemClass(choice){if(this.isOptionSelected(choice)){return"o_select_menu_item p-2 o_select_active bg-primary fw-bolder fst-italic";}else{return"o_select_menu_item p-2";}} async executeOnInput(searchString){await this.props.onInput(searchString);} onInput(searchString){this.filterOptions(searchString);this.state.searchValue=searchString;const inputEl=this.inputRef.el;if(inputEl&&inputEl.parentNode){inputEl.parentNode.scrollTo(0,0);} if(this.props.onInput){this.executeOnInput(searchString);}} getSelectedChoice(props){const choices=[...props.choices,...props.groups.flatMap((g)=>g.choices)];if(!this.props.multiSelect){return choices.find((c)=>c.value===props.value);} const valueSet=new Set(props.value);return[...(this.selectedChoice||[]),...choices].filter((c,index,self)=>valueSet.has(c.value)&&self.findIndex((t)=>t.value===c.value)===index);} onItemSelected(value){if(this.props.multiSelect){const values=[...this.props.value];const valueIndex=values.indexOf(value);if(valueIndex!==-1){values.splice(valueIndex,1);this.props.onSelect(values);}else{this.props.onSelect([...this.props.value,value]);}}else if(!this.selectedChoice||this.selectedChoice.value!==value){this.props.onSelect(value);} if(this.inputRef.el){this.inputRef.el.value="";this.state.searchValue="";}} filterOptions(searchString="",groups){const groupsList=groups||[{choices:this.props.choices},...this.props.groups];this.state.choices=[];for(const group of groupsList){let filteredOptions=[];if(searchString){filteredOptions=fuzzyLookup(searchString,group.choices,(choice)=>choice.label);}else{filteredOptions=group.choices;if(this.props.autoSort){filteredOptions.sort((optionA,optionB)=>optionA.label.localeCompare(optionB.label));}} if(filteredOptions.length===0){continue;} if(group.label){this.state.choices.push({...group,isGroup:true});} this.state.choices.push(...filteredOptions);} this.sliceDisplayedOptions();} onScroll(event){const el=event.target;const hasReachMax=this.state.displayedOptions.length>=this.state.choices.length;const remainingDistance=el.scrollHeight-el.scrollTop;const distanceToReload=el.clientHeight+this.constructor.SCROLL_SETTINGS.distanceBeforeReload;if(!hasReachMax&&remainingDistance{},};setup(){this.htmlId=htmlId++;this.defaultName=this.props.signature.name||"";this.currentFont=0;this.drawTimeout=null;this.state=useState({signMode:this.props.mode||(this.props.noInputName&&!this.defaultName?"draw":"auto"),showSignatureArea:!!(this.props.noInputName||this.defaultName),showFontList:false,});this.signNameInputRef=useRef("signNameInput");this.signInputLoad=useRef("signInputLoad");useAutofocus({refName:"signNameInput"});useEffect((el)=>{if(el){el.click();}},()=>[this.signInputLoad.el]);onWillStart(async()=>{this.fonts=await rpc(`/web/sign/get_fonts/${this.props.defaultFont}`);});onWillStart(async()=>{await loadJS("/web/static/lib/signature_pad/signature_pad.umd.js");});this.signatureRef=useRef("signature");useEffect((el)=>{if(el){this.signaturePad=new SignaturePad(el,{penColor:this.props.fontColor,backgroundColor:"rgba(255,255,255,0)",minWidth:2,maxWidth:2,});this.signaturePad.addEventListener("endStroke",()=>{this.props.signature.isSignatureEmpty=this.isSignatureEmpty;this.props.onSignatureChange(this.state.signMode);});this.resetSignature();this.props.signature.getSignatureImage=()=>this.signaturePad.toDataURL();this.props.signature.resetSignature=()=>this.resetSignature();if(this.state.signMode==="auto"){this.drawCurrentName();} if(this.props.signature.signatureImage){this.clear();this.fromDataURL(this.props.signature.signatureImage);}}},()=>[this.signatureRef.el]);} async drawCurrentName(){const font=this.fonts[this.currentFont];const text=this.getCleanedName();const canvas=this.signatureRef.el;const img=this.getSVGText(font,text,canvas.width,canvas.height);await this.printImage(img);} focusName(){if(!isMobileOS()&&this.signNameInputRef.el){this.signNameInputRef.el.focus();}} clear(){this.signaturePad.clear();this.props.signature.isSignatureEmpty=this.isSignatureEmpty;} async fromDataURL(){await this.signaturePad.fromDataURL(...arguments);this.props.signature.isSignatureEmpty=this.isSignatureEmpty;this.props.onSignatureChange(this.state.signMode);} getCleanedName(){const text=this.props.signature.name;if(this.props.signatureType==="initial"&&text){return(text.split(" ").map(function(w){return w[0];}).join(".")+".");} return text;} getSVGText(font,text,width,height){const svg=renderToString("web.sign_svg_text",{width:width,height:height,font:font,text:text,type:this.props.signatureType,color:this.props.fontColor,});return"data:image/svg+xml,"+encodeURI(svg);} getSVGTextFont(font){const height=100;const width=parseInt(height*this.props.displaySignatureRatio);return this.getSVGText(font,this.getCleanedName(),width,height);} uploadFile(){this.signInputLoad.el?.click();} async onChangeSignLoadInput(ev){var file=ev.target.files[0];if(file===undefined){return false;} if(file.type.substr(0,5)!=="image"){this.clear();this.state.loadIsInvalid=true;return false;} this.state.loadIsInvalid=false;const result=await getDataURLFromFile(file);await this.printImage(result);} onClickSignAutoSelectStyle(){this.state.showFontList=true;} onClickSignDrawClear(){this.clear();this.props.onSignatureChange(this.state.signMode);} onClickSignLoad(){this.setMode("load");} onClickSignAuto(){this.setMode("auto");} onInputSignName(ev){this.props.signature.name=ev.target.value;if(!this.state.showSignatureArea&&this.getCleanedName()){this.state.showSignatureArea=true;return;} if(this.state.signMode==="auto"){this.drawCurrentName();}} onSelectFont(index){this.currentFont=index;this.drawCurrentName();} async printImage(imgSrc){this.clear();const c=this.signaturePad.canvas;const img=new Image();img.onload=()=>{const ctx=c.getContext("2d");var ratio=((img.width/img.height)>(c.width/c.height))?c.width/img.width:c.height/img.height;ctx.drawImage(img,(c.width/2)-(img.width*ratio/2),(c.height/2)-(img.height*ratio/2),img.width*ratio,img.height*ratio);this.props.signature.isSignatureEmpty=this.isSignatureEmpty;this.props.onSignatureChange(this.state.signMode);};img.src=imgSrc;this.signaturePad._isEmpty=false;} resetSignature(){this.resizeSignature();this.clear();this.setMode(this.state.signMode,true);this.focusName();} resizeSignature(){const width=this.signatureRef.el.clientWidth;const height=parseInt(width/this.props.displaySignatureRatio);Object.assign(this.signatureRef.el,{width,height});} setMode(mode,reset){if(reset!==true&&mode===this.signMode){return;} this.state.signMode=mode;this.signaturePad[this.state.signMode==="draw"?"on":"off"]();this.clear();if(this.state.signMode==="auto"){this.drawCurrentName();} this.props.onSignatureChange(this.state.signMode);} get isSignatureEmpty(){return this.signaturePad.isEmpty();} get loadIsInvalid(){return this.state.signMode==="load"&&this.state.loadIsInvalid;}} return __exports;});; /* /web/static/src/core/signature/signature_dialog.js */ odoo.define('@web/core/signature/signature_dialog',['@web/core/dialog/dialog','@web/core/signature/name_and_signature','@odoo/owl'],function(require){'use strict';let __exports={};const{Dialog}=require("@web/core/dialog/dialog");const{NameAndSignature}=require("@web/core/signature/name_and_signature");const{Component,useState}=require("@odoo/owl");const SignatureDialog=__exports.SignatureDialog=class SignatureDialog extends Component{static template="web.SignatureDialog";static components={Dialog,NameAndSignature};static props={defaultName:{type:String,optional:true},nameAndSignatureProps:Object,uploadSignature:Function,close:Function,};static defaultProps={defaultName:"",};setup(){this.signature=useState({name:this.props.defaultName,isSignatureEmpty:true,});} onClickConfirm(){this.props.uploadSignature({name:this.signature.name,signatureImage:this.signature.getSignatureImage(),});this.props.close();} get nameAndSignatureProps(){return{...this.props.nameAndSignatureProps,signature:this.signature,};}} return __exports;});; /* /web/static/src/core/tags_list/tags_list.js */ odoo.define('@web/core/tags_list/tags_list',['@odoo/owl'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const TagsList=__exports.TagsList=class TagsList extends Component{static template="web.TagsList";static defaultProps={displayText:true,};static props={displayText:{type:Boolean,optional:true},visibleItemsLimit:{type:Number,optional:true},tags:{type:Object},};get visibleTagsCount(){return this.props.visibleItemsLimit-1;} get visibleTags(){if(this.props.visibleItemsLimit&&this.props.tags.length>this.props.visibleItemsLimit){return this.props.tags.slice(0,this.visibleTagsCount);} return this.props.tags;} get otherTags(){if(!this.props.visibleItemsLimit||this.props.tags.length<=this.props.visibleItemsLimit){return[];} return this.props.tags.slice(this.visibleTagsCount);} get tooltipInfo(){return JSON.stringify({tags:this.otherTags.map((tag)=>({text:tag.text,id:tag.id,})),});}} return __exports;});; /* /web/static/src/core/template_inheritance.js */ odoo.define('@web/core/template_inheritance',[],function(require){'use strict';let __exports={};const RSTRIP_REGEXP=/(?=\n[ \t]*$)/;function addBefore(target,operation){const nodes=getNodes(target,operation);if(nodes.length===0){return;} const{previousSibling}=target;target.before(...nodes);if(previousSibling?.nodeType===Node.TEXT_NODE){const[text1,text2]=previousSibling.data.split(RSTRIP_REGEXP);previousSibling.data=text1.trimEnd();if(nodes[0].nodeType===Node.TEXT_NODE){mergeTextNodes(previousSibling,nodes[0]);} if(text2&&nodes.some((n)=>n.nodeType!==Node.TEXT_NODE)){const textNode=document.createTextNode(text2);target.before(textNode);if(textNode.previousSibling.nodeType===Node.TEXT_NODE){mergeTextNodes(textNode.previousSibling,textNode);}}}} function getRoot(element){while(element.parentElement){element=element.parentElement;} return element;} const HASCLASS_REGEXP=/hasclass\(([^)]*)\)/g;function getXpath(operation){const xpath=operation.getAttribute("expr");return xpath.replaceAll(HASCLASS_REGEXP,(_,capturedGroup)=>{return capturedGroup.split(",").map((c)=>`contains(concat(' ', @class, ' '), ' ${c.trim().slice(1, -1)} ')`).join(" and ");});} function getNode(element,operation){const root=getRoot(element);const doc=new Document();doc.appendChild(root);if(operation.tagName==="xpath"){const xpath=getXpath(operation);const result=doc.evaluate(xpath,root,null,XPathResult.FIRST_ORDERED_NODE_TYPE);return result.singleNodeValue;} for(const elem of root.querySelectorAll(operation.tagName)){if([...operation.attributes].every(({name,value})=>name==="position"||elem.getAttribute(name)===value)){return elem;}} return null;} function getElement(element,operation){const node=getNode(element,operation);if(!node){throw new Error(`Element '${operation.outerHTML}' cannot be located in element tree`);} if(!(node instanceof Element)){throw new Error(`Found node ${node} instead of an element`);} return node;} function getNodes(element,operation){const nodes=[];for(const childNode of operation.childNodes){if(childNode.tagName==="xpath"&&childNode.getAttribute?.("position")==="move"){const node=getElement(element,childNode);removeNode(node);nodes.push(node);}else{nodes.push(childNode);}} return nodes;} function mergeTextNodes(first,second,trimEnd=true){first.data=(trimEnd?first.data.trimEnd():first.data)+second.data;second.remove();} function splitAndTrim(str,separator){return str.split(separator).map((s)=>s.trim());} function modifyAttributes(target,operation){for(const child of operation.children){if(child.tagName!=="attribute"){continue;} const attributeName=child.getAttribute("name");const firstNode=child.childNodes[0];let value=firstNode?.nodeType===Node.TEXT_NODE?firstNode.data:"";const add=child.getAttribute("add")||"";const remove=child.getAttribute("remove")||"";if(add||remove){if(firstNode?.nodeType===Node.TEXT_NODE){throw new Error(`Useless element content ${firstNode.outerHTML}`);} const separator=child.getAttribute("separator")||",";const toRemove=new Set(splitAndTrim(remove,separator));const values=splitAndTrim(target.getAttribute(attributeName)||"",separator).filter((s)=>!toRemove.has(s));values.push(...splitAndTrim(add,separator).filter((s)=>s));value=values.join(separator);} if(value){target.setAttribute(attributeName,value);}else{target.removeAttribute(attributeName);}}} function removeNode(node){const{nextSibling,previousSibling}=node;node.remove();if(nextSibling?.nodeType===Node.TEXT_NODE&&previousSibling?.nodeType===Node.TEXT_NODE){mergeTextNodes(previousSibling,nextSibling,previousSibling.parentElement.firstChild===previousSibling);}} function replace(root,target,operation){const mode=operation.getAttribute("mode")||"outer";switch(mode){case"outer":{const result=operation.ownerDocument.evaluate(".//*[text()='$0']",operation,null,XPathResult.ORDERED_NODE_SNAPSHOT_TYPE);for(let i=0;i`${name}=${JSON.stringify(name === "position" ? position : value)}`);const comment=document.createComment(` From file: ${url} ; ${attributes.join(" ; ")} `);if(position==="attributes"){target.before(comment);}else{operation.prepend(comment);}} switch(position){case"replace":{root=replace(root,target,operation);break;} case"attributes":{modifyAttributes(target,operation);break;} case"inside":{const sentinel=document.createElement("sentinel");target.append(sentinel);addBefore(sentinel,operation);removeNode(sentinel);break;} case"after":{const sentinel=document.createElement("sentinel");target.after(sentinel);addBefore(sentinel,operation);removeNode(sentinel);break;} case"before":{addBefore(target,operation);break;} default:throw new Error(`Invalid position attribute: '${position}'`);}} return root;} return __exports;});; /* /web/static/src/core/templates.js */ odoo.define('@web/core/templates',['@web/core/template_inheritance'],function(require){'use strict';let __exports={};const{applyInheritance}=require("@web/core/template_inheritance");function getClone(template){const c=template.cloneNode(true);new Document().append(c);return c;} function getParsedTemplate(templateString){const doc=parser.parseFromString(templateString,"text/xml");for(const processor of templateProcessors){processor(doc);} return doc.firstChild;} function _getTemplate(name,blockId=null){if(!(name in parsedTemplates)){if(!(name in templates)){return null;} const templateString=templates[name];parsedTemplates[name]=getParsedTemplate(templateString);} let processedTemplate=parsedTemplates[name];const inheritFrom=processedTemplate.getAttribute("t-inherit");if(inheritFrom){const parentTemplate=_getTemplate(inheritFrom,blockId||info[name].blockId);if(!parentTemplate){throw new Error(`Constructing template ${name}: template parent ${inheritFrom} not found`);} const element=getClone(processedTemplate);processedTemplate=applyInheritance(getClone(parentTemplate),element,info[name].url);if(processedTemplate.tagName!==element.tagName){const temp=processedTemplate;processedTemplate=new Document().createElement(element.tagName);processedTemplate.append(...temp.childNodes);} for(const{name,value}of element.attributes){if(!["t-inherit","t-inherit-mode"].includes(name)){processedTemplate.setAttribute(name,value);}}} for(const otherBlockId in templateExtensions[name]||{}){if(blockId&&otherBlockId>blockId){break;} if(!(name in parsedTemplateExtensions)){parsedTemplateExtensions[name]={};} if(!(otherBlockId in parsedTemplateExtensions[name])){parsedTemplateExtensions[name][otherBlockId]=[];for(const{templateString,url}of templateExtensions[name][otherBlockId]){parsedTemplateExtensions[name][otherBlockId].push({template:getParsedTemplate(templateString),url,});}} for(const{template,url}of parsedTemplateExtensions[name][otherBlockId]){if(!urlFilters.every((filter)=>filter(url))){continue;} processedTemplate=applyInheritance(inheritFrom?processedTemplate:getClone(processedTemplate),getClone(template),url);}} return processedTemplate;} function isRegistered(...args){const key=JSON.stringify([...args]);if(registered.has(key)){return true;} registered.add(key);return false;} const info=Object.create(null);const parsedTemplateExtensions=Object.create(null);const parsedTemplates=Object.create(null);const parser=new DOMParser();const processedTemplates=new Map();const registered=new Set();const templateExtensions=Object.create(null);const templateProcessors=[];const templates=Object.create(null);let blockType=null;let blockId=0;let urlFilters=[];__exports.checkPrimaryTemplateParents=checkPrimaryTemplateParents;function checkPrimaryTemplateParents(namesToCheck){const missing=new Set(namesToCheck.filter((name)=>!(name in templates)));if(missing.size){console.error(`Missing (primary) parent templates: ${[...missing].join(", ")}`);}} __exports.clearProcessedTemplates=clearProcessedTemplates;function clearProcessedTemplates(){processedTemplates.clear();} __exports.getTemplate=getTemplate;function getTemplate(name){if(!processedTemplates.has(name)){processedTemplates.set(name,_getTemplate(name));} return processedTemplates.get(name);} __exports.registerTemplate=registerTemplate;function registerTemplate(name,url,templateString){if(isRegistered(...arguments)){return;} if(blockType!=="templates"){blockType="templates";blockId++;} if(name in templates&&(info[name].url!==url||templates[name]!==templateString)){throw new Error(`Template ${name} already exists`);} templates[name]=templateString;info[name]={blockId,url};} __exports.registerTemplateExtension=registerTemplateExtension;function registerTemplateExtension(inheritFrom,url,templateString){if(isRegistered(...arguments)){return;} if(blockType!=="extensions"){blockType="extensions";blockId++;} if(!templateExtensions[inheritFrom]){templateExtensions[inheritFrom]=[];} if(!templateExtensions[inheritFrom][blockId]){templateExtensions[inheritFrom][blockId]=[];} templateExtensions[inheritFrom][blockId].push({templateString,url,});} __exports.registerTemplateProcessor=registerTemplateProcessor;function registerTemplateProcessor(processor){templateProcessors.push(processor);} __exports.setUrlFilters=setUrlFilters;function setUrlFilters(filters){urlFilters=filters;} return __exports;});; /* /web/static/src/core/tooltip/tooltip.js */ odoo.define('@web/core/tooltip/tooltip',['@odoo/owl'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const Tooltip=__exports.Tooltip=class Tooltip extends Component{static template="web.Tooltip";static props={close:Function,tooltip:{type:String,optional:true},template:{type:String,optional:true},info:{optional:true},};} return __exports;});; /* /web/static/src/core/tooltip/tooltip_hook.js */ odoo.define('@web/core/tooltip/tooltip_hook',['@web/core/utils/hooks','@odoo/owl'],function(require){'use strict';let __exports={};const{useService}=require("@web/core/utils/hooks");const{useEffect,useRef}=require("@odoo/owl");__exports.useTooltip=useTooltip;function useTooltip(refName,params){const tooltip=useService("tooltip");const ref=useRef(refName);useEffect((el)=>tooltip.add(el,params),()=>[ref.el]);} return __exports;});; /* /web/static/src/core/tooltip/tooltip_service.js */ odoo.define('@web/core/tooltip/tooltip_service',['@web/core/browser/browser','@web/core/registry','@web/core/tooltip/tooltip','@web/core/browser/feature_detection','@odoo/owl'],function(require){'use strict';let __exports={};const{browser}=require("@web/core/browser/browser");const{registry}=require("@web/core/registry");const{Tooltip}=require("@web/core/tooltip/tooltip");const{hasTouch}=require("@web/core/browser/feature_detection");const{whenReady}=require("@odoo/owl");const OPEN_DELAY=__exports.OPEN_DELAY=400;const CLOSE_DELAY=__exports.CLOSE_DELAY=200;const SHOW_AFTER_DELAY=__exports.SHOW_AFTER_DELAY=250;const tooltipService=__exports.tooltipService={dependencies:["popover"],start(env,{popover}){let openTooltipTimeout;let closeTooltip;let showTimer;let target=null;const elementsWithTooltips=new WeakMap();function cleanup(){target=null;browser.clearTimeout(openTooltipTimeout);openTooltipTimeout=null;if(closeTooltip){closeTooltip();closeTooltip=null;}} function shouldCleanup(){if(!target){return false;} if(!document.body.contains(target)){return true;} return false;} function openTooltip(el,{tooltip="",template,info,position,delay=OPEN_DELAY}){cleanup();if(!tooltip&&!template){return;} target=el;openTooltipTimeout=browser.setTimeout(()=>{if(target.isConnected){closeTooltip=popover.add(target,Tooltip,{tooltip,template,info},{position});target.title="";}},delay);} function openElementsTooltip(el){if(el.nodeType===Node.TEXT_NODE){return;} const element=el.closest("[data-tooltip], [data-tooltip-template]");if(elementsWithTooltips.has(el)){openTooltip(el,elementsWithTooltips.get(el));}else if(element){const dataset=element.dataset;const params={tooltip:dataset.tooltip,template:dataset.tooltipTemplate,position:dataset.tooltipPosition,};if(dataset.tooltipInfo){params.info=JSON.parse(dataset.tooltipInfo);} if(dataset.tooltipDelay){params.delay=parseInt(dataset.tooltipDelay,10);} openTooltip(element,params);}} function onMouseenter(ev){openElementsTooltip(ev.target);} function cleanupTooltip(ev){if(target===ev.target.closest("[data-tooltip], [data-tooltip-template]")){cleanup();}} function onTouchStart(ev){cleanup();showTimer=browser.setTimeout(()=>{openElementsTooltip(ev.target);},SHOW_AFTER_DELAY);} whenReady(()=>{browser.setInterval(()=>{if(shouldCleanup()){cleanup();}},CLOSE_DELAY);if(hasTouch()){document.body.addEventListener("touchstart",onTouchStart);document.body.addEventListener("touchend",(ev)=>{if(ev.target.closest("[data-tooltip], [data-tooltip-template]")){if(!ev.target.dataset.tooltipTouchTapToShow){browser.clearTimeout(showTimer);browser.clearTimeout(openTooltipTimeout);}}});document.body.addEventListener("touchcancel",(ev)=>{if(ev.target.closest("[data-tooltip], [data-tooltip-template]")){if(!ev.target.dataset.tooltipTouchTapToShow){browser.clearTimeout(showTimer);browser.clearTimeout(openTooltipTimeout);}}});} document.body.addEventListener("mouseenter",onMouseenter,{capture:true});document.body.addEventListener("mouseleave",cleanupTooltip,{capture:true});document.body.addEventListener("click",cleanupTooltip,{capture:true});});return{add(el,params){elementsWithTooltips.set(el,params);return()=>{elementsWithTooltips.delete(el);if(target===el){cleanup();}};},};},};registry.category("services").add("tooltip",tooltipService);return __exports;});; /* /web/static/src/core/transition.js */ odoo.define('@web/core/transition',['@web/core/browser/browser','@odoo/owl'],function(require){'use strict';let __exports={};const{browser}=require("@web/core/browser/browser");const{Component,onWillUpdateProps,status,useComponent,useEffect,useState,xml,}=require("@odoo/owl");const config=__exports.config={disabled:false,};__exports.useTransition=useTransition;function useTransition({name,initialVisibility=true,immediate=false,leaveDuration=500,onLeave=()=>{},}){const component=useComponent();const state=useState({shouldMount:initialVisibility,stage:initialVisibility?"enter":"leave",});if(config.disabled){return{get shouldMount(){return state.shouldMount;},set shouldMount(val){state.shouldMount=val;},get className(){return`${name} ${name}-enter-active`;},get stage(){return"enter-active";},};} let onNextPatch=null;useEffect(()=>{if(onNextPatch){onNextPatch();onNextPatch=null;}});let prevState,timer;const transition={get shouldMount(){return state.shouldMount;},set shouldMount(newState){if(newState===prevState){return;} browser.clearTimeout(timer);prevState=newState;if(newState){if(status(component)==="mounted"||immediate){state.stage="enter";component.render();onNextPatch=()=>{state.stage="enter-active";};}else{state.stage="enter-active";} state.shouldMount=true;}else{state.stage="leave";timer=browser.setTimeout(()=>{state.shouldMount=false;onLeave();},leaveDuration);}},get className(){return`${name} ${name}-${state.stage}`;},get stage(){return state.stage;},};transition.shouldMount=initialVisibility;return transition;} const Transition=__exports.Transition=class Transition extends Component{static template=xml``;static props={name:String,visible:{type:Boolean,optional:true},immediate:{type:Boolean,optional:true},leaveDuration:{type:Number,optional:true},onLeave:{type:Function,optional:true},slots:Object,};setup(){const{immediate,visible,leaveDuration,name,onLeave}=this.props;this.transition=useTransition({initialVisibility:visible,immediate,leaveDuration,name,onLeave,});onWillUpdateProps(({visible=true})=>{this.transition.shouldMount=visible;});}} return __exports;});; /* /web/static/src/core/tree_editor/condition_tree.js */ odoo.define('@web/core/tree_editor/condition_tree',['@web/core/domain','@web/core/py_js/py','@web/core/py_js/py_utils','@web/core/utils/objects'],function(require){'use strict';let __exports={};const{Domain}=require("@web/core/domain");const{formatAST,parseExpr}=require("@web/core/py_js/py");const{toPyValue}=require("@web/core/py_js/py_utils");const{deepCopy,deepEqual}=require("@web/core/utils/objects");const TERM_OPERATORS_NEGATION=__exports.TERM_OPERATORS_NEGATION={"<":">=",">":"<=","<=":">",">=":"<","=":"!=","!=":"=",in:"not in",like:"not like",ilike:"not ilike","not in":"in","not like":"like","not ilike":"ilike",};const TERM_OPERATORS_NEGATION_EXTENDED={...TERM_OPERATORS_NEGATION,is:"is not","is not":"is","==":"!=","!=":"==",};const EXCHANGE={"<":">","<=":">=",">":"<",">=":"<=","=":"=","!=":"!=",};const COMPARATORS=["<","<=",">",">=","in","not in","==","is","!=","is not"];const DATETIME_TODAY_STRING_EXPRESSION=`datetime.datetime.combine(context_today(), datetime.time(0, 0, 0)).to_utc().strftime("%Y-%m-%d %H:%M:%S")`;const DATE_TODAY_STRING_EXPRESSION=`context_today().strftime("%Y-%m-%d")`;const DELTA_DATE_AST=parseExpr(`(context_today() + relativedelta(period=amount)).strftime('%Y-%m-%d')`);const DELTA_DATETIME_AST=parseExpr(`datetime.datetime.combine(context_today() + relativedelta(period=amount), datetime.time(0, 0, 0)).to_utc().strftime("%Y-%m-%d %H:%M:%S")`);function replaceKwargs(ast,fieldType,kwargs={}){const astCopy=deepCopy(ast);if(fieldType==="date"){astCopy.fn.obj.right.kwargs=kwargs;}else{astCopy.fn.obj.fn.obj.args[0].right.kwargs=kwargs;} return astCopy;} function getDelta(ast,fieldType){const kwargs=(fieldType==="date"?ast.fn?.obj?.right?.kwargs:ast.fn?.obj?.fn?.obj?.args?.[0]?.right?.kwargs)||{};if(Object.keys(kwargs).length!==1){return null;} if(!deepEqual(replaceKwargs(ast,fieldType),replaceKwargs(fieldType==="date"?DELTA_DATE_AST:DELTA_DATETIME_AST,fieldType))){return null;} const[option,amountAST]=Object.entries(kwargs)[0];return[toValue(amountAST),option];} function getDeltaExpression(value,fieldType){const ast=replaceKwargs(fieldType==="date"?DELTA_DATE_AST:DELTA_DATETIME_AST,fieldType,{[value[1]]:toAST(value[0])});return expression(formatAST(ast));} function isTodayExpr(val,type){return(val._expr===(type==="date"?DATE_TODAY_STRING_EXPRESSION:DATETIME_TODAY_STRING_EXPRESSION));} const Expression=__exports.Expression=class Expression{constructor(ast){if(typeof ast==="string"){ast=parseExpr(ast);} this._ast=ast;this._expr=formatAST(ast);} toAST(){return this._ast;} toString(){return this._expr;}} __exports.expression=expression;function expression(expr){return new Expression(expr);} __exports.connector=connector;function connector(value,children=[],negate=false){return{type:"connector",value,children,negate};} __exports.condition=condition;function condition(path,operator,value,negate=false){return{type:"condition",path,operator,value,negate};} __exports.complexCondition=complexCondition;function complexCondition(value){parseExpr(value);return{type:"complex_condition",value};} function cloneValue(value){if(value instanceof Expression){return new Expression(value.toAST());} if(Array.isArray(value)){return value.map(cloneValue);} return value;} __exports.cloneTree=cloneTree;function cloneTree(tree){const clone={};for(const key in tree){clone[key]=cloneValue(tree[key]);} return clone;} __exports.formatValue=formatValue;function formatValue(value){return formatAST(toAST(value));} __exports.normalizeValue=normalizeValue;function normalizeValue(value){return toValue(toAST(value));} __exports.toValue=toValue;function toValue(ast,isWithinArray=false){if([4,10].includes(ast.type)&&!isWithinArray){return ast.value.map((v)=>toValue(v,true));}else if([0,1,2].includes(ast.type)){return ast.value;}else if(ast.type===6&&ast.op==="-"&&ast.right.type===0){return-ast.right.value;}else if(ast.type===5&&["false","true"].includes(ast.value)){return JSON.parse(ast.value);}else{return new Expression(ast);}} __exports.isTree=isTree;function isTree(value){return(typeof value==="object"&&!(value instanceof Domain)&&!(value instanceof Expression)&&!Array.isArray(value)&&value!==null);} function toAST(value){if(isTree(value)){const domain=new Domain(domainFromTree(value));return domain.ast;} if(value instanceof Expression){return value.toAST();} if(Array.isArray(value)){return{type:4,value:value.map(toAST)};} return toPyValue(value);} function addChild(parent,child){if(child.type==="connector"&&!child.negate&&child.value===parent.value){parent.children.push(...child.children);}else{parent.children.push(child);}} function getNormalizedCondition(condition){let{operator,negate}=condition;if(negate&&typeof operator==="string"&&TERM_OPERATORS_NEGATION[operator]){operator=TERM_OPERATORS_NEGATION[operator];negate=false;} return{...condition,operator,negate};} function normalizeCondition(condition){Object.assign(condition,getNormalizedCondition(condition));} function _construcTree(ASTs,distributeNot,negate=false){const[firstAST,...tailASTs]=ASTs;if(firstAST.type===1&&firstAST.value==="!"){return _construcTree(tailASTs,distributeNot,!negate);} const tree={type:firstAST.type===1?"connector":"condition"};if(tree.type==="connector"){tree.value=firstAST.value;if(distributeNot&&negate){tree.value=tree.value==="&"?"|":"&";tree.negate=false;}else{tree.negate=negate;} tree.children=[];}else{const[pathAST,operatorAST,valueAST]=firstAST.value;tree.path=toValue(pathAST);tree.negate=negate;tree.operator=toValue(operatorAST);tree.value=toValue(valueAST);if(["any","not any"].includes(tree.operator)){try{tree.value=treeFromDomain(formatAST(valueAST));}catch{tree.value=Array.isArray(tree.value)?tree.value:[tree.value];}} normalizeCondition(tree);} let remaimingASTs=tailASTs;if(tree.type==="connector"){for(let i=0;i<2;i++){const{tree:child,remaimingASTs:otherASTs}=_construcTree(remaimingASTs,distributeNot,distributeNot&&negate);remaimingASTs=otherASTs;addChild(tree,child);}} return{tree,remaimingASTs};} function construcTree(initialASTs,options){if(!initialASTs.length){return connector("&");} const{tree}=_construcTree(initialASTs,options.distributeNot);return tree;} function getASTs(tree){const ASTs=[];if(tree.type==="condition"){if(tree.negate){ASTs.push(toAST("!"));} ASTs.push({type:10,value:[tree.path,tree.operator,tree.value].map(toAST),});return ASTs;} const length=tree.children.length;if(length&&tree.negate){ASTs.push(toAST("!"));} for(let i=0;inull);if(ast.type===5){return getFieldDef(ast.value)!==null;} return false;} function isX2Many(ast,options){if(isValidPath(ast,options)){const fieldDef=options.getFieldDef(ast.value);return["many2many","one2many"].includes(fieldDef.type);} return false;} function _getConditionFromComparator(ast,options){if(["is","is not"].includes(ast.op)){return null;} let operator=ast.op;if(operator==="=="){operator="=";} let left=ast.left;let right=ast.right;if(isValidPath(left,options)==isValidPath(right,options)){return null;} if(!isValidPath(left,options)){if(operator in EXCHANGE){const temp=left;left=right;right=temp;operator=EXCHANGE[operator];}else{return null;}} return condition(left.value,operator,toValue(right));} function isValidPath2(ast,options){if(!ast){return null;} if([4,10].includes(ast.type)&&ast.value.length===1){return isValidPath(ast.value[0],options);} return isValidPath(ast,options);} function _getConditionFromIntersection(ast,options,negate=false){let left=ast.fn.obj.args[0];let right=ast.args[0];if(!left){return condition(negate?1:0,"=",1);} if(isValidPath2(left,options)==isValidPath2(right,options)){return null;} if(!isValidPath2(left,options)){const temp=left;left=right;right=temp;} if([4,10].includes(left.type)&&left.value.length===1){left=left.value[0];} if(!right){return condition(left.value,negate?"=":"!=",false);} if(isSet(right)){if(!right.args[0]){right={type:4,value:[]};} if([4,10].includes(right.args[0].type)){right=right.args[0];}} if(![4,10].includes(right.type)){return null;} return condition(left.value,negate?"not in":"in",toValue(right));} function _leafFromAST(ast,options,negate=false){if(isNot(ast)){return _treeFromAST(ast.right,options,!negate);} if(ast.type===5&&isValidPath(ast,options)){return condition(ast.value,negate?"=":"!=",false);} const astValue=toValue(ast);if(["boolean","number","string"].includes(typeof astValue)){return condition(astValue?1:0,"=",1);} if(ast.type===8&&ast.fn.type===15&&isSet(ast.fn.obj)&&ast.fn.key==="intersection"){const tree=_getConditionFromIntersection(ast,options,negate);if(tree){return tree;}} if(ast.type===7&&COMPARATORS.includes(ast.op)){if(negate){return _leafFromAST(not(ast),options);} const tree=_getConditionFromComparator(ast,options);if(tree){return tree;}} return complexCondition(formatAST(negate?not(ast):ast));} function _treeFromAST(ast,options,negate=false){if(isNot(ast)){return _treeFromAST(ast.right,options,!negate);} if(ast.type===14){const tree=connector(ast.op==="and"?"&":"|");if(options.distributeNot&&negate){tree.value=tree.value==="&"?"|":"&";}else{tree.negate=negate;} const subASTs=[ast.left,ast.right];for(const subAST of subASTs){const child=_treeFromAST(subAST,options,options.distributeNot&&negate);addChild(tree,child);} return tree;} if(ast.type===13){const newAST=or(and(ast.condition,ast.ifTrue),and(not(ast.condition),ast.ifFalse));return _treeFromAST(newAST,options,negate);} return _leafFromAST(ast,options,negate);} function _expressionFromTree(tree,options,isRoot=false){if(tree.type==="connector"&&tree.value==="|"&&tree.children.length===2){const isSimpleAnd=(tree)=>tree.type==="connector"&&tree.value==="&"&&tree.children.length===2;if(tree.children.every((c)=>isSimpleAnd(c))){const[c1,c2]=tree.children;for(let i=0;i<2;i++){const c1Child=c1.children[i];const str1=_expressionFromTree({...c1Child},options);for(let j=0;j<2;j++){const c2Child=c2.children[j];const str2=_expressionFromTree(c2Child,options);if(str1===`not ${str2}`||`not ${str1}`===str2){const others=[c1.children[1-i],c2.children[1-j]];const str=_expressionFromTree(c1Child,options);const strs=others.map((c)=>_expressionFromTree(c,options));return`${strs[0]} if ${str} else ${strs[1]}`;}}}}} if(tree.type==="connector"){const connector=tree.value==="&"?"and":"or";const subExpressions=tree.children.map((c)=>_expressionFromTree(c,options));if(!subExpressions.length){return connector==="and"?"1":"0";} let expression=subExpressions.join(` ${connector} `);if(!isRoot||tree.negate){expression=`( ${expression} )`;} if(tree.negate){expression=`not ${expression}`;} return expression;} if(tree.type==="complex_condition"){return tree.value;} tree=getNormalizedCondition(tree);const{path,operator,value}=tree;const op=operator==="="?"==":operator;if(typeof op!=="string"||!COMPARATORS.includes(op)){throw new Error("Invalid operator");} if([0,1].includes(path)){if(operator!=="="||value!==1){return new Error("Invalid condition");} return formatAST({type:2,value:Boolean(path)});} const pathAST=toAST(path);if(typeof path=="string"&&isValidPath(name(path),options)){pathAST.type=5;} if(value===false&&["=","!="].includes(operator)){return formatAST(operator==="="?not(pathAST):pathAST);} let valueAST=toAST(value);if(["in","not in"].includes(operator)&&!(value instanceof Expression)&&![4,10].includes(valueAST.type)){valueAST={type:4,value:[valueAST]};} if(pathAST.type===5&&isX2Many(pathAST,options)&&["in","not in"].includes(operator)){const ast={type:8,fn:{type:15,obj:{args:[pathAST],type:8,fn:{type:5,value:"set",},},key:"intersection",},args:[valueAST],};return formatAST(operator==="not in"?not(ast):ast);} return formatAST({type:7,op,left:pathAST,right:valueAST,});} function createBetweenOperators(tree){if(["condition","complex_condition"].includes(tree.type)){return tree;} const processedChildren=tree.children.map(createBetweenOperators);if(tree.value==="|"){return{...tree,children:processedChildren};} const children=[];for(let i=0;i="&&child2.operator==="<="){children.push(condition(child1.path,"between",normalizeValue([child1.value,child2.value])));i+=1;}else{children.push(child1);}} if(children.length===1){return{...children[0]};} return{...tree,children};} function createWithinOperators(tree,options={}){if(tree.children){return{...tree,children:tree.children.map((child)=>createWithinOperators(child,options)),};} const fieldType=options.getFieldDef?.(tree.path)?.type;if(tree.operator!=="between"||!["date","datetime"].includes(fieldType)){return tree;} function getProcessedDelta(val,periodShouldBePositive=true){const delta=getDelta(toAST(val),fieldType);if(delta){const[amount]=delta;if(Number.isInteger(amount)&&((amount<0&&periodShouldBePositive)||(amount>0&&!periodShouldBePositive))){return null;}} return delta;} const newTree={...tree};if(isTodayExpr(newTree.value[0],fieldType)){const delta=getProcessedDelta(newTree.value[1]);if(delta){newTree.operator="within";newTree.value=[...delta,fieldType];}}else if(isTodayExpr(newTree.value[1],fieldType)){const delta=getProcessedDelta(newTree.value[0],false);if(delta){newTree.operator="within";newTree.value=[...delta,fieldType];}} return newTree;} __exports.removeBetweenOperators=removeBetweenOperators;function removeBetweenOperators(tree){if(tree.type==="complex_condition"){return tree;} if(tree.type==="condition"){if(tree.operator!=="between"){return tree;} const{negate,path,value}=tree;return connector("&",[condition(path,">=",value[0]),condition(path,"<=",value[1])],negate);} const processedChildren=tree.children.map(removeBetweenOperators);if(tree.value==="|"){return{...tree,children:processedChildren};} const newTree={...tree,children:[]};for(let i=0;i0;return condition(path,"between",reverse?Object.values(expressions):Object.values(expressions).reverse(),negate);} const processedChildren=tree.children.map(removeWithinOperators);return{...tree,children:processedChildren};} __exports.createVirtualOperators=createVirtualOperators;function createVirtualOperators(tree,options={}){if(tree.type==="condition"){const{path,operator,value}=tree;if(["=","!="].includes(operator)){const fieldDef=options.getFieldDef?.(path)||null;if(fieldDef){if(fieldDef.type==="boolean"){return{...tree,operator:operator==="="?"is":"is_not"};}else if(!["many2one","date","datetime"].includes(fieldDef?.type)&&value===false){return{...tree,operator:operator==="="?"not_set":"set"};}}} if(operator==="=ilike"){if(value.endsWith?.("%")){return{...tree,operator:"starts_with",value:value.slice(0,-1)};} if(value.startsWith?.("%")){return{...tree,operator:"ends_with",value:value.slice(1)};}} return tree;} if(tree.type==="complex_condition"){return tree;} const processedChildren=tree.children.map((c)=>createVirtualOperators(c,options));return{...tree,children:processedChildren};} __exports.removeVirtualOperators=removeVirtualOperators;function removeVirtualOperators(tree){if(tree.type==="condition"){const{operator,value}=tree;if(["is","is_not"].includes(operator)){return{...tree,operator:operator==="is"?"=":"!="};} if(["set","not_set"].includes(operator)){return{...tree,operator:operator==="set"?"!=":"="};} if(["starts_with","ends_with"].includes(operator)){return{...tree,value:operator==="starts_with"?`${value}%`:`%${value}`,operator:"=ilike",};} return tree;} if(tree.type==="complex_condition"){return tree;} const processedChildren=tree.children.map((c)=>removeVirtualOperators(c));return{...tree,children:processedChildren};} function createComplexConditions(tree){if(tree.type==="condition"){if(tree.path instanceof Expression&&tree.operator==="="&&tree.value===1){return complexCondition(String(tree.path));} return cloneTree(tree);} if(tree.type==="complex_condition"){return cloneTree(tree);} return{...tree,children:tree.children.map((child)=>createComplexConditions(child)),};} function removeComplexConditions(tree){if(tree.type==="condition"){return cloneTree(tree);} if(tree.type==="complex_condition"){const ast=parseExpr(tree.value);return condition(new Expression(bool(ast)),"=",1);} return{...tree,children:tree.children.map((child)=>removeComplexConditions(child)),};} __exports.treeFromExpression=treeFromExpression;function treeFromExpression(expression,options={}){const ast=parseExpr(expression);const tree=_treeFromAST(ast,options);return createVirtualOperators(createWithinOperators(createBetweenOperators(tree),options),options);} __exports.expressionFromTree=expressionFromTree;function expressionFromTree(tree,options={}){const simplifiedTree=createComplexConditions(removeBetweenOperators(removeWithinOperators(removeVirtualOperators(tree))));return _expressionFromTree(simplifiedTree,options,true);} __exports.domainFromTree=domainFromTree;function domainFromTree(tree){const simplifiedTree=removeBetweenOperators(removeWithinOperators(removeVirtualOperators(removeComplexConditions(tree))));const domainAST={type:4,value:getASTs(simplifiedTree),};return formatAST(domainAST);} __exports.treeFromDomain=treeFromDomain;function treeFromDomain(domain,options={}){domain=new Domain(domain);const domainAST=domain.ast;const tree=construcTree(domainAST.value,options);return createVirtualOperators(createWithinOperators(createBetweenOperators(tree),options),options);} __exports.expressionFromDomain=expressionFromDomain;function expressionFromDomain(domain,options={}){const tree=treeFromDomain(domain,options);return expressionFromTree(tree,options);} __exports.domainFromExpression=domainFromExpression;function domainFromExpression(expression,options={}){const tree=treeFromExpression(expression,options);return domainFromTree(tree);} return __exports;});; /* /web/static/src/core/tree_editor/tree_editor.js */ odoo.define('@web/core/tree_editor/tree_editor',['@web/core/tree_editor/utils','@odoo/owl','@web/core/utils/hooks','@web/core/dropdown/dropdown','@web/core/dropdown/dropdown_item','@web/core/tree_editor/condition_tree','@web/core/tree_editor/tree_editor_value_editors','@web/core/model_field_selector/model_field_selector','@web/core/model_field_selector/utils','@web/core/utils/objects'],function(require){'use strict';let __exports={};const{getResModel,useMakeGetFieldDef,useMakeGetConditionDescription,}=require("@web/core/tree_editor/utils");const{Component,onWillStart,onWillUpdateProps}=require("@odoo/owl");const{useService}=require("@web/core/utils/hooks");const{Dropdown}=require("@web/core/dropdown/dropdown");const{DropdownItem}=require("@web/core/dropdown/dropdown_item");const{condition,cloneTree,formatValue,removeVirtualOperators,connector,isTree,}=require("@web/core/tree_editor/condition_tree");const{getDefaultValue,getValueEditorInfo,}=require("@web/core/tree_editor/tree_editor_value_editors");const{ModelFieldSelector}=require("@web/core/model_field_selector/model_field_selector");const{useLoadFieldInfo}=require("@web/core/model_field_selector/utils");const{deepEqual,shallowEqual}=require("@web/core/utils/objects");const TRUE_TREE=condition(1,"=",1);function collectDifferences(tree,otherTree){if(tree.type!==otherTree.type){return[{type:"other"}];} if(tree.negate!==otherTree.negate){return[{type:"other"}];} if(tree.type==="condition"){if(formatValue(tree.path)!==formatValue(otherTree.path)){return[{type:"other"}];} if(formatValue(tree.value)!==formatValue(otherTree.value)){return[{type:"other"}];} if(formatValue(tree.operator)!==formatValue(otherTree.operator)){if(tree.operator==="!="&&otherTree.operator==="set"){return[{type:"replacement",tree,operator:"set"}];}else if(tree.operator==="="&&otherTree.operator==="not_set"){return[{type:"replacement",tree,operator:"not_set"}];}else{return[{type:"other"}];}} return[];} if(tree.value!==otherTree.value){return[{type:"other"}];} if(tree.type==="complex_condition"){return[];} if(tree.children.length!==otherTree.children.length){return[{type:"other"}];} const diffs=[];for(let i=0;id.type!=="replacement")){return[{type:"other"}];} diffs.push(...childDiffs);} return diffs;} function restoreVirtualOperators(tree,otherTree){const diffs=collectDifferences(tree,otherTree);if(diffs.some((d)=>d.type!=="replacement")){return;} for(const{tree,operator}of diffs){tree.operator=operator;}} const TreeEditor=__exports.TreeEditor=class TreeEditor extends Component{static template="web.TreeEditor";static components={Dropdown,DropdownItem,ModelFieldSelector,TreeEditor,};static props={tree:Object,resModel:String,update:Function,getDefaultCondition:Function,getPathEditorInfo:Function,getOperatorEditorInfo:Function,getDefaultOperator:Function,readonly:{type:Boolean,optional:true},slots:{type:Object,optional:true},isDebugMode:{type:Boolean,optional:true},defaultConnector:{type:[{value:"&"},{value:"|"}],optional:true},isSubTree:{type:Boolean,optional:true},};static defaultProps={defaultConnector:"&",readonly:false,isSubTree:false,};setup(){this.isTree=isTree;this.fieldService=useService("field");this.nameService=useService("name");this.loadFieldInfo=useLoadFieldInfo(this.fieldService);this.makeGetFieldDef=useMakeGetFieldDef(this.fieldService);this.makeGetConditionDescription=useMakeGetConditionDescription(this.fieldService,this.nameService);onWillStart(()=>this.onPropsUpdated(this.props));onWillUpdateProps((nextProps)=>this.onPropsUpdated(nextProps));} async onPropsUpdated(props){this.tree=cloneTree(props.tree);if(shallowEqual(this.tree,TRUE_TREE)){this.tree=connector(props.defaultConnector);}else if(this.tree.type!=="connector"){this.tree=connector(props.defaultConnector,[this.tree]);} if(this.previousTree){restoreVirtualOperators(this.tree,this.previousTree);this.previousTree=null;} const[fieldDefs,getFieldDef]=await Promise.all([this.fieldService.loadFields(props.resModel),this.makeGetFieldDef(props.resModel,this.tree),]);this.getFieldDef=getFieldDef;this.defaultCondition=props.getDefaultCondition(fieldDefs);if(props.readonly){this.getConditionDescription=await this.makeGetConditionDescription(props.resModel,this.tree,this.getFieldDef);}} get className(){return`${this.props.readonly ? "o_read_mode" : "o_edit_mode"}`;} get isDebugMode(){return this.props.isDebugMode!==undefined?this.props.isDebugMode:!!this.env.debug;} notifyChanges(){this.previousTree=cloneTree(this.tree);this.props.update(this.tree);} updateConnector(node,value){node.value=value;node.negate=false;this.notifyChanges();} updateComplexCondition(node,value){node.value=value;this.notifyChanges();} createNewLeaf(){return cloneTree(this.defaultCondition);} createNewBranch(value){return connector(value,[this.createNewLeaf(),this.createNewLeaf()]);} insertRootLeaf(parent){parent.children.push(this.createNewLeaf());this.notifyChanges();} insertLeaf(parent,node){const newNode=node.type!=="connector"?cloneTree(node):this.createNewLeaf();const index=parent.children.indexOf(node);parent.children.splice(index+1,0,newNode);this.notifyChanges();} insertBranch(parent,node){const nextConnector=parent.value==="&"?"|":"&";const newNode=this.createNewBranch(nextConnector);const index=parent.children.indexOf(node);parent.children.splice(index+1,0,newNode);this.notifyChanges();} delete(parent,node){const index=parent.children.indexOf(node);parent.children.splice(index,1);this.notifyChanges();} getResModel(node){const fieldDef=this.getFieldDef(node.path);const resModel=getResModel(fieldDef);return resModel;} getPathEditorInfo(){return this.props.getPathEditorInfo(this.props.resModel,this.defaultCondition);} getOperatorEditorInfo(node){const fieldDef=this.getFieldDef(node.path);return this.props.getOperatorEditorInfo(fieldDef);} getValueEditorInfo(node){const fieldDef=this.getFieldDef(node.path);return getValueEditorInfo(fieldDef,node.operator);} async updatePath(node,path){const{fieldDef}=await this.loadFieldInfo(this.props.resModel,path);node.path=path;node.negate=false;node.operator=this.props.getDefaultOperator(fieldDef);node.value=getDefaultValue(fieldDef,node.operator);this.notifyChanges();} updateLeafOperator(node,operator,negate){const previousNode=cloneTree(node);const fieldDef=this.getFieldDef(node.path);node.negate=negate;node.operator=operator;node.value=getDefaultValue(fieldDef,operator,node.value);if(deepEqual(removeVirtualOperators(node),removeVirtualOperators(previousNode))){this.render();} this.notifyChanges();} updateLeafValue(node,value){node.value=value;this.notifyChanges();} highlightNode(target){const nodeEl=target.closest(".o_tree_editor_node");nodeEl.classList.toggle("o_hovered_button");}} return __exports;});; /* /web/static/src/core/tree_editor/tree_editor_autocomplete.js */ odoo.define('@web/core/tree_editor/tree_editor_autocomplete',['@web/core/record_selectors/multi_record_selector','@web/core/l10n/translation','@web/core/py_js/py_utils','@web/core/tree_editor/condition_tree','@web/core/record_selectors/record_selector'],function(require){'use strict';let __exports={};const{MultiRecordSelector}=require("@web/core/record_selectors/multi_record_selector");const{_t}=require("@web/core/l10n/translation");const{formatAST,toPyValue}=require("@web/core/py_js/py_utils");const{Expression}=require("@web/core/tree_editor/condition_tree");const{RecordSelector}=require("@web/core/record_selectors/record_selector");const isId=__exports.isId=(val)=>Number.isInteger(val)&&val>=1;const getFormat=__exports.getFormat=(val,displayNames)=>{let text;let colorIndex;if(isId(val)){text=typeof displayNames[val]==="string"?displayNames[val]:_t("Inaccessible/missing record ID: %s",val);colorIndex=typeof displayNames[val]==="string"?0:2;}else{text=val instanceof Expression?String(val):_t("Invalid record ID: %s",formatAST(toPyValue(val)));colorIndex=val instanceof Expression?2:1;} return{text,colorIndex};};const DomainSelectorAutocomplete=__exports.DomainSelectorAutocomplete=class DomainSelectorAutocomplete extends MultiRecordSelector{static props={...MultiRecordSelector.props,resIds:true,};getIds(props=this.props){return props.resIds.filter((val)=>isId(val));} getTags(props,displayNames){return props.resIds.map((val,index)=>{const{text,colorIndex}=getFormat(val,displayNames);return{text,colorIndex,onDelete:()=>{this.props.update([...this.props.resIds.slice(0,index),...this.props.resIds.slice(index+1),]);},};});}} const DomainSelectorSingleAutocomplete=__exports.DomainSelectorSingleAutocomplete=class DomainSelectorSingleAutocomplete extends RecordSelector{static props={...RecordSelector.props,resId:true,};getDisplayName(props=this.props,displayNames){const{resId}=props;if(resId===false){return"";} const{text}=getFormat(resId,displayNames);return text;} getIds(props=this.props){if(isId(props.resId)){return[props.resId];} return[];}} return __exports;});; /* /web/static/src/core/tree_editor/tree_editor_components.js */ odoo.define('@web/core/tree_editor/tree_editor_components',['@odoo/owl','@web/core/tags_list/tags_list','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const{TagsList}=require("@web/core/tags_list/tags_list");const{_t}=require("@web/core/l10n/translation");const Input=__exports.Input=class Input extends Component{static props=["value","update","startEmpty?"];static template="web.TreeEditor.Input";} const Select=__exports.Select=class Select extends Component{static props=["value","update","options","addBlankOption?"];static template="web.TreeEditor.Select";deserialize(value){return JSON.parse(value);} serialize(value){return JSON.stringify(value);}} const Range=__exports.Range=class Range extends Component{static props=["value","update","editorInfo"];static template="web.TreeEditor.Range";update(index,newValue){const result=[...this.props.value];result[index]=newValue;return this.props.update(result);}} const Within=__exports.Within=class Within extends Component{static props=["value","update","amountEditorInfo","optionEditorInfo"];static template="web.TreeEditor.Within";static components={Input,Select};static options=[["days",_t("days")],["weeks",_t("weeks")],["months",_t("months")],["years",_t("years")],];update(index,newValue){const result=[...this.props.value];result[index]=newValue;return this.props.update(result);}} const List=__exports.List=class List extends Component{static components={TagsList};static props=["value","update","editorInfo"];static template="web.TreeEditor.List";get tags(){const{isSupported,stringify}=this.props.editorInfo;return this.props.value.map((val,index)=>({text:stringify(val),colorIndex:isSupported(val)?0:2,onDelete:()=>{this.props.update([...this.props.value.slice(0,index),...this.props.value.slice(index+1),]);},}));} update(newValue){return this.props.update([...this.props.value,newValue]);}} return __exports;});; /* /web/static/src/core/tree_editor/tree_editor_operator_editor.js */ odoo.define('@web/core/tree_editor/tree_editor_operator_editor',['@web/core/l10n/translation','@web/core/tree_editor/condition_tree','@web/core/utils/strings','@web/core/py_js/py','@web/core/tree_editor/tree_editor_components'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{formatValue,TERM_OPERATORS_NEGATION,toValue,}=require("@web/core/tree_editor/condition_tree");const{sprintf}=require("@web/core/utils/strings");const{parseExpr}=require("@web/core/py_js/py");const{Select}=require("@web/core/tree_editor/tree_editor_components");const OPERATOR_DESCRIPTIONS={"=":"=","!=":"!=","<=":"<=","<":"<",">":">",">=":">=","=?":"=?","=like":_t("=like"),"=ilike":_t("=ilike"),like:_t("like"),"not like":_t("not like"),ilike:_t("contains"),"not ilike":_t("does not contain"),in:_t("is in"),"not in":_t("is not in"),child_of:_t("child of"),parent_of:_t("parent of"),is:_t("is"),is_not:_t("is not"),set:_t("is set"),not_set:_t("is not set"),starts_with:_t("starts with"),ends_with:_t("ends with"),between:_t("is between"),within:_t("is within"),any:(fieldDefType)=>{switch(fieldDefType){case"many2one":return _t("matches");default:return _t("match");}},"not any":(fieldDefType)=>{switch(fieldDefType){case"many2one":return _t("matches none of");default:return _t("match none of");}},};function toKey(operator,negate=false){if(!negate&&typeof operator==="string"&&operator in OPERATOR_DESCRIPTIONS){return operator;} return JSON.stringify([formatValue(operator),negate]);} function toOperator(key){if(!key.includes("[")){return[key,false];} const[expr,negate]=JSON.parse(key);return[toValue(parseExpr(expr)),negate];} function getOperatorDescription(operator,fieldDefType){const description=OPERATOR_DESCRIPTIONS[operator];if(typeof description==="function"&&description.constructor?.name!=="LazyTranslatedString"){return description(fieldDefType);} return description;} __exports.getOperatorLabel=getOperatorLabel;function getOperatorLabel(operator,fieldDefType,negate=false){let label;if(typeof operator==="string"&&operator in OPERATOR_DESCRIPTIONS){if(negate&&operator in TERM_OPERATORS_NEGATION){return getOperatorDescription(TERM_OPERATORS_NEGATION[operator],fieldDefType);} label=getOperatorDescription(operator,fieldDefType);}else{label=formatValue(operator);} if(negate){return sprintf(`not %s`,label);} return label;} function getOperatorInfo(operator,fieldDefType,negate=false){const key=toKey(operator,negate);const label=getOperatorLabel(operator,fieldDefType,negate);return[key,label];} __exports.getOperatorEditorInfo=getOperatorEditorInfo;function getOperatorEditorInfo(operators,fieldDef){const defaultOperator=operators[0];const operatorsInfo=operators.map((operator)=>getOperatorInfo(operator,fieldDef?.type));return{component:Select,extractProps:({update,value:[operator,negate]})=>{const[operatorKey,operatorLabel]=getOperatorInfo(operator,fieldDef?.type,negate);const options=[...operatorsInfo];if(!options.some(([key])=>key===operatorKey)){options.push([operatorKey,operatorLabel]);} return{value:operatorKey,update:(operatorKey)=>update(...toOperator(operatorKey)),options,};},defaultValue:()=>defaultOperator,isSupported:([operator])=>typeof operator==="string"&&operator in OPERATOR_DESCRIPTIONS,message:_t("Operator not supported"),stringify:([operator,negate])=>getOperatorLabel(operator,negate),};} return __exports;});; /* /web/static/src/core/tree_editor/tree_editor_value_editors.js */ odoo.define('@web/core/tree_editor/tree_editor_value_editors',['@web/core/l10n/dates','@web/core/l10n/translation','@web/core/registry','@web/core/datetime/datetime_input','@web/core/tree_editor/tree_editor_autocomplete','@web/core/utils/arrays','@web/core/tree_editor/tree_editor_components','@web/core/tree_editor/condition_tree','@web/core/tree_editor/utils','@web/core/domain'],function(require){'use strict';let __exports={};const{deserializeDate,deserializeDateTime,serializeDate,serializeDateTime,}=require("@web/core/l10n/dates");const{_t}=require("@web/core/l10n/translation");const{registry}=require("@web/core/registry");const{DateTimeInput}=require("@web/core/datetime/datetime_input");const{DomainSelectorAutocomplete,DomainSelectorSingleAutocomplete,}=require("@web/core/tree_editor/tree_editor_autocomplete");const{unique}=require("@web/core/utils/arrays");const{Input,Select,List,Range,Within}=require("@web/core/tree_editor/tree_editor_components");const{connector,formatValue,isTree}=require("@web/core/tree_editor/condition_tree");const{getResModel,disambiguate,isId}=require("@web/core/tree_editor/utils");const{Domain}=require("@web/core/domain");const{DateTime}=luxon;const formatters=registry.category("formatters");const parsers=registry.category("parsers");function parseValue(fieldType,value){const parser=parsers.get(fieldType,(value)=>value);try{return parser(value);}catch{return value;}} function isParsable(fieldType,value){const parser=parsers.get(fieldType,(value)=>value);try{parser(value);}catch{return false;} return true;} function genericSerializeDate(type,value){return type==="date"?serializeDate(value):serializeDateTime(value);} function genericDeserializeDate(type,value){return type==="date"?deserializeDate(value):deserializeDateTime(value);} const STRING_EDITOR={component:Input,extractProps:({value,update})=>({value,update}),isSupported:(value)=>typeof value==="string",defaultValue:()=>"",};function makeSelectEditor(options,params={}){const getOption=(value)=>options.find(([v])=>v===value)||null;return{component:Select,extractProps:({value,update})=>({value,update,options,addBlankOption:params.addBlankOption,}),isSupported:(value)=>Boolean(getOption(value)),defaultValue:()=>options[0]?.[0]??false,stringify:(value,disambiguate)=>{const option=getOption(value);return option?option[1]:disambiguate?formatValue(value):String(value);},message:_t("Value not in selection"),};} function getDomain(fieldDef){if(fieldDef.type==="many2one"){return[];} try{return new Domain(fieldDef.domain||[]).toList();}catch{return[];}} function makeAutoCompleteEditor(fieldDef){return{component:DomainSelectorAutocomplete,extractProps:({value,update})=>{return{resModel:getResModel(fieldDef),fieldString:fieldDef.string,domain:getDomain(fieldDef),update:(value)=>update(unique(value)),resIds:unique(value),};},isSupported:(value)=>Array.isArray(value),defaultValue:()=>[],};} function getPartialValueEditorInfo(fieldDef,operator,params={}){switch(operator){case"set":case"not_set":return{component:null,extractProps:null,isSupported:(value)=>value===false,defaultValue:()=>false,};case"=like":case"=ilike":case"like":case"not like":case"ilike":case"not ilike":return STRING_EDITOR;case"between":{const editorInfo=getValueEditorInfo(fieldDef,"=");return{component:Range,extractProps:({value,update})=>({value,update,editorInfo,}),isSupported:(value)=>Array.isArray(value)&&value.length===2,defaultValue:()=>{const{defaultValue}=editorInfo;return[defaultValue(),defaultValue()];},};} case"within":{return{component:Within,extractProps:({value,update})=>({value,update,amountEditorInfo:getValueEditorInfo({type:"integer"},"="),optionEditorInfo:makeSelectEditor(Within.options),}),isSupported:(value)=>Array.isArray(value)&&value.length===3&&typeof value[1]==="string"&&value[2]===fieldDef.type,defaultValue:()=>{return[-1,"months",fieldDef.type];},};} case"in":case"not in":{switch(fieldDef.type){case"tags":return STRING_EDITOR;case"many2one":case"many2many":case"one2many":return makeAutoCompleteEditor(fieldDef);default:{const editorInfo=getValueEditorInfo(fieldDef,"=",{addBlankOption:true,startEmpty:true,});return{component:List,extractProps:({value,update})=>{if(!disambiguate(value)){const{stringify}=editorInfo;editorInfo.stringify=(val)=>stringify(val,false);} return{value,update,editorInfo,};},isSupported:(value)=>Array.isArray(value),defaultValue:()=>[],};}}} case"any":case"not any":{switch(fieldDef.type){case"many2one":case"many2many":case"one2many":{return{component:null,extractProps:null,isSupported:isTree,defaultValue:()=>connector("&"),};}}}} const{type}=fieldDef;switch(type){case"integer":case"float":case"monetary":{const formatType=type==="integer"?"integer":"float";return{component:Input,extractProps:({value,update})=>({value:String(value),update:(value)=>update(parseValue(formatType,value)),startEmpty:params.startEmpty,}),isSupported:()=>true,defaultValue:()=>1,shouldResetValue:(value)=>parseValue(formatType,value)===value,};} case"date":case"datetime":return{component:DateTimeInput,extractProps:({value,update})=>({value:params.startEmpty||value===false?false:genericDeserializeDate(type,value),type,onApply:(value)=>{if(!params.startEmpty||value){update(genericSerializeDate(type,value||DateTime.local()));}},}),isSupported:(value)=>value===false||(typeof value==="string"&&isParsable(type,value)),defaultValue:()=>genericSerializeDate(type,DateTime.local()),stringify:(value)=>{if(value===false){return _t("False");} if(typeof value==="string"&&isParsable(type,value)){const formatter=formatters.get(type,formatValue);return formatter(genericDeserializeDate(type,value));} return formatValue(value);},message:_t("Not a valid %s",type),};case"char":case"html":case"text":return STRING_EDITOR;case"boolean":{if(["is","is_not"].includes(operator)){const options=[[true,_t("set")],[false,_t("not set")],];return makeSelectEditor(options,params);} const options=[[true,_t("True")],[false,_t("False")],];return makeSelectEditor(options,params);} case"many2one":{if(["=","!="].includes(operator)){return{component:DomainSelectorSingleAutocomplete,extractProps:({value,update})=>({resModel:getResModel(fieldDef),fieldString:fieldDef.string,update,resId:value,}),isSupported:()=>true,defaultValue:()=>false,shouldResetValue:(value)=>value!==false&&!isId(value),};}else if(["parent_of","child_of"].includes(operator)){return makeAutoCompleteEditor(fieldDef);} break;} case"many2many":case"one2many":if(["=","!="].includes(operator)){return makeAutoCompleteEditor(fieldDef);} break;case"selection":{const options=fieldDef.selection||[];return makeSelectEditor(options,params);} case undefined:{const options=[[1,"1"]];return makeSelectEditor(options,params);}} return{component:Input,extractProps:({value,update})=>({value:String(value),update,}),isSupported:()=>true,defaultValue:()=>"",};} __exports.getValueEditorInfo=getValueEditorInfo;function getValueEditorInfo(fieldDef,operator,options={}){const info=getPartialValueEditorInfo(fieldDef||{},operator,options);return{extractProps:({value,update})=>({value,update}),message:_t("Value not supported"),stringify:(val,disambiguate=true)=>{if(disambiguate){return formatValue(val);} return String(val);},...info,};} __exports.getDefaultValue=getDefaultValue;function getDefaultValue(fieldDef,operator,value=null){const{isSupported,shouldResetValue,defaultValue}=getValueEditorInfo(fieldDef,operator);if(value===null||!isSupported(value)||shouldResetValue?.(value)){return defaultValue();} return value;} return __exports;});; /* /web/static/src/core/tree_editor/utils.js */ odoo.define('@web/core/tree_editor/utils',['@web/core/utils/arrays','@web/core/tree_editor/tree_editor_operator_editor','@web/core/tree_editor/condition_tree','@web/core/utils/hooks','@web/core/l10n/translation','@web/core/l10n/dates','@web/core/model_field_selector/utils','@web/core/tree_editor/tree_editor_components'],function(require){'use strict';let __exports={};const{unique,zip}=require("@web/core/utils/arrays");const{getOperatorLabel}=require("@web/core/tree_editor/tree_editor_operator_editor");const{Expression,condition,createVirtualOperators,normalizeValue,isTree,}=require("@web/core/tree_editor/condition_tree");const{useService}=require("@web/core/utils/hooks");const{_t}=require("@web/core/l10n/translation");const{deserializeDate,deserializeDateTime,formatDate,formatDateTime,}=require("@web/core/l10n/dates");const{useLoadFieldInfo,useLoadPathDescription}=require("@web/core/model_field_selector/utils");const{Within}=require("@web/core/tree_editor/tree_editor_components");function formatValue(val,disambiguate,fieldDef,displayNames){if(val instanceof Expression){return val.toString();} if(displayNames&&isId(val)){if(typeof displayNames[val]==="string"){val=displayNames[val];}else{return _t("Inaccessible/missing record ID: %s",val);}} if(fieldDef?.type==="selection"){const[,label]=(fieldDef.selection||[]).find(([v])=>v===val)||[];if(label!==undefined){val=label;}} if(typeof val==="string"){if(fieldDef?.type==="datetime"){return formatDateTime(deserializeDateTime(val));} if(fieldDef?.type==="date"){return formatDate(deserializeDate(val));}} if(disambiguate&&typeof val==="string"){return JSON.stringify(val);} return val;} __exports.isId=isId;function isId(value){return Number.isInteger(value)&&value>=1;} __exports.disambiguate=disambiguate;function disambiguate(value,displayNames){if(!Array.isArray(value)){return value==="";} let hasSomeString=false;let hasSomethingElse=false;for(const val of value){if(val===""){return true;} if(typeof val==="string"||(displayNames&&isId(val))){hasSomeString=true;}else{hasSomethingElse=true;}} return hasSomeString&&hasSomethingElse;} __exports.useMakeGetFieldDef=useMakeGetFieldDef;function useMakeGetFieldDef(fieldService){fieldService||=useService("field");const loadFieldInfo=useLoadFieldInfo(fieldService);return async(resModel,tree,additionalsPath=[])=>{const pathsInTree=getPathsInTree(tree);const paths=new Set([...pathsInTree,...additionalsPath]);const promises=[];const fieldDefs={};for(const path of paths){if(typeof path==="string"){promises.push(loadFieldInfo(resModel,path).then(({fieldDef})=>{fieldDefs[path]=fieldDef;}));}} await Promise.all(promises);return(path)=>{if(typeof path==="string"){return fieldDefs[path];} return null;};};} function useGetTreePathDescription(fieldService){fieldService||=useService("field");const loadPathDescription=useLoadPathDescription(fieldService);return async(resModel,tree)=>{const paths=getPathsInTree(tree);const promises=[];const pathDescriptions=new Map();for(const path of paths){promises.push(loadPathDescription(resModel,path).then(({displayNames})=>{pathDescriptions.set(path,displayNames.join(" \u2794 "));}));} await Promise.all(promises);return(path)=>pathDescriptions.get(path);};} async function getDisplayNames(tree,getFieldDef,nameService){const resIdsByModel=extractIdsFromTree(tree,getFieldDef);const proms=[];const resModels=[];for(const[resModel,resIds]of Object.entries(resIdsByModel)){resModels.push(resModel);proms.push(nameService.loadDisplayNames(resModel,resIds));} return Object.fromEntries(zip(resModels,await Promise.all(proms)));} __exports.useMakeGetConditionDescription=useMakeGetConditionDescription;function useMakeGetConditionDescription(fieldService,nameService){const makeGetPathDescriptions=useGetTreePathDescription(fieldService);return async(resModel,tree,getFieldDef)=>{tree=simplifyTree(tree);const[displayNames,getPathDescription]=await Promise.all([getDisplayNames(tree,getFieldDef,nameService),makeGetPathDescriptions(resModel,tree),]);return(node)=>_getConditionDescription(node,getFieldDef,getPathDescription,displayNames);};} function _getConditionDescription(node,getFieldDef,getPathDescription,displayNames){const nodeWithVirtualOperators=createVirtualOperators(node,{getFieldDef});const{operator,negate,value,path}=nodeWithVirtualOperators;const fieldDef=getFieldDef(path);const operatorLabel=getOperatorLabel(operator,fieldDef?.type,negate);const pathDescription=getPathDescription(path);const description={pathDescription,operatorDescription:operatorLabel,valueDescription:null,};if(isTree(node.value)){return description;} if(["set","not_set"].includes(operator)){return description;} if(["is","is_not"].includes(operator)){description.valueDescription={values:[value?_t("set"):_t("not set")],join:"",addParenthesis:false,};return description;} const coModeldisplayNames=displayNames[getResModel(fieldDef)];const dis=disambiguate(value,coModeldisplayNames);const values=operator=="within"?[value[0],Within.options.find((option)=>option[0]===value[1])[1]]:(Array.isArray(value)?value:[value]).slice(0,21).map((val,index)=>index<20?formatValue(val,dis,fieldDef,coModeldisplayNames):"...");let join;let addParenthesis=Array.isArray(value);switch(operator){case"between":join=_t("and");addParenthesis=false;break;case"within":join=" ";addParenthesis=false;break;case"in":case"not in":join=",";break;default:join=_t("or");} description.valueDescription={values,join,addParenthesis};return description;} __exports.useGetTreeDescription=useGetTreeDescription;function useGetTreeDescription(fieldService,nameService){fieldService||=useService("field");nameService||=useService("name");const makeGetFieldDef=useMakeGetFieldDef(fieldService);const makeGetConditionDescription=useMakeGetConditionDescription(fieldService,nameService);return async(resModel,tree)=>{async function getTreeDescription(resModel,tree,isSubExpression=false){tree=simplifyTree(tree);if(tree.type==="connector"){const childDescriptions=tree.children.map((node)=>getTreeDescription(resModel,node,true));const separator=tree.value==="&"?_t("and"):_t("or");let description=await Promise.all(childDescriptions);description=description.join(` ${separator} `);if(isSubExpression||tree.negate){description=`( ${description} )`;} if(tree.negate){description=`! ${description}`;} return description;} const getFieldDef=await makeGetFieldDef(resModel,tree);const getConditionDescription=await makeGetConditionDescription(resModel,tree,getFieldDef);const{pathDescription,operatorDescription,valueDescription}=getConditionDescription(tree);const stringDescription=[pathDescription,operatorDescription];if(valueDescription){const{values,join,addParenthesis}=valueDescription;const jointedValues=values.join(` ${join} `);stringDescription.push(addParenthesis?`( ${jointedValues} )`:jointedValues);}else if(isTree(tree.value)){const _fieldDef=getFieldDef(tree.path);const _resModel=getResModel(_fieldDef);const _tree=tree.value;const description=await getTreeDescription(_resModel,_tree);stringDescription.push(`( ${description} )`);} return stringDescription.join(" ");} return getTreeDescription(resModel,tree);};} __exports.getResModel=getResModel;function getResModel(fieldDef){if(fieldDef){return fieldDef.is_property?fieldDef.comodel:fieldDef.relation;} return null;} function extractIdsFromTree(tree,getFieldDef){const idsByModel=_extractIdsRecursive(tree,getFieldDef,{});for(const resModel in idsByModel){idsByModel[resModel]=unique(idsByModel[resModel]);} return idsByModel;} function _extractIdsRecursive(tree,getFieldDef,idsByModel){if(tree.type==="condition"){const fieldDef=getFieldDef(tree.path);if(["many2one","many2many","one2many"].includes(fieldDef?.type)){const value=tree.value;const values=Array.isArray(value)?value:[value];const ids=values.filter((val)=>isId(val));const resModel=getResModel(fieldDef);if(ids.length){if(!idsByModel[resModel]){idsByModel[resModel]=[];} idsByModel[resModel].push(...ids);}}} if(tree.type==="connector"){for(const child of tree.children){_extractIdsRecursive(child,getFieldDef,idsByModel);}} return idsByModel;} __exports.getPathsInTree=getPathsInTree;function getPathsInTree(tree){const paths=[];if(tree.type==="condition"){paths.push(tree.path);} if(tree.type==="connector"&&tree.children){for(const child of tree.children){paths.push(...getPathsInTree(child));}} return unique(paths);} const SPECIAL_FIELDS=["country_id","user_id","partner_id","stage_id","id"];__exports.getDefaultPath=getDefaultPath;function getDefaultPath(fieldDefs){for(const name of SPECIAL_FIELDS){const fieldDef=fieldDefs[name];if(fieldDef){return fieldDef.name;}} const name=Object.keys(fieldDefs)[0];if(name){return name;} throw new Error(`No field found`);} function simplifyTree(tree){if(tree.type==="condition"){return tree;} const processedChildren=tree.children.map(simplifyTree);if(tree.value==="&"){return{...tree,children:processedChildren};} const children=[];const childrenByPath={};for(const child of processedChildren){if(child.type==="connector"||typeof child.path!=="string"||!["=","in"].includes(child.operator)){children.push(child);}else{if(!childrenByPath[child.path]){childrenByPath[child.path]=[];} childrenByPath[child.path].push(child);}} for(const path in childrenByPath){if(childrenByPath[path].length===1){children.push(childrenByPath[path][0]);continue;} const value=[];for(const child of childrenByPath[path]){if(child.operator==="="){value.push(child.value);}else{value.push(...child.value);}} children.push(condition(path,"in",normalizeValue(value)));} if(children.length===1){return{...children[0]};} return{...tree,children};} return __exports;});; /* /web/static/src/core/ui/block_ui.js */ odoo.define('@web/core/ui/block_ui',['@web/core/l10n/translation','@web/core/browser/browser','@odoo/owl'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{browser}=require("@web/core/browser/browser");const{EventBus,Component,useState,xml}=require("@odoo/owl");const BlockUI=__exports.BlockUI=class BlockUI extends Component{static props={bus:EventBus,};static template=xml`
Loading...

`;setup(){this.messagesByDuration=[{time:20,l1:_t("Loading...")},{time:40,l1:_t("Still loading...")},{time:60,l1:_t("Still loading..."),l2:_t("Please be patient."),},{time:180,l1:_t("Don't leave yet,"),l2:_t("it's still loading..."),},{time:120,l1:_t("You may not believe it,"),l2:_t("but the application is actually loading..."),},{time:3180,l1:_t("Take a minute to get a coffee,"),l2:_t("because it's loading..."),},{time:null,l1:_t("Maybe you should consider reloading the application by pressing F5..."),},];this.BLOCK_STATES={UNBLOCKED:0,BLOCKED:1,VISIBLY_BLOCKED:2};this.state=useState({blockState:this.BLOCK_STATES.UNBLOCKED,line1:"",line2:"",});this.props.bus.addEventListener("BLOCK",this.block.bind(this));this.props.bus.addEventListener("UNBLOCK",this.unblock.bind(this));} replaceMessage(index){const message=this.messagesByDuration[index];this.state.line1=message.l1;this.state.line2=message.l2||"";if(message.time!==null){this.msgTimer=browser.setTimeout(()=>{this.replaceMessage(index+1);},message.time*1000);}} block(ev){const showBlockedUI=()=>(this.state.blockState=this.BLOCK_STATES.VISIBLY_BLOCKED);const delay=ev.detail?.delay;if(delay){this.state.blockState=this.BLOCK_STATES.BLOCKED;this.showBlockedUITimer=setTimeout(showBlockedUI,delay);}else{showBlockedUI();} if(ev.detail?.message){this.state.line1=ev.detail.message;}else{this.replaceMessage(0);}} unblock(){this.state.blockState=this.BLOCK_STATES.UNBLOCKED;clearTimeout(this.showBlockedUITimer);clearTimeout(this.msgTimer);this.state.line1="";this.state.line2="";}} return __exports;});; /* /web/static/src/core/ui/ui_service.js */ odoo.define('@web/core/ui/ui_service',['@web/core/utils/hooks','@web/core/registry','@web/core/utils/timing','@web/core/ui/block_ui','@web/core/browser/browser','@web/core/utils/ui','@web/core/hotkeys/hotkey_service','@odoo/owl'],function(require){'use strict';let __exports={};const{useService}=require("@web/core/utils/hooks");const{registry}=require("@web/core/registry");const{throttleForAnimation}=require("@web/core/utils/timing");const{BlockUI}=require("@web/core/ui/block_ui");const{browser}=require("@web/core/browser/browser");const{getTabableElements}=require("@web/core/utils/ui");const{getActiveHotkey}=require("@web/core/hotkeys/hotkey_service");const{EventBus,reactive,useEffect,useRef}=require("@odoo/owl");const SIZES=__exports.SIZES={XS:0,VSM:1,SM:2,MD:3,LG:4,XL:5,XXL:6};function getFirstAndLastTabableElements(el){const tabableEls=getTabableElements(el);return[tabableEls[0],tabableEls[tabableEls.length-1]];} __exports.useActiveElement=useActiveElement;function useActiveElement(refName){if(!refName){throw new Error("refName not given to useActiveElement");} const uiService=useService("ui");const ref=useRef(refName);function trapFocus(e){const hotkey=getActiveHotkey(e);if(!["tab","shift+tab"].includes(hotkey)){return;} const el=e.currentTarget;const[firstTabableEl,lastTabableEl]=getFirstAndLastTabableElements(el);switch(hotkey){case"tab":if(document.activeElement===lastTabableEl){firstTabableEl.focus();e.preventDefault();e.stopPropagation();} break;case"shift+tab":if(document.activeElement===firstTabableEl){lastTabableEl.focus();e.preventDefault();e.stopPropagation();} break;}} useEffect((el)=>{if(el){const[firstTabableEl]=getFirstAndLastTabableElements(el);if(!firstTabableEl){return;} const oldActiveElement=document.activeElement;uiService.activateElement(el);el.addEventListener("keydown",trapFocus);if(!el.contains(document.activeElement)){firstTabableEl.focus();} return async()=>{await Promise.resolve();uiService.deactivateElement(el);el.removeEventListener("keydown",trapFocus);if(el.contains(document.activeElement)||document.activeElement===document.body){oldActiveElement.focus();}};}},()=>[ref.el]);} const MEDIAS_BREAKPOINTS=__exports.MEDIAS_BREAKPOINTS=[{maxWidth:474},{minWidth:475,maxWidth:575},{minWidth:576,maxWidth:767},{minWidth:768,maxWidth:991},{minWidth:992,maxWidth:1199},{minWidth:1200,maxWidth:1533},{minWidth:1534},];__exports.getMediaQueryLists=getMediaQueryLists;function getMediaQueryLists(){return MEDIAS_BREAKPOINTS.map(({minWidth,maxWidth})=>{if(!maxWidth){return window.matchMedia(`(min-width: ${minWidth}px)`);} if(!minWidth){return window.matchMedia(`(max-width: ${maxWidth}px)`);} return window.matchMedia(`(min-width: ${minWidth}px) and (max-width: ${maxWidth}px)`);});} const MEDIAS=getMediaQueryLists();const utils=__exports.utils={getSize(){return MEDIAS.findIndex((media)=>media.matches);},isSmall(ui={}){return(ui.size||utils.getSize())<=SIZES.SM;},};const bus=new EventBus();__exports.listenSizeChange=listenSizeChange;function listenSizeChange(callback){bus.addEventListener("resize",callback);return()=>bus.removeEventListener("resize",callback);} const uiService=__exports.uiService={start(env){registry.category("main_components").add("BlockUI",{Component:BlockUI,props:{bus}});let blockCount=0;function block(data){blockCount++;if(blockCount===1){bus.trigger("BLOCK",{message:data?.message,delay:data?.delay,});}} function unblock(){blockCount--;if(blockCount<0){console.warn("Unblock ui was called more times than block, you should only unblock the UI if you have previously blocked it.");blockCount=0;} if(blockCount===0){bus.trigger("UNBLOCK");}} let activeElems=[document];function activateElement(el){activeElems.push(el);bus.trigger("active-element-changed",el);} function deactivateElement(el){activeElems=activeElems.filter((x)=>x!==el);bus.trigger("active-element-changed",ui.activeElement);} function getActiveElementOf(el){for(const activeElement of[...activeElems].reverse()){if(activeElement.contains(el)){return activeElement;}}} const ui=reactive({bus,size:utils.getSize(),get activeElement(){return activeElems[activeElems.length-1];},get isBlocked(){return blockCount>0;},isSmall:utils.isSmall(),block,unblock,activateElement,deactivateElement,getActiveElementOf,});const updateSize=()=>{const prevSize=ui.size;ui.size=utils.getSize();if(ui.size!==prevSize){ui.isSmall=utils.isSmall(ui);bus.trigger("resize");}};browser.addEventListener("resize",throttleForAnimation(updateSize));Object.defineProperty(env,"isSmall",{get(){return ui.isSmall;},});return ui;},};registry.category("services").add("ui",uiService);return __exports;});; /* /web/static/src/core/user.js */ odoo.define('@web/core/user',['@web/core/browser/browser','@web/core/l10n/utils/locales','@web/core/network/rpc','@web/core/utils/cache','@web/session','@web/core/utils/arrays'],function(require){'use strict';let __exports={};const{browser}=require("@web/core/browser/browser");const{pyToJsLocale}=require("@web/core/l10n/utils/locales");const{rpc}=require("@web/core/network/rpc");const{Cache}=require("@web/core/utils/cache");const{session}=require("@web/session");const{ensureArray}=require("@web/core/utils/arrays");__exports._makeUser=_makeUser;function _makeUser(session){const{home_action_id:homeActionId,is_admin:isAdmin,is_internal_user:isInternalUser,is_system:isSystem,name,partner_id:partnerId,show_effect:showEffect,uid:userId,username:login,user_context:context,user_settings,partner_write_date:writeDate,}=session;const settings=user_settings||{};delete session.home_action_id;delete session.is_admin;delete session.is_internal_user;delete session.is_system;delete session.name;delete session.partner_id;delete session.show_effect;delete session.uid;delete session.username;delete session.user_context;delete session.user_settings;delete session.partner_write_date;const getGroupCacheValue=(group,context)=>{if(!userId){return Promise.resolve(false);} return rpc("/web/dataset/call_kw/res.users/has_group",{model:"res.users",method:"has_group",args:[userId,group],kwargs:{context},});};const getGroupCacheKey=(group)=>group;const groupCache=new Cache(getGroupCacheValue,getGroupCacheKey);if(isInternalUser!==undefined){groupCache.cache["base.group_user"]=Promise.resolve(isInternalUser);} if(isSystem!==undefined){groupCache.cache["base.group_system"]=Promise.resolve(isSystem);} const getAccessRightCacheValue=(model,operation,ids,context)=>{const url=`/web/dataset/call_kw/${model}/has_access`;return rpc(url,{model,method:"has_access",args:[ids,operation],kwargs:{context},});};const getAccessRightCacheKey=(model,operation,ids)=>JSON.stringify([model,operation,ids]);const accessRightCache=new Cache(getAccessRightCacheValue,getAccessRightCacheKey);const lang=pyToJsLocale(context?.lang);const user={name,login,isAdmin,isSystem,isInternalUser,partnerId,homeActionId,showEffect,userId,writeDate,get context(){return Object.assign({},context,{uid:this.userId});},get lang(){return lang;},get tz(){return this.context.tz;},get settings(){return Object.assign({},settings);},updateContext(update){Object.assign(context,update);},hasGroup(group){return groupCache.read(group,this.context);},checkAccessRight(model,operation,ids=[]){return accessRightCache.read(model,operation,ensureArray(ids),this.context);},async setUserSettings(key,value){const model="res.users.settings";const method="set_res_users_settings";const changedSettings=await rpc(`/web/dataset/call_kw/${model}/${method}`,{model,method,args:[[this.settings.id]],kwargs:{new_settings:{[key]:value,},context:this.context,},});Object.assign(settings,changedSettings);},};return user;} const user=__exports.user=_makeUser(session);const LAST_CONNECTED_USER_KEY="web.lastConnectedUser";const getLastConnectedUsers=__exports.getLastConnectedUsers=()=>{const lastConnectedUsers=browser.localStorage.getItem(LAST_CONNECTED_USER_KEY);return lastConnectedUsers?JSON.parse(lastConnectedUsers):[];};const setLastConnectedUsers=__exports.setLastConnectedUsers=(users)=>{browser.localStorage.setItem(LAST_CONNECTED_USER_KEY,JSON.stringify(users.slice(0,5)));};if(user.login&&user.login!=="__system__"){const users=getLastConnectedUsers();const lastConnectedUsers=[{login:user.login,name:user.name,partnerId:user.partnerId,partnerWriteDate:user.writeDate,userId:user.userId,},...users.filter((u)=>u.userId!==user.userId),];setLastConnectedUsers(lastConnectedUsers);} return __exports;});; /* /web/static/src/core/user_switch/user_switch.js */ odoo.define('@web/core/user_switch/user_switch',['@odoo/owl','@web/core/registry','@web/core/user','@web/core/utils/urls'],function(require){'use strict';let __exports={};const{Component,useRef,useState,useEffect}=require("@odoo/owl");const{registry}=require("@web/core/registry");const{getLastConnectedUsers,setLastConnectedUsers}=require("@web/core/user");const{imageUrl}=require("@web/core/utils/urls");const UserSwitch=__exports.UserSwitch=class UserSwitch extends Component{static template="web.login_user_switch";static props={};setup(){const users=getLastConnectedUsers();this.root=useRef("root");this.state=useState({users,displayUserChoice:users.length>1,});this.form=document.querySelector("form.oe_login_form");this.form.classList.toggle("d-none",users.length>1);this.form.querySelector(":placeholder-shown")?.focus();useEffect((el)=>el?.querySelector("button.list-group-item-action")?.focus(),()=>[this.root.el]);} toggleFormDisplay(){this.state.displayUserChoice=!this.state.displayUserChoice&&this.state.users.length;this.form.classList.toggle("d-none",this.state.displayUserChoice);this.form.querySelector(":placeholder-shown")?.focus();} getAvatarUrl({partnerId,partnerWriteDate:unique}){return imageUrl("res.partner",partnerId,"avatar_128",{unique});} remove(deletedUser){this.state.users=this.state.users.filter((user)=>user!==deletedUser);setLastConnectedUsers(this.state.users);if(!this.state.users.length){this.fillForm();}} fillForm(login=""){this.form.querySelector("input#login").value=login;this.form.querySelector("input#password").value="";this.toggleFormDisplay();}} registry.category("public_components").add("web.user_switch",UserSwitch);return __exports;});; /* /web/static/src/core/utils/arrays.js */ odoo.define('@web/core/utils/arrays',['@web/core/utils/objects'],function(require){'use strict';let __exports={};const{shallowEqual:_shallowEqual}=require("@web/core/utils/objects");function _cartesian(...args){if(args.length===0){return[undefined];} const firstArray=args.shift().map((elem)=>[elem]);if(args.length===0){return firstArray;} const result=[];const productOfOtherArrays=_cartesian(...args);for(const array of firstArray){for(const tuple of productOfOtherArrays){result.push([...array,...tuple]);}} return result;} function _getExtractorFrom(criterion){if(criterion){switch(typeof criterion){case"string":return(element)=>element[criterion];case"function":return criterion;default:throw new Error(`Expected criterion of type 'string' or 'function' and got '${typeof criterion}'`);}}else{return(element)=>element;}} __exports.ensureArray=ensureArray;function ensureArray(value){return isIterable(value)?[...value]:[value];} __exports.intersection=intersection;function intersection(iter1,iter2){const set2=new Set(iter2);return unique(iter1).filter((v)=>set2.has(v));} __exports.isIterable=isIterable;function isIterable(value){return Boolean(value&&typeof value==="object"&&value[Symbol.iterator]);} __exports.groupBy=groupBy;function groupBy(iterable,criterion){const extract=_getExtractorFrom(criterion);const groups={};for(const element of iterable){const group=String(extract(element));if(!(group in groups)){groups[group]=[];} groups[group].push(element);} return groups;} __exports.sortBy=sortBy;function sortBy(iterable,criterion,order="asc"){const extract=_getExtractorFrom(criterion);return[...iterable].sort((elA,elB)=>{const a=extract(elA);const b=extract(elB);let result;if(isNaN(a)&&isNaN(b)){result=a>b?1:a!array2.includes(value)),...array2.filter((value)=>!array1.includes(value)),];} __exports.cartesian=cartesian;function cartesian(...args){if(args.length===0){return[undefined];}else if(args.length===1){return args[0];}else{return _cartesian(...args);}} const shallowEqual=__exports.shallowEqual=_shallowEqual;__exports.sections=sections;function sections(iterable){const array=[...iterable];const sections=[];for(let i=0;imapFn(e1,e2));} __exports.slidingWindow=slidingWindow;function slidingWindow(arr,width){const res=[];for(let i=0;i<=arr.length-width;i++){res.push(arr.slice(i,i+width));} return res;} __exports.rotate=rotate;function rotate(i,arr,inc=1){return(arr.length+i+inc)%arr.length;} return __exports;});; /* /web/static/src/core/utils/autoresize.js */ odoo.define('@web/core/utils/autoresize',['@odoo/owl','@web/core/browser/browser'],function(require){'use strict';let __exports={};const{useEffect}=require("@odoo/owl");const{browser}=require("@web/core/browser/browser");__exports.useAutoresize=useAutoresize;function useAutoresize(ref,options={}){let wasProgrammaticallyResized=false;let resize=null;useEffect((el)=>{if(el){resize=(programmaticResize=false)=>{wasProgrammaticallyResized=programmaticResize;if(el instanceof HTMLInputElement){resizeInput(el,options);}else{resizeTextArea(el,options);} options.onResize?.(el,options);};el.addEventListener("input",()=>resize(true));const resizeObserver=new ResizeObserver(()=>{if(wasProgrammaticallyResized){wasProgrammaticallyResized=false;return;} resize();});resizeObserver.observe(el);return()=>{el.removeEventListener("input",resize);resizeObserver.unobserve(el);resizeObserver.disconnect();resize=null;};}},()=>[ref.el]);useEffect(()=>{if(resize){resize(true);}});} function resizeInput(input){input.style.width="100%";const maxWidth=input.clientWidth;const isSafari16=/Version\/16.+Safari/i.test(browser.navigator.userAgent);input.style.width="10px";if(input.value===""&&input.placeholder!==""){input.style.width="auto";return;} if(input.scrollWidth+5+(isSafari16?8:0)>maxWidth){input.style.width="100%";return;} input.style.width=input.scrollWidth+5+(isSafari16?8:0)+"px";} __exports.resizeTextArea=resizeTextArea;function resizeTextArea(textarea,options={}){const minimumHeight=options.minimumHeight||0;let heightOffset=0;const style=window.getComputedStyle(textarea);if(style.boxSizing==="border-box"){const paddingHeight=parseFloat(style.paddingTop)+parseFloat(style.paddingBottom);const borderHeight=parseFloat(style.borderTopWidth)+parseFloat(style.borderBottomWidth);heightOffset=borderHeight+paddingHeight;} const previousStyle={borderTopWidth:style.borderTopWidth,borderBottomWidth:style.borderBottomWidth,padding:style.padding,};Object.assign(textarea.style,{height:"auto",borderTopWidth:0,borderBottomWidth:0,paddingTop:0,paddingRight:style.paddingRight,paddingBottom:0,paddingLeft:style.paddingLeft,});textarea.style.height="auto";const height=Math.max(minimumHeight,textarea.scrollHeight+heightOffset);Object.assign(textarea.style,previousStyle,{height:`${height}px`});textarea.parentElement.style.height=`${height}px`;} return __exports;});; /* /web/static/src/core/utils/binary.js */ odoo.define('@web/core/utils/binary',['@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");__exports.isBinarySize=isBinarySize;function isBinarySize(value){return/^\d+(\.\d*)? [^0-9]+$/.test(value);} __exports.toBase64Length=toBase64Length;function toBase64Length(maxBytes){return Math.ceil(maxBytes*4/3);} __exports.humanSize=humanSize;function humanSize(size){const units=_t("Bytes|Kb|Mb|Gb|Tb|Pb|Eb|Zb|Yb").split("|");let i=0;while(size>=1024){size/=1024;++i;} return`${size.toFixed(2)} ${units[i].trim()}`;} return __exports;});; /* /web/static/src/core/utils/cache.js */ odoo.define('@web/core/utils/cache',[],function(require){'use strict';let __exports={};const Cache=__exports.Cache=class Cache{constructor(getValue,getKey){this.cache={};this.getKey=getKey;this.getValue=getValue;} _getCacheAndKey(...path){let cache=this.cache;let key;if(this.getKey){key=this.getKey(...path);}else{for(let i=0;i{classObj[s]=true;});return classObj;}else{console.warn(`toClassObj only supports strings, objects and undefined className (got ${typeof classProp})`);return{};}} return __exports;});; /* /web/static/src/core/utils/colors.js */ odoo.define('@web/core/utils/colors',[],function(require){'use strict';let __exports={};__exports.convertRgbToHsl=convertRgbToHsl;function convertRgbToHsl(r,g,b){if(typeof(r)!=='number'||isNaN(r)||r<0||r>255||typeof(g)!=='number'||isNaN(g)||g<0||g>255||typeof(b)!=='number'||isNaN(b)||b<0||b>255){return false;} var red=r/255;var green=g/255;var blue=b/255;var maxColor=Math.max(red,green,blue);var minColor=Math.min(red,green,blue);var delta=maxColor-minColor;var hue=0;var saturation=0;var lightness=(maxColor+minColor)/2;if(delta){if(maxColor===red){hue=(green-blue)/delta;} if(maxColor===green){hue=2+(blue-red)/delta;} if(maxColor===blue){hue=4+(red-green)/delta;} if(maxColor){saturation=delta/(1-Math.abs(2*lightness-1));}} hue=60*hue;return{hue:hue<0?hue+360:hue,saturation:saturation*100,lightness:lightness*100,};};__exports.convertHslToRgb=convertHslToRgb;function convertHslToRgb(h,s,l){if(typeof(h)!=='number'||isNaN(h)||h<0||h>360||typeof(s)!=='number'||isNaN(s)||s<0||s>100||typeof(l)!=='number'||isNaN(l)||l<0||l>100){return false;} var huePrime=h/60;var saturation=s/100;var lightness=l/100;var chroma=saturation*(1-Math.abs(2*lightness-1));var secondComponent=chroma*(1-Math.abs(huePrime%2-1));var lightnessAdjustment=lightness-chroma/2;var precision=255;chroma=Math.round((chroma+lightnessAdjustment)*precision);secondComponent=Math.round((secondComponent+lightnessAdjustment)*precision);lightnessAdjustment=Math.round((lightnessAdjustment)*precision);if(huePrime>=0&&huePrime<1){return{red:chroma,green:secondComponent,blue:lightnessAdjustment,};} if(huePrime>=1&&huePrime<2){return{red:secondComponent,green:chroma,blue:lightnessAdjustment,};} if(huePrime>=2&&huePrime<3){return{red:lightnessAdjustment,green:chroma,blue:secondComponent,};} if(huePrime>=3&&huePrime<4){return{red:lightnessAdjustment,green:secondComponent,blue:chroma,};} if(huePrime>=4&&huePrime<5){return{red:secondComponent,green:lightnessAdjustment,blue:chroma,};} if(huePrime>=5&&huePrime<=6){return{red:chroma,green:lightnessAdjustment,blue:secondComponent,};} return false;};__exports.convertRgbaToCSSColor=convertRgbaToCSSColor;function convertRgbaToCSSColor(r,g,b,a){if(typeof(r)!=='number'||isNaN(r)||r<0||r>255||typeof(g)!=='number'||isNaN(g)||g<0||g>255||typeof(b)!=='number'||isNaN(b)||b<0||b>255){return false;} if(typeof(a)!=='number'||isNaN(a)||a<0||Math.abs(a-100)Math.round(rgb2[idx]+(rgb1[idx]-rgb2[idx])*weight));return convertRgbaToCSSColor(r,g,b);};return __exports;});; /* /web/static/src/core/utils/components.js */ odoo.define('@web/core/utils/components',['@odoo/owl'],function(require){'use strict';let __exports={};const{Component,onError,xml}=require("@odoo/owl");const ErrorHandler=__exports.ErrorHandler=class ErrorHandler extends Component{static template=xml``;static props=["onError","slots"];setup(){onError((error)=>{this.props.onError(error);});}} return __exports;});; /* /web/static/src/core/utils/concurrency.js */ odoo.define('@web/core/utils/concurrency',[],function(require){'use strict';let __exports={};__exports.delay=delay;function delay(wait){return new Promise(function(resolve){setTimeout(resolve,wait);});} const KeepLast=__exports.KeepLast=class KeepLast{constructor(){this._id=0;} add(promise){this._id++;const currentId=this._id;return new Promise((resolve,reject)=>{promise.then((value)=>{if(this._id===currentId){resolve(value);}}).catch((reason)=>{if(this._id===currentId){reject(reason);}});});}} const Mutex=__exports.Mutex=class Mutex{constructor(){this._lock=Promise.resolve();this._queueSize=0;this._unlockedProm=undefined;this._unlock=undefined;} async exec(action){this._queueSize++;if(!this._unlockedProm){this._unlockedProm=new Promise((resolve)=>{this._unlock=()=>{resolve();this._unlockedProm=undefined;};});} const always=()=>{return Promise.resolve(action()).finally(()=>{if(--this._queueSize===0){this._unlock();}});};this._lock=this._lock.then(always,always);return this._lock;} getUnlockedDef(){return this._unlockedProm||Promise.resolve();}} const Race=__exports.Race=class Race{constructor(){this.currentProm=null;this.currentPromResolver=null;this.currentPromRejecter=null;} add(promise){if(!this.currentProm){this.currentProm=new Promise((resolve,reject)=>{this.currentPromResolver=(value)=>{this.currentProm=null;this.currentPromResolver=null;this.currentPromRejecter=null;resolve(value);};this.currentPromRejecter=(error)=>{this.currentProm=null;this.currentPromResolver=null;this.currentPromRejecter=null;reject(error);};});} promise.then(this.currentPromResolver).catch(this.currentPromRejecter);return this.currentProm;} getCurrentProm(){return this.currentProm;}} const Deferred=__exports.Deferred=class Deferred extends Promise{constructor(){let resolve;let reject;const prom=new Promise((res,rej)=>{resolve=res;reject=rej;});return Object.assign(prom,{resolve,reject});}} return __exports;});; /* /web/static/src/core/utils/draggable.js */ odoo.define('@web/core/utils/draggable',['@web/core/utils/draggable_hook_builder_owl','@web/core/utils/objects'],function(require){'use strict';let __exports={};const{makeDraggableHook}=require("@web/core/utils/draggable_hook_builder_owl");const{pick}=require("@web/core/utils/objects");const useDraggable=__exports.useDraggable=makeDraggableHook({name:"useDraggable",onWillStartDrag:({ctx})=>pick(ctx.current,"element"),onDragStart:({ctx})=>pick(ctx.current,"element"),onDrag:({ctx})=>pick(ctx.current,"element"),onDragEnd:({ctx})=>pick(ctx.current,"element"),onDrop:({ctx})=>pick(ctx.current,"element"),});return __exports;});; /* /web/static/src/core/utils/draggable_hook_builder.js */ odoo.define('@web/core/utils/draggable_hook_builder',['@web/core/utils/numbers','@web/core/utils/objects','@web/core/utils/scrolling','@web/core/utils/timing','@web/core/browser/browser','@web/core/browser/feature_detection'],function(require){'use strict';let __exports={};const{clamp}=require("@web/core/utils/numbers");const{omit}=require("@web/core/utils/objects");const{closestScrollableX,closestScrollableY}=require("@web/core/utils/scrolling");const{setRecurringAnimationFrame}=require("@web/core/utils/timing");const{browser}=require("@web/core/browser/browser");const{hasTouch,isBrowserFirefox,isIOS}=require("@web/core/browser/feature_detection");const DRAGGABLE_CLASS="o_draggable";const DRAGGED_CLASS=__exports.DRAGGED_CLASS="o_dragged";const DEFAULT_ACCEPTED_PARAMS={enable:[Boolean,Function],preventDrag:[Function],ref:[Object],elements:[String],handle:[String,Function],ignore:[String,Function],cursor:[String],edgeScrolling:[Object,Function],delay:[Number],tolerance:[Number],touchDelay:[Number],iframeWindow:[Object,Function],};const DEFAULT_DEFAULT_PARAMS={elements:`.${DRAGGABLE_CLASS}`,enable:true,preventDrag:()=>false,edgeScrolling:{speed:10,threshold:30,},delay:0,tolerance:10,touchDelay:300,};const LEFT_CLICK=0;const MANDATORY_PARAMS=["ref"];const WHITE_LISTED_KEYS=["Alt","Control","Meta","Shift"];const elCache={};function camelToKebab(str){return str.replace(/([a-z])([A-Z])/g,"$1-$2").toLowerCase();} function getReturnValue(valueOrFn){if(typeof valueOrFn==="function"){return valueOrFn();} return valueOrFn;} function getScrollParents(el){return[closestScrollableX(el),closestScrollableY(el)];} function makeCleanupManager(defaultCleanupFn){const add=(cleanupFn)=>typeof cleanupFn==="function"&&cleanups.push(cleanupFn);const cleanup=()=>{while(cleanups.length){cleanups.pop()();} add(defaultCleanupFn);};const cleanups=[];add(defaultCleanupFn);return{add,cleanup};} function makeDOMHelpers(cleanup){const addClass=(el,...classNames)=>{if(!el||!classNames.length){return;} cleanup.add(()=>el.classList.remove(...classNames));el.classList.add(...classNames);};const addListener=(el,event,callback,options={})=>{if(!el||!event||!callback){return;} const{noAddedStyle}=options;delete options.noAddedStyle;el.addEventListener(event,callback,options);if(!noAddedStyle&&/mouse|pointer|touch/.test(event)){addStyle(el,{pointerEvents:"auto"});} cleanup.add(()=>el.removeEventListener(event,callback,options));};const addStyle=(el,style)=>{if(!el||!style||!Object.keys(style).length){return;} cleanup.add(saveAttribute(el,"style"));for(const key in style){const[value,priority]=String(style[key]).split(/\s*!\s*/);el.style.setProperty(camelToKebab(key),value,priority);}};const getRect=(el,options={})=>{if(!el){return{};} const rect=el.getBoundingClientRect();if(options.adjust){const style=getComputedStyle(el);const[pl,pr,pt,pb]=["padding-left","padding-right","padding-top","padding-bottom",].map((prop)=>pixelValueToNumber(style.getPropertyValue(prop)));rect.x+=pl;rect.y+=pt;rect.width-=pl+pr;rect.height-=pt+pb;} return rect;};const removeAttribute=(el,attribute)=>{if(!el||!attribute){return;} cleanup.add(saveAttribute(el,attribute));el.removeAttribute(attribute);};const removeClass=(el,...classNames)=>{if(!el||!classNames.length){return;} cleanup.add(saveAttribute(el,"class"));el.classList.remove(...classNames);};const removeStyle=(el,...properties)=>{if(!el||!properties.length){return;} cleanup.add(saveAttribute(el,"style"));for(const key of properties){el.style.removeProperty(camelToKebab(key));}};const setAttribute=(el,attribute,value)=>{if(!el||!attribute){return;} cleanup.add(saveAttribute(el,attribute));el.setAttribute(attribute,String(value));};return{addClass,addListener,addStyle,getRect,removeAttribute,removeClass,removeStyle,setAttribute,};} function pixelValueToNumber(val){return Number(val.endsWith("px")?val.slice(0,-2):val);} function safePrevent(ev,{stop}={}){if(ev.cancelable){ev.preventDefault();if(stop){ev.stopPropagation();}}} function saveAttribute(el,attribute){const restoreAttribute=()=>{cache.delete(el);if(hasAttribute){el.setAttribute(attribute,originalValue);}else{el.removeAttribute(attribute);}};if(!(attribute in elCache)){elCache[attribute]=new Set();} const cache=elCache[attribute];if(cache.has(el)){return;} cache.add(el);const hasAttribute=el.hasAttribute(attribute);const originalValue=el.getAttribute(attribute);return restoreAttribute;} function toFunction(value){return typeof value==="function"?value:()=>value;} __exports.makeDraggableHook=makeDraggableHook;function makeDraggableHook(hookParams){hookParams=getReturnValue(hookParams);const hookName=hookParams.name||"useAnonymousDraggable";const{setupHooks}=hookParams;const allAcceptedParams={...DEFAULT_ACCEPTED_PARAMS,...hookParams.acceptedParams};const defaultParams={...DEFAULT_DEFAULT_PARAMS,...hookParams.defaultParams};const computeParams=(params)=>{const computedParams={enable:()=>true};for(const prop in allAcceptedParams){if(prop in params){if(prop==="enable"){computedParams[prop]=toFunction(params[prop]);}else if(allAcceptedParams[prop].length===1&&allAcceptedParams[prop][0]===Function){computedParams[prop]=params[prop];}else{computedParams[prop]=getReturnValue(params[prop]);}}} return Object.entries(computedParams);};const makeError=(reason)=>new Error(`Error in hook ${hookName}: ${reason}.`);let preventClick=false;return{[hookName](params){const callBuildHandler=(hookHandlerName,arg)=>{if(typeof hookParams[hookHandlerName]!=="function"){return;} const returnValue=hookParams[hookHandlerName]({ctx,...helpers,...arg});if(returnValue){callHandler(hookHandlerName,returnValue);}};const callHandler=(handlerName,arg)=>{if(typeof params[handlerName]!=="function"){return;} try{params[handlerName]({...dom,...ctx.pointer,...arg});}catch(err){dragEnd(null,true);throw err;}};const canStartDrag=()=>{const{pointer,current:{initialPosition},}=ctx;return(!ctx.tolerance||Math.hypot(pointer.x-initialPosition.x,pointer.y-initialPosition.y)>=ctx.tolerance);};const dragStart=()=>{state.dragging=true;state.willDrag=false;const isDocumentScrollingElement=ctx.current.container===ctx.current.container.ownerDocument.scrollingElement;[ctx.current.scrollParentX,ctx.current.scrollParentY]=isDocumentScrollingElement?[ctx.current.container,ctx.current.container]:getScrollParents(ctx.current.container);updateRects();const{x,y,width,height}=ctx.current.elementRect;ctx.current.offset={x:ctx.current.initialPosition.x-x,y:ctx.current.initialPosition.y-y,};if(ctx.followCursor){dom.addStyle(ctx.current.element,{width:`${width}px`,height:`${height}px`,position:"fixed !important",});updateElementPosition();} dom.addClass(document.body,"pe-none","user-select-none");if(params.iframeWindow){for(const iframe of document.getElementsByTagName("iframe")){if(iframe.contentWindow===params.iframeWindow){dom.addClass(iframe,"pe-none","user-select-none");}}} if(ctx.cursor){dom.addStyle(document.body,{cursor:ctx.cursor});} if((ctx.current.scrollParentX||ctx.current.scrollParentY)&&ctx.edgeScrolling.enabled){const cleanupFn=setRecurringAnimationFrame(handleEdgeScrolling);cleanup.add(cleanupFn);} dom.addClass(ctx.current.element,DRAGGED_CLASS);callBuildHandler("onDragStart");};const dragEnd=(target,inErrorState)=>{if(state.dragging){preventClick=true;if(!inErrorState){if(target){callBuildHandler("onDrop",{target});} callBuildHandler("onDragEnd");}} cleanup.cleanup();};const handleEdgeScrolling=(deltaTime)=>{updateRects();const{x:pointerX,y:pointerY}=ctx.pointer;const xRect=ctx.current.scrollParentXRect;const yRect=ctx.current.scrollParentYRect;const scrollParentYEl=ctx.current.scrollParentY;if(scrollParentYEl===ctx.current.container.ownerDocument.scrollingElement){yRect.y+=scrollParentYEl.scrollTop;} const{direction,speed,threshold}=ctx.edgeScrolling;const correctedSpeed=(speed/16)*deltaTime;const diff={};ctx.current.scrollingEdge=null;if(xRect){const maxWidth=xRect.x+xRect.width;if(pointerX-xRect.x(1-Math.max(delta,0)/threshold)*correctedSpeed*sign;if((!direction||direction==="vertical")&&diff.y){ctx.current.scrollParentY.scrollBy({top:diffToScroll(diff.y)});} if((!direction||direction==="horizontal")&&diff.x){ctx.current.scrollParentX.scrollBy({left:diffToScroll(diff.x)});} callBuildHandler("onDrag");};const onClick=(ev)=>{if(preventClick){safePrevent(ev,{stop:true});}};const onKeyDown=(ev)=>{if(!state.dragging||!ctx.enable()){return;} if(!WHITE_LISTED_KEYS.includes(ev.key)){safePrevent(ev,{stop:true});dragEnd(null);}};const onPointerCancel=()=>{dragEnd(null);};const onPointerDown=(ev)=>{preventClick=false;updatePointerPosition(ev);const initiationDelay=ev.pointerType==="touch"?ctx.touchDelay:ctx.delay;dragEnd(null);const fullSelectorEl=ev.target.closest(ctx.fullSelector);if(ev.button!==LEFT_CLICK||!ctx.enable()||!fullSelectorEl||(ctx.ignoreSelector&&ev.target.closest(ctx.ignoreSelector))||ctx.preventDrag(fullSelectorEl)){return;} safePrevent(ev);let activeElement=document.activeElement;while(activeElement?.nodeName==="IFRAME"){activeElement=activeElement.contentDocument?.activeElement;} if(activeElement&&!activeElement.contains(ev.target)){activeElement.blur();} const{currentTarget,pointerId,target}=ev;ctx.current.initialPosition={...ctx.pointer};if(target.hasPointerCapture(pointerId)){target.releasePointerCapture(pointerId);} if(initiationDelay){if(hasTouch()){if(ev.pointerType==="touch"){dom.addClass(target.closest(ctx.elementSelector),"o_touch_bounce");} if(isBrowserFirefox()){const links=[...currentTarget.querySelectorAll("[href]")];if(currentTarget.hasAttribute("href")){links.unshift(currentTarget);} for(const link of links){dom.removeAttribute(link,"href");}} if(isIOS()){for(const image of currentTarget.getElementsByTagName("img")){dom.setAttribute(image,"draggable",false);}}} ctx.current.timeout=browser.setTimeout(()=>{ctx.current.initialPosition={...ctx.pointer};willStartDrag(target);const{x:px,y:py}=ctx.pointer;const{x,y,width,height}=dom.getRect(ctx.current.element);if(pxbrowser.clearTimeout(ctx.current.timeout));}else{willStartDrag(target);}};const onPointerMove=(ev)=>{updatePointerPosition(ev);if(!ctx.current.element||!ctx.enable()){return;} safePrevent(ev);if(!state.dragging){if(!canStartDrag()){return;} dragStart();} if(ctx.followCursor){updateElementPosition();} callBuildHandler("onDrag");};const onPointerUp=(ev)=>{updatePointerPosition(ev);dragEnd(ev.target);};const updateElementPosition=()=>{const{containerRect,element,elementRect,offset}=ctx.current;const{width:ew,height:eh}=elementRect;const{x:cx,y:cy,width:cw,height:ch}=containerRect;dom.addStyle(element,{left:`${clamp(ctx.pointer.x - offset.x, cx, cx + cw - ew)}px`,top:`${clamp(ctx.pointer.y - offset.y, cy, cy + ch - eh)}px`,});};const updatePointerPosition=(ev)=>{ctx.pointer.x=ev.clientX;ctx.pointer.y=ev.clientY;};const updateRects=()=>{const{current}=ctx;const{container,element,scrollParentX,scrollParentY}=current;current.containerRect=dom.getRect(container,{adjust:true});let iframeOffsetX=0;let iframeOffsetY=0;const iframeEl=container.ownerDocument.defaultView.frameElement;if(iframeEl&&!iframeEl.contentDocument?.contains(element)){const{x,y}=dom.getRect(iframeEl);iframeOffsetX=x;iframeOffsetY=y;current.containerRect.x+=iframeOffsetX;current.containerRect.y+=iframeOffsetY;} current.containerRect.width=container.scrollWidth;current.containerRect.height=container.scrollHeight;current.scrollParentXRect=null;current.scrollParentYRect=null;if(ctx.edgeScrolling.enabled){if(scrollParentX){current.scrollParentXRect=dom.getRect(scrollParentX,{adjust:true});current.scrollParentXRect.x+=iframeOffsetX;current.scrollParentXRect.y+=iframeOffsetY;const right=Math.min(current.containerRect.left+container.scrollWidth,current.scrollParentXRect.right);current.containerRect.x=Math.max(current.containerRect.x,current.scrollParentXRect.x);current.containerRect.width=right-current.containerRect.x;} if(scrollParentY){current.scrollParentYRect=dom.getRect(scrollParentY,{adjust:true});current.scrollParentYRect.x+=iframeOffsetX;current.scrollParentYRect.y+=iframeOffsetY;const bottom=Math.min(current.containerRect.top+container.scrollHeight,current.scrollParentYRect.bottom);current.containerRect.y=Math.max(current.containerRect.y,current.scrollParentYRect.y);current.containerRect.height=bottom-current.containerRect.y;}} ctx.current.elementRect=dom.getRect(element);};const willStartDrag=(target)=>{ctx.current.element=target.closest(ctx.elementSelector);ctx.current.container=ctx.ref.el;cleanup.add(()=>(ctx.current={}));state.willDrag=true;callBuildHandler("onWillStartDrag");if(hasTouch()){dom.addListener(window,"touchmove",safePrevent,{passive:false,noAddedStyle:true,});if(params.iframeWindow){dom.addListener(params.iframeWindow,"touchmove",safePrevent,{passive:false,noAddedStyle:true,});}}};const cleanup=makeCleanupManager(()=>(state.dragging=false));const effectCleanup=makeCleanupManager();const dom=makeDOMHelpers(cleanup);const helpers={...dom,addCleanup:cleanup.add,addEffectCleanup:effectCleanup.add,callHandler,};const state=setupHooks.wrapState({dragging:false});for(const prop in allAcceptedParams){const type=typeof params[prop];const acceptedTypes=allAcceptedParams[prop].map((t)=>t.name.toLowerCase());if(params[prop]){if(!acceptedTypes.includes(type)){throw makeError(`invalid type for property "${prop}" in parameters: expected { ${acceptedTypes.join( ", " )} } and got ${type}`);}}else if(MANDATORY_PARAMS.includes(prop)&&!defaultParams[prop]){throw makeError(`missing required property "${prop}" in parameters`);}} const ctx={enable:()=>false,preventDrag:()=>false,ref:params.ref,ignoreSelector:null,fullSelector:null,followCursor:true,cursor:null,pointer:{x:0,y:0},edgeScrolling:{enabled:true},get dragging(){return state.dragging;},get willDrag(){return state.willDrag;},current:{},};setupHooks.setup((...deps)=>{const params=Object.fromEntries(deps);const actualParams={...defaultParams,...omit(params,"edgeScrolling")};if(params.edgeScrolling){actualParams.edgeScrolling={...actualParams.edgeScrolling,...params.edgeScrolling,};} if(!ctx.ref.el){return;} ctx.enable=actualParams.enable;if(actualParams.preventDrag){ctx.preventDrag=actualParams.preventDrag;} ctx.elementSelector=actualParams.elements;if(!ctx.elementSelector){throw makeError(`no value found by "elements" selector: ${ctx.elementSelector}`);} const allSelectors=[ctx.elementSelector];ctx.cursor=actualParams.cursor||null;if(actualParams.handle){allSelectors.push(actualParams.handle);} if(actualParams.ignore){ctx.ignoreSelector=actualParams.ignore;} ctx.fullSelector=allSelectors.join(" ");Object.assign(ctx.edgeScrolling,actualParams.edgeScrolling);ctx.delay=actualParams.delay;ctx.touchDelay=actualParams.delay||actualParams.touchDelay;ctx.tolerance=actualParams.tolerance;callBuildHandler("onComputeParams",{params:actualParams});return effectCleanup.cleanup;},()=>computeParams(params));const useMouseEvents=isBrowserFirefox()&&!hasTouch()&¶ms.iframeWindow;setupHooks.setup((el)=>{if(el){const{add,cleanup}=makeCleanupManager();const{addListener}=makeDOMHelpers({add});const event=useMouseEvents?"mousedown":"pointerdown";addListener(el,event,onPointerDown,{noAddedStyle:true});addListener(el,"click",onClick);if(hasTouch()){addListener(el,"contextmenu",safePrevent);addListener(el,"touchstart",()=>{},{passive:false,noAddedStyle:true,});} return cleanup;}},()=>[ctx.ref.el]);const addWindowListener=(type,listener,options)=>{if(params.iframeWindow){setupHooks.addListener(params.iframeWindow,type,listener,options);} setupHooks.addListener(window,type,listener,options);};const throttledOnPointerMove=setupHooks.throttle(onPointerMove);addWindowListener(useMouseEvents?"mousemove":"pointermove",throttledOnPointerMove,{passive:false});addWindowListener(useMouseEvents?"mouseup":"pointerup",onPointerUp);addWindowListener("pointercancel",onPointerCancel);addWindowListener("keydown",onKeyDown,{capture:true});setupHooks.teardown(()=>dragEnd(null));return state;},}[hookName];} return __exports;});; /* /web/static/src/core/utils/draggable_hook_builder_owl.js */ odoo.define('@web/core/utils/draggable_hook_builder_owl',['@odoo/owl','@web/core/utils/timing','@web/core/utils/draggable_hook_builder'],function(require){'use strict';let __exports={};const{onWillUnmount,reactive,useEffect,useExternalListener}=require("@odoo/owl");const{useThrottleForAnimation}=require("@web/core/utils/timing");const{makeDraggableHook:nativeMakeDraggableHook}=require("@web/core/utils/draggable_hook_builder");__exports.makeDraggableHook=makeDraggableHook;function makeDraggableHook(params){return nativeMakeDraggableHook({...params,setupHooks:{addListener:useExternalListener,setup:useEffect,teardown:onWillUnmount,throttle:useThrottleForAnimation,wrapState:reactive,},});} return __exports;});; /* /web/static/src/core/utils/files.js */ odoo.define('@web/core/utils/files',['@web/core/utils/numbers','@web/core/utils/hooks','@web/session','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{humanNumber}=require("@web/core/utils/numbers");const{useService}=require("@web/core/utils/hooks");const{session}=require("@web/session");const{_t}=require("@web/core/l10n/translation");const DEFAULT_MAX_FILE_SIZE=__exports.DEFAULT_MAX_FILE_SIZE=128*1024*1024;__exports.checkFileSize=checkFileSize;function checkFileSize(fileSize,notificationService){const maxUploadSize=session.max_file_upload_size||DEFAULT_MAX_FILE_SIZE;if(fileSize>maxUploadSize){notificationService.add(_t("The selected file (%(size)sB) is larger than the maximum allowed file size (%(maxSize)sB).",{size:humanNumber(fileSize),maxSize:humanNumber(maxUploadSize)}),{type:"danger",});return false;} return true;} __exports.useFileUploader=useFileUploader;function useFileUploader(){const http=useService("http");const notification=useService("notification");return async(route,params)=>{if((params.ufile&¶ms.ufile.length)||params.file){const fileSize=(params.ufile&¶ms.ufile[0].size)||params.file.size;if(!checkFileSize(fileSize,notification)){return null;}} const fileData=await http.post(route,params,"text");const parsedFileData=JSON.parse(fileData);if(parsedFileData.error){throw new Error(parsedFileData.error);} return parsedFileData;};} return __exports;});; /* /web/static/src/core/utils/functions.js */ odoo.define('@web/core/utils/functions',[],function(require){'use strict';let __exports={};__exports.memoize=memoize;function memoize(func){const cache=new Map();const funcName=func.name?func.name+" (memoized)":"memoized";return{[funcName](...args){if(!cache.has(args[0])){cache.set(args[0],func(...args));} return cache.get(...args);},}[funcName];} __exports.uniqueId=uniqueId;function uniqueId(prefix=""){return`${prefix}${++uniqueId.nextId}`;} uniqueId.nextId=0;return __exports;});; /* /web/static/src/core/utils/hooks.js */ odoo.define('@web/core/utils/hooks',['@web/core/browser/feature_detection','@odoo/owl'],function(require){'use strict';let __exports={};const{hasTouch,isMobileOS}=require("@web/core/browser/feature_detection");const{status,useComponent,useEffect,useRef,onWillUnmount}=require("@odoo/owl");__exports.useAutofocus=useAutofocus;function useAutofocus({refName,selectAll,mobile}={}){const ref=useRef(refName||"autofocus");const uiService=useService("ui");if(!mobile&&hasTouch()){return ref;} if(!mobile&&isMobileOS()){return ref;} useEffect((el)=>{if(el&&(!uiService.activeElement||uiService.activeElement.contains(el))){el.focus();if(["INPUT","TEXTAREA"].includes(el.tagName)&&el.type!=="number"){el.selectionEnd=el.value.length;el.selectionStart=selectAll?0:el.value.length;}}},()=>[ref.el]);return ref;} __exports.useBus=useBus;function useBus(bus,eventName,callback){const component=useComponent();useEffect(()=>{const listener=callback.bind(component);bus.addEventListener(eventName,listener);return()=>bus.removeEventListener(eventName,listener);},()=>[]);} const useServiceProtectMethodHandling=__exports.useServiceProtectMethodHandling={fn(){return this.original();},mocked(){return new Promise(()=>{});},original(){return Promise.reject(new Error("Component is destroyed"));},};function _protectMethod(component,fn){return function(...args){if(status(component)==="destroyed"){return useServiceProtectMethodHandling.fn();} const prom=Promise.resolve(fn.call(this,...args));const protectedProm=prom.then((result)=>status(component)==="destroyed"?new Promise(()=>{}):result);return Object.assign(protectedProm,{abort:prom.abort,cancel:prom.cancel,});};} const SERVICES_METADATA=__exports.SERVICES_METADATA={};__exports.useService=useService;function useService(serviceName){const component=useComponent();const{services}=component.env;if(!(serviceName in services)){throw new Error(`Service ${serviceName} is not available`);} const service=services[serviceName];if(serviceName in SERVICES_METADATA){if(service instanceof Function){return _protectMethod(component,service);}else{const methods=SERVICES_METADATA[serviceName];const result=Object.create(service);for(const method of methods){result[method]=_protectMethod(component,service[method]);} return result;}} return service;} __exports.useSpellCheck=useSpellCheck;function useSpellCheck({refName}={}){const elements=[];const ref=useRef(refName||"spellcheck");function toggleSpellcheck(ev){ev.target.spellcheck=document.activeElement===ev.target;} useEffect((el)=>{if(el){const inputs=["INPUT","TEXTAREA"].includes(el.nodeName)||el.isContentEditable?[el]:el.querySelectorAll("input, textarea, [contenteditable=true]");inputs.forEach((input)=>{if(input.spellcheck!==false){elements.push(input);input.addEventListener("focus",toggleSpellcheck);input.addEventListener("blur",toggleSpellcheck);}});} return()=>{elements.forEach((input)=>{input.removeEventListener("focus",toggleSpellcheck);input.removeEventListener("blur",toggleSpellcheck);});};},()=>[ref.el]);} __exports.useChildRef=useChildRef;function useChildRef(){let defined=false;let value;return function ref(v){value=v;if(defined){return;} Object.defineProperty(ref,"el",{get(){return value.el;},});defined=true;};} __exports.useForwardRefToParent=useForwardRefToParent;function useForwardRefToParent(refName){const component=useComponent();const ref=useRef(refName);if(component.props[refName]){component.props[refName](ref);} return ref;} __exports.useOwnedDialogs=useOwnedDialogs;function useOwnedDialogs(){const dialogService=useService("dialog");const cbs=[];onWillUnmount(()=>{cbs.forEach((cb)=>cb());});const addDialog=(...args)=>{const close=dialogService.add(...args);cbs.push(close);return close;};return addDialog;} __exports.useRefListener=useRefListener;function useRefListener(ref,...listener){useEffect((el)=>{el?.addEventListener(...listener);return()=>el?.removeEventListener(...listener);},()=>[ref.el]);} return __exports;});; /* /web/static/src/core/utils/html.js */ odoo.define('@web/core/utils/html',['@odoo/owl','@web/core/utils/strings'],function(require){'use strict';let __exports={};const{markup}=require("@odoo/owl");const{escape}=require("@web/core/utils/strings");const Markup=markup().constructor;__exports.htmlEscape=htmlEscape;function htmlEscape(content){return content instanceof Markup?content:markup(escape(content));} __exports.isHtmlEmpty=isHtmlEmpty;function isHtmlEmpty(content=""){const div=document.createElement("div");setElementContent(div,content);return div.textContent.trim()==="";} __exports.setElementContent=setElementContent;function setElementContent(element,content){if(content instanceof Markup){element.innerHTML=content;}else{element.textContent=content;}} return __exports;});; /* /web/static/src/core/utils/misc.js */ odoo.define('@web/core/utils/misc',[],function(require){'use strict';let __exports={};const eventHandledWeakMap=new WeakMap();__exports.isEventHandled=isEventHandled;function isEventHandled(ev,markName){if(!eventHandledWeakMap.get(ev)){return false;} return eventHandledWeakMap.get(ev).includes(markName);} __exports.markEventHandled=markEventHandled;function markEventHandled(ev,markName){if(!eventHandledWeakMap.get(ev)){eventHandledWeakMap.set(ev,[]);} eventHandledWeakMap.get(ev).push(markName);} return __exports;});; /* /web/static/src/core/utils/nested_sortable.js */ odoo.define('@web/core/utils/nested_sortable',['@web/core/l10n/localization','@web/core/utils/draggable_hook_builder_owl'],function(require){'use strict';let __exports={};const{localization}=require("@web/core/l10n/localization");const{makeDraggableHook}=require("@web/core/utils/draggable_hook_builder_owl");const useNestedSortable=__exports.useNestedSortable=makeDraggableHook({name:"useNestedSortable",acceptedParams:{groups:[String,Function],connectGroups:[Boolean,Function],nest:[Boolean],listTagName:[String],nestInterval:[Number],maxLevels:[Number],isAllowed:[Function],useElementSize:[Boolean],},defaultParams:{connectGroups:false,currentGroup:null,cursor:"grabbing",edgeScrolling:{speed:20,threshold:60},elements:"li",groupSelector:null,nest:false,listTagName:"ul",nestInterval:15,maxLevels:0,isAllowed:(ctx)=>true,useElementSize:false,},onComputeParams({ctx,params}){ctx.groupSelector=params.groups||null;if(ctx.groupSelector){ctx.fullSelector=[ctx.groupSelector,ctx.fullSelector].join(" ");} ctx.connectGroups=params.connectGroups;ctx.nest=params.nest;ctx.listTagName=params.listTagName;ctx.nestInterval=params.nestInterval;ctx.isRTL=localization.direction==="rtl";ctx.maxLevels=params.maxLevels||0;ctx.isAllowed=params.isAllowed??(()=>true);ctx.useElementSize=params.useElementSize;},onWillStartDrag({ctx,addCleanup}){if(ctx.groupSelector){ctx.currentGroup=ctx.current.element.closest(ctx.groupSelector);if(!ctx.connectGroups){ctx.current.container=ctx.currentGroup;}} if(ctx.nest){ctx.prevNestX=ctx.pointer.x;} ctx.current.placeHolder=ctx.current.element.cloneNode(false);ctx.current.placeHolder.removeAttribute("id");ctx.current.placeHolder.classList.add("w-100","d-block");if(ctx.useElementSize){ctx.current.placeHolder.style.height=getComputedStyle(ctx.current.element).height;ctx.current.placeHolder.classList.add("o_nested_sortable_placeholder_realsize");}else{ctx.current.placeHolder.classList.add("o_nested_sortable_placeholder");} addCleanup(()=>ctx.current.placeHolder.remove());},onDragStart({ctx,addStyle}){ctx.selectorX=ctx.isRTL?ctx.current.elementRect.left+1:ctx.current.elementRect.right-1;ctx.current.element.after(ctx.current.placeHolder);addStyle(ctx.current.element,{opacity:0.5});addStyle(document.body,{"pointer-events":"auto"});addStyle(document.querySelector(".o_navbar"),{"pointer-events":"none"});addStyle(document.querySelector(".o_action_manager"),{"pointer-events":"none"});addStyle(ctx.current.container,{"pointer-events":"auto"});return{element:ctx.current.element,group:ctx.currentGroup,};},_getDeepestChildLevel(ctx,node,depth=0){let result=0;const childSelector=`${ctx.listTagName} ${ctx.elementSelector}`;for(const childNode of node.querySelectorAll(childSelector)){result=Math.max(this._getDeepestChildLevel(ctx,childNode,depth+1),result);} return depth?result+1:result;},_hasReachMaxAllowedLevel(ctx){if(!ctx.nest||ctx.maxLevels<1){return false;} let level=this._getDeepestChildLevel(ctx,ctx.current.element);let list=ctx.current.placeHolder.closest(ctx.listTagName);while(list){level++;list=list.parentNode.closest(ctx.listTagName);} return level>ctx.maxLevels;},_isAllowedNodeMove(ctx){return(!this._hasReachMaxAllowedLevel(ctx)&&ctx.isAllowed(ctx.current,ctx.elementSelector));},onDrag({ctx,callHandler}){const onMove=(prevPos)=>{if(!this._isAllowedNodeMove(ctx)){ctx.current.placeHolder.classList.add("d-none");return;} ctx.current.placeHolder.classList.remove("d-none");callHandler("onMove",{element:ctx.current.element,previous:ctx.current.placeHolder.previousElementSibling,next:ctx.current.placeHolder.nextElementSibling,parent:ctx.nest?ctx.current.placeHolder.parentElement.closest(ctx.elementSelector):false,group:ctx.currentGroup,newGroup:ctx.connectGroups?ctx.current.placeHolder.closest(ctx.groupSelector):ctx.currentGroup,prevPos,placeholder:ctx.current.placeHolder,});};const getChildList=(el)=>{let list=el.querySelector(ctx.listTagName);if(!list){list=document.createElement(ctx.listTagName);el.appendChild(list);} return list;};const getPosition=(el)=>{return{previous:el.previousElementSibling,next:el.nextElementSibling,parent:el.parentElement?.closest(ctx.elementSelector)||null,group:ctx.groupSelector?el.closest(ctx.groupSelector):false,};};const position=getPosition(ctx.current.placeHolder);if(ctx.nest){const xInterval=ctx.prevNestX-ctx.pointer.x;if(ctx.nestInterval-(-1)**ctx.isRTL*xInterval<1){let nextElement=position.next;if(nextElement===ctx.current.element){nextElement=nextElement.nextElementSibling;} if(!nextElement){const newSibling=position.parent;if(newSibling){newSibling.after(ctx.current.placeHolder);onMove(position);}} ctx.prevNestX=ctx.pointer.x;return;}else if(ctx.nestInterval+(-1)**ctx.isRTL*xInterval<1){let parent=position.previous;if(parent===ctx.current.element){parent=parent.previousElementSibling;} if(parent&&parent.matches(ctx.elementSelector)){getChildList(parent).appendChild(ctx.current.placeHolder);onMove(position);} ctx.prevNestX=ctx.pointer.x;return;}} const currentTop=ctx.pointer.y-ctx.current.offset.y;const closestEl=document.elementFromPoint(ctx.selectorX,currentTop);if(!closestEl){return;} const element=closestEl.closest(ctx.elementSelector);if(element&&element!==ctx.current.placeHolder){const elementPosition=getPosition(element);const eRect=element.getBoundingClientRect();const pos=ctx.current.placeHolder.compareDocumentPosition(element);if(currentTop-eRect.y<10){if(pos&Node.DOCUMENT_POSITION_PRECEDING&&(ctx.nest||elementPosition.parent===position.parent)){element.before(ctx.current.placeHolder);onMove(position);ctx.prevNestX=ctx.pointer.x;}}else if(currentTop-eRect.y>15&&pos===Node.DOCUMENT_POSITION_FOLLOWING){if(ctx.nest){const elementChildList=getChildList(element);if(elementChildList.querySelector(ctx.elementSelector)){elementChildList.prepend(ctx.current.placeHolder);onMove(position);}else{element.after(ctx.current.placeHolder);onMove(position);} ctx.prevNestX=ctx.pointer.x;}else if(elementPosition.parent===position.parent){element.after(ctx.current.placeHolder);onMove(position);}}}else{const group=closestEl.closest(ctx.groupSelector);if(group&&group!==position.group&&(ctx.nest||!position.parent)){if(group.compareDocumentPosition(position.group)===Node.DOCUMENT_POSITION_PRECEDING){getChildList(group).prepend(ctx.current.placeHolder);onMove(position);}else{getChildList(group).appendChild(ctx.current.placeHolder);onMove(position);} ctx.prevNestX=ctx.pointer.x;callHandler("onGroupEnter",{group,placeholder:ctx.current.placeHolder});callHandler("onGroupLeave",{group:position.group,placeholder:ctx.current.placeHolder,});}}},onDrop({ctx}){if(!this._isAllowedNodeMove(ctx)){return;} const previous=ctx.current.placeHolder.previousElementSibling;const next=ctx.current.placeHolder.nextElementSibling;if(previous!==ctx.current.element&&next!==ctx.current.element){return{element:ctx.current.element,group:ctx.currentGroup,previous,next,newGroup:ctx.groupSelector&&ctx.current.placeHolder.closest(ctx.groupSelector),parent:ctx.current.placeHolder.parentElement.closest(ctx.elementSelector),placeholder:ctx.current.placeHolder,};}},onDragEnd({ctx}){return{element:ctx.current.element,group:ctx.currentGroup,};},});return __exports;});; /* /web/static/src/core/utils/numbers.js */ odoo.define('@web/core/utils/numbers',['@web/core/l10n/localization','@web/core/l10n/translation','@web/core/utils/strings'],function(require){'use strict';let __exports={};const{localization:l10n}=require("@web/core/l10n/localization");const{_t}=require("@web/core/l10n/translation");const{intersperse}=require("@web/core/utils/strings");__exports.clamp=clamp;function clamp(num,min,max){return Math.max(Math.min(num,max),min);} __exports.range=range;function range(start,stop,step=1){const array=[];const nsteps=Math.floor((stop-start)/step);for(let i=0;ival/roundingFactor;let denormalize=(val)=>val*roundingFactor;if(roundingFactor<1){roundingFactor=invertFloat(roundingFactor);[normalize,denormalize]=[denormalize,normalize];} const normalizedValue=normalize(value);const sign=Math.sign(normalizedValue);const epsilonMagnitude=Math.log2(Math.abs(normalizedValue));const epsilon=Math.pow(2,epsilonMagnitude-50);let roundedValue;switch(method){case"DOWN":{roundedValue=Math.trunc(normalizedValue+sign*epsilon);break;} case"HALF-DOWN":{roundedValue=Math.round(normalizedValue-sign*epsilon);break;} case"HALF-UP":{roundedValue=Math.round(normalizedValue+sign*epsilon);break;} case"HALF-EVEN":{const integral=Math.floor(normalizedValue);const remainder=Math.abs(normalizedValue-integral);const isHalf=Math.abs(0.5-remainder)=21){number=Math.round(number*Math.pow(10,decimals-numberMagnitude))/d2;return`${number}e+${numberMagnitude}`;} const unitSymbols=_t("kMGTPE").toString();const sign=Math.sign(number);number=Math.abs(number);let symbol="";for(let i=unitSymbols.length;i>0;i--){const s=Math.pow(10,i*3);if(s<=number/Math.pow(10,minDigits-1)){number=Math.round((number*d2)/s)/d2;symbol=unitSymbols[i-1];break;}} const{decimalPoint,grouping,thousandsSep}=l10n;const decimalsToKeep=number>=1000?0:decimals;number=sign*number;const[integerPart,decimalPart]=number.toFixed(decimalsToKeep).split(".");const int=insertThousandsSep(integerPart,thousandsSep,grouping);if(!decimalPart){return int+symbol;} return int+decimalPoint+decimalPart+symbol;} __exports.formatFloat=formatFloat;function formatFloat(value,options={}){if(options.humanReadable){return humanNumber(value,options);} const grouping=options.grouping||l10n.grouping;const thousandsSep="thousandsSep"in options?options.thousandsSep:l10n.thousandsSep;const decimalPoint="decimalPoint"in options?options.decimalPoint:l10n.decimalPoint;let precision;if(options.digits&&options.digits[1]!==undefined){precision=options.digits[1];}else{precision=2;} const formatted=value.toFixed(precision).split(".");formatted[0]=insertThousandsSep(formatted[0],thousandsSep,grouping);if(options.trailingZeros===false&&formatted[1]){formatted[1]=formatted[1].replace(/0+$/,"");} return formatted[1]?formatted.join(decimalPoint):formatted[0];} const _INVERTDICT=Object.freeze({1e-1:1e+1,1e-2:1e+2,1e-3:1e+3,1e-4:1e+4,1e-5:1e+5,1e-6:1e+6,1e-7:1e+7,1e-8:1e+8,1e-9:1e+9,1e-10:1e+10,2e-1:5e+0,2e-2:5e+1,2e-3:5e+2,2e-4:5e+3,2e-5:5e+4,2e-6:5e+5,2e-7:5e+6,2e-8:5e+7,2e-9:5e+8,2e-10:5e+9,5e-1:2e+0,5e-2:2e+1,5e-3:2e+2,5e-4:2e+3,5e-5:2e+4,5e-6:2e+5,5e-7:2e+6,5e-8:2e+7,5e-9:2e+8,5e-10:2e+9,});__exports.invertFloat=invertFloat;function invertFloat(value){let res=_INVERTDICT[value];if(res===undefined){const[coeff,expt]=value.toExponential().split("e").map(Number.parseFloat);res=Number.parseFloat(`${coeff}e${-expt}`)/Math.pow(coeff,2);} return res;} return __exports;});; /* /web/static/src/core/utils/objects.js */ odoo.define('@web/core/utils/objects',[],function(require){'use strict';let __exports={};__exports.shallowEqual=shallowEqual;function shallowEqual(obj1,obj2,comparisonFn=(a,b)=>a===b){if(!isObject(obj1)||!isObject(obj2)){return obj1===obj2;} const obj1Keys=Reflect.ownKeys(obj1);return(obj1Keys.length===Reflect.ownKeys(obj2).length&&obj1Keys.every((key)=>comparisonFn(obj1[key],obj2[key])));} const deepEqual=__exports.deepEqual=(obj1,obj2)=>shallowEqual(obj1,obj2,deepEqual);__exports.deepCopy=deepCopy;function deepCopy(object){return object&&JSON.parse(JSON.stringify(object));} __exports.isObject=isObject;function isObject(object){return!!object&&(typeof object==="object"||typeof object==="function");} __exports.omit=omit;function omit(object,...properties){const result={};const propertiesSet=new Set(properties);for(const key in object){if(!propertiesSet.has(key)){result[key]=object[key];}} return result;} __exports.pick=pick;function pick(object,...properties){return Object.fromEntries(properties.filter((prop)=>prop in object).map((prop)=>[prop,object[prop]]));} __exports.deepMerge=deepMerge;function deepMerge(target,extension){if(!isObject(target)&&!isObject(extension)){return;} target=target||{};const output=Object.assign({},target);if(isObject(extension)){for(const key of Reflect.ownKeys(extension)){if(key in target&&isObject(extension[key])&&!Array.isArray(extension[key])&&typeof extension[key]!=="function"){output[key]=deepMerge(target[key],extension[key]);}else{Object.assign(output,{[key]:extension[key]});}}} return output;} return __exports;});; /* /web/static/src/core/utils/patch.js */ odoo.define('@web/core/utils/patch',[],function(require){'use strict';let __exports={};const patchDescriptions=new WeakMap();function getPatchDescription(objToPatch){if(!patchDescriptions.has(objToPatch)){patchDescriptions.set(objToPatch,{originalProperties:new Map(),skeleton:Object.create(Object.getPrototypeOf(objToPatch)),extensions:new Set(),});} return patchDescriptions.get(objToPatch);} function isClassPrototype(objToPatch){return(Object.hasOwn(objToPatch,"constructor")&&objToPatch.constructor?.prototype===objToPatch);} function findAncestorPropertyDescriptor(objToPatch,key){let descriptor=null;let prototype=objToPatch;do{descriptor=Object.getOwnPropertyDescriptor(prototype,key);prototype=Object.getPrototypeOf(prototype);}while(!descriptor&&prototype);return descriptor;} __exports.patch=patch;function patch(objToPatch,extension){if(typeof extension==="string"){throw new Error(`Patch "${extension}": Second argument is not the patch name anymore, it should be the object containing the patched properties`);} const description=getPatchDescription(objToPatch);description.extensions.add(extension);const properties=Object.getOwnPropertyDescriptors(extension);for(const[key,newProperty]of Object.entries(properties)){const oldProperty=Object.getOwnPropertyDescriptor(objToPatch,key);if(oldProperty){Object.defineProperty(description.skeleton,key,oldProperty);} if(!description.originalProperties.has(key)){description.originalProperties.set(key,oldProperty);} if(isClassPrototype(objToPatch)){newProperty.enumerable=false;} if((newProperty.get&&1)^(newProperty.set&&1)){const ancestorProperty=findAncestorPropertyDescriptor(objToPatch,key);newProperty.get=newProperty.get??ancestorProperty?.get;newProperty.set=newProperty.set??ancestorProperty?.set;} Object.defineProperty(objToPatch,key,newProperty);} description.skeleton=Object.setPrototypeOf(extension,description.skeleton);return()=>{patchDescriptions.delete(objToPatch);for(const[key,property]of description.originalProperties){if(property){Object.defineProperty(objToPatch,key,property);}else{delete objToPatch[key];}} description.extensions.delete(extension);for(const extension of description.extensions){patch(objToPatch,extension);}};} return __exports;});; /* /web/static/src/core/utils/reactive.js */ odoo.define('@web/core/utils/reactive',['@odoo/owl'],function(require){'use strict';let __exports={};const{reactive}=require("@odoo/owl");const Reactive=__exports.Reactive=class Reactive{constructor(){return reactive(this);}} __exports.effect=effect;function effect(cb,deps){const reactiveDeps=reactive(deps,()=>{cb(...reactiveDeps);});cb(...reactiveDeps);} __exports.withComputedProperties=withComputedProperties;function withComputedProperties(obj,sources,descriptor){for(const[key,compute]of Object.entries(descriptor)){effect((obj,sources)=>{obj[key]=compute.call(obj,...sources);},[obj,sources]);} return obj;} return __exports;});; /* /web/static/src/core/utils/render.js */ odoo.define('@web/core/utils/render',['@odoo/owl','@web/core/templates','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{App,blockDom,Component,markup}=require("@odoo/owl");const{getTemplate}=require("@web/core/templates");const{_t}=require("@web/core/l10n/translation");__exports.renderToElement=renderToElement;function renderToElement(template,context={}){const el=render(template,context).firstElementChild;if(el?.nextElementSibling){throw new Error(`The rendered template '${template}' contains multiple root `+`nodes that will be ignored using renderToElement, you should `+`consider using renderToFragment or refactoring the template.`);} el?.remove();return el;} __exports.renderToFragment=renderToFragment;function renderToFragment(template,context={}){const frag=document.createDocumentFragment();for(const el of[...render(template,context).children]){frag.appendChild(el);} return frag;} __exports.renderToString=renderToString;function renderToString(template,context={}){return render(template,context).innerHTML;} let app;Object.defineProperty(renderToString,"app",{get:()=>{if(!app){app=new App(Component,{name:"renderToString",getTemplate,translatableAttributes:["data-tooltip"],translateFn:_t,});} return app;},});function render(template,context={}){const app=renderToString.app;const templateFn=app.getTemplate(template);const bdom=templateFn(context,{});const div=document.createElement("div");blockDom.mount(bdom,div);return div;} __exports.renderToMarkup=renderToMarkup;function renderToMarkup(template,context={}){return markup(renderToString(template,context));} return __exports;});; /* /web/static/src/core/utils/scrolling.js */ odoo.define('@web/core/utils/scrolling',[],function(require){'use strict';let __exports={};__exports.isScrollableX=isScrollableX;function isScrollableX(el){if(el.scrollWidth>el.clientWidth&&el.clientWidth>0){return couldBeScrollableX(el);} return false;} __exports.couldBeScrollableX=couldBeScrollableX;function couldBeScrollableX(el){if(el){const overflow=getComputedStyle(el).getPropertyValue("overflow-x");if(/\bauto\b|\bscroll\b/.test(overflow)){return true;}} return false;} __exports.closestScrollableX=closestScrollableX;function closestScrollableX(el){if(!el){return null;} if(isScrollableX(el)){return el;} return closestScrollableX(el.parentElement);} __exports.isScrollableY=isScrollableY;function isScrollableY(el){if(el&&el.scrollHeight>el.clientHeight&&el.clientHeight>0){return couldBeScrollableY(el);} return false;} __exports.couldBeScrollableY=couldBeScrollableY;function couldBeScrollableY(el){if(el){const overflow=getComputedStyle(el).getPropertyValue("overflow-y");if(/\bauto\b|\bscroll\b/.test(overflow)){return true;}} return false;} __exports.closestScrollableY=closestScrollableY;function closestScrollableY(el){if(!el){return null;} if(isScrollableY(el)){return el;} return closestScrollableY(el.parentElement);} __exports.scrollTo=scrollTo;function scrollTo(element,options={}){const{behavior="auto",isAnchor=false,offset=0}=options;const scrollable=closestScrollableY(options.scrollable||element.parentElement);if(!scrollable){return;} const scrollBottom=scrollable.getBoundingClientRect().bottom;const scrollTop=scrollable.getBoundingClientRect().top;const elementBottom=element.getBoundingClientRect().bottom;const elementTop=element.getBoundingClientRect().top;const scrollPromises=[];if(elementBottom>scrollBottom&&!isAnchor){scrollPromises.push(new Promise((resolve)=>{scrollable.addEventListener("scrollend",()=>resolve(),{once:true});}));scrollable.scrollTo({top:scrollable.scrollTop+ elementTop- scrollBottom+ Math.ceil(element.getBoundingClientRect().height)+ offset,behavior,});}else if(elementTop{scrollable.addEventListener("scrollend",()=>resolve(),{once:true});}));scrollable.scrollTo({top:scrollable.scrollTop-scrollTop+elementTop+offset,behavior,});if(options.isAnchor){const parentScrollable=closestScrollableY(scrollable.parentElement);if(parentScrollable){scrollPromises.push(scrollTo(scrollable,{behavior,isAnchor:true,scrollable:parentScrollable,}));}}} return Promise.all(scrollPromises);} __exports.compensateScrollbar=compensateScrollbar;function compensateScrollbar(el,add=true,isScrollElement=true,cssProperty="padding-right"){if(!el){return;} const scrollableEl=isScrollElement?el:closestScrollableY(el.parentElement);if(!scrollableEl){return;} const isRTL=scrollableEl.classList.contains(".o_rtl");if(isRTL){cssProperty=cssProperty.replace("right","left");} el.style.removeProperty(cssProperty);if(!add){return;} const style=window.getComputedStyle(el);const borderLeftWidth=Math.ceil(parseFloat(style.borderLeftWidth.replace("px","")));const borderRightWidth=Math.ceil(parseFloat(style.borderRightWidth.replace("px","")));const bordersWidth=borderLeftWidth+borderRightWidth;const newValue=parseInt(style[cssProperty])+ scrollableEl.offsetWidth- scrollableEl.clientWidth- bordersWidth;el.style.setProperty(cssProperty,`${newValue}px`,"important");} __exports.getScrollingElement=getScrollingElement;function getScrollingElement(document=window.document){const baseScrollingElement=document.scrollingElement;if(isScrollableY(baseScrollingElement)){return baseScrollingElement;} const bodyHeight=window.getComputedStyle(document.body).height;for(const el of document.body.children){if(bodyHeight-el.scrollHeight>1.5){continue;} if(isScrollableY(el)){return el;}} return baseScrollingElement;} return __exports;});; /* /web/static/src/core/utils/search.js */ odoo.define('@web/core/utils/search',['@web/core/utils/strings'],function(require){'use strict';let __exports={};const{unaccent}=require("@web/core/utils/strings");function match(pattern,strs){if(!Array.isArray(strs)){strs=[strs];} let globalScore=0;for(const str of strs){globalScore=Math.max(globalScore,_match(pattern,str));} return globalScore;} function _match(pattern,str){let totalScore=0;let currentScore=0;const len=str.length;let patternIndex=0;pattern=unaccent(pattern,false);str=unaccent(str,false);for(let i=0;i{const score=match(pattern,fn(data));if(score>0){results.push({score,elem:data});}});results.sort((a,b)=>b.score-a.score);return results.map((r)=>r.elem);} __exports.fuzzyTest=fuzzyTest;function fuzzyTest(pattern,string){return _match(pattern,string)!==0;} return __exports;});; /* /web/static/src/core/utils/sortable.js */ odoo.define('@web/core/utils/sortable',['@web/core/utils/draggable_hook_builder','@web/core/utils/objects'],function(require){'use strict';let __exports={};const{DRAGGED_CLASS,makeDraggableHook:nativeMakeDraggableHook,}=require("@web/core/utils/draggable_hook_builder");const{pick}=require("@web/core/utils/objects");const hookParams={name:"useSortable",acceptedParams:{groups:[String,Function],connectGroups:[Boolean,Function],clone:[Boolean],placeholderClasses:[Object],applyChangeOnDrop:[Boolean],followingElementClasses:[Object],},defaultParams:{connectGroups:false,edgeScrolling:{speed:20,threshold:60},groupSelector:null,clone:true,placeholderClasses:[],applyChangeOnDrop:false,followingElementClasses:[],},onComputeParams({ctx,params}){ctx.groupSelector=params.groups||null;if(ctx.groupSelector){ctx.fullSelector=[ctx.groupSelector,ctx.fullSelector].join(" ");} ctx.connectGroups=params.connectGroups;ctx.placeholderClone=params.clone;ctx.placeholderClasses=params.placeholderClasses;ctx.applyChangeOnDrop=params.applyChangeOnDrop;ctx.followingElementClasses=params.followingElementClasses;},onDragStart({ctx,addListener,addStyle,callHandler}){const onElementPointerEnter=(ev)=>{const element=ev.currentTarget;if(connectGroups||!groupSelector||current.group===element.closest(groupSelector)){const pos=current.placeHolder.compareDocumentPosition(element);if(pos===Node.DOCUMENT_POSITION_PRECEDING){element.before(current.placeHolder);}else if(pos===Node.DOCUMENT_POSITION_FOLLOWING){element.after(current.placeHolder);}} callHandler("onElementEnter",{element});};const onElementPointerLeave=(ev)=>{const element=ev.currentTarget;callHandler("onElementLeave",{element});};const onElementComplexPointerEnter=(ev)=>{if(ctx.haveAlreadyChanged){return;} const element=ev.currentTarget;const siblingArray=[...element.parentElement.children].filter((el)=>el===current.placeHolder||(el.matches(elementSelector)&&!el.classList.contains(DRAGGED_CLASS)));const elementIndex=siblingArray.indexOf(element);const placeholderIndex=siblingArray.indexOf(current.placeHolder);const isDirectSibling=Math.abs(elementIndex-placeholderIndex)===1;if(connectGroups||!groupSelector||current.group===element.closest(groupSelector)){const pos=current.placeHolder.compareDocumentPosition(element);if(isDirectSibling){if(pos===Node.DOCUMENT_POSITION_PRECEDING){element.before(current.placeHolder);ctx.haveAlreadyChanged=true;}else if(pos===Node.DOCUMENT_POSITION_FOLLOWING){element.after(current.placeHolder);ctx.haveAlreadyChanged=true;}}else{if(pos===Node.DOCUMENT_POSITION_FOLLOWING){element.before(current.placeHolder);ctx.haveAlreadyChanged=true;}else if(pos===Node.DOCUMENT_POSITION_PRECEDING){element.after(current.placeHolder);ctx.haveAlreadyChanged=true;}}} callHandler("onElementEnter",{element});};const onElementComplexPointerLeave=(ev)=>{if(ctx.haveAlreadyChanged){return;} const element=ev.currentTarget;const elementRect=element.getBoundingClientRect();const relatedElement=ev.relatedTarget;const relatedElementRect=element.getBoundingClientRect();const siblingArray=[...element.parentElement.children].filter((el)=>el===current.placeHolder||(el.matches(elementSelector)&&!el.classList.contains(DRAGGED_CLASS)));const pointerOnSiblings=siblingArray.indexOf(relatedElement)>-1;const elementIndex=siblingArray.indexOf(element);const isFirst=elementIndex===0;const isAbove=relatedElementRect.top<=elementRect.top;const isLast=elementIndex===siblingArray.length-1;const isBelow=relatedElementRect.bottom>=elementRect.bottom;const pos=current.placeHolder.compareDocumentPosition(element);if(!pointerOnSiblings){if(isFirst&&isAbove&&pos===Node.DOCUMENT_POSITION_PRECEDING){element.before(current.placeHolder);ctx.haveAlreadyChanged=true;}else if(isLast&&isBelow&&pos===Node.DOCUMENT_POSITION_FOLLOWING){element.after(current.placeHolder);ctx.haveAlreadyChanged=true;}} callHandler("onElementLeave",{element});};const onGroupPointerEnter=(ev)=>{const group=ev.currentTarget;group.appendChild(current.placeHolder);callHandler("onGroupEnter",{group});};const onGroupPointerLeave=(ev)=>{const group=ev.currentTarget;callHandler("onGroupLeave",{group});};const{connectGroups,current,elementSelector,groupSelector,ref}=ctx;if(ctx.placeholderClone){const{width,height}=current.elementRect;addStyle(current.placeHolder,{visibility:"hidden",display:"block",width:`${width}px`,height:`${height}px`,});} if(connectGroups&&groupSelector){for(const siblingGroup of ref.el.querySelectorAll(groupSelector)){addListener(siblingGroup,"pointerenter",onGroupPointerEnter);addListener(siblingGroup,"pointerleave",onGroupPointerLeave);}} for(const siblingEl of ref.el.querySelectorAll(elementSelector)){if(siblingEl!==current.element&&siblingEl!==current.placeHolder){if(ctx.placeholderClone){addListener(siblingEl,"pointerenter",onElementPointerEnter);addListener(siblingEl,"pointerleave",onElementPointerLeave);}else{addListener(siblingEl,"pointerenter",onElementComplexPointerEnter);addListener(siblingEl,"pointerleave",onElementComplexPointerLeave);}}} current.element.after(current.placeHolder);return pick(current,"element","group");},onDrag({ctx}){ctx.haveAlreadyChanged=false;},onDragEnd({ctx}){return pick(ctx.current,"element","group");},onDrop({ctx}){const{current,groupSelector}=ctx;const previous=current.placeHolder.previousElementSibling;const next=current.placeHolder.nextElementSibling;if(previous!==current.element&&next!==current.element){const element=current.element;if(ctx.applyChangeOnDrop){if(previous){previous.after(element);}else if(next){next.before(element);}} return{element,group:current.group,previous,next,parent:groupSelector&¤t.placeHolder.closest(groupSelector),};}},onWillStartDrag({ctx,addCleanup}){const{connectGroups,current,groupSelector}=ctx;if(groupSelector){current.group=current.element.closest(groupSelector);if(!connectGroups){current.container=current.group;}} if(ctx.placeholderClone){current.placeHolder=current.element.cloneNode(false);}else{current.placeHolder=document.createElement("div");} current.placeHolder.classList.add(...ctx.placeholderClasses);current.element.classList.add(...ctx.followingElementClasses);addCleanup(()=>current.element.classList.remove(...ctx.followingElementClasses));addCleanup(()=>current.placeHolder.remove());return pick(current,"element","group");},};const useSortable=__exports.useSortable=(sortableParams)=>{const{setupHooks}=sortableParams;delete sortableParams.setupHooks;return nativeMakeDraggableHook({...hookParams,setupHooks})(sortableParams);};return __exports;});; /* /web/static/src/core/utils/sortable_owl.js */ odoo.define('@web/core/utils/sortable_owl',['@odoo/owl','@web/core/utils/timing','@web/core/utils/sortable'],function(require){'use strict';let __exports={};const{onWillUnmount,reactive,useEffect,useExternalListener}=require("@odoo/owl");const{useThrottleForAnimation}=require("@web/core/utils/timing");const{useSortable:nativeUseSortable}=require("@web/core/utils/sortable");__exports.useSortable=useSortable;function useSortable(params){return nativeUseSortable({...params,setupHooks:{addListener:useExternalListener,setup:useEffect,teardown:onWillUnmount,throttle:useThrottleForAnimation,wrapState:reactive,},});} return __exports;});; /* /web/static/src/core/utils/sortable_service.js */ odoo.define('@web/core/utils/sortable_service',['@web/core/registry','@web/core/utils/sortable','@web/core/utils/timing','@odoo/owl'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{useSortable}=require("@web/core/utils/sortable");const{throttleForAnimation}=require("@web/core/utils/timing");const{reactive}=require("@odoo/owl");const DEFAULT_SORTABLE_ID=Symbol.for("defaultSortable");const sortableService=__exports.sortableService={start(){const boundElements=new Map();return{create:(hookParams)=>{const element=hookParams.ref.el;const sortableId=hookParams.sortableId??DEFAULT_SORTABLE_ID;if(boundElements.has(element)){const boundElement=boundElements.get(element);if(sortableId in boundElement){return{enable(){return{cleanup:boundElement[sortableId],};},};}} const setupFunctions=new Map();const cleanupFunctions=[];const cleanup=()=>{const boundElement=boundElements.get(element);if(sortableId in boundElement){delete boundElement[sortableId];if(boundElement.length===0){boundElements.delete(element);}} cleanupFunctions.forEach((fn)=>fn());};const setupHooks={wrapState:reactive,throttle:throttleForAnimation,addListener:(el,type,listener)=>{el.addEventListener(type,listener);cleanupFunctions.push(()=>el.removeEventListener(type,listener));},setup:(setupFn,dependenciesFn)=>setupFunctions.set(setupFn,dependenciesFn),teardown:(fn)=>cleanupFunctions.push(fn),};useSortable({setupHooks,...hookParams});const boundElement=boundElements.get(element);if(boundElement){boundElement[sortableId]=cleanup;}else{boundElements.set(element,{[sortableId]:cleanup});} return{enable(){setupFunctions.forEach((dependenciesFn,setupFn)=>setupFn(...dependenciesFn()));return{cleanup,};},};},};},};registry.category("services").add("sortable",sortableService);return __exports;});; /* /web/static/src/core/utils/strings.js */ odoo.define('@web/core/utils/strings',[],function(require){'use strict';let __exports={};const nbsp=__exports.nbsp="\u00a0";__exports.escape=escape;function escape(str){if(str===undefined){return"";} if(typeof str==="number"){return String(str);} [["&","&"],["<","<"],[">",">"],["'","'"],['"',"""],["`","`"],].forEach((pairs)=>{str=String(str).replaceAll(pairs[0],pairs[1]);});return str;} __exports.escapeRegExp=escapeRegExp;function escapeRegExp(str){return str.replace(/[.*+?^${}()|[\]\\]/g,"\\$&");} __exports.intersperse=intersperse;function intersperse(str,indices,separator=""){separator=separator||"";const result=[];let last=str.length;for(let i=0;ivaluesDict[value]);}else if(values.length>0){s=s.replace(/%s/g,()=>values.shift());} return s;} __exports.capitalize=capitalize;function capitalize(s){return s?s[0].toUpperCase()+s.slice(1):"";} const diacriticsMap={'\u0041':'A','\u24B6':'A','\uFF21':'A','\u00C0':'A','\u00C1':'A','\u00C2':'A','\u1EA6':'A','\u1EA4':'A','\u1EAA':'A','\u1EA8':'A','\u00C3':'A','\u0100':'A','\u0102':'A','\u1EB0':'A','\u1EAE':'A','\u1EB4':'A','\u1EB2':'A','\u0226':'A','\u01E0':'A','\u00C4':'A','\u01DE':'A','\u1EA2':'A','\u00C5':'A','\u01FA':'A','\u01CD':'A','\u0200':'A','\u0202':'A','\u1EA0':'A','\u1EAC':'A','\u1EB6':'A','\u1E00':'A','\u0104':'A','\u023A':'A','\u2C6F':'A','\uA732':'AA','\u00C6':'AE','\u01FC':'AE','\u01E2':'AE','\uA734':'AO','\uA736':'AU','\uA738':'AV','\uA73A':'AV','\uA73C':'AY','\u0042':'B','\u24B7':'B','\uFF22':'B','\u1E02':'B','\u1E04':'B','\u1E06':'B','\u0243':'B','\u0182':'B','\u0181':'B','\u0043':'C','\u24B8':'C','\uFF23':'C','\u0106':'C','\u0108':'C','\u010A':'C','\u010C':'C','\u00C7':'C','\u1E08':'C','\u0187':'C','\u023B':'C','\uA73E':'C','\u0044':'D','\u24B9':'D','\uFF24':'D','\u1E0A':'D','\u010E':'D','\u1E0C':'D','\u1E10':'D','\u1E12':'D','\u1E0E':'D','\u0110':'D','\u018B':'D','\u018A':'D','\u0189':'D','\uA779':'D','\u01F1':'DZ','\u01C4':'DZ','\u01F2':'Dz','\u01C5':'Dz','\u0045':'E','\u24BA':'E','\uFF25':'E','\u00C8':'E','\u00C9':'E','\u00CA':'E','\u1EC0':'E','\u1EBE':'E','\u1EC4':'E','\u1EC2':'E','\u1EBC':'E','\u0112':'E','\u1E14':'E','\u1E16':'E','\u0114':'E','\u0116':'E','\u00CB':'E','\u1EBA':'E','\u011A':'E','\u0204':'E','\u0206':'E','\u1EB8':'E','\u1EC6':'E','\u0228':'E','\u1E1C':'E','\u0118':'E','\u1E18':'E','\u1E1A':'E','\u0190':'E','\u018E':'E','\u0046':'F','\u24BB':'F','\uFF26':'F','\u1E1E':'F','\u0191':'F','\uA77B':'F','\u0047':'G','\u24BC':'G','\uFF27':'G','\u01F4':'G','\u011C':'G','\u1E20':'G','\u011E':'G','\u0120':'G','\u01E6':'G','\u0122':'G','\u01E4':'G','\u0193':'G','\uA7A0':'G','\uA77D':'G','\uA77E':'G','\u0048':'H','\u24BD':'H','\uFF28':'H','\u0124':'H','\u1E22':'H','\u1E26':'H','\u021E':'H','\u1E24':'H','\u1E28':'H','\u1E2A':'H','\u0126':'H','\u2C67':'H','\u2C75':'H','\uA78D':'H','\u0049':'I','\u24BE':'I','\uFF29':'I','\u00CC':'I','\u00CD':'I','\u00CE':'I','\u0128':'I','\u012A':'I','\u012C':'I','\u0130':'I','\u00CF':'I','\u1E2E':'I','\u1EC8':'I','\u01CF':'I','\u0208':'I','\u020A':'I','\u1ECA':'I','\u012E':'I','\u1E2C':'I','\u0197':'I','\u004A':'J','\u24BF':'J','\uFF2A':'J','\u0134':'J','\u0248':'J','\u004B':'K','\u24C0':'K','\uFF2B':'K','\u1E30':'K','\u01E8':'K','\u1E32':'K','\u0136':'K','\u1E34':'K','\u0198':'K','\u2C69':'K','\uA740':'K','\uA742':'K','\uA744':'K','\uA7A2':'K','\u004C':'L','\u24C1':'L','\uFF2C':'L','\u013F':'L','\u0139':'L','\u013D':'L','\u1E36':'L','\u1E38':'L','\u013B':'L','\u1E3C':'L','\u1E3A':'L','\u0141':'L','\u023D':'L','\u2C62':'L','\u2C60':'L','\uA748':'L','\uA746':'L','\uA780':'L','\u01C7':'LJ','\u01C8':'Lj','\u004D':'M','\u24C2':'M','\uFF2D':'M','\u1E3E':'M','\u1E40':'M','\u1E42':'M','\u2C6E':'M','\u019C':'M','\u004E':'N','\u24C3':'N','\uFF2E':'N','\u01F8':'N','\u0143':'N','\u00D1':'N','\u1E44':'N','\u0147':'N','\u1E46':'N','\u0145':'N','\u1E4A':'N','\u1E48':'N','\u0220':'N','\u019D':'N','\uA790':'N','\uA7A4':'N','\u01CA':'NJ','\u01CB':'Nj','\u004F':'O','\u24C4':'O','\uFF2F':'O','\u00D2':'O','\u00D3':'O','\u00D4':'O','\u1ED2':'O','\u1ED0':'O','\u1ED6':'O','\u1ED4':'O','\u00D5':'O','\u1E4C':'O','\u022C':'O','\u1E4E':'O','\u014C':'O','\u1E50':'O','\u1E52':'O','\u014E':'O','\u022E':'O','\u0230':'O','\u00D6':'O','\u022A':'O','\u1ECE':'O','\u0150':'O','\u01D1':'O','\u020C':'O','\u020E':'O','\u01A0':'O','\u1EDC':'O','\u1EDA':'O','\u1EE0':'O','\u1EDE':'O','\u1EE2':'O','\u1ECC':'O','\u1ED8':'O','\u01EA':'O','\u01EC':'O','\u00D8':'O','\u01FE':'O','\u0186':'O','\u019F':'O','\uA74A':'O','\uA74C':'O','\u01A2':'OI','\uA74E':'OO','\u0222':'OU','\u0050':'P','\u24C5':'P','\uFF30':'P','\u1E54':'P','\u1E56':'P','\u01A4':'P','\u2C63':'P','\uA750':'P','\uA752':'P','\uA754':'P','\u0051':'Q','\u24C6':'Q','\uFF31':'Q','\uA756':'Q','\uA758':'Q','\u024A':'Q','\u0052':'R','\u24C7':'R','\uFF32':'R','\u0154':'R','\u1E58':'R','\u0158':'R','\u0210':'R','\u0212':'R','\u1E5A':'R','\u1E5C':'R','\u0156':'R','\u1E5E':'R','\u024C':'R','\u2C64':'R','\uA75A':'R','\uA7A6':'R','\uA782':'R','\u0053':'S','\u24C8':'S','\uFF33':'S','\u1E9E':'S','\u015A':'S','\u1E64':'S','\u015C':'S','\u1E60':'S','\u0160':'S','\u1E66':'S','\u1E62':'S','\u1E68':'S','\u0218':'S','\u015E':'S','\u2C7E':'S','\uA7A8':'S','\uA784':'S','\u0054':'T','\u24C9':'T','\uFF34':'T','\u1E6A':'T','\u0164':'T','\u1E6C':'T','\u021A':'T','\u0162':'T','\u1E70':'T','\u1E6E':'T','\u0166':'T','\u01AC':'T','\u01AE':'T','\u023E':'T','\uA786':'T','\uA728':'TZ','\u0055':'U','\u24CA':'U','\uFF35':'U','\u00D9':'U','\u00DA':'U','\u00DB':'U','\u0168':'U','\u1E78':'U','\u016A':'U','\u1E7A':'U','\u016C':'U','\u00DC':'U','\u01DB':'U','\u01D7':'U','\u01D5':'U','\u01D9':'U','\u1EE6':'U','\u016E':'U','\u0170':'U','\u01D3':'U','\u0214':'U','\u0216':'U','\u01AF':'U','\u1EEA':'U','\u1EE8':'U','\u1EEE':'U','\u1EEC':'U','\u1EF0':'U','\u1EE4':'U','\u1E72':'U','\u0172':'U','\u1E76':'U','\u1E74':'U','\u0244':'U','\u0056':'V','\u24CB':'V','\uFF36':'V','\u1E7C':'V','\u1E7E':'V','\u01B2':'V','\uA75E':'V','\u0245':'V','\uA760':'VY','\u0057':'W','\u24CC':'W','\uFF37':'W','\u1E80':'W','\u1E82':'W','\u0174':'W','\u1E86':'W','\u1E84':'W','\u1E88':'W','\u2C72':'W','\u0058':'X','\u24CD':'X','\uFF38':'X','\u1E8A':'X','\u1E8C':'X','\u0059':'Y','\u24CE':'Y','\uFF39':'Y','\u1EF2':'Y','\u00DD':'Y','\u0176':'Y','\u1EF8':'Y','\u0232':'Y','\u1E8E':'Y','\u0178':'Y','\u1EF6':'Y','\u1EF4':'Y','\u01B3':'Y','\u024E':'Y','\u1EFE':'Y','\u005A':'Z','\u24CF':'Z','\uFF3A':'Z','\u0179':'Z','\u1E90':'Z','\u017B':'Z','\u017D':'Z','\u1E92':'Z','\u1E94':'Z','\u01B5':'Z','\u0224':'Z','\u2C7F':'Z','\u2C6B':'Z','\uA762':'Z','\u0061':'a','\u24D0':'a','\uFF41':'a','\u1E9A':'a','\u00E0':'a','\u00E1':'a','\u00E2':'a','\u1EA7':'a','\u1EA5':'a','\u1EAB':'a','\u1EA9':'a','\u00E3':'a','\u0101':'a','\u0103':'a','\u1EB1':'a','\u1EAF':'a','\u1EB5':'a','\u1EB3':'a','\u0227':'a','\u01E1':'a','\u00E4':'a','\u01DF':'a','\u1EA3':'a','\u00E5':'a','\u01FB':'a','\u01CE':'a','\u0201':'a','\u0203':'a','\u1EA1':'a','\u1EAD':'a','\u1EB7':'a','\u1E01':'a','\u0105':'a','\u2C65':'a','\u0250':'a','\uA733':'aa','\u00E6':'ae','\u01FD':'ae','\u01E3':'ae','\uA735':'ao','\uA737':'au','\uA739':'av','\uA73B':'av','\uA73D':'ay','\u0062':'b','\u24D1':'b','\uFF42':'b','\u1E03':'b','\u1E05':'b','\u1E07':'b','\u0180':'b','\u0183':'b','\u0253':'b','\u0063':'c','\u24D2':'c','\uFF43':'c','\u0107':'c','\u0109':'c','\u010B':'c','\u010D':'c','\u00E7':'c','\u1E09':'c','\u0188':'c','\u023C':'c','\uA73F':'c','\u2184':'c','\u0064':'d','\u24D3':'d','\uFF44':'d','\u1E0B':'d','\u010F':'d','\u1E0D':'d','\u1E11':'d','\u1E13':'d','\u1E0F':'d','\u0111':'d','\u018C':'d','\u0256':'d','\u0257':'d','\uA77A':'d','\u01F3':'dz','\u01C6':'dz','\u0065':'e','\u24D4':'e','\uFF45':'e','\u00E8':'e','\u00E9':'e','\u00EA':'e','\u1EC1':'e','\u1EBF':'e','\u1EC5':'e','\u1EC3':'e','\u1EBD':'e','\u0113':'e','\u1E15':'e','\u1E17':'e','\u0115':'e','\u0117':'e','\u00EB':'e','\u1EBB':'e','\u011B':'e','\u0205':'e','\u0207':'e','\u1EB9':'e','\u1EC7':'e','\u0229':'e','\u1E1D':'e','\u0119':'e','\u1E19':'e','\u1E1B':'e','\u0247':'e','\u025B':'e','\u01DD':'e','\u0066':'f','\u24D5':'f','\uFF46':'f','\u1E1F':'f','\u0192':'f','\uA77C':'f','\u0067':'g','\u24D6':'g','\uFF47':'g','\u01F5':'g','\u011D':'g','\u1E21':'g','\u011F':'g','\u0121':'g','\u01E7':'g','\u0123':'g','\u01E5':'g','\u0260':'g','\uA7A1':'g','\u1D79':'g','\uA77F':'g','\u0068':'h','\u24D7':'h','\uFF48':'h','\u0125':'h','\u1E23':'h','\u1E27':'h','\u021F':'h','\u1E25':'h','\u1E29':'h','\u1E2B':'h','\u1E96':'h','\u0127':'h','\u2C68':'h','\u2C76':'h','\u0265':'h','\u0195':'hv','\u0069':'i','\u24D8':'i','\uFF49':'i','\u00EC':'i','\u00ED':'i','\u00EE':'i','\u0129':'i','\u012B':'i','\u012D':'i','\u00EF':'i','\u1E2F':'i','\u1EC9':'i','\u01D0':'i','\u0209':'i','\u020B':'i','\u1ECB':'i','\u012F':'i','\u1E2D':'i','\u0268':'i','\u0131':'i','\u006A':'j','\u24D9':'j','\uFF4A':'j','\u0135':'j','\u01F0':'j','\u0249':'j','\u006B':'k','\u24DA':'k','\uFF4B':'k','\u1E31':'k','\u01E9':'k','\u1E33':'k','\u0137':'k','\u1E35':'k','\u0199':'k','\u2C6A':'k','\uA741':'k','\uA743':'k','\uA745':'k','\uA7A3':'k','\u006C':'l','\u24DB':'l','\uFF4C':'l','\u0140':'l','\u013A':'l','\u013E':'l','\u1E37':'l','\u1E39':'l','\u013C':'l','\u1E3D':'l','\u1E3B':'l','\u017F':'l','\u0142':'l','\u019A':'l','\u026B':'l','\u2C61':'l','\uA749':'l','\uA781':'l','\uA747':'l','\u01C9':'lj','\u006D':'m','\u24DC':'m','\uFF4D':'m','\u1E3F':'m','\u1E41':'m','\u1E43':'m','\u0271':'m','\u026F':'m','\u006E':'n','\u24DD':'n','\uFF4E':'n','\u01F9':'n','\u0144':'n','\u00F1':'n','\u1E45':'n','\u0148':'n','\u1E47':'n','\u0146':'n','\u1E4B':'n','\u1E49':'n','\u019E':'n','\u0272':'n','\u0149':'n','\uA791':'n','\uA7A5':'n','\u01CC':'nj','\u006F':'o','\u24DE':'o','\uFF4F':'o','\u00F2':'o','\u00F3':'o','\u00F4':'o','\u1ED3':'o','\u1ED1':'o','\u1ED7':'o','\u1ED5':'o','\u00F5':'o','\u1E4D':'o','\u022D':'o','\u1E4F':'o','\u014D':'o','\u1E51':'o','\u1E53':'o','\u014F':'o','\u022F':'o','\u0231':'o','\u00F6':'o','\u022B':'o','\u1ECF':'o','\u0151':'o','\u01D2':'o','\u020D':'o','\u020F':'o','\u01A1':'o','\u1EDD':'o','\u1EDB':'o','\u1EE1':'o','\u1EDF':'o','\u1EE3':'o','\u1ECD':'o','\u1ED9':'o','\u01EB':'o','\u01ED':'o','\u00F8':'o','\u01FF':'o','\u0254':'o','\uA74B':'o','\uA74D':'o','\u0275':'o','\u01A3':'oi','\u0223':'ou','\uA74F':'oo','\u0070':'p','\u24DF':'p','\uFF50':'p','\u1E55':'p','\u1E57':'p','\u01A5':'p','\u1D7D':'p','\uA751':'p','\uA753':'p','\uA755':'p','\u0071':'q','\u24E0':'q','\uFF51':'q','\u024B':'q','\uA757':'q','\uA759':'q','\u0072':'r','\u24E1':'r','\uFF52':'r','\u0155':'r','\u1E59':'r','\u0159':'r','\u0211':'r','\u0213':'r','\u1E5B':'r','\u1E5D':'r','\u0157':'r','\u1E5F':'r','\u024D':'r','\u027D':'r','\uA75B':'r','\uA7A7':'r','\uA783':'r','\u0073':'s','\u24E2':'s','\uFF53':'s','\u00DF':'s','\u015B':'s','\u1E65':'s','\u015D':'s','\u1E61':'s','\u0161':'s','\u1E67':'s','\u1E63':'s','\u1E69':'s','\u0219':'s','\u015F':'s','\u023F':'s','\uA7A9':'s','\uA785':'s','\u1E9B':'s','\u0074':'t','\u24E3':'t','\uFF54':'t','\u1E6B':'t','\u1E97':'t','\u0165':'t','\u1E6D':'t','\u021B':'t','\u0163':'t','\u1E71':'t','\u1E6F':'t','\u0167':'t','\u01AD':'t','\u0288':'t','\u2C66':'t','\uA787':'t','\uA729':'tz','\u0075':'u','\u24E4':'u','\uFF55':'u','\u00F9':'u','\u00FA':'u','\u00FB':'u','\u0169':'u','\u1E79':'u','\u016B':'u','\u1E7B':'u','\u016D':'u','\u00FC':'u','\u01DC':'u','\u01D8':'u','\u01D6':'u','\u01DA':'u','\u1EE7':'u','\u016F':'u','\u0171':'u','\u01D4':'u','\u0215':'u','\u0217':'u','\u01B0':'u','\u1EEB':'u','\u1EE9':'u','\u1EEF':'u','\u1EED':'u','\u1EF1':'u','\u1EE5':'u','\u1E73':'u','\u0173':'u','\u1E77':'u','\u1E75':'u','\u0289':'u','\u0076':'v','\u24E5':'v','\uFF56':'v','\u1E7D':'v','\u1E7F':'v','\u028B':'v','\uA75F':'v','\u028C':'v','\uA761':'vy','\u0077':'w','\u24E6':'w','\uFF57':'w','\u1E81':'w','\u1E83':'w','\u0175':'w','\u1E87':'w','\u1E85':'w','\u1E98':'w','\u1E89':'w','\u2C73':'w','\u0078':'x','\u24E7':'x','\uFF58':'x','\u1E8B':'x','\u1E8D':'x','\u0079':'y','\u24E8':'y','\uFF59':'y','\u1EF3':'y','\u00FD':'y','\u0177':'y','\u1EF9':'y','\u0233':'y','\u1E8F':'y','\u00FF':'y','\u1EF7':'y','\u1E99':'y','\u1EF5':'y','\u01B4':'y','\u024F':'y','\u1EFF':'y','\u007A':'z','\u24E9':'z','\uFF5A':'z','\u017A':'z','\u1E91':'z','\u017C':'z','\u017E':'z','\u1E93':'z','\u1E95':'z','\u01B6':'z','\u0225':'z','\u0240':'z','\u2C6C':'z','\uA763':'z',};__exports.unaccent=unaccent;function unaccent(str,caseSensitive){str=str.replace(/[^\u0000-\u007E]/g,function(accented){return diacriticsMap[accented]||accented;});return caseSensitive?str:str.toLowerCase();} __exports.isEmail=isEmail;function isEmail(value){const re=/^(([^<>()\[\]\.,;:\s@\"]+(\.[^<>()\[\]\.,;:\s@\"]+)*)|(\".+\"))@(([^<>()[\]\.,;:\s@\"]+\.)+[^<>()[\]\.,;:\s@\"]{2,})$/i;return re.test(value);} __exports.isNumeric=isNumeric;function isNumeric(value){return Boolean(value?.match(/^\d+$/));} __exports.exprToBoolean=exprToBoolean;function exprToBoolean(str,trueIfEmpty=false){return str?!/^false|0$/i.test(str):trueIfEmpty;} return __exports;});; /* /web/static/src/core/utils/timing.js */ odoo.define('@web/core/utils/timing',['@web/core/browser/browser','@odoo/owl'],function(require){'use strict';let __exports={};const{browser}=require("@web/core/browser/browser");const{onWillUnmount,useComponent}=require("@odoo/owl");__exports.batched=batched;function batched(callback,synchronize=()=>Promise.resolve()){let scheduled=false;return async(...args)=>{if(!scheduled){scheduled=true;await synchronize();scheduled=false;callback(...args);}};} __exports.debounce=debounce;function debounce(func,delay,options){let handle;const funcName=func.name?func.name+" (debounce)":"debounce";const useAnimationFrame=delay==="animationFrame";const setFnName=useAnimationFrame?"requestAnimationFrame":"setTimeout";const clearFnName=useAnimationFrame?"cancelAnimationFrame":"clearTimeout";let lastArgs;let leading=false;let trailing=true;if(typeof options==="boolean"){leading=options;trailing=!options;}else if(options){leading=options.leading??leading;trailing=options.trailing??trailing;} return Object.assign({[funcName](...args){return new Promise((resolve)=>{if(leading&&!handle){Promise.resolve(func.apply(this,args)).then(resolve);}else{lastArgs=args;} browser[clearFnName](handle);handle=browser[setFnName](()=>{handle=null;if(trailing&&lastArgs){Promise.resolve(func.apply(this,lastArgs)).then(resolve);lastArgs=null;}},delay);});},}[funcName],{cancel(execNow=false){browser[clearFnName](handle);if(execNow&&lastArgs){func.apply(this,lastArgs);}},});} __exports.setRecurringAnimationFrame=setRecurringAnimationFrame;function setRecurringAnimationFrame(callback){const handler=(timestamp)=>{callback(timestamp-lastTimestamp);lastTimestamp=timestamp;handle=browser.requestAnimationFrame(handler);};const stop=()=>{browser.cancelAnimationFrame(handle);};let lastTimestamp=browser.performance.now();let handle=browser.requestAnimationFrame(handler);return stop;} __exports.throttleForAnimation=throttleForAnimation;function throttleForAnimation(func){let handle=null;const calls=new Set();const funcName=func.name?`${func.name} (throttleForAnimation)`:"throttleForAnimation";const pending=()=>{if(calls.size){handle=browser.requestAnimationFrame(pending);const{args,resolve}=[...calls].pop();calls.clear();Promise.resolve(func.apply(this,args)).then(resolve);}else{handle=null;}};return Object.assign({[funcName](...args){return new Promise((resolve)=>{const isNew=handle===null;if(isNew){handle=browser.requestAnimationFrame(pending);Promise.resolve(func.apply(this,args)).then(resolve);}else{calls.add({args,resolve});}});},}[funcName],{cancel(){browser.cancelAnimationFrame(handle);calls.clear();handle=null;},});} __exports.useDebounced=useDebounced;function useDebounced(callback,delay,{execBeforeUnmount=false,immediate=false}={}){const component=useComponent();const debounced=debounce(callback.bind(component),delay,immediate);onWillUnmount(()=>debounced.cancel(execBeforeUnmount));return debounced;} __exports.useThrottleForAnimation=useThrottleForAnimation;function useThrottleForAnimation(func){const component=useComponent();const throttledForAnimation=throttleForAnimation(func.bind(component));onWillUnmount(()=>throttledForAnimation.cancel());return throttledForAnimation;} return __exports;});; /* /web/static/src/core/utils/urls.js */ odoo.define('@web/core/utils/urls',['@web/session','@web/core/browser/browser','@web/core/utils/objects'],function(require){'use strict';let __exports={};const{session}=require("@web/session");const{browser}=require("@web/core/browser/browser");const{shallowEqual}=require("@web/core/utils/objects");const{DateTime}=luxon;const RedirectionError=__exports.RedirectionError=class RedirectionError extends Error{} __exports.objectToUrlEncodedString=objectToUrlEncodedString;function objectToUrlEncodedString(obj){return Object.entries(obj).map(([k,v])=>`${encodeURIComponent(k)}=${encodeURIComponent(v || "")}`).join("&");} __exports.getOrigin=getOrigin;function getOrigin(origin){if(origin){origin=origin.replace(/\/+$/,"");}else{const{host,protocol}=browser.location;origin=`${protocol}//${host}`;} return origin;} __exports.url=url;function url(route,queryParams,options={}){const origin=getOrigin(options.origin??session.origin);if(!route){return origin;} let queryString=objectToUrlEncodedString(queryParams||{});queryString=queryString.length>0?`?${queryString}`:queryString;let prefix=["http://","https://","//"].some((el)=>route.length>=el.length&&route.slice(0,el.length)===el);prefix=prefix?"":origin;return`${prefix}${route}${queryString}`;} __exports.imageUrl=imageUrl;function imageUrl(model,id,field,{access_token,filename,height,unique,width}={}){let route=`/web/image/${model}/${id}/${field}`;if(width&&height){route=`${route}/${width}x${height}`;} if(filename){route=`${route}/${filename}`;} const urlParams={};if(access_token){Object.assign(urlParams,{access_token});} if(unique){if(unique instanceof DateTime){urlParams.unique=unique.ts;}else{const dateTimeFromUnique=DateTime.fromSQL(unique);if(dateTimeFromUnique.isValid){urlParams.unique=dateTimeFromUnique.ts;}else if(typeof unique==="string"&&unique.length>0){urlParams.unique=unique;}}} return url(route,urlParams);} __exports.getDataURLFromFile=getDataURLFromFile;function getDataURLFromFile(file){if(!file){return Promise.reject();} return new Promise((resolve,reject)=>{const reader=new FileReader();reader.addEventListener("load",()=>{if(reader.result==="data:"){resolve(`data:${file.type};base64,`);}else{resolve(reader.result);}});reader.addEventListener("abort",reject);reader.addEventListener("error",reject);reader.readAsDataURL(file);});} __exports.redirect=redirect;function redirect(url){const{origin,pathname}=browser.location;const _url=new URL(url,`${origin}${pathname}`);if(_url.origin!==origin){throw new RedirectionError("Can't redirect to another origin");} browser.location.assign(_url.href);} __exports.compareUrls=compareUrls;function compareUrls(_url1,_url2){const url1=new URL(_url1);const url2=new URL(_url2);return(url1.origin===url2.origin&&url1.pathname===url2.pathname&&shallowEqual(Object.fromEntries(url1.searchParams),Object.fromEntries(url2.searchParams))&&url1.hash===url2.hash);} return __exports;});; /* /web/static/src/core/utils/xml.js */ odoo.define('@web/core/utils/xml',['@web/core/utils/arrays'],function(require){'use strict';let __exports={};const{isIterable}=require("@web/core/utils/arrays");const serializer=new XMLSerializer();const parser=new DOMParser();const xmlDocument=parser.parseFromString("","text/xml");function hasParsingError(parsedDocument){return parsedDocument.getElementsByTagName("parsererror").length>0;} __exports.parseXML=parseXML;function parseXML(str){const xml=parser.parseFromString(str,"text/xml");if(hasParsingError(xml)){throw new Error(`An error occured while parsing ${str}: ${xml.getElementsByTagName("parsererror")}`);} return xml.documentElement;} __exports.serializeXML=serializeXML;function serializeXML(xml){return serializer.serializeToString(xml);} __exports.visitXML=visitXML;function visitXML(xml,callback){const visit=(el)=>{if(el){let didVisitChildren=false;const visitChildren=()=>{for(const child of el.children){visit(child);} didVisitChildren=true;};const shouldVisitChildren=callback(el,visitChildren);if(shouldVisitChildren!==false&&!didVisitChildren){visitChildren();}}};const xmlDoc=typeof xml==="string"?parseXML(xml):xml;visit(xmlDoc);} __exports.append=append;function append(parent,node){const nodes=Array.isArray(node)?node:[node];parent.append(...nodes.filter(Boolean));return parent;} __exports.combineAttributes=combineAttributes;function combineAttributes(el,attr,parts,glue=" "){const allValues=[];if(el.hasAttribute(attr)){allValues.push(el.getAttribute(attr));} parts=Array.isArray(parts)?parts:[parts];parts=parts.filter((part)=>!!part);allValues.push(...parts);el.setAttribute(attr,allValues.join(glue));} __exports.createElement=createElement;function createElement(tagName,...args){const el=xmlDocument.createElement(tagName);for(const arg of args){if(!arg){continue;} if(isIterable(arg)){el.append(...arg);}else if(typeof arg==="object"){for(const name in arg){el.setAttribute(name,arg[name]);}}} return el;} __exports.createTextNode=createTextNode;function createTextNode(data){return xmlDocument.createTextNode(data);} __exports.extractAttributes=extractAttributes;function extractAttributes(el,attributes){const attrs=Object.create(null);for(const attr of attributes){attrs[attr]=el.getAttribute(attr)||"";el.removeAttribute(attr);} return attrs;} __exports.getTag=getTag;function getTag(node,lower=false){const tag=(node&&node.nodeName)||"";return lower?tag.toLowerCase():tag;} __exports.setAttributes=setAttributes;function setAttributes(node,attributes){for(const[name,value]of Object.entries(attributes)){node.setAttribute(name,value);}} return __exports;});; /* /web/static/src/core/virtual_grid_hook.js */ odoo.define('@web/core/virtual_grid_hook',['@odoo/owl','@web/core/utils/objects','@web/core/utils/timing'],function(require){'use strict';let __exports={};const{useComponent,useEffect,useExternalListener}=require("@odoo/owl");const{pick,shallowEqual}=require("@web/core/utils/objects");const{useThrottleForAnimation}=require("@web/core/utils/timing");const BUFFER_COEFFICIENT=1;function getIndexes({sizes,start,span,prevStartIndex,bufferCoef=BUFFER_COEFFICIENT}){if(!sizes||!sizes.length){return[];} if(sizes.at(-1)0&&sizes[startIndex]>bufferStart){startIndex--;} while(startIndexstartIndex&&(sizes[endIndex-1]??0)>=bufferEnd){endIndex--;} return[startIndex,endIndex];} __exports.useVirtualGrid=useVirtualGrid;function useVirtualGrid({scrollableRef,initialScroll,onChange,bufferCoef}){const comp=useComponent();onChange||=()=>comp.render();const current={scroll:{left:0,top:0,...initialScroll}};const computeColumnsIndexes=()=>{return getIndexes({sizes:current.summedColumnsWidths,start:Math.abs(current.scroll.left),span:window.innerWidth,prevStartIndex:current.columnsIndexes?.[0],bufferCoef,});};const computeRowsIndexes=()=>{return getIndexes({sizes:current.summedRowsHeights,start:current.scroll.top,span:window.innerHeight,prevStartIndex:current.rowsIndexes?.[0],bufferCoef,});};const throttledCompute=useThrottleForAnimation(()=>{const changed=[];const columnsVisibleIndexes=computeColumnsIndexes();if(!shallowEqual(columnsVisibleIndexes,current.columnsIndexes)){current.columnsIndexes=columnsVisibleIndexes;changed.push("columnsIndexes");} const rowsVisibleIndexes=computeRowsIndexes();if(!shallowEqual(rowsVisibleIndexes,current.rowsIndexes)){current.rowsIndexes=rowsVisibleIndexes;changed.push("rowsIndexes");} if(changed.length){onChange(pick(current,...changed));}});const scrollListener=(ev)=>{current.scroll.left=ev.target.scrollLeft;current.scroll.top=ev.target.scrollTop;throttledCompute();};useEffect((el)=>{el?.addEventListener("scroll",scrollListener);return()=>el?.removeEventListener("scroll",scrollListener);},()=>[scrollableRef.el]);useExternalListener(window,"resize",()=>throttledCompute());return{get columnsIndexes(){return current.columnsIndexes;},get rowsIndexes(){return current.rowsIndexes;},setColumnsWidths(widths){let acc=0;current.summedColumnsWidths=widths.map((w)=>(acc+=w));delete current.columnsIndexes;current.columnsIndexes=computeColumnsIndexes();},setRowsHeights(heights){let acc=0;current.summedRowsHeights=heights.map((h)=>(acc+=h));delete current.rowsIndexes;current.rowsIndexes=computeRowsIndexes();},};} return __exports;});; /* /web/static/src/core/commands/default_providers.js */ odoo.define('@web/core/commands/default_providers',['@web/core/browser/feature_detection','@web/core/hotkeys/hotkey_hook','@web/core/l10n/translation','@web/core/registry','@web/core/utils/strings','@web/core/utils/ui','@web/core/commands/command_palette','@odoo/owl'],function(require){'use strict';let __exports={};const{isMacOS}=require("@web/core/browser/feature_detection");const{useHotkey}=require("@web/core/hotkeys/hotkey_hook");const{_t}=require("@web/core/l10n/translation");const{registry}=require("@web/core/registry");const{capitalize}=require("@web/core/utils/strings");const{getVisibleElements}=require("@web/core/utils/ui");const{DefaultCommandItem}=require("@web/core/commands/command_palette");const{Component}=require("@odoo/owl");const commandSetupRegistry=registry.category("command_setup");commandSetupRegistry.add("default",{emptyMessage:_t("No command found"),placeholder:_t("Search for a command..."),});const HotkeyCommandItem=__exports.HotkeyCommandItem=class HotkeyCommandItem extends Component{static template="web.HotkeyCommandItem";static props=["hotkey","hotkeyOptions?","name?","searchValue?","executeCommand","slots"];setup(){useHotkey(this.props.hotkey,this.props.executeCommand);} getKeysToPress(command){const{hotkey}=command;let result=hotkey.split("+");if(isMacOS()){result=result.map((x)=>x.replace("control","command")).map((x)=>x.replace("alt","control"));} return result.map((key)=>key.toUpperCase());}} const commandCategoryRegistry=registry.category("command_categories");const commandProviderRegistry=registry.category("command_provider");commandProviderRegistry.add("command",{provide:(env,options={})=>{const commands=env.services.command.getCommands(options.activeElement).map((cmd)=>{cmd.category=commandCategoryRegistry.contains(cmd.category)?cmd.category:"default";return cmd;}).filter((command)=>command.isAvailable===undefined||command.isAvailable());const uniqueCommands=commands.filter((obj,index)=>{return(index===commands.findIndex((o)=>obj.name===o.name&&obj.category===o.category));});return uniqueCommands.map((command)=>({Component:command.hotkey?HotkeyCommandItem:DefaultCommandItem,action:command.action,category:command.category,name:command.name,props:{hotkey:command.hotkey,hotkeyOptions:command.hotkeyOptions,},}));},});commandProviderRegistry.add("data-hotkeys",{provide:(env,options={})=>{const commands=[];const overlayModifier=registry.category("services").get("hotkey").overlayModifier;for(const el of getVisibleElements(options.activeElement,"[data-hotkey]:not(:disabled)")){const closest=el.closest("[data-command-category]");const category=closest?closest.dataset.commandCategory:"default";if(category==="disabled"){continue;} const description=el.title||el.dataset.bsOriginalTitle||el.dataset.tooltip||el.placeholder||(el.innerText&&`${el.innerText.slice(0, 50)}${el.innerText.length > 50 ? "..." : ""}`)||_t("no description provided");commands.push({Component:HotkeyCommandItem,action:()=>{el.focus();el.click();},category,name:capitalize(description.trim().toLowerCase()),props:{hotkey:`${overlayModifier}+${el.dataset.hotkey}`,},});} return commands;},});return __exports;});; /* /web/static/src/core/commands/command_palette.js */ odoo.define('@web/core/commands/command_palette',['@web/core/dialog/dialog','@web/core/hotkeys/hotkey_hook','@web/core/l10n/translation','@web/core/utils/concurrency','@web/core/utils/hooks','@web/core/utils/scrolling','@web/core/utils/search','@web/core/utils/timing','@web/core/browser/feature_detection','@web/core/utils/strings','@odoo/owl'],function(require){'use strict';let __exports={};const{Dialog}=require("@web/core/dialog/dialog");const{useHotkey}=require("@web/core/hotkeys/hotkey_hook");const{_t}=require("@web/core/l10n/translation");const{KeepLast,Race}=require("@web/core/utils/concurrency");const{useAutofocus,useService}=require("@web/core/utils/hooks");const{scrollTo}=require("@web/core/utils/scrolling");const{fuzzyLookup}=require("@web/core/utils/search");const{debounce}=require("@web/core/utils/timing");const{isMacOS,isMobileOS}=require("@web/core/browser/feature_detection");const{escapeRegExp}=require("@web/core/utils/strings");const{Component,onWillStart,onWillDestroy,EventBus,useRef,useState,markRaw,useExternalListener,}=require("@odoo/owl");const DEFAULT_PLACEHOLDER=_t("Search...");const DEFAULT_EMPTY_MESSAGE=_t("No result found");const FUZZY_NAMESPACES=["default"];function commandsWithinCategory(categoryName,categories){return(cmd)=>{const inCurrentCategory=categoryName===cmd.category;const fallbackCategory=categoryName==="default"&&!categories.includes(cmd.category);return inCurrentCategory||fallbackCategory;};} __exports.splitCommandName=splitCommandName;function splitCommandName(name,searchValue){if(name){const splitName=name.split(new RegExp(`(${escapeRegExp(searchValue)})`,"ig"));return searchValue.length&&splitName.length>1?splitName:[name];} return[];} const DefaultCommandItem=__exports.DefaultCommandItem=class DefaultCommandItem extends Component{static template="web.DefaultCommandItem";static props={slots:{type:Object,optional:true},hotkey:{type:String,optional:true},hotkeyOptions:{type:String,optional:true},name:{type:String,optional:true},searchValue:{type:String,optional:true},executeCommand:{type:Function,optional:true},};} const CommandPalette=__exports.CommandPalette=class CommandPalette extends Component{static template="web.CommandPalette";static components={Dialog};static lastSessionId=0;static props={bus:{type:EventBus,optional:true},close:Function,config:Object,closeMe:{type:Function,optional:true},};setup(){if(this.props.bus){const setConfig=({detail})=>this.setCommandPaletteConfig(detail);this.props.bus.addEventListener(`SET-CONFIG`,setConfig);onWillDestroy(()=>this.props.bus.removeEventListener(`SET-CONFIG`,setConfig));} this.keyId=1;this.race=new Race();this.keepLast=new KeepLast();this._sessionId=CommandPalette.lastSessionId++;this.DefaultCommandItem=DefaultCommandItem;this.activeElement=useService("ui").activeElement;this.inputRef=useAutofocus();useHotkey("Enter",()=>this.executeSelectedCommand(),{bypassEditableProtection:true});useHotkey("Control+Enter",()=>this.executeSelectedCommand(true),{bypassEditableProtection:true,});useHotkey("ArrowUp",()=>this.selectCommandAndScrollTo("PREV"),{bypassEditableProtection:true,allowRepeat:true,});useHotkey("ArrowDown",()=>this.selectCommandAndScrollTo("NEXT"),{bypassEditableProtection:true,allowRepeat:true,});useExternalListener(window,"mousedown",this.onWindowMouseDown);this.state=useState({});this.root=useRef("root");this.listboxRef=useRef("listbox");onWillStart(()=>this.setCommandPaletteConfig(this.props.config));} get commandsByCategory(){const categories=[];for(const category of this.categoryKeys){const commands=this.state.commands.filter(commandsWithinCategory(category,this.categoryKeys));if(commands.length){categories.push({commands,name:this.categoryNames[category],keyId:category,});}} return categories;} async setCommandPaletteConfig(config){this.configByNamespace=config.configByNamespace||{};this.state.FooterComponent=config.FooterComponent;this.providersByNamespace={default:[]};for(const provider of config.providers){const namespace=provider.namespace||"default";if(namespace in this.providersByNamespace){this.providersByNamespace[namespace].push(provider);}else{this.providersByNamespace[namespace]=[provider];}} const{namespace,searchValue}=this.processSearchValue(config.searchValue||"");this.switchNamespace(namespace);this.state.searchValue=searchValue;await this.race.add(this.search(searchValue));} async setCommands(namespace,options={}){this.categoryKeys=["default"];this.categoryNames={};const proms=this.providersByNamespace[namespace].map((provider)=>{const{provide}=provider;const result=provide(this.env,options);return result;});let commands=(await this.keepLast.add(Promise.all(proms))).flat();const namespaceConfig=this.configByNamespace[namespace]||{};if(options.searchValue&&FUZZY_NAMESPACES.includes(namespace)){commands=fuzzyLookup(options.searchValue,commands,(c)=>c.name);}else{if(namespaceConfig.categories){let commandsSorted=[];this.categoryKeys=namespaceConfig.categories;this.categoryNames=namespaceConfig.categoryNames||{};if(!this.categoryKeys.includes("default")){this.categoryKeys.push("default");} for(const category of this.categoryKeys){commandsSorted=commandsSorted.concat(commands.filter(commandsWithinCategory(category,this.categoryKeys)));} commands=commandsSorted;}} this.state.commands=markRaw(commands.slice(0,100).map((command)=>({...command,keyId:this.keyId++,splitName:splitCommandName(command.name,options.searchValue),})));this.selectCommand(this.state.commands.length?0:-1);this.mouseSelectionActive=false;this.state.emptyMessage=(namespaceConfig.emptyMessage||DEFAULT_EMPTY_MESSAGE).toString();} selectCommand(index){if(index===-1||index>=this.state.commands.length){this.state.selectedCommand=null;return;} this.state.selectedCommand=markRaw(this.state.commands[index]);} selectCommandAndScrollTo(type){this.mouseSelectionActive=false;const index=this.state.commands.indexOf(this.state.selectedCommand);if(index===-1){return;} let nextIndex;if(type==="NEXT"){nextIndex=index0?index-1:this.state.commands.length-1;} this.selectCommand(nextIndex);const command=this.listboxRef.el.querySelector(`#o_command_${nextIndex}`);scrollTo(command,{scrollable:this.listboxRef.el});} onCommandClicked(event,index){event.preventDefault();this.selectCommand(index);const ctrlKey=isMacOS()?event.metaKey:event.ctrlKey;this.executeSelectedCommand(ctrlKey);} async executeCommand(command){const config=await command.action();if(config){this.setCommandPaletteConfig(config);}else{this.props.close();}} async executeSelectedCommand(ctrlKey){await this.searchValuePromise;const selectedCommand=this.state.selectedCommand;if(selectedCommand){if(!ctrlKey){this.executeCommand(selectedCommand);}else if(selectedCommand.href){window.open(selectedCommand.href,"_blank");}}} onCommandMouseEnter(index){if(this.mouseSelectionActive){this.selectCommand(index);}else{this.mouseSelectionActive=true;}} async search(searchValue){this.state.isLoading=true;try{await this.setCommands(this.state.namespace,{searchValue,activeElement:this.activeElement,sessionId:this._sessionId,});}finally{this.state.isLoading=false;} if(this.inputRef.el){this.inputRef.el.focus();}} debounceSearch(value){const{namespace,searchValue}=this.processSearchValue(value);if(namespace!=="default"&&this.state.namespace!==namespace){this.switchNamespace(namespace);} this.state.searchValue=searchValue;this.searchValuePromise=this.lastDebounceSearch(searchValue).catch(()=>{this.searchValuePromise=null;});} onSearchInput(ev){this.debounceSearch(ev.target.value);} onKeyDown(ev){if(ev.key.toLowerCase()==="backspace"&&!ev.target.value.length&&!ev.repeat){this.switchNamespace("default");this.state.searchValue="";this.searchValuePromise=this.lastDebounceSearch("").catch(()=>{this.searchValuePromise=null;});}} onWindowMouseDown(ev){if(!this.root.el.contains(ev.target)){this.props.close();}} switchNamespace(namespace){if(this.lastDebounceSearch){this.lastDebounceSearch.cancel();} const namespaceConfig=this.configByNamespace[namespace]||{};this.lastDebounceSearch=debounce((value)=>this.search(value),namespaceConfig.debounceDelay||0);this.state.namespace=namespace;this.state.placeholder=namespaceConfig.placeholder||DEFAULT_PLACEHOLDER.toString();} processSearchValue(searchValue){let namespace="default";if(searchValue.length&&this.providersByNamespace[searchValue[0]]){namespace=searchValue[0];searchValue=searchValue.slice(1);} return{namespace,searchValue};} get isMacOS(){return isMacOS();} get isMobileOS(){return isMobileOS();}} return __exports;});; /* /web/static/src/public/error_notifications.js */ odoo.define('@web/public/error_notifications',['@web/core/registry','@web/core/errors/error_dialogs','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{odooExceptionTitleMap}=require("@web/core/errors/error_dialogs");const{_t}=require("@web/core/l10n/translation");odooExceptionTitleMap.forEach((title,exceptionName)=>{registry.category("error_notifications").add(exceptionName,{title:title,type:"warning",sticky:true,});});const sessionExpired={title:_t("Odoo Session Expired"),message:_t("Your Odoo session expired. The current page is about to be refreshed."),buttons:[{text:_t("Ok"),click:()=>window.location.reload(true),close:true,},],};registry.category("error_notifications").add("odoo.http.SessionExpiredException",sessionExpired).add("werkzeug.exceptions.Forbidden",sessionExpired).add("504",{title:_t("Request timeout"),message:_t("The operation was interrupted. This usually means that the current operation is taking too much time."),});return __exports;});; /* /web/static/src/public/public_component_service.js */ odoo.define('@web/public/public_component_service',['@odoo/owl','@web/core/registry','@web/core/templates','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{App}=require("@odoo/owl");const{registry}=require("@web/core/registry");const{getTemplate}=require("@web/core/templates");const{_t}=require("@web/core/l10n/translation");class ComponentManager{constructor(env){this.env=env;this.appConfig={getTemplate,env:env,dev:env.debug,translateFn:_t,translatableAttributes:["data-tooltip"],};this.apps=new Map();} async mountComponents(){for(const[key,component]of registry.category("public_components").getEntries()){for(const el of document.querySelectorAll(`owl-component[name="${CSS.escape(key)}"]`)){if(!this.apps.has(el)){const props=JSON.parse(el.getAttribute("props")||"{}");const app=new App(component,{...this.appConfig,props,});this.apps.set(el,{app,mountProm:app.mount(el)});}}} await Promise.all([...this.apps.values()].map(({mountProm})=>mountProm));} destroyComponents(){for(const{app}of this.apps.values()){app.destroy();} this.apps.clear();}} const publicComponentService=__exports.publicComponentService={start(env){return new ComponentManager(env);},};registry.category("services").add("public_component",publicComponentService);return __exports;});; /* /web/static/src/public/datetime_picker_widget.js */ odoo.define('@web/public/datetime_picker_widget',['@web/core/l10n/dates','@web/legacy/js/public/public_widget'],function(require){'use strict';let __exports={};const{deserializeDate,deserializeDateTime,parseDate,parseDateTime,}=require("@web/core/l10n/dates");const PublicWidget=require("@web/legacy/js/public/public_widget")[Symbol.for("default")];const DateTimePickerWidget=__exports.DateTimePickerWidget=PublicWidget.Widget.extend({selector:"[data-widget='datetime-picker']",disabledInEditableMode:true,start(){this._super(...arguments);const{widgetType,minDate,maxDate}=this.el.dataset;const type=widgetType||"datetime";const{value}=this.el;const[parse,deserialize]=type==="date"?[parseDate,deserializeDate]:[parseDateTime,deserializeDateTime];this.disableDateTimePicker=this.call("datetime_picker","create",{target:this.el,pickerProps:{type,minDate:minDate&&deserialize(minDate),maxDate:maxDate&&deserialize(maxDate),value:parse(value),},}).enable();},destroy(){this.disableDateTimePicker();return this._super(...arguments);},});PublicWidget.registry.DateTimePickerWidget=DateTimePickerWidget;return __exports;});; /* /web/static/src/libs/pdfjs.js */ odoo.define('@web/libs/pdfjs',['@web/core/browser/feature_detection','@web/core/assets'],function(require){'use strict';let __exports={};const{isMobileOS}=require("@web/core/browser/feature_detection");const{loadJS}=require("@web/core/assets");__exports.hidePDFJSButtons=hidePDFJSButtons;function hidePDFJSButtons(rootElement){const cssStyle=document.createElement("style");cssStyle.rel="stylesheet";cssStyle.textContent=`button#secondaryOpenFile.secondaryToolbarButton, button#openFile.toolbarButton, button#editorFreeText.toolbarButton, button#editorInk.toolbarButton, button#editorStamp.toolbarButton, button#secondaryOpenFile.secondaryToolbarButton, a#secondaryViewBookmark.secondaryToolbarButton, a#viewBookmark.toolbarButton { display: none !important; }`;if(isMobileOS()){cssStyle.textContent=`${cssStyle.innerHTML} button#secondaryDownload.secondaryToolbarButton, button#download.toolbarButton, button#editorFreeText.toolbarButton, button#editorInk.toolbarButton, button#editorStamp.toolbarButton, button#secondaryPrint.secondaryToolbarButton, button#print.toolbarButton{ display: none !important; }`;} const iframe=rootElement.tagName==="IFRAME"?rootElement:rootElement.querySelector("iframe");if(iframe){if(!iframe.dataset.hideButtons){iframe.dataset.hideButtons="true";iframe.addEventListener("load",(event)=>{if(iframe.contentDocument&&iframe.contentDocument.head){iframe.contentDocument.head.appendChild(cssStyle);}});}}else{console.warn("No IFRAME found");}} __exports.loadPDFJSAssets=loadPDFJSAssets;async function loadPDFJSAssets(){return Promise.all([loadJS("/web/static/lib/pdfjs/build/pdf.js"),loadJS("/web/static/lib/pdfjs/build/pdf.worker.js"),]);} return __exports;});; /* /web/static/src/legacy/js/public/public_root.js */ odoo.define('@web/legacy/js/public/public_root',['@web/core/browser/cookie','@web/legacy/js/public/public_widget','@web/legacy/js/public/lazyloader','@web/env','@web/core/templates','@web/core/main_components_container','@web/core/browser/browser','@web/core/l10n/translation','@web/core/l10n/utils','@odoo/owl','@web/core/network/rpc'],function(require){'use strict';let __exports={};const{cookie}=require("@web/core/browser/cookie");const publicWidget=require('@web/legacy/js/public/public_widget')[Symbol.for("default")];const lazyloader=require("@web/legacy/js/public/lazyloader")[Symbol.for("default")];const{makeEnv,startServices}=require("@web/env");const{getTemplate}=require('@web/core/templates');const{MainComponentsContainer}=require("@web/core/main_components_container");const{browser}=require('@web/core/browser/browser');const{_t}=require("@web/core/l10n/translation");const{jsToPyLocale,pyToJsLocale}=require("@web/core/l10n/utils");const{App,Component,whenReady}=require("@odoo/owl");const{RPCError}=require('@web/core/network/rpc');const{Settings}=luxon;function getLang(){var html=document.documentElement;return jsToPyLocale(html.getAttribute('lang'))||'en_US';} const lang=cookie.get('frontend_lang')||getLang();const PublicRoot=__exports.PublicRoot=publicWidget.Widget.extend({events:{'submit .js_website_submit_form':'_onWebsiteFormSubmit','click .js_disable_on_click':'_onDisableOnClick',},custom_events:{call_service:'_onCallService',context_get:'_onContextGet',main_object_request:'_onMainObjectRequest',widgets_start_request:'_onWidgetsStartRequest',widgets_stop_request:'_onWidgetsStopRequest',},init:function(_,env){this._super.apply(this,arguments);this.env=env;this.publicWidgets=[];},start:function(){var defs=[this._super.apply(this,arguments),this._startWidgets()];this.$(".o_image[data-mimetype^='image']").each(function(){var $img=$(this);if(/gif|jpe|jpg|png|webp/.test($img.data('mimetype'))&&$img.data('src')){$img.css('background-image',"url('"+$img.data('src')+"')");}});if(window.location.hash.indexOf("scrollTop=")>-1){this.el.scrollTop=+window.location.hash.match(/scrollTop=([0-9]+)/)[1];} return Promise.all(defs);},_getContext:function(context){return Object.assign({'lang':getLang(),},context||{});},_getExtraContext:function(context){return this._getContext(context);},_getPublicWidgetsRegistry:function(options){return publicWidget.registry;},_startWidgets:function($from,options){var self=this;if($from===undefined){$from=this.$('#wrapwrap');if(!$from.length){$from=this.$el;}} options=Object.assign({},options,{wysiwyg:$('#wrapwrap').data('wysiwyg'),});this._stopWidgets($from);var defs=Object.values(this._getPublicWidgetsRegistry(options)).map((PublicWidget)=>{const selector=PublicWidget.prototype.selector;if(!selector){return;} const selectorHas=PublicWidget.prototype.selectorHas;const selectorFunc=typeof selector==='function'?selector:fromEl=>{const els=[...fromEl.querySelectorAll(selector)];if(fromEl.matches(selector)){els.push(fromEl);} return els;};let targetEls=[];for(const fromEl of $from){targetEls.push(...selectorFunc(fromEl));} if(selectorHas){targetEls=targetEls.filter(el=>!!el.querySelector(selectorHas));} const proms=targetEls.map(el=>{var widget=new PublicWidget(self,options);self.publicWidgets.push(widget);return widget.attachTo(el);});return Promise.all(proms);});return Promise.all(defs);},_stopWidgets:function($from){var removedWidgets=this.publicWidgets.map((widget)=>{if(!$from||$from.filter(widget.el).length||$from.find(widget.el).length){widget.destroy();return widget;} return null;});this.publicWidgets=this.publicWidgets.filter((x)=>removedWidgets.indexOf(x)<0);},_onCallService:function(ev){const payload=ev.data;const service=this.env.services[payload.service];const result=service[payload.method].apply(service,payload.args||[]);payload.callback(result);ev.stopPropagation();},_onContextGet:function(ev){if(ev.data.extra){ev.data.callback(this._getExtraContext(ev.data.context));}else{ev.data.callback(this._getContext(ev.data.context));}},_onMainObjectRequest:function(ev){var repr=$('html').data('main-object');var m=repr.match(/(.+)\((\d+),(.*)\)/);ev.data.callback({model:m[1],id:m[2]|0,});},_onWidgetsStartRequest:function(ev){this._startWidgets(ev.data.$target,ev.data.options).then(ev.data.onSuccess).catch((e)=>{if(ev.data.onFailure){ev.data.onFailure(e);} if(!(e instanceof RPCError)){return Promise.reject(e);}});},_onWidgetsStopRequest:function(ev){this._stopWidgets(ev.data.$target);},_onWebsiteFormSubmit:function(ev){var $buttons=$(ev.currentTarget).find('button[type="submit"], a.a-submit').toArray();$buttons.forEach((btn)=>{var $btn=$(btn);$btn.prepend(' ');$btn.prop('disabled',true);});},_onDisableOnClick:function(ev){$(ev.currentTarget).addClass('disabled');},_onDateTimePickerError:function(ev){return false;},});__exports.createPublicRoot=createPublicRoot;async function createPublicRoot(RootWidget){await lazyloader.allScriptsLoaded;await whenReady();const env=makeEnv();await startServices(env);Component.env=env;await env.services.public_component.mountComponents();const publicRoot=new RootWidget(null,env);const app=new App(MainComponentsContainer,{getTemplate,env,dev:env.debug,translateFn:_t,translatableAttributes:["data-tooltip"],});const locale=pyToJsLocale(lang)||browser.navigator.language;Settings.defaultLocale=locale;const[root]=await Promise.all([app.mount(document.body),publicRoot.attachTo(document.body),]);odoo.__WOWL_DEBUG__={root};return publicRoot;} __exports[Symbol.for("default")]={PublicRoot,createPublicRoot};return __exports;});; /* /website/static/src/js/content/website_root_instance.js */ odoo.define('@website/js/content/website_root_instance',['@web/legacy/js/public/public_root','@web/legacy/js/public/lazyloader','@website/js/content/website_root','@web/core/assets'],function(require){'use strict';let __exports={};const{createPublicRoot}=require("@web/legacy/js/public/public_root");const lazyloader=require("@web/legacy/js/public/lazyloader")[Symbol.for("default")];const{WebsiteRoot}=require("@website/js/content/website_root");const{loadBundle}=require("@web/core/assets");const prom=createPublicRoot(WebsiteRoot).then(async rootInstance=>{if(window.frameElement&&window.frameElement.dataset.loadWysiwyg==='true'){await loadBundle("website.assets_all_wysiwyg");window.dispatchEvent(new CustomEvent('PUBLIC-ROOT-READY',{detail:{rootInstance}}));} return rootInstance;});lazyloader.registerPageReadinessDelay(prom);__exports[Symbol.for("default")]=prom;return __exports;});odoo.define(`root.widget`,['@website/js/content/website_root_instance'],function(require){return require('@website/js/content/website_root_instance')[Symbol.for("default")];});; /* /web/static/src/legacy/js/public/public_widget.js */ odoo.define('@web/legacy/js/public/public_widget',['@odoo/owl','@web/legacy/js/core/class','@web/core/assets','@web/core/utils/hooks','@web/core/utils/render','@web/legacy/js/public/minimal_dom'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const Class=require("@web/legacy/js/core/class")[Symbol.for("default")];const{loadBundle,loadCSS,loadJS}=require('@web/core/assets');const{SERVICES_METADATA}=require("@web/core/utils/hooks");const{renderToElement}=require("@web/core/utils/render");const{makeAsyncHandler,makeButtonHandler}=require("@web/legacy/js/public/minimal_dom");const ParentedMixin={__parentedMixin:true,init:function(){this.__parentedDestroyed=false;this.__parentedChildren=[];this.__parentedParent=null;},setParent(parent){if(this.getParent()){if(this.getParent().__parentedMixin){const children=this.getParent().getChildren();this.getParent().__parentedChildren=children.filter((child)=>child.$el!==this.$el);}} this.__parentedParent=parent;if(parent&&parent.__parentedMixin){parent.__parentedChildren.push(this);}},getParent(){return this.__parentedParent;},getChildren(){return[...this.__parentedChildren];},isDestroyed(){return this.__parentedDestroyed;},destroy(){this.getChildren().forEach(function(child){child.destroy();});this.setParent(undefined);this.__parentedDestroyed=true;},};function OdooEvent(target,name,data){this.target=target;this.name=name;this.data=Object.create(null);Object.assign(this.data,data);this.stopped=false;} OdooEvent.prototype.stopPropagation=function(){this.stopped=true;};OdooEvent.prototype.is_stopped=function(){return this.stopped;};class Events{on(events,callback,context){var ev;events=events.split(/\s+/);var calls=this._callbacks||(this._callbacks={});while((ev=events.shift())){var list=calls[ev]||(calls[ev]={});var tail=list.tail||(list.tail=list.next={});tail.callback=callback;tail.context=context;list.tail=tail.next={};} return this;} off(events,callback,context){var ev,calls,node;if(!events){delete this._callbacks;}else if((calls=this._callbacks)){events=events.split(/\s+/);while((ev=events.shift())){node=calls[ev];delete calls[ev];if(!callback||!node){continue;} while((node=node.next)&&node.next){if(node.callback===callback&&(!context||node.context===context)){continue;} this.on(ev,node.callback,node.context);}}} return this;} callbackList(){var lst=[];for(const[eventName,el]of Object.entries(this._callbacks||{})){var node=el;while((node=node.next)&&node.next){lst.push([eventName,node.callback,node.context]);}} return lst;} trigger(events){var event,node,calls,tail,args,all,rest;if(!(calls=this._callbacks)){return this;} all=calls.all;(events=events.split(/\s+/)).push(null);while((event=events.shift())){if(all){events.push({next:all.next,tail:all.tail,event:event});} if(!(node=calls[event])){continue;} events.push({next:node.next,tail:node.tail});} rest=Array.prototype.slice.call(arguments,1);while((node=events.pop())){tail=node.tail;args=node.event?[node.event].concat(rest):rest;while((node=node.next)!==tail){node.callback.apply(node.context||this,args);}} return this;}} const EventDispatcherMixin=Object.assign({},ParentedMixin,{__eventDispatcherMixin:true,"custom_events":{},init(){ParentedMixin.init.call(this);this.__edispatcherEvents=new Events();this.__edispatcherRegisteredEvents=[];this._delegateCustomEvents();},proxy(method){var self=this;return function(){var fn=(typeof method==='string')?self[method]:method;if(fn===void 0){throw new Error("Couldn't find method '"+method+"' in widget "+self);} return fn.apply(self,arguments);};},_delegateCustomEvents(){if(Object.keys(this.custom_events||{}).length===0){return;} for(var key in this.custom_events){if(!Object.prototype.hasOwnProperty.call(this.custom_events,key)){continue;} var method=this.proxy(this.custom_events[key]);this.on(key,this,method);}},on(events,dest,func){var self=this;if(typeof func!=="function"){throw new Error("Event handler must be a function.");} events=events.split(/\s+/);events.forEach((eventName)=>{self.__edispatcherEvents.on(eventName,func,dest);if(dest&&dest.__eventDispatcherMixin){dest.__edispatcherRegisteredEvents.push({name:eventName,func:func,source:self});}});return this;},off(events,dest,func){var self=this;events=events.split(/\s+/);events.forEach((eventName)=>{self.__edispatcherEvents.off(eventName,func,dest);if(dest&&dest.__eventDispatcherMixin){dest.__edispatcherRegisteredEvents=dest.__edispatcherRegisteredEvents.filter(el=>{return!(el.name===eventName&&el.func===func&&el.source===self);});}});return this;},trigger(){this.__edispatcherEvents.trigger.apply(this.__edispatcherEvents,arguments);return this;},"trigger_up":function(name,info){var event=new OdooEvent(this,name,info);this._trigger_up(event);return event;},"_trigger_up":function(event){var parent;this.__edispatcherEvents.trigger(event.name,event);if(!event.is_stopped()&&(parent=this.getParent())){parent._trigger_up(event);}},destroy(){var self=this;this.__edispatcherRegisteredEvents.forEach((event)=>{event.source.__edispatcherEvents.off(event.name,event.func,self);});this.__edispatcherRegisteredEvents=[];this.__edispatcherEvents.callbackList().forEach(((cal)=>{this.off(cal[0],cal[2],cal[1]);}).bind(this));this.__edispatcherEvents.off();ParentedMixin.destroy.call(this);},});function protectMethod(widget,fn){return function(...args){return new Promise((resolve,reject)=>{Promise.resolve(fn.call(this,...args)).then((result)=>{if(!widget.isDestroyed()){resolve(result);}}).catch((reason)=>{if(!widget.isDestroyed()){reject(reason);}});});};} const ServicesMixin={bindService:function(serviceName){const{services}=Component.env;const service=services[serviceName];if(!service){throw new Error(`Service ${serviceName} is not available`);} if(serviceName in SERVICES_METADATA){if(service instanceof Function){return protectMethod(this,service);}else{const methods=SERVICES_METADATA[serviceName];const result=Object.create(service);for(const method of methods){result[method]=protectMethod(this,service[method]);} return result;}} return service;},call:function(service,method){var args=Array.prototype.slice.call(arguments,2);var result;this.trigger_up('call_service',{service:service,method:method,args:args,callback:function(r){result=r;},});return result;},};const PublicWidget=__exports.PublicWidget=Class.extend(EventDispatcherMixin,ServicesMixin,{tagName:'div',id:null,className:null,attributes:{},template:null,cssLibs:null,jsLibs:null,assetLibs:null,selector:false,selectorHas:false,events:{},init:function(parent,options){EventDispatcherMixin.init.call(this);this.setParent(parent);this.options=options||{};},willStart:function(){var proms=[];if(this.jsLibs||this.cssLibs||this.assetLibs){var assetsPromise=Promise.all([...(this.cssLibs||[]).map(loadCSS),...(this.jsLibs||[]).map(loadJS),]);for(const bundleName of this.assetLibs||[]){if(typeof bundleName==="string"){assetsPromise=assetsPromise.then(()=>{return loadBundle(bundleName);});}else{assetsPromise=assetsPromise.then(()=>{return Promise.all([...bundleName.map(loadBundle)]);});}} proms.push(assetsPromise);} return Promise.all(proms);},start:function(){return Promise.resolve();},destroy:function(){EventDispatcherMixin.destroy.call(this);if(this.$el){this._undelegateEvents();if(!this.selector){this.$el.remove();}}},appendTo:function(target){var self=this;return this._widgetRenderAndInsert(function(t){self.$el.appendTo(t);},target);},attachTo:function(target){var self=this;this.setElement(target.$el||target);return this.willStart().then(function(){if(self.__parentedDestroyed){return;} return self.start();});},insertAfter:function(target){var self=this;return this._widgetRenderAndInsert(function(t){self.$el.insertAfter(t);},target);},insertBefore:function(target){var self=this;return this._widgetRenderAndInsert(function(t){self.$el.insertBefore(t);},target);},prependTo:function(target){var self=this;return this._widgetRenderAndInsert(function(t){self.$el.prependTo(t);},target);},renderElement:function(){var $el;if(this.template){$el=$(renderToElement(this.template,{widget:this}));}else{$el=this._makeDescriptive();} this._replaceElement($el);},replace:function(target){return this._widgetRenderAndInsert((t)=>{this.$el.replaceAll(t);},target);},setElement:function(element){if(this.$el){this._undelegateEvents();} this.$el=(element instanceof $)?element:$(element);this.el=this.$el[0];this._delegateEvents();if(this.selector){this.$target=this.$el;this.target=this.el;} return this;},$:function(selector){if(selector===undefined){return this.$el;} return this.$el.find(selector);},_delegateEvents:function(){var self=this;const _delegateEvent=(method,key)=>{var match=/^(\S+)(\s+(.*))?$/.exec(key);var event=match[1];var selector=match[3];event+='.widget_events';if(!selector){self.$el.on(event,method);}else{self.$el.on(event,selector,method);}};Object.entries(this.events||{}).forEach(([event,method])=>{if(typeof method!=='string'){_delegateEvent(self.proxy(method),event);return;} var methodOptions=method.split(' ');if(methodOptions.length<=1){_delegateEvent(self.proxy(method),event);return;} var isAsync=methodOptions.includes('async');if(!isAsync){_delegateEvent(self.proxy(method),event);return;} method=self.proxy(methodOptions[methodOptions.length-1]);if(String(event).startsWith("click")){method=makeButtonHandler(method);}else{method=makeAsyncHandler(method);} _delegateEvent(method,event);});},_getContext:function(extra,extraContext){var context;this.trigger_up('context_get',{extra:extra||false,context:extraContext,callback:function(ctx){context=ctx;},});return context;},_makeDescriptive:function(){var attrs=Object.assign({},this.attributes||{});if(this.id){attrs.id=this.id;} if(this.className){attrs['class']=this.className;} var $el=$(document.createElement(this.tagName));if(Object.keys(attrs||{}).length>0){$el.attr(attrs);} return $el;},_replaceElement:function($el){var $oldel=this.$el;this.setElement($el);if($oldel&&!$oldel.is(this.$el)){if($oldel.length>1){$oldel.wrapAll('
');$oldel.parent().replaceWith(this.$el);}else{$oldel.replaceWith(this.$el);}} return this;},_undelegateEvents:function(){this.$el.off('.widget_events');},_widgetRenderAndInsert:function(insertion,target){var self=this;return this.willStart().then(function(){if(self.__parentedDestroyed){return;} self.renderElement();insertion(target);return self.start();});},});var registry={};__exports[Symbol.for("default")]={Widget:PublicWidget,registry:registry,ParentedMixin:ParentedMixin,EventDispatcherMixin:EventDispatcherMixin,ServicesMixin:ServicesMixin,};return __exports;});; /* /web/static/src/legacy/js/public/signin.js */ odoo.define('@web/legacy/js/public/signin',['@web/legacy/js/public/public_widget','@web/core/utils/ui'],function(require){'use strict';let __exports={};const publicWidget=require('@web/legacy/js/public/public_widget')[Symbol.for("default")];const{addLoadingEffect}=require('@web/core/utils/ui');publicWidget.registry.login=publicWidget.Widget.extend({selector:'.oe_login_form',events:{'submit':'_onSubmit',},_onSubmit(ev){if(!ev.defaultPrevented){const btnEl=ev.currentTarget.querySelector('button[type="submit"]');const removeLoadingEffect=addLoadingEffect(btnEl);const oldPreventDefault=ev.preventDefault.bind(ev);ev.preventDefault=()=>{removeLoadingEffect();oldPreventDefault();};}},});return __exports;});; /* /bus/static/src/bus_parameters_service.js */ odoo.define('@bus/bus_parameters_service',['@web/core/registry'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const busParametersService=__exports.busParametersService={start(){return{serverURL:window.origin,};},};registry.category("services").add("bus.parameters",busParametersService);return __exports;});; /* /bus/static/src/im_status_service.js */ odoo.define('@bus/im_status_service',['@web/core/browser/browser','@web/core/registry','@web/core/user','@web/session'],function(require){'use strict';let __exports={};const{browser}=require("@web/core/browser/browser");const{registry}=require("@web/core/registry");const{user}=require("@web/core/user");const{session}=require("@web/session");const AWAY_DELAY=__exports.AWAY_DELAY=30*60*1000;const FIRST_UPDATE_DELAY=__exports.FIRST_UPDATE_DELAY=500;const UPDATE_BUS_PRESENCE_DELAY=__exports.UPDATE_BUS_PRESENCE_DELAY=60000;const imStatusService=__exports.imStatusService={dependencies:["bus_service","presence"],start(env,{bus_service,presence}){let lastSentInactivity;let becomeAwayTimeout;const updateBusPresence=()=>{lastSentInactivity=presence.getInactivityPeriod();startAwayTimeout();bus_service.send("update_presence",{inactivity_period:lastSentInactivity,im_status_ids_by_model:{},});};this.updateBusPresence=updateBusPresence;const startAwayTimeout=()=>{clearTimeout(becomeAwayTimeout);const awayTime=AWAY_DELAY-presence.getInactivityPeriod();if(awayTime>0){becomeAwayTimeout=browser.setTimeout(()=>updateBusPresence(),awayTime);}};bus_service.addEventListener("connect",()=>updateBusPresence(),{once:true});bus_service.subscribe("bus.bus/im_status_updated",async({partner_id,im_status})=>{if(session.is_public||!partner_id||partner_id!==user.partnerId){return;} const isOnline=presence.getInactivityPeriod(){if(lastSentInactivity>=AWAY_DELAY){this.updateBusPresence();} startAwayTimeout();});return{updateBusPresence};},};registry.category("services").add("im_status",imStatusService);return __exports;});; /* /bus/static/src/misc.js */ odoo.define('@bus/misc',['@web/core/browser/browser'],function(require){'use strict';let __exports={};const{browser}=require("@web/core/browser/browser");function throttle(func,wait,options){let timeout,context,args,result;let previous=0;if(!options){options={};} const later=function(){previous=options.leading===false?0:luxon.DateTime.now().ts;timeout=null;result=func.apply(context,args);if(!timeout){context=args=null;}};const throttled=function(){const _now=luxon.DateTime.now().ts;if(!previous&&options.leading===false){previous=_now;} const remaining=wait-(_now-previous);context=this;args=arguments;if(remaining<=0||remaining>wait){if(timeout){browser.clearTimeout(timeout);timeout=null;} previous=_now;result=func.apply(context,args);if(!timeout){context=args=null;}}else if(!timeout&&options.trailing!==false){timeout=browser.setTimeout(later,remaining);} return result;};throttled.cancel=function(){browser.clearTimeout(timeout);previous=0;timeout=context=args=null;};return throttled;} const timings=__exports.timings={throttle,};return __exports;});; /* /bus/static/src/multi_tab_service.js */ odoo.define('@bus/multi_tab_service',['@web/core/registry','@web/core/browser/browser','@odoo/owl'],function(require){'use strict';let __exports={};const{registry}=require("@web/core/registry");const{browser}=require("@web/core/browser/browser");const{EventBus}=require("@odoo/owl");let multiTabId=0;const multiTabService=__exports.multiTabService={start(){const bus=new EventBus();const TAB_HEARTBEAT_PERIOD=10000;const MAIN_TAB_HEARTBEAT_PERIOD=1500;const HEARTBEAT_OUT_OF_DATE_PERIOD=5000;const HEARTBEAT_KILL_OLD_PERIOD=15000;const PRIVATE_LOCAL_STORAGE_KEYS=["main","heartbeat"];let _isOnMainTab=false;let lastHeartbeat=0;let heartbeatTimeout;const sanitizedOrigin=location.origin.replace(/:\/{0,2}/g,"_");const localStoragePrefix=`${this.name}.${sanitizedOrigin}.`;const now=new Date().getTime();const tabId=`${this.name}${multiTabId++}:${now}`;function generateLocalStorageKey(baseKey){return localStoragePrefix+baseKey;} function getItemFromStorage(key,defaultValue){const item=browser.localStorage.getItem(generateLocalStorageKey(key));try{return item?JSON.parse(item):defaultValue;}catch{return item;}} function setItemInStorage(key,value){browser.localStorage.setItem(generateLocalStorageKey(key),JSON.stringify(value));} function startElection(){if(_isOnMainTab){return;} const now=new Date().getTime();const lastPresenceByTab=getItemFromStorage("lastPresenceByTab",{});const heartbeatKillOld=now-HEARTBEAT_KILL_OLD_PERIOD;let newMain;for(const[tab,lastPresence]of Object.entries(lastPresenceByTab)){if(lastPresencenow){cleanedTabs[tabId]=lastPresence;}} if(heartbeatValue!==lastHeartbeat){_isOnMainTab=false;lastHeartbeat=0;lastPresenceByTab[tabId]=now;setItemInStorage("lastPresenceByTab",lastPresenceByTab);bus.trigger("no_longer_main_tab");}else{lastHeartbeat=now;setItemInStorage("heartbeat",now);setItemInStorage("lastPresenceByTab",cleanedTabs);}}else{lastPresenceByTab[tabId]=now;setItemInStorage("lastPresenceByTab",lastPresenceByTab);} const hbPeriod=_isOnMainTab?MAIN_TAB_HEARTBEAT_PERIOD:TAB_HEARTBEAT_PERIOD;heartbeatTimeout=browser.setTimeout(heartbeat,hbPeriod);} function onStorage({key,newValue}){if(key===generateLocalStorageKey("main")&&!newValue){startElection();} if(PRIVATE_LOCAL_STORAGE_KEYS.includes(key)){return;} if(key&&key.includes(localStoragePrefix)){const baseKey=key.replace(localStoragePrefix,"");bus.trigger("shared_value_updated",{key:baseKey,newValue});}} function unregister(){clearTimeout(heartbeatTimeout);const lastPresenceByTab=getItemFromStorage("lastPresenceByTab",{});delete lastPresenceByTab[tabId];setItemInStorage("lastPresenceByTab",lastPresenceByTab);if(_isOnMainTab){_isOnMainTab=false;bus.trigger("no_longer_main_tab");browser.localStorage.removeItem(generateLocalStorageKey("main"));}} browser.addEventListener("pagehide",unregister);browser.addEventListener("storage",onStorage);const lastPresenceByTab=getItemFromStorage("lastPresenceByTab",{});lastPresenceByTab[tabId]=now;setItemInStorage("lastPresenceByTab",lastPresenceByTab);if(!getItemFromStorage("main")){startElection();} heartbeat();return{bus,get currentTabId(){return tabId;},isOnMainTab(){return _isOnMainTab;},getSharedValue(key,defaultValue){return getItemFromStorage(key,defaultValue);},setSharedValue(key,value){if(value===undefined){return this.removeSharedValue(key);} setItemInStorage(key,value);},removeSharedValue(key){browser.localStorage.removeItem(generateLocalStorageKey(key));},unregister:unregister,};},};registry.category("services").add("multi_tab",multiTabService);return __exports;});; /* /bus/static/src/outdated_page_watcher_service.js */ odoo.define('@bus/outdated_page_watcher_service',['@web/core/browser/browser','@web/core/l10n/dates','@web/core/l10n/translation','@web/core/network/rpc','@web/core/registry'],function(require){'use strict';let __exports={};const{browser}=require("@web/core/browser/browser");const{deserializeDateTime}=require("@web/core/l10n/dates");const{_t}=require("@web/core/l10n/translation");const{rpc}=require("@web/core/network/rpc");const{registry}=require("@web/core/registry");const{DateTime}=luxon;const OutdatedPageWatcherService=__exports.OutdatedPageWatcherService=class OutdatedPageWatcherService{constructor(env,services){this.setup(env,services);} setup(env,{bus_service,multi_tab,notification}){this.notification=notification;const vacuumInfo=multi_tab.getSharedValue("bus.autovacuum_info");this.lastAutovacuumDt=vacuumInfo?deserializeDateTime(vacuumInfo.lastcall):null;this.nextAutovacuumDt=vacuumInfo?deserializeDateTime(vacuumInfo.nextcall):null;this.lastDisconnectDt=null;this.closeNotificationFn;bus_service.addEventListener("disconnect",()=>(this.lastDisconnectDt=DateTime.now()));bus_service.addEventListener("reconnect",async()=>{if(!multi_tab.isOnMainTab()||!this.lastDisconnectDt){return;} if(!this.lastAutovacuumDt||DateTime.now()>=this.nextAutovacuumDt){const{lastcall,nextcall}=await rpc("/bus/get_autovacuum_info",{},{silent:true});this.lastAutovacuumDt=deserializeDateTime(lastcall);this.nextAutovacuumDt=deserializeDateTime(nextcall);multi_tab.setSharedValue("bus.autovacuum_info",{lastcall,nextcall});} if(this.lastDisconnectDt<=this.lastAutovacuumDt){this.showOutdatedPageNotification();}});multi_tab.bus.addEventListener("shared_value_updated",({detail:{key,newValue}})=>{if(key!=="bus.autovacuum_info"){return;} const infos=JSON.parse(newValue);this.lastAutovacuumDt=deserializeDateTime(infos.lastcall);this.nextAutovacuumDt=deserializeDateTime(infos.nextcall);if(this.lastDisconnectDt<=this.lastAutovacuumDt){this.showOutdatedPageNotification();}});} showOutdatedPageNotification(){this.closeNotificationFn?.();this.closeNotificationFn=this.notification.add(_t("Save your work and refresh to get the latest updates and avoid potential issues."),{title:_t("The page is out of date"),type:"warning",sticky:true,buttons:[{name:_t("Refresh"),primary:true,onClick:()=>browser.location.reload(),},],});}} const outdatedPageWatcherService=__exports.outdatedPageWatcherService={dependencies:["bus_service","multi_tab","notification"],start(env,services){return new OutdatedPageWatcherService(env,services);},};registry.category("services").add("bus.outdated_page_watcher",outdatedPageWatcherService);return __exports;});; /* /bus/static/src/services/bus_monitoring_service.js */ odoo.define('@bus/services/bus_monitoring_service',['@bus/workers/websocket_worker','@odoo/owl','@web/core/browser/browser','@web/core/registry'],function(require){'use strict';let __exports={};const{WORKER_STATE}=require("@bus/workers/websocket_worker");const{reactive}=require("@odoo/owl");const{browser}=require("@web/core/browser/browser");const{registry}=require("@web/core/registry");const BusMonitoringService=__exports.BusMonitoringService=class BusMonitoringService{isConnectionLost=false;constructor(env,services){const reactiveThis=reactive(this);reactiveThis.setup(env,services);return reactiveThis;} setup(env,{bus_service}){bus_service.addEventListener("worker_state_updated",({detail})=>this.workerStateOnChange(detail));browser.addEventListener("offline",()=>(this.isReconnecting=false));} workerStateOnChange(state){if(!navigator.onLine){return;} switch(state){case WORKER_STATE.CONNECTING:{this.isReconnecting=true;break;} case WORKER_STATE.CONNECTED:{this.isReconnecting=false;this.isConnectionLost=false;break;} case WORKER_STATE.DISCONNECTED:{if(this.isReconnecting){this.isConnectionLost=true;this.isReconnecting=false;} break;}}}} const busMonitoringservice=__exports.busMonitoringservice={dependencies:["bus_service"],start(env,services){return new BusMonitoringService(env,services);},};registry.category("services").add("bus.monitoring_service",busMonitoringservice);return __exports;});; /* /bus/static/src/services/bus_service.js */ odoo.define('@bus/services/bus_service',['@web/core/browser/browser','@web/core/l10n/translation','@web/core/utils/concurrency','@web/core/registry','@web/session','@web/core/browser/feature_detection','@odoo/owl','@web/core/user'],function(require){'use strict';let __exports={};const{browser}=require("@web/core/browser/browser");const{_t}=require("@web/core/l10n/translation");const{Deferred}=require("@web/core/utils/concurrency");const{registry}=require("@web/core/registry");const{session}=require("@web/session");const{isIosApp}=require("@web/core/browser/feature_detection");const{EventBus}=require("@odoo/owl");const{user}=require("@web/core/user");const INTERNAL_EVENTS=new Set(["initialized","outdated","log_debug","notification"]);const BACK_ONLINE_RECONNECT_DELAY=__exports.BACK_ONLINE_RECONNECT_DELAY=5000;const busService=__exports.busService={dependencies:["bus.parameters","localization","multi_tab","notification"],start(env,{multi_tab:multiTab,notification,"bus.parameters":params}){const bus=new EventBus();const notificationBus=new EventBus();const subscribeFnToWrapper=new Map();let worker;let workerState;let isActive=false;let isInitialized=false;let isUsingSharedWorker=browser.SharedWorker&&!isIosApp();let backOnlineTimeout;const startedAt=luxon.DateTime.now().set({milliseconds:0});const connectionInitializedDeferred=new Deferred();function send(action,data){if(!worker){return;} const message={action,data};if(isUsingSharedWorker){worker.port.postMessage(message);}else{worker.postMessage(message);}} function handleMessage(messageEv){const{type,data}=messageEv.data;switch(type){case"notification":{const notifications=data.map(({id,message})=>({id,...message}));multiTab.setSharedValue("last_notification_id",notifications.at(-1).id);for(const{id,type,payload}of notifications){notificationBus.trigger(type,{id,payload});busService._onMessage(id,type,payload);} break;} case"initialized":{isInitialized=true;connectionInitializedDeferred.resolve();break;} case"worker_state_updated":workerState=data;break;case"log_debug":console.debug(...data);break;case"outdated":{multiTab.unregister();notification.add(_t("Save your work and refresh to get the latest updates and avoid potential issues."),{title:_t("The page is out of date"),type:"warning",sticky:true,buttons:[{name:_t("Refresh"),primary:true,onClick:()=>{browser.location.reload();},},],});break;}} if(!INTERNAL_EVENTS.has(type)){bus.trigger(type,data);}} function initializeWorkerConnection(){let uid=Array.isArray(session.user_id)?session.user_id[0]:user.userId;if(!uid&&uid!==undefined){uid=false;} send("initialize_connection",{websocketURL:`${params.serverURL.replace("http", "ws")}/websocket?version=${ session.websocket_worker_version }`,db:session.db,debug:odoo.debug,lastNotificationId:multiTab.getSharedValue("last_notification_id",0),uid,startTs:startedAt.valueOf(),});} function startWorker(){let workerURL=`${params.serverURL}/bus/websocket_worker_bundle?v=${session.websocket_worker_version}`;if(params.serverURL!==window.origin){const source=`importScripts("${workerURL}");`;workerURL="data:application/javascript;base64,"+window.btoa(source);} const workerClass=isUsingSharedWorker?browser.SharedWorker:browser.Worker;worker=new workerClass(workerURL,{name:isUsingSharedWorker?"odoo:websocket_shared_worker":"odoo:websocket_worker",});worker.addEventListener("error",(e)=>{if(!isInitialized&&workerClass===browser.SharedWorker){console.warn('Error while loading "bus_service" SharedWorker, fallback on Worker.');isUsingSharedWorker=false;startWorker();}else if(!isInitialized){isInitialized=true;connectionInitializedDeferred.resolve();console.warn("Bus service failed to initialized.");}});if(isUsingSharedWorker){worker.port.start();worker.port.addEventListener("message",handleMessage);}else{worker.addEventListener("message",handleMessage);} initializeWorkerConnection();} browser.addEventListener("pagehide",({persisted})=>{if(!persisted){send("leave");}});browser.addEventListener("online",()=>{backOnlineTimeout=browser.setTimeout(()=>{if(isActive){send("start");}},BACK_ONLINE_RECONNECT_DELAY);},{capture:true});browser.addEventListener("offline",()=>{clearTimeout(backOnlineTimeout);send("stop");},{capture:true,});return{addEventListener:bus.addEventListener.bind(bus),addChannel:async(channel)=>{if(!worker){startWorker();} await connectionInitializedDeferred;send("add_channel",channel);send("start");isActive=true;},deleteChannel:(channel)=>send("delete_channel",channel),forceUpdateChannels:()=>send("force_update_channels"),trigger:bus.trigger.bind(bus),removeEventListener:bus.removeEventListener.bind(bus),send:(eventName,data)=>send("send",{event_name:eventName,data}),start:async()=>{if(!worker){startWorker();} await connectionInitializedDeferred;send("start");isActive=true;},stop:()=>{send("leave");isActive=false;},get isActive(){return isActive;},subscribe(notificationType,callback){const wrapper=({detail})=>{const{id,payload}=detail;callback(payload,{id});};subscribeFnToWrapper.set(callback,wrapper);notificationBus.addEventListener(notificationType,wrapper);},unsubscribe(notificationType,callback){notificationBus.removeEventListener(notificationType,subscribeFnToWrapper.get(callback));subscribeFnToWrapper.delete(callback);},startedAt,get workerState(){return workerState;},};},_onMessage(id,type,payload){},};registry.category("services").add("bus_service",busService);return __exports;});; /* /bus/static/src/services/presence_service.js */ odoo.define('@bus/services/presence_service',['@odoo/owl','@web/core/browser/browser','@web/core/registry'],function(require){'use strict';let __exports={};const{EventBus}=require("@odoo/owl");const{browser}=require("@web/core/browser/browser");const{registry}=require("@web/core/registry");const presenceService=__exports.presenceService={start(env){const LOCAL_STORAGE_PREFIX="presence";const bus=new EventBus();let isOdooFocused=true;let lastPresenceTime=browser.localStorage.getItem(`${LOCAL_STORAGE_PREFIX}.lastPresence`)||luxon.DateTime.now().ts;function onPresence(){lastPresenceTime=luxon.DateTime.now().ts;browser.localStorage.setItem(`${LOCAL_STORAGE_PREFIX}.lastPresence`,lastPresenceTime);bus.trigger("presence");} function onFocusChange(isFocused){try{isFocused=parent.document.hasFocus();}catch{} isOdooFocused=isFocused;browser.localStorage.setItem(`${LOCAL_STORAGE_PREFIX}.focus`,isOdooFocused);if(isOdooFocused){lastPresenceTime=luxon.DateTime.now().ts;env.bus.trigger("window_focus",isOdooFocused);}} function onStorage({key,newValue}){if(key===`${LOCAL_STORAGE_PREFIX}.focus`){isOdooFocused=JSON.parse(newValue);env.bus.trigger("window_focus",newValue);} if(key===`${LOCAL_STORAGE_PREFIX}.lastPresence`){lastPresenceTime=JSON.parse(newValue);bus.trigger("presence");}} browser.addEventListener("storage",onStorage);browser.addEventListener("focus",()=>onFocusChange(true));browser.addEventListener("blur",()=>onFocusChange(false));browser.addEventListener("pagehide",()=>onFocusChange(false));browser.addEventListener("click",onPresence);browser.addEventListener("keydown",onPresence);return{bus,getLastPresence(){return lastPresenceTime;},isOdooFocused(){return isOdooFocused;},getInactivityPeriod(){return luxon.DateTime.now().ts-this.getLastPresence();},};},};registry.category("services").add("presence",presenceService);return __exports;});; /* /bus/static/src/workers/websocket_worker.js */ odoo.define('@bus/workers/websocket_worker',['@bus/workers/websocket_worker_utils'],function(require){'use strict';let __exports={};const{debounce,Deferred}=require("@bus/workers/websocket_worker_utils");const WEBSOCKET_CLOSE_CODES=__exports.WEBSOCKET_CLOSE_CODES=Object.freeze({CLEAN:1000,GOING_AWAY:1001,PROTOCOL_ERROR:1002,INCORRECT_DATA:1003,ABNORMAL_CLOSURE:1006,INCONSISTENT_DATA:1007,MESSAGE_VIOLATING_POLICY:1008,MESSAGE_TOO_BIG:1009,EXTENSION_NEGOTIATION_FAILED:1010,SERVER_ERROR:1011,RESTART:1012,TRY_LATER:1013,BAD_GATEWAY:1014,SESSION_EXPIRED:4001,KEEP_ALIVE_TIMEOUT:4002,RECONNECTING:4003,});const WORKER_STATE=__exports.WORKER_STATE=Object.freeze({CONNECTED:"CONNECTED",DISCONNECTED:"DISCONNECTED",IDLE:"IDLE",CONNECTING:"CONNECTING",});const MAXIMUM_RECONNECT_DELAY=60000;const WebsocketWorker=__exports.WebsocketWorker=class WebsocketWorker{INITIAL_RECONNECT_DELAY=1000;RECONNECT_JITTER=1000;constructor(){this.newestStartTs=undefined;this.websocketURL="";this.currentUID=null;this.currentDB=null;this.isWaitingForNewUID=true;this.channelsByClient=new Map();this.connectRetryDelay=this.INITIAL_RECONNECT_DELAY;this.connectTimeout=null;this.debugModeByClient=new Map();this.isDebug=false;this.active=true;this.state=WORKER_STATE.IDLE;this.isReconnecting=false;this.lastChannelSubscription=null;this.firstSubscribeDeferred=new Deferred();this.lastNotificationId=0;this.messageWaitQueue=[];this._forceUpdateChannels=debounce(this._forceUpdateChannels,300);this._debouncedUpdateChannels=debounce(this._updateChannels,300);this._debouncedSendToServer=debounce(this._sendToServer,300);this._onWebsocketClose=this._onWebsocketClose.bind(this);this._onWebsocketError=this._onWebsocketError.bind(this);this._onWebsocketMessage=this._onWebsocketMessage.bind(this);this._onWebsocketOpen=this._onWebsocketOpen.bind(this);} broadcast(type,data){this._logDebug("broadcast",type,data);for(const client of this.channelsByClient.keys()){client.postMessage({type,data:data?JSON.parse(JSON.stringify(data)):undefined});}} registerClient(messagePort){messagePort.onmessage=(ev)=>{this._onClientMessage(messagePort,ev.data);};this.channelsByClient.set(messagePort,[]);} sendToClient(client,type,data){this._logDebug("sendToClient",type,data);client.postMessage({type,data:data?JSON.parse(JSON.stringify(data)):undefined});} _onClientMessage(client,{action,data}){this._logDebug("_onClientMessage",action,data);switch(action){case"send":{if(data["event_name"]==="update_presence"){this._debouncedSendToServer(data);}else{this._sendToServer(data);} return;} case"start":return this._start();case"stop":return this._stop();case"leave":return this._unregisterClient(client);case"add_channel":return this._addChannel(client,data);case"delete_channel":return this._deleteChannel(client,data);case"force_update_channels":return this._forceUpdateChannels();case"initialize_connection":return this._initializeConnection(client,data);}} _addChannel(client,channel){const clientChannels=this.channelsByClient.get(client);if(!clientChannels.includes(channel)){clientChannels.push(channel);this.channelsByClient.set(client,clientChannels);this._debouncedUpdateChannels();}} _deleteChannel(client,channel){const clientChannels=this.channelsByClient.get(client);if(!clientChannels){return;} const channelIndex=clientChannels.indexOf(channel);if(channelIndex!==-1){clientChannels.splice(channelIndex,1);this._debouncedUpdateChannels();}} _forceUpdateChannels(){this._updateChannels({force:true});} _unregisterClient(client){this.channelsByClient.delete(client);this.debugModeByClient.delete(client);this.isDebug=[...this.debugModeByClient.values()].some(Boolean);this._debouncedUpdateChannels();} _initializeConnection(client,{db,debug,lastNotificationId,uid,websocketURL,startTs}){if(this.newestStartTs&&this.newestStartTs>startTs){this.debugModeByClient.set(client,debug);this.isDebug=[...this.debugModeByClient.values()].some(Boolean);this.sendToClient(client,"update_state",this.state);this.sendToClient(client,"initialized");return;} this.newestStartTs=startTs;this.websocketURL=websocketURL;this.lastNotificationId=lastNotificationId;this.debugModeByClient.set(client,debug);this.isDebug=[...this.debugModeByClient.values()].some(Boolean);const isCurrentUserKnown=uid!==undefined;if(this.isWaitingForNewUID&&isCurrentUserKnown){this.isWaitingForNewUID=false;this.currentUID=uid;} if((this.currentUID!==uid&&isCurrentUserKnown)||this.currentDB!==db){this.currentUID=uid;this.currentDB=db;if(this.websocket){this.websocket.close(WEBSOCKET_CLOSE_CODES.CLEAN);} this.channelsByClient.forEach((_,key)=>this.channelsByClient.set(key,[]));} this.sendToClient(client,"update_state",this.state);this.sendToClient(client,"initialized");if(!this.active){this.sendToClient(client,"outdated");}} _isWebsocketConnected(){return this.websocket&&this.websocket.readyState===1;} _isWebsocketConnecting(){return this.websocket&&this.websocket.readyState===0;} _isWebsocketClosing(){return this.websocket&&this.websocket.readyState===2;} _onWebsocketClose({code,reason}){this._logDebug("_onWebsocketClose",code,reason);this._updateState(WORKER_STATE.DISCONNECTED);this.lastChannelSubscription=null;this.firstSubscribeDeferred=new Deferred();if(this.isReconnecting){return;} this.broadcast("disconnect",{code,reason});if(code===WEBSOCKET_CLOSE_CODES.CLEAN){if(reason==="OUTDATED_VERSION"){console.warn("Worker deactivated due to an outdated version.");this.active=false;this.broadcast("outdated");} return;} this.broadcast("reconnecting",{closeCode:code});this.isReconnecting=true;if(code===WEBSOCKET_CLOSE_CODES.KEEP_ALIVE_TIMEOUT){this.connectRetryDelay=0;} if(code===WEBSOCKET_CLOSE_CODES.SESSION_EXPIRED){this.isWaitingForNewUID=true;} this._retryConnectionWithDelay();} _onWebsocketError(){this._logDebug("_onWebsocketError");this._retryConnectionWithDelay();} _onWebsocketMessage(messageEv){const notifications=JSON.parse(messageEv.data);this._logDebug("_onWebsocketMessage",notifications);this.lastNotificationId=notifications[notifications.length-1].id;this.broadcast("notification",notifications);} _logDebug(title,...args){const clientsInDebug=[...this.debugModeByClient.keys()].filter((client)=>this.debugModeByClient.get(client));for(const client of clientsInDebug){client.postMessage({type:"log_debug",data:[`%c${new Date().toLocaleString()} - [${title}]`,"color: #c6e; font-weight: bold;",...args,],});}} _onWebsocketOpen(){this._logDebug("_onWebsocketOpen");this._updateState(WORKER_STATE.CONNECTED);this.broadcast(this.isReconnecting?"reconnect":"connect");this._debouncedUpdateChannels();this.connectRetryDelay=this.INITIAL_RECONNECT_DELAY;this.connectTimeout=null;this.isReconnecting=false;this.firstSubscribeDeferred.then(()=>{this.messageWaitQueue.forEach((msg)=>this.websocket.send(msg));this.messageWaitQueue=[];});} _retryConnectionWithDelay(){this.connectRetryDelay=Math.min(this.connectRetryDelay*1.5,MAXIMUM_RECONNECT_DELAY)+ this.RECONNECT_JITTER*Math.random();this._logDebug("_retryConnectionWithDelay",this.connectRetryDelay);this.connectTimeout=setTimeout(this._start.bind(this),this.connectRetryDelay);} _sendToServer(message){this._logDebug("_sendToServer",message);const payload=JSON.stringify(message);if(!this._isWebsocketConnected()){if(message["event_name"]==="subscribe"){this.messageWaitQueue=this.messageWaitQueue.filter((msg)=>JSON.parse(msg).event_name!=="subscribe");this.messageWaitQueue.unshift(payload);}else{this.messageWaitQueue.push(payload);}}else{if(message["event_name"]==="subscribe"){this.websocket.send(payload);}else{this.firstSubscribeDeferred.then(()=>this.websocket.send(payload));}}} _removeWebsocketListeners(){this.websocket?.removeEventListener("open",this._onWebsocketOpen);this.websocket?.removeEventListener("message",this._onWebsocketMessage);this.websocket?.removeEventListener("error",this._onWebsocketError);this.websocket?.removeEventListener("close",this._onWebsocketClose);} _start(){this._logDebug("_start");if(!this.active||this._isWebsocketConnected()||this._isWebsocketConnecting()){return;} this._removeWebsocketListeners();if(this._isWebsocketClosing()){this.lastChannelSubscription=null;this.broadcast("disconnect",{code:WEBSOCKET_CLOSE_CODES.ABNORMAL_CLOSURE});} this._updateState(WORKER_STATE.CONNECTING);this.websocket=new WebSocket(this.websocketURL);this.websocket.addEventListener("open",this._onWebsocketOpen);this.websocket.addEventListener("error",this._onWebsocketError);this.websocket.addEventListener("message",this._onWebsocketMessage);this.websocket.addEventListener("close",this._onWebsocketClose);} _stop(){this._logDebug("_stop");clearTimeout(this.connectTimeout);this.connectRetryDelay=this.INITIAL_RECONNECT_DELAY;this.isReconnecting=false;this.lastChannelSubscription=null;this.websocket?.close();this._removeWebsocketListeners();} _updateChannels({force=false}={}){const allTabsChannels=[...new Set([].concat.apply([],[...this.channelsByClient.values()])),].sort();const allTabsChannelsString=JSON.stringify(allTabsChannels);const shouldUpdateChannelSubscription=allTabsChannelsString!==this.lastChannelSubscription;if(force||shouldUpdateChannelSubscription){this.lastChannelSubscription=allTabsChannelsString;this._sendToServer({event_name:"subscribe",data:{channels:allTabsChannels,last:this.lastNotificationId},});this.firstSubscribeDeferred.resolve();}} _updateState(newState){this.state=newState;this.broadcast("worker_state_updated",newState);}} return __exports;});; /* /bus/static/src/workers/websocket_worker_utils.js */ odoo.define('@bus/workers/websocket_worker_utils',[],function(require){'use strict';let __exports={};__exports.debounce=debounce;function debounce(func,wait,immediate){let timeout;return function(){const context=this;const args=arguments;function later(){timeout=null;if(!immediate){func.apply(context,args);}} const callNow=immediate&&!timeout;clearTimeout(timeout);timeout=setTimeout(later,wait);if(callNow){func.apply(context,args);}};} const Deferred=__exports.Deferred=class Deferred extends Promise{constructor(){let resolve;let reject;const prom=new Promise((res,rej)=>{resolve=res;reject=rej;});return Object.assign(prom,{resolve,reject});}} return __exports;});; /* /web_tour/static/src/tour_pointer/tour_pointer.js */ odoo.define('@web_tour/tour_pointer/tour_pointer',['@odoo/owl','@web/core/position/position_hook'],function(require){'use strict';let __exports={};const{Component,useEffect,useRef}=require("@odoo/owl");const{usePosition}=require("@web/core/position/position_hook");const TourPointer=__exports.TourPointer=class TourPointer extends Component{static props={pointerState:{type:Object,shape:{anchor:{type:HTMLElement,optional:true},content:{type:String,optional:true},isOpen:{type:Boolean,optional:true},isVisible:{type:Boolean,optional:true},isZone:{type:Boolean,optional:true},onClick:{type:[Function,{value:null}],optional:true},onMouseEnter:{type:[Function,{value:null}],optional:true},onMouseLeave:{type:[Function,{value:null}],optional:true},position:{type:[{value:"left"},{value:"right"},{value:"top"},{value:"bottom"},],optional:true,},rev:{type:Number,optional:true},},},bounce:{type:Boolean,optional:true},};static defaultProps={bounce:true,};static template="web_tour.TourPointer";static width=28;static height=28;setup(){const positionOptions={margin:6,onPositioned:(pointer,position)=>{const popperRect=pointer.getBoundingClientRect();const{top,left,direction}=position;if(direction==="top"){pointer.style.bottom=`${window.innerHeight - top - popperRect.height}px`;pointer.style.removeProperty("top");}else if(direction==="left"){pointer.style.right=`${window.innerWidth - left - popperRect.width}px`;pointer.style.removeProperty("left");}},};Object.defineProperty(positionOptions,"position",{get:()=>this.position,enumerable:true,});const position=usePosition("pointer",()=>this.props.pointerState.anchor,positionOptions);const rootRef=useRef("pointer");const zoneRef=useRef("zone");let dimensions=null;let lastMeasuredContent=null;let lastOpenState=this.isOpen;let lastAnchor;let[anchorX,anchorY]=[0,0];useEffect(()=>{const{el:pointer}=rootRef;const{el:zone}=zoneRef;if(pointer){const hasContentChanged=lastMeasuredContent!==this.content;const hasOpenStateChanged=lastOpenState!==this.isOpen;lastOpenState=this.isOpen;if(this.props.pointerState.isZone){const{anchor}=this.props.pointerState;let offsetLeft=0;let offsetTop=0;if(document!==anchor.ownerDocument){const iframe=[...document.querySelectorAll("iframe")].filter((e)=>e.contentDocument===anchor.ownerDocument)[0];offsetLeft=iframe.getBoundingClientRect().left;offsetTop=iframe.getBoundingClientRect().top;} const{left,top,width,height}=anchor.getBoundingClientRect();zone.style.minWidth=width+"px";zone.style.minHeight=height+"px";zone.style.left=left+offsetLeft+"px";zone.style.top=top+offsetTop+"px";} if(hasContentChanged){lastMeasuredContent=this.content;pointer.style.removeProperty("width");pointer.style.removeProperty("height");dimensions=pointer.getBoundingClientRect();} if(hasContentChanged||hasOpenStateChanged){const[width,height]=this.isOpen?[dimensions.width,dimensions.height]:[this.constructor.width,this.constructor.height];if(this.isOpen){pointer.style.removeProperty("transition");}else{pointer.style.setProperty("transition","none");} pointer.style.setProperty("width",`${width}px`);pointer.style.setProperty("height",`${height}px`);} if(!this.isOpen){const{anchor}=this.props.pointerState;if(anchor===lastAnchor){const{x,y,width}=anchor.getBoundingClientRect();const[lastAnchorX,lastAnchorY]=[anchorX,anchorY];[anchorX,anchorY]=[x,y];const delta=Math.sqrt(Math.pow(x-lastAnchorX,2)+Math.pow(y-lastAnchorY,2));if(delta<1){position.lock();return;} const wouldOverflow=window.innerWidth-x-width/2new TourStepAutomatic(step,this,index));this.config=tourState.getCurrentConfig()||{};} get currentIndex(){return tourState.getCurrentIndex();} get currentStep(){return this.steps[this.currentIndex];} get debugMode(){return this.config.debug!==false;} start(){setupEventActions(document.createElement("div"),{allowSubmit:true});const{delayToCheckUndeterminisms,stepDelay}=this.config;const macroSteps=this.steps.filter((step)=>step.index>=this.currentIndex).flatMap((step)=>[{action:async()=>{if(this.debugMode){console.groupCollapsed(step.describeMe);console.log(step.stringify);if(step.break){debugger;}}else{console.log(step.describeMe);} await new Promise((resolve)=>requestAnimationFrame(resolve));if(stepDelay>0){await hoot.delay(stepDelay);}},},{initialDelay:()=>(this.previousStepIsJustACheck?0:null),trigger:step.trigger?()=>step.findTrigger():null,timeout:step.timeout||this.timeout||10000,action:async(trigger)=>{if(delayToCheckUndeterminisms>0){await step.checkForUndeterminisms(trigger,delayToCheckUndeterminisms);} this.previousStepIsJustACheck=!step.hasAction;if(this.debugMode){console.log(step.element);if(step.skipped){console.log("This step has been skipped");}else{console.log("This step has run successfully");} console.groupEnd();} const result=await step.doAction();if(step.pause&&this.debugMode){await this.pause();} tourState.setCurrentIndex(step.index+1);return result;},},]);const end=()=>{delete window.hoot;transitionConfig.disabled=false;tourState.clear();window.addEventListener("error",(ev)=>{ev.preventDefault();ev.stopImmediatePropagation();},true);window.addEventListener("unhandledrejection",(ev)=>{ev.preventDefault();ev.stopImmediatePropagation();},true);};this.macro=new Macro({name:this.name,checkDelay:this.checkDelay||200,steps:macroSteps,onError:(error)=>{if(error.type==="Timeout"){this.throwError(...this.currentStep.describeWhyIFailed,error.message);}else{this.throwError(error.message);} end();},onComplete:()=>{browser.console.log("tour succeeded");const succeeded=`║ TOUR ${this.name} SUCCEEDED ║`;const msg=[succeeded];msg.unshift("╔"+"═".repeat(succeeded.length-2)+"╗");msg.push("╚"+"═".repeat(succeeded.length-2)+"╝");browser.console.log(`\n\n${msg.join("\n")}\n`);end();},});if(this.debugMode&&this.currentIndex===0){debugger;} transitionConfig.disabled=true;window.hoot=hoot;this.macro.start();} get describeWhereIFailed(){const offset=3;const start=Math.max(this.currentIndex-offset,0);const end=Math.min(this.currentIndex+offset,this.steps.length-1);const result=[];for(let i=start;i<=end;i++){const step=this.steps[i];const stepString=step.stringify;const text=[stepString];if(i===this.currentIndex){const line="-".repeat(10);const failing_step=`${line} FAILED: ${step.describeMe} ${line}`;text.unshift(failing_step);text.push("-".repeat(failing_step.length));} result.push(...text);} return result.join("\n");} throwError(...args){console.groupEnd();tourState.setCurrentTourOnError();browser.console.error([`FAILED: ${this.currentStep.describeMe}.`,...args].join("\n"));browser.console.dir(this.describeWhereIFailed);if(this.debugMode){debugger;}} async pause(){const styles=["background: black; color: white; font-size: 14px","background: black; color: orange; font-size: 14px",];console.log(`%cTour is paused. Use %cplay()%c to continue.`,styles[0],styles[1],styles[0]);await new Promise((resolve)=>{window.play=()=>{resolve();delete window.play;};});}} return __exports;});; /* /web_tour/static/src/tour_service/tour_helpers.js */ odoo.define('@web_tour/tour_service/tour_helpers',['@odoo/hoot-dom'],function(require){'use strict';let __exports={};const hoot=require("@odoo/hoot-dom");const TourHelpers=__exports.TourHelpers=class TourHelpers{constructor(anchor){this.anchor=anchor;this.delay=20;} async check(selector){const element=this._get_action_element(selector);await hoot.check(element);} async clear(selector){const element=this._get_action_element(selector);await hoot.click(element);await hoot.clear();} async click(selector){const element=this._get_action_element(selector);await hoot.click(element);} async dblclick(selector){const element=this._get_action_element(selector);await hoot.dblclick(element);} async drag_and_drop(selector,options){if(typeof options!=="object"){options={position:"top",relative:true};} const dragEffectDelay=async()=>{await new Promise((resolve)=>requestAnimationFrame(resolve));await new Promise((resolve)=>setTimeout(resolve,this.delay));};const element=this.anchor;const{drop,moveTo}=await hoot.drag(element);await dragEffectDelay();await hoot.hover(element,{position:{top:20,left:20,},relative:true,});await dragEffectDelay();const target=await hoot.waitFor(selector,{visible:true,timeout:500,});await moveTo(target,options);await dragEffectDelay();await drop();await dragEffectDelay();} async edit(text,selector){const element=this._get_action_element(selector);await hoot.click(element);await hoot.edit(text);} async editor(text,selector){const element=this._get_action_element(selector);const InEditor=Boolean(element.closest(".odoo-editor-editable"));if(!InEditor){throw new Error("run 'editor' always on an element in an editor");} await hoot.click(element);this._set_range(element,"start");await hoot.keyDown("_");element.textContent=text;await hoot.manuallyDispatchProgrammaticEvent(element,"input");this._set_range(element,"stop");await hoot.keyUp("_");await hoot.manuallyDispatchProgrammaticEvent(element,"change");} async fill(value,selector){const element=this._get_action_element(selector);await hoot.click(element);await hoot.fill(value);} async hover(selector){const element=this._get_action_element(selector);await hoot.hover(element);} async range(value,selector){const element=this._get_action_element(selector);await hoot.click(element);await hoot.setInputRange(element,value);} press(...args){return hoot.press(args.flatMap((arg)=>typeof arg==="string"&&arg.split("+")));} async select(value,selector){const element=this._get_action_element(selector);await hoot.click(element);await hoot.select(value,{target:element});} async selectByIndex(index,selector){const element=this._get_action_element(selector);await hoot.click(element);const value=hoot.queryValue(`option:eq(${index})`,{root:element});if(value){await hoot.select(value,{target:element});await hoot.manuallyDispatchProgrammaticEvent(element,"input");}} async selectByLabel(contains,selector){const element=this._get_action_element(selector);await hoot.click(element);const values=hoot.queryAllValues(`option:contains(${contains})`,{root:element});await hoot.select(values,{target:element});} uncheck(selector){const element=this._get_action_element(selector);hoot.uncheck(element);} goToUrl(url){const linkEl=document.createElement("a");linkEl.href=url;linkEl.click();} _get_action_element(selector){if(typeof selector==="string"&&selector.length){const nodes=hoot.queryAll(selector);return nodes.find(hoot.isVisible)||nodes.at(0);}else if(typeof selector==="object"&&Boolean(selector?.nodeType)){return selector;} return this.anchor;} _set_range(element,start_or_stop){function _node_length(node){if(node.nodeType===Node.TEXT_NODE){return node.nodeValue.length;}else{return node.childNodes.length;}} const selection=element.ownerDocument.getSelection();selection.removeAllRanges();const range=new Range();let node=element;let length=0;if(start_or_stop==="start"){while(node.firstChild){node=node.firstChild;}}else{while(node.lastChild){node=node.lastChild;} length=_node_length(node);} range.setStart(node,length);range.setEnd(node,length);selection.addRange(range);}} return __exports;});; /* /web_tour/static/src/tour_service/tour_interactive.js */ odoo.define('@web_tour/tour_service/tour_interactive',['@web_tour/tour_service/tour_state','@web/core/utils/timing','@web_tour/tour_service/tour_utils','@odoo/hoot-dom','@web/core/ui/ui_service','@web_tour/tour_service/tour_step','@web/core/macro'],function(require){'use strict';let __exports={};const{tourState}=require("@web_tour/tour_service/tour_state");const{debounce}=require("@web/core/utils/timing");const{getScrollParent}=require("@web_tour/tour_service/tour_utils");const hoot=require("@odoo/hoot-dom");const{utils}=require("@web/core/ui/ui_service");const{TourStep}=require("@web_tour/tour_service/tour_step");const{MacroMutationObserver}=require("@web/core/macro");const TourInteractive=__exports.TourInteractive=class TourInteractive{mode="manual";currentAction;currentActionIndex;anchorEls=[];removeListeners=()=>{};constructor(data){Object.assign(this,data);this.steps=this.steps.map((step)=>new TourStep(step,this));this.actions=this.steps.flatMap((s)=>this.getSubActions(s));} start(pointer,onTourEnd){this.pointer=pointer;this.debouncedToggleOpen=debounce(this.pointer.showContent,50,true);this.onTourEnd=onTourEnd;this.observer=new MacroMutationObserver(()=>this._onMutation());this.observer.observe(document.body);this.currentActionIndex=tourState.getCurrentIndex();this.play();} backward(){let tempIndex=this.currentActionIndex;let tempAction,tempAnchors=[];while(!tempAnchors.length&&tempIndex>=0){tempIndex--;tempAction=this.actions.at(tempIndex);if(!tempAction.step.active){continue;} tempAnchors=tempAction&&this.findTriggers(tempAction.anchor);} if(tempIndex>=0){this.currentActionIndex=tempIndex;this.play();}} findTriggers(anchor){if(!anchor){anchor=this.currentAction.anchor;} return anchor.split(/,\s*(?![^(]*\))/).map((part)=>hoot.queryFirst(part,{visible:true})).filter((el)=>!!el).map((el)=>this.getAnchorEl(el,this.currentAction.event)).filter((el)=>!!el);} play(){this.removeListeners();if(this.currentActionIndex===this.actions.length){this.observer.disconnect();this.onTourEnd();return;} this.currentAction=this.actions.at(this.currentActionIndex);if(!this.currentAction.step.active||this.currentAction.event==="warn"){if(this.currentAction.event==="warn"){console.warn(`Step '${this.currentAction.anchor}' ignored.`);} this.currentActionIndex++;this.play();return;} console.log(this.currentAction.event,this.currentAction.anchor);tourState.setCurrentIndex(this.currentActionIndex);this.anchorEls=this.findTriggers();this.setActionListeners();this.updatePointer();} updatePointer(){if(this.anchorEls.length){this.pointer.pointTo(this.anchorEls[0],this.currentAction.pointerInfo,this.currentAction.event==="drop");this.pointer.setState({onMouseEnter:()=>this.debouncedToggleOpen(true),onMouseLeave:()=>this.debouncedToggleOpen(false),});}} setActionListeners(){const cleanups=this.anchorEls.flatMap((anchorEl,index)=>{const toListen={anchorEl,consumeEvents:this.getConsumeEventType(anchorEl,this.currentAction.event),onConsume:()=>{this.pointer.hide();this.currentActionIndex++;this.play();},onError:()=>{if(this.currentAction.event==="drop"){this.pointer.hide();this.currentActionIndex--;this.play();}},};if(index===0){return this.setupListeners({...toListen,onMouseEnter:()=>this.pointer.showContent(true),onMouseLeave:()=>this.pointer.showContent(false),onScroll:()=>this.updatePointer(),});}else{return this.setupListeners({...toListen,onScroll:()=>{},});}});this.removeListeners=()=>{this.anchorEls=[];while(cleanups.length){cleanups.pop()();}};} setupListeners({anchorEl,consumeEvents,onMouseEnter,onMouseLeave,onScroll,onConsume,onError=()=>{},}){consumeEvents=consumeEvents.map((c)=>({target:c.target,type:c.name,listener:function(ev){if(!c.conditional||c.conditional(ev)){onConsume();}else{onError();}},}));for(const consume of consumeEvents){consume.target.addEventListener(consume.type,consume.listener,true);} anchorEl.addEventListener("mouseenter",onMouseEnter);anchorEl.addEventListener("mouseleave",onMouseLeave);const cleanups=[()=>{for(const consume of consumeEvents){consume.target.removeEventListener(consume.type,consume.listener,true);} anchorEl.removeEventListener("mouseenter",onMouseEnter);anchorEl.removeEventListener("mouseleave",onMouseLeave);},];const scrollEl=getScrollParent(anchorEl);if(scrollEl){const debouncedOnScroll=debounce(onScroll,50);scrollEl.addEventListener("scroll",debouncedOnScroll);cleanups.push(()=>scrollEl.removeEventListener("scroll",debouncedOnScroll));} return cleanups;} getSubActions(step){const actions=[];if(!step.run||typeof step.run==="function"){actions.push({step,event:"warn",anchor:step.trigger,});return actions;} for(const todo of step.run.split("&&")){const m=String(todo).trim().match(/^(?\w*) *\(? *(?.*?)\)?$/);let action=m.groups?.action;const anchor=m.groups?.arguments||step.trigger;const pointerInfo={content:step.content,tooltipPosition:step.tooltipPosition,};if(action==="drag_and_drop"){actions.push({step,event:"drag",anchor:step.trigger,pointerInfo,});action="drop";} actions.push({step,event:action,anchor:action==="edit"?step.trigger:anchor,pointerInfo,});} return actions;} getConsumeEventType(element,runCommand){const consumeEvents=[];if(runCommand==="click"){consumeEvents.push({name:"click",target:element,});if(element.querySelector(".o-autocomplete--input")){consumeEvents.push({name:"keydown",target:element.querySelector(".o-autocomplete--input"),conditional:(ev)=>["Tab","Enter"].includes(ev.key)&&ev.target.parentElement.querySelector(".o-autocomplete--dropdown-item .ui-state-active"),});} if(element.closest(".o-autocomplete--dropdown-menu")){consumeEvents.push({name:"keydown",target:element.closest(".o-autocomplete").querySelector("input"),conditional:(ev)=>["Tab","Enter"].includes(ev.key),});} if(element.tagName==="BUTTON"){consumeEvents.push({name:"keydown",target:element,conditional:(ev)=>ev.key==="Enter",});if(element.closest(".input-group")){for(const inputEl of element.parentElement.querySelectorAll("input")){consumeEvents.push({name:"keydown",target:inputEl,conditional:(ev)=>ev.key==="Enter",});}}}} if(["fill","edit"].includes(runCommand)){if(utils.isSmall()&&element.closest(".o_field_widget")?.matches(".o_field_many2one, .o_field_many2many")){consumeEvents.push({name:"click",target:element,});}else{consumeEvents.push({name:"input",target:element,});}} if(runCommand==="drag"){consumeEvents.push({name:"pointerdown",target:element,});} if(runCommand==="drop"){consumeEvents.push({name:"pointerup",target:element.ownerDocument,conditional:(ev)=>element.ownerDocument.elementsFromPoint(ev.clientX,ev.clientY).includes(element),});consumeEvents.push({name:"drop",target:element.ownerDocument,conditional:(ev)=>element.ownerDocument.elementsFromPoint(ev.clientX,ev.clientY).includes(element),});} return consumeEvents;} getAnchorEl(el,consumeEvent){if(consumeEvent==="drag"){return el.closest(".ui-draggable, .o_draggable, .o_we_draggable, .o-draggable, [draggable='true']");} if(consumeEvent==="input"&&!["textarea","input"].includes(el.tagName.toLowerCase())){return el.closest("[contenteditable='true']");} if(consumeEvent==="sort"){return el.closest(".ui-sortable, .o_sortable");} return el;} _onMutation(){if(this.currentAction){const tempAnchors=this.findTriggers();if(tempAnchors.length&&(tempAnchors.some((a)=>!this.anchorEls.includes(a))||this.anchorEls.some((a)=>!tempAnchors.includes(a)))){this.removeListeners();this.anchorEls=tempAnchors;this.setActionListeners();}else if(!tempAnchors.length&&this.anchorEls.length){this.pointer.hide();if(!hoot.queryFirst(".o_home_menu",{visible:true})){this.backward();} return;} this.updatePointer();}}} return __exports;});; /* /web_tour/static/src/tour_service/tour_pointer_state.js */ odoo.define('@web_tour/tour_service/tour_pointer_state',['@odoo/owl','@web/core/l10n/translation','@web_tour/tour_pointer/tour_pointer','@web_tour/tour_service/tour_utils'],function(require){'use strict';let __exports={};const{reactive}=require("@odoo/owl");const{_t}=require("@web/core/l10n/translation");const{TourPointer}=require("@web_tour/tour_pointer/tour_pointer");const{getScrollParent}=require("@web_tour/tour_service/tour_utils");class Intersection{constructor(){this.currentTarget=null;this.rootBounds=null;this._targetPosition="unknown";this._observer=new IntersectionObserver((observations)=>this._handleObservations(observations));} _handleObservations(observations){if(observations.length<1){return;} const observation=observations[observations.length-1];this.rootBounds=observation.rootBounds;if(this.rootBounds&&this.currentTarget){if(observation.isIntersecting){this._targetPosition="in";}else{const scrollParentElement=getScrollParent(this.currentTarget)||document.documentElement;const targetBounds=this.currentTarget.getBoundingClientRect();if(targetBounds.bottom>scrollParentElement.clientHeight){this._targetPosition="out-below";}else if(targetBounds.top<0){this._targetPosition="out-above";}else if(targetBounds.left<0){this._targetPosition="out-left";}else if(targetBounds.right>scrollParentElement.clientWidth){this._targetPosition="out-right";}}}else{this._targetPosition="unknown";}} get targetPosition(){if(!this.rootBounds){return this.currentTarget?"in":"unknown";}else{return this._targetPosition;}} setTarget(newTarget){if(this.currentTarget!==newTarget){if(this.currentTarget){this._observer.unobserve(this.currentTarget);} if(newTarget){this._observer.observe(newTarget);} this.currentTarget=newTarget;}} stop(){this._observer.disconnect();}} __exports.createPointerState=createPointerState;function createPointerState(){const setState=(newState)=>{Object.assign(state,newState);};const pointTo=(anchor,step,isZone)=>{intersection.setTarget(anchor);if(anchor){let{tooltipPosition,content}=step;switch(intersection.targetPosition){case"unknown":{break;} case"in":{if(document.body.contains(floatingAnchor)){floatingAnchor.remove();} setState({anchor,content,isZone,onClick:null,position:tooltipPosition,isVisible:true,});break;} default:{const onClick=()=>{anchor.scrollIntoView({behavior:"smooth",block:"nearest"});hide();};const scrollParent=getScrollParent(anchor);if(!scrollParent){setState({anchor,content,isZone,onClick:null,position:tooltipPosition,isVisible:true,});return;} let{x,y,width,height}=scrollParent.getBoundingClientRect();const iframeEl=scrollParent.ownerDocument.defaultView.frameElement;if(iframeEl){const iframeOffset=iframeEl.getBoundingClientRect();x+=iframeOffset.x;y+=iframeOffset.y;} if(intersection.targetPosition==="out-below"){tooltipPosition="top";content=_t("Scroll down to reach the next step.");floatingAnchor.style.top=`${y + height - TourPointer.height}px`;floatingAnchor.style.left=`${x + width / 2}px`;}else if(intersection.targetPosition==="out-above"){tooltipPosition="bottom";content=_t("Scroll up to reach the next step.");floatingAnchor.style.top=`${y + TourPointer.height}px`;floatingAnchor.style.left=`${x + width / 2}px`;} if(intersection.targetPosition==="out-left"){tooltipPosition="right";content=_t("Scroll left to reach the next step.");floatingAnchor.style.top=`${y + height / 2}px`;floatingAnchor.style.left=`${x + TourPointer.width}px`;}else if(intersection.targetPosition==="out-right"){tooltipPosition="left";content=_t("Scroll right to reach the next step.");floatingAnchor.style.top=`${y + height / 2}px`;floatingAnchor.style.left=`${x + width - TourPointer.width}px`;} if(!document.contains(floatingAnchor)){document.body.appendChild(floatingAnchor);} setState({anchor:floatingAnchor,content,onClick,position:tooltipPosition,isZone,isVisible:true,});}}}else{hide();}};function hide(){setState({content:"",isVisible:false,isOpen:false});} function showContent(isOpen){setState({isOpen});} function destroy(){intersection.stop();if(document.body.contains(floatingAnchor)){floatingAnchor.remove();}} const state=reactive({});const intersection=new Intersection();const floatingAnchor=document.createElement("div");floatingAnchor.className="position-fixed";return{state,setState,showContent,pointTo,hide,destroy};} return __exports;});; /* /web_tour/static/src/tour_service/tour_recorder/tour_recorder.js */ odoo.define('@web_tour/tour_service/tour_recorder/tour_recorder',['@web/core/utils/hooks','@web/core/dropdown/dropdown','@web/core/dropdown/dropdown_item','@web/core/browser/browser','@odoo/hoot-dom','@odoo/owl','@web/core/l10n/translation','@web/core/orm_service','@web_tour/tour_service/tour_recorder/tour_recorder_state'],function(require){'use strict';let __exports={};const{useService}=require("@web/core/utils/hooks");const{Dropdown}=require("@web/core/dropdown/dropdown");const{DropdownItem}=require("@web/core/dropdown/dropdown_item");const{browser}=require("@web/core/browser/browser");const{queryAll,queryFirst,queryOne}=require("@odoo/hoot-dom");const{Component,useState,useExternalListener}=require("@odoo/owl");const{_t}=require("@web/core/l10n/translation");const{x2ManyCommands}=require("@web/core/orm_service");const{tourRecorderState}=require("@web_tour/tour_service/tour_recorder/tour_recorder_state");const TOUR_RECORDER_ACTIVE_LOCAL_STORAGE_KEY=__exports.TOUR_RECORDER_ACTIVE_LOCAL_STORAGE_KEY="tour_recorder_active";const PRECISE_IDENTIFIERS=["data-menu-xmlid","name","contenteditable"];const ODOO_CLASS_REGEX=/^oe?(-|_)[\w-]+$/;const VALIDATING_KEYS=["Enter","Tab"];const getShortestSelector=(paths)=>{paths.reverse();let filteredPath=[];let hasOdooClass=false;for(let currentElem=paths.pop();(currentElem&&queryAll(filteredPath.join(" > ")).length!==1)||!hasOdooClass;currentElem=paths.pop()){if(currentElem.parentElement.contentEditable==="true"){continue;} let currentPredicate=currentElem.tagName.toLowerCase();const odooClass=[...currentElem.classList].find((c)=>c.match(ODOO_CLASS_REGEX));if(odooClass){currentPredicate=`.${odooClass}`;hasOdooClass=true;} if(["BUTTON","A"].includes(currentElem.tagName)){filteredPath=[];} for(const identifier of PRECISE_IDENTIFIERS){const identifierValue=currentElem.getAttribute(identifier);if(identifierValue){currentPredicate+=`[${identifier}='${CSS.escape(identifierValue)}']`;}} const siblingNodes=queryAll(":scope > "+currentPredicate,{root:currentElem.parentElement,});if(siblingNodes.length>1){currentPredicate+=`:nth-child(${ [...currentElem.parentElement.children].indexOf(currentElem) + 1 })`;} filteredPath.unshift(currentPredicate);} if(filteredPath.length>2){return reducePath(filteredPath);} return filteredPath.join(" > ");};const reducePath=(paths)=>{const numberOfElement=paths.length-2;let currentElement="";let hasReduced=false;let path=paths.shift();for(let i=0;i ")}`).length===1){hasReduced=true;}else{path+=`${hasReduced ? " " : " > "}${currentElement}`;hasReduced=false;}} path+=`${hasReduced ? " " : " > "}${paths.shift()}`;return path;};const TourRecorder=__exports.TourRecorder=class TourRecorder extends Component{static template="web_tour.TourRecorder";static components={Dropdown,DropdownItem};static props={onClose:{type:Function},};static defaultState={recording:false,url:"",editedElement:undefined,tourName:"",};setup(){this.originClickEvent=false;this.notification=useService("notification");this.orm=useService("orm");this.state=useState({...TourRecorder.defaultState,steps:[],});this.state.steps=tourRecorderState.getCurrentTourRecorder();this.state.recording=tourRecorderState.isRecording()==="1";useExternalListener(document,"pointerdown",this.setStartingEvent,{capture:true});useExternalListener(document,"pointerup",this.recordClickEvent,{capture:true});useExternalListener(document,"keydown",this.recordConfirmationKeyboardEvent,{capture:true,});useExternalListener(document,"keyup",this.recordKeyboardEvent,{capture:true});} setStartingEvent(ev){if(!this.state.recording||ev.target.closest(".o_tour_recorder")){return;} this.originClickEvent=ev.composedPath().filter((p)=>p instanceof Element);} recordClickEvent(ev){if(!this.state.recording||ev.target.closest(".o_tour_recorder")){return;} const pathElements=ev.composedPath().filter((p)=>p instanceof Element);this.addTourStep([...pathElements]);const lastStepInput=this.state.steps.at(-1);if(JSON.stringify(pathElements.map((e)=>e.tagName))!==JSON.stringify(this.originClickEvent.map((e)=>e.tagName))){lastStepInput.run=`drag_and_drop ${lastStepInput.trigger}`;lastStepInput.trigger=getShortestSelector(this.originClickEvent);}else{const lastStepInput=this.state.steps.at(-1);lastStepInput.run="click";} tourRecorderState.setCurrentTourRecorder(this.state.steps);} recordConfirmationKeyboardEvent(ev){if(!this.state.recording||!this.state.editedElement||ev.target.closest(".o_tour_recorder")){return;} if([...this.state.editedElement.classList].includes("o-autocomplete--input")&&VALIDATING_KEYS.includes(ev.key)){const selectedRow=queryFirst(".ui-state-active",{root:this.state.editedElement.parentElement,});this.state.steps.push({trigger:`.o-autocomplete--dropdown-item > a:contains('${selectedRow.textContent}'), .fa-circle-o-notch`,run:"click",});this.state.editedElement=undefined;} tourRecorderState.setCurrentTourRecorder(this.state.steps);} recordKeyboardEvent(ev){if(!this.state.recording||VALIDATING_KEYS.includes(ev.key)||ev.target.closest(".o_tour_recorder")){return;} if(!this.state.editedElement){if(ev.target.matches("input:not(:disabled), textarea:not(:disabled), [contenteditable=true]")){this.state.editedElement=ev.target;this.state.steps.push({trigger:getShortestSelector(ev.composedPath()),});}else{return;}} if(!this.state.editedElement){return;} const lastStep=this.state.steps.at(-1);if(this.state.editedElement.contentEditable==="true"){lastStep.run=`editor ${this.state.editedElement.textContent}`;}else{lastStep.run=`edit ${this.state.editedElement.value}`;} tourRecorderState.setCurrentTourRecorder(this.state.steps);} toggleRecording(){this.state.recording=!this.state.recording;tourRecorderState.setIsRecording(this.state.recording);this.state.editedElement=undefined;if(this.state.recording&&!this.state.url){this.state.url=browser.location.pathname+browser.location.search;}} async saveTour(){const newTour={name:this.state.tourName.replaceAll(" ","_"),url:this.state.url,step_ids:this.state.steps.map((s)=>x2ManyCommands.create(undefined,s)),custom:true,};const result=await this.orm.create("web_tour.tour",[newTour]);if(result){this.notification.add(_t("Custom tour '%s' has been added.",newTour.name),{type:"success",});this.resetTourRecorderState();}else{this.notification.add(_t("Custom tour '%s' couldn't be saved!",newTour.name),{type:"danger",});}} resetTourRecorderState(){Object.assign(this.state,{...TourRecorder.defaultState,steps:[]});tourRecorderState.clear();} addTourStep(path){const shortestPath=getShortestSelector(path);const target=queryOne(shortestPath);this.state.editedElement=target.matches("input:not(:disabled), textarea:not(:disabled), [contenteditable=true]")&⌖this.state.steps.push({trigger:shortestPath,});}} return __exports;});; /* /web_tour/static/src/tour_service/tour_recorder/tour_recorder_state.js */ odoo.define('@web_tour/tour_service/tour_recorder/tour_recorder_state',['@web/core/browser/browser'],function(require){'use strict';let __exports={};const{browser}=require("@web/core/browser/browser");const CURRENT_TOUR_RECORDER_LOCAL_STORAGE="current_tour_recorder";const CURRENT_TOUR_RECORDER_RECORD_LOCAL_STORAGE="current_tour_recorder.record";const tourRecorderState=__exports.tourRecorderState={isRecording(){return browser.localStorage.getItem(CURRENT_TOUR_RECORDER_RECORD_LOCAL_STORAGE)||"0";},setIsRecording(isRecording){browser.localStorage.setItem(CURRENT_TOUR_RECORDER_RECORD_LOCAL_STORAGE,isRecording?"1":"0");},setCurrentTourRecorder(tour){tour=JSON.stringify(tour);browser.localStorage.setItem(CURRENT_TOUR_RECORDER_LOCAL_STORAGE,tour);},getCurrentTourRecorder(){const tour=browser.localStorage.getItem(CURRENT_TOUR_RECORDER_LOCAL_STORAGE)||"[]";return JSON.parse(tour);},clear(){browser.localStorage.removeItem(CURRENT_TOUR_RECORDER_LOCAL_STORAGE);browser.localStorage.removeItem(CURRENT_TOUR_RECORDER_RECORD_LOCAL_STORAGE);},};return __exports;});; /* /web_tour/static/src/tour_service/tour_service.js */ odoo.define('@web_tour/tour_service/tour_service',['@odoo/owl','@web/core/browser/browser','@web/core/l10n/translation','@web/core/registry','@web/session','@web_tour/tour_pointer/tour_pointer','@web_tour/tour_service/tour_pointer_state','@web_tour/tour_service/tour_state','@web_tour/tour_service/tour_interactive','@web_tour/tour_service/tour_automatic','@web_tour/tour_service/tour_utils','@web_tour/tour_service/tour_recorder/tour_recorder','@web/core/utils/urls','@web_tour/tour_service/tour_recorder/tour_recorder_state'],function(require){'use strict';let __exports={};const{markup,whenReady,validate}=require("@odoo/owl");const{browser}=require("@web/core/browser/browser");const{_t}=require("@web/core/l10n/translation");const{registry}=require("@web/core/registry");const{session}=require("@web/session");const{TourPointer}=require("@web_tour/tour_pointer/tour_pointer");const{createPointerState}=require("@web_tour/tour_service/tour_pointer_state");const{tourState}=require("@web_tour/tour_service/tour_state");const{TourInteractive}=require("@web_tour/tour_service/tour_interactive");const{TourAutomatic}=require("@web_tour/tour_service/tour_automatic");const{callWithUnloadCheck}=require("@web_tour/tour_service/tour_utils");const{TOUR_RECORDER_ACTIVE_LOCAL_STORAGE_KEY,TourRecorder,}=require("@web_tour/tour_service/tour_recorder/tour_recorder");const{redirect}=require("@web/core/utils/urls");const{tourRecorderState}=require("@web_tour/tour_service/tour_recorder/tour_recorder_state");const StepSchema={id:{type:[String],optional:true},content:{type:[String,Object],optional:true},debugHelp:{type:String,optional:true},isActive:{type:Array,element:String,optional:true},run:{type:[String,Function,Boolean],optional:true},timeout:{optional:true,validate(value){return value>=0&&value<=60000;},},tooltipPosition:{optional:true,validate(value){return["top","bottom","left","right"].includes(value);},},trigger:{type:String},pause:{type:Boolean,optional:true},break:{type:Boolean,optional:true},};const TourSchema={checkDelay:{type:Number,optional:true},name:{type:String,optional:true},steps:Function,url:{type:String,optional:true},wait_for:{type:[Function,Object],optional:true},};registry.category("web_tour.tours").addValidation(TourSchema);const userMenuRegistry=registry.category("user_menuitems");const tourService=__exports.tourService={dependencies:["orm","effect","overlay","localization"],start:async(_env,{orm,effect,overlay})=>{await whenReady();let toursEnabled=session?.tour_enabled;const tourRegistry=registry.category("web_tour.tours");const pointer=createPointerState();pointer.stop=()=>{};userMenuRegistry.add("web_tour.tour_enabled",()=>({type:"switch",id:"web_tour.tour_enabled",description:_t("Onboarding"),callback:async()=>{tourState.clear();toursEnabled=await orm.call("res.users","switch_tour_enabled",[!toursEnabled]);browser.location.reload();},isChecked:toursEnabled,sequence:30,}));function getTourFromRegistry(tourName){if(!tourRegistry.contains(tourName)){return;} const tour=tourRegistry.get(tourName);return{...tour,steps:tour.steps(),name:tourName,wait_for:tour.wait_for||Promise.resolve(),};} async function getTourFromDB(tourName){const tour=await orm.call("web_tour.tour","get_tour_json_by_name",[tourName]);if(!tour){throw new Error(`Tour '${tourName}' is not found in the database.`);} if(!tour.steps.length&&tourRegistry.contains(tour.name)){tour.steps=tourRegistry.get(tour.name).steps();} return tour;} function validateStep(step){try{validate(step,StepSchema);}catch(error){console.error(`Error in schema for TourStep ${JSON.stringify(step, null, 4)}\n${ error.message }`);}} async function startTour(tourName,options={}){pointer.stop();const tourFromRegistry=getTourFromRegistry(tourName);if(!tourFromRegistry&&!options.fromDB){return;} const tour=options.fromDB?{name:tourName,url:options.url}:tourFromRegistry;if(!session.is_public&&!toursEnabled&&options.mode==="manual"){toursEnabled=await orm.call("res.users","switch_tour_enabled",[!toursEnabled]);} let tourConfig={delayToCheckUndeterminisms:0,stepDelay:0,keepWatchBrowser:false,mode:"auto",showPointerDuration:0,debug:false,redirect:true,};tourConfig=Object.assign(tourConfig,options);tourState.setCurrentConfig(tourConfig);tourState.setCurrentTour(tour.name);tourState.setCurrentIndex(0);const willUnload=callWithUnloadCheck(()=>{if(tour.url&&tourConfig.startUrl!=tour.url&&tourConfig.redirect){redirect(tour.url);}});if(!willUnload){resumeTour();}} async function resumeTour(){const tourName=tourState.getCurrentTour();const tourConfig=tourState.getCurrentConfig();let tour=getTourFromRegistry(tourName);if(tourConfig.fromDB){tour=await getTourFromDB(tourName);} if(!tour){return;} tour.steps.forEach((step)=>validateStep(step));pointer.stop=overlay.add(TourPointer,{pointerState:pointer.state,bounce:!(tourConfig.mode==="auto"&&tourConfig.keepWatchBrowser),},{sequence:1100,});if(tourConfig.mode==="auto"){new TourAutomatic(tour).start();}else{new TourInteractive(tour).start(pointer,async()=>{pointer.stop();tourState.clear();browser.console.log("tour succeeded");let message=tourConfig.rainbowManMessage||tour.rainbowManMessage;if(message){message=window.DOMPurify.sanitize(tourConfig.rainbowManMessage);effect.add({type:"rainbow_man",message:markup(message),});} const nextTour=await orm.call("web_tour.tour","consume",[tour.name]);if(nextTour){startTour(nextTour.name,{mode:"manual",redirect:false,rainbowManMessage:nextTour.rainbowManMessage,});}});}} function startTourRecorder(){if(!browser.localStorage.getItem(TOUR_RECORDER_ACTIVE_LOCAL_STORAGE_KEY)){const remove=overlay.add(TourRecorder,{onClose:()=>{remove();browser.localStorage.removeItem(TOUR_RECORDER_ACTIVE_LOCAL_STORAGE_KEY);tourRecorderState.clear();},},{sequence:99999});} browser.localStorage.setItem(TOUR_RECORDER_ACTIVE_LOCAL_STORAGE_KEY,"1");} if(!window.frameElement){const paramsTourName=new URLSearchParams(browser.location.search).get("tour");if(paramsTourName){startTour(paramsTourName,{mode:"manual",fromDB:true});} if(tourState.getCurrentTour()){if(tourState.getCurrentConfig().mode==="auto"||toursEnabled){resumeTour();}else{tourState.clear();}}else if(session.current_tour){startTour(session.current_tour.name,{mode:"manual",redirect:false,rainbowManMessage:session.current_tour.rainbowManMessage,});} if(browser.localStorage.getItem(TOUR_RECORDER_ACTIVE_LOCAL_STORAGE_KEY)&&!session.is_public){const remove=overlay.add(TourRecorder,{onClose:()=>{remove();browser.localStorage.removeItem(TOUR_RECORDER_ACTIVE_LOCAL_STORAGE_KEY);tourRecorderState.clear();},},{sequence:99999});}} odoo.startTour=startTour;odoo.isTourReady=(tourName)=>getTourFromRegistry(tourName).wait_for.then(()=>true);return{startTour,startTourRecorder,};},};registry.category("services").add("tour_service",tourService);return __exports;});; /* /web_tour/static/src/tour_service/tour_state.js */ odoo.define('@web_tour/tour_service/tour_state',['@web/core/browser/browser'],function(require){'use strict';let __exports={};const{browser}=require("@web/core/browser/browser");const CURRENT_TOUR_LOCAL_STORAGE="current_tour";const CURRENT_TOUR_CONFIG_LOCAL_STORAGE="current_tour.config";const CURRENT_TOUR_INDEX_LOCAL_STORAGE="current_tour.index";const CURRENT_TOUR_ON_ERROR_LOCAL_STORAGE="current_tour.on_error";const tourState=__exports.tourState={getCurrentTour(){return browser.localStorage.getItem(CURRENT_TOUR_LOCAL_STORAGE);},setCurrentTour(tourName){browser.localStorage.setItem(CURRENT_TOUR_LOCAL_STORAGE,tourName);},getCurrentIndex(){const index=browser.localStorage.getItem(CURRENT_TOUR_INDEX_LOCAL_STORAGE,"0");return parseInt(index,10);},setCurrentIndex(index){browser.localStorage.setItem(CURRENT_TOUR_INDEX_LOCAL_STORAGE,index.toString());},getCurrentConfig(){const config=browser.localStorage.getItem(CURRENT_TOUR_CONFIG_LOCAL_STORAGE,"{}");return JSON.parse(config);},setCurrentConfig(config){config=JSON.stringify(config);browser.localStorage.setItem(CURRENT_TOUR_CONFIG_LOCAL_STORAGE,config);},getCurrentTourOnError(){return browser.localStorage.getItem(CURRENT_TOUR_ON_ERROR_LOCAL_STORAGE);},setCurrentTourOnError(){browser.localStorage.setItem(CURRENT_TOUR_ON_ERROR_LOCAL_STORAGE,"1");},clear(){browser.localStorage.removeItem(CURRENT_TOUR_ON_ERROR_LOCAL_STORAGE);browser.localStorage.removeItem(CURRENT_TOUR_CONFIG_LOCAL_STORAGE);browser.localStorage.removeItem(CURRENT_TOUR_INDEX_LOCAL_STORAGE);browser.localStorage.removeItem(CURRENT_TOUR_LOCAL_STORAGE);},};return __exports;});; /* /web_tour/static/src/tour_service/tour_step.js */ odoo.define('@web_tour/tour_service/tour_step',['@web/session','@web/core/ui/ui_service','@odoo/hoot-dom','@web/core/utils/objects'],function(require){'use strict';let __exports={};const{session}=require("@web/session");const{utils}=require("@web/core/ui/ui_service");const hoot=require("@odoo/hoot-dom");const{pick}=require("@web/core/utils/objects");const TourStep=__exports.TourStep=class TourStep{constructor(data,tour){Object.assign(this,data);this.tour=tour;} get active(){this.checkHasTour();const mode=this.tour.mode;const isSmall=utils.isSmall();const standardKeyWords=["enterprise","community","mobile","desktop","auto","manual"];const isActiveArray=Array.isArray(this.isActive)?this.isActive:[];if(isActiveArray.length===0){return true;} const selectors=isActiveArray.filter((key)=>!standardKeyWords.includes(key));if(selectors.length){for(const selector of selectors){const el=hoot.queryFirst(selector);if(!el){return false;}}} const checkMode=isActiveArray.includes(mode)||(!isActiveArray.includes("manual")&&!isActiveArray.includes("auto"));const edition=(session.server_version_info||"").at(-1)==="e"?"enterprise":"community";const checkEdition=isActiveArray.includes(edition)||(!isActiveArray.includes("enterprise")&&!isActiveArray.includes("community"));const onlyForMobile=isActiveArray.includes("mobile")&&isSmall;const onlyForDesktop=isActiveArray.includes("desktop")&&!isSmall;const checkDevice=onlyForMobile||onlyForDesktop||(!isActiveArray.includes("mobile")&&!isActiveArray.includes("desktop"));return checkEdition&&checkDevice&&checkMode;} checkHasTour(){if(!this.tour){throw new Error(`TourStep instance must have a tour`);}} get describeMe(){this.checkHasTour();return(`[${this.index + 1}/${this.tour.steps.length}] Tour ${this.tour.name} → Step `+ (this.content?`${this.content} (trigger: ${this.trigger})`:this.trigger));} get stringify(){return(JSON.stringify(pick(this,"isActive","content","trigger","run","tooltipPosition","timeout"),(_key,value)=>{if(typeof value==="function"){return"[function]";}else{return value;}},2)+",");}} return __exports;});; /* /web_tour/static/src/tour_service/tour_step_automatic.js */ odoo.define('@web_tour/tour_service/tour_step_automatic',['@web_tour/tour_service/tour_state','@odoo/hoot-dom','@web_tour/tour_service/tour_utils','@web_tour/tour_service/tour_helpers','@web_tour/tour_service/tour_step','@web/core/utils/xml','@web/core/macro'],function(require){'use strict';let __exports={};const{tourState}=require("@web_tour/tour_service/tour_state");const hoot=require("@odoo/hoot-dom");const{callWithUnloadCheck,serializeChanges,serializeMutation}=require("@web_tour/tour_service/tour_utils");const{TourHelpers}=require("@web_tour/tour_service/tour_helpers");const{TourStep}=require("@web_tour/tour_service/tour_step");const{getTag}=require("@web/core/utils/xml");const{waitForStable}=require("@web/core/macro");const TourStepAutomatic=__exports.TourStepAutomatic=class TourStepAutomatic extends TourStep{skipped=false;error="";constructor(data,tour,index){super(data,tour);this.index=index;this.tourConfig=tourState.getCurrentConfig();} async checkForUndeterminisms(initialElement,delay){if(delay<=0||!initialElement){return;} const tagName=initialElement.tagName?.toLowerCase();if(["body","html"].includes(tagName)||!tagName){return;} const snapshot=initialElement.cloneNode(true);const mutations=await waitForStable(initialElement,delay);let reason;if(!hoot.isVisible(initialElement)){reason=`Initial element is no longer visible`;}else if(!initialElement.isEqualNode(snapshot)){reason=`Initial element has changed:\n`+ JSON.stringify(serializeChanges(snapshot,initialElement),null,2);}else if(mutations.length){const changes=[...new Set(mutations.map(serializeMutation))];reason=`Initial element has mutated ${mutations.length} times:\n`+ JSON.stringify(changes,null,2);} if(reason){throw new Error(`Potential non deterministic behavior found in ${delay}ms for trigger ${this.trigger}.\n${reason}`);}} get describeWhyIFailed(){const errors=[];if(this.element){errors.push(`Element has been found.`);if(this.isUIBlocked){errors.push("BUT: DOM is blocked by UI.");} if(!this.elementIsInModal){errors.push(`BUT: It is not allowed to do action on an element that's below a modal.`);} if(!this.elementIsEnabled){errors.push(`BUT: Element is not enabled. TIP: You can use :enable to wait the element is enabled before doing action on it.`);} if(!this.parentFrameIsReady){errors.push(`BUT: parent frame is not ready ([is-ready='false']).`);}}else{const checkElement=hoot.queryFirst(this.trigger);if(checkElement){errors.push(`Element has been found.`);errors.push(`BUT: Element is not visible. TIP: You can use :not(:visible) to force the search for an invisible element.`);}else{errors.push(`Element (${this.trigger}) has not been found.`);}} return errors;} async doAction(){let result=false;if(!this.skipped){const actionHelper=new TourHelpers(this.element);if(typeof this.run==="function"){const willUnload=await callWithUnloadCheck(async()=>{await this.run.call({anchor:this.element},actionHelper);});result=willUnload&&"will unload";}else if(typeof this.run==="string"){for(const todo of this.run.split("&&")){const m=String(todo).trim().match(/^(?\w*) *\(? *(?.*?)\)?$/);await actionHelper[m.groups?.action](m.groups?.arguments);}}} return result;} findTrigger(){if(!this.active){this.skipped=true;return true;} const visible=!/:(hidden|visible)\b/.test(this.trigger);this.element=hoot.queryFirst(this.trigger,{visible});if(this.element){return!this.isUIBlocked&&this.elementIsEnabled&&this.elementIsInModal&&this.parentFrameIsReady?this.element:false;} return false;} get isUIBlocked(){return(document.body.classList.contains("o_lazy_js_waiting")||document.body.classList.contains("o_ui_blocked")||document.querySelector(".o_blockUI")||document.querySelector(".o_is_blocked"));} get parentFrameIsReady(){const parentFrame=hoot.getParentFrame(this.element);return parentFrame&&parentFrame.hasAttribute("is-ready")?parentFrame.getAttribute("is-ready")==="true":true;} get elementIsInModal(){if(this.hasAction){const overlays=hoot.queryFirst(".popover, .o-we-command, .o_notification");const modal=hoot.queryFirst(".modal:visible:not(.o_inactive_modal):last");if(modal&&!overlays&&!this.trigger.startsWith("body")){return(modal.contains(hoot.getParentFrame(this.element))||modal.contains(this.element));}} return true;} get elementIsEnabled(){const isTag=(array)=>array.includes(getTag(this.element,true));if(this.hasAction){if(isTag(["input","textarea"])){return hoot.isEditable(this.element);}else if(isTag(["button","select"])){return!this.element.disabled;}} return true;} get hasAction(){return["string","function"].includes(typeof this.run)&&!this.skipped;}} return __exports;});; /* /web_tour/static/src/tour_service/tour_utils.js */ odoo.define('@web_tour/tour_service/tour_utils',['@odoo/hoot-dom','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const hoot=require("@odoo/hoot-dom");const{_t}=require("@web/core/l10n/translation");__exports.callWithUnloadCheck=callWithUnloadCheck;function callWithUnloadCheck(func,...args){let willUnload=false;const beforeunload=()=>(willUnload=true);window.addEventListener("beforeunload",beforeunload);const result=func(...args);if(result instanceof Promise){return result.then(()=>{window.removeEventListener("beforeunload",beforeunload);return willUnload;});}else{window.removeEventListener("beforeunload",beforeunload);return willUnload;}} function formatValue(key,value,maxLength=200){if(!value){return"(empty)";} return value.length>maxLength?value.slice(0,maxLength)+"...":value;} function serializeNode(node){if(node.nodeType===Node.TEXT_NODE){return`"${node.nodeValue.trim()}"`;} return node.outerHTML?formatValue("node",node.outerHTML,500):"[Unknown Node]";} __exports.serializeChanges=serializeChanges;function serializeChanges(snapshot,current){const changes={node:serializeNode(current),};function pushChanges(key,obj){changes[key]=changes[key]||[];changes[key].push(obj);} if(snapshot.textContent!==current.textContent){pushChanges("modifiedText",{before:snapshot.textContent,after:current.textContent});} const oldChildren=[...snapshot.childNodes].filter((node)=>node.nodeType!==Node.TEXT_NODE);const newChildren=[...current.childNodes].filter((node)=>node.nodeType!==Node.TEXT_NODE);oldChildren.forEach((oldNode,index)=>{if(!newChildren[index]||!oldNode.isEqualNode(newChildren[index])){pushChanges("removedNodes",{oldNode:serializeNode(oldNode)});}});newChildren.forEach((newNode,index)=>{if(!oldChildren[index]||!newNode.isEqualNode(oldChildren[index])){pushChanges("addedNodes",{newNode:serializeNode(newNode)});}});const oldAttrNames=new Set([...snapshot.attributes].map((attr)=>attr.name));const newAttrNames=new Set([...current.attributes].map((attr)=>attr.name));new Set([...oldAttrNames,...newAttrNames]).forEach((attributeName)=>{const oldValue=snapshot.getAttribute(attributeName);const newValue=current.getAttribute(attributeName);const before=oldValue!==newValue||!newAttrNames.has(attributeName)?oldValue:null;const after=oldValue!==newValue||!oldAttrNames.has(attributeName)?newValue:null;if(before||after){pushChanges("modifiedAttributes",{attributeName,before,after});}});return changes;} __exports.serializeMutation=serializeMutation;function serializeMutation(mutation){const{type,attributeName}=mutation;if(type==="attributes"&&attributeName){return`attribute: ${attributeName}`;}else{return type;}} __exports.getScrollParent=getScrollParent;function getScrollParent(element){if(!element){return null;} const overflowY=window.getComputedStyle(element).overflowY;const isScrollable=overflowY==="auto"||overflowY==="scroll"||(overflowY==="visible"&&element===element.ownerDocument.scrollingElement);if(isScrollable){return element;}else{return getScrollParent(element.parentNode);}} const stepUtils=__exports.stepUtils={_getHelpMessage(functionName,...args){return`Generated by function tour utils ${functionName}(${args.join(", ")})`;},addDebugHelp(helpMessage,step){if(typeof step.debugHelp==="string"){step.debugHelp=step.debugHelp+"\n"+helpMessage;}else{step.debugHelp=helpMessage;} return step;},showAppsMenuItem(){return{isActive:["auto","community","desktop"],trigger:".o_navbar_apps_menu button:enabled",tooltipPosition:"bottom",run:"click",};},toggleHomeMenu(){return[{isActive:[".o_main_navbar .o_menu_toggle"],trigger:".o_main_navbar .o_menu_toggle",content:_t("Click the top left corner to navigate across apps."),tooltipPosition:"bottom",run:"click",},{isActive:["mobile"],trigger:".o_sidebar_topbar a.btn-primary",tooltipPosition:"right",run:"click",},];},autoExpandMoreButtons(isActiveMobile=false){const isActive=["auto"];if(isActiveMobile){isActive.push("mobile");} return{isActive,content:`autoExpandMoreButtons`,trigger:".o-form-buttonbox",run(){const more=hoot.queryFirst(".o-form-buttonbox .o_button_more");if(more){hoot.click(more);}},};},goToAppSteps(dataMenuXmlid,description){return[this.showAppsMenuItem(),{isActive:["community"],trigger:`.o_app[data-menu-xmlid="${dataMenuXmlid}"]`,content:description,tooltipPosition:"right",run:"click",},{isActive:["enterprise"],trigger:`.o_app[data-menu-xmlid="${dataMenuXmlid}"]`,content:description,tooltipPosition:"bottom",run:"click",},].map((step)=>this.addDebugHelp(this._getHelpMessage("goToApp",dataMenuXmlid,description),step));},statusbarButtonsSteps(innerTextButton,description,trigger){const steps=[];if(trigger){steps.push({isActive:["auto","mobile"],trigger,});} steps.push({isActive:["auto","mobile"],trigger:".o_cp_action_menus",run:(actions)=>{const node=hoot.queryFirst(".o_cp_action_menus .fa-cog");if(node){hoot.click(node);}},},{trigger:`.o_statusbar_buttons button:enabled:contains('${innerTextButton}'), .dropdown-item button:enabled:contains('${innerTextButton}')`,content:description,tooltipPosition:"bottom",run:"click",});return steps.map((step)=>this.addDebugHelp(this._getHelpMessage("statusbarButtonsSteps",innerTextButton,description),step));},mobileKanbanSearchMany2X(modalTitle,valueSearched){return[{isActive:["mobile"],trigger:`.modal:not(.o_inactive_modal) .o_control_panel_navigation .btn .fa-search`,tooltipPosition:"bottom",run:"click",},{isActive:["mobile"],trigger:".o_searchview_input",tooltipPosition:"bottom",run:`edit ${valueSearched}`,},{isActive:["mobile"],trigger:".dropdown-menu.o_searchview_autocomplete",},{isActive:["mobile"],trigger:".o_searchview_input",tooltipPosition:"bottom",run:"press Enter",},{isActive:["mobile"],trigger:`.o_kanban_record:contains('${valueSearched}')`,tooltipPosition:"bottom",run:"click",},].map((step)=>this.addDebugHelp(this._getHelpMessage("mobileKanbanSearchMany2X",modalTitle,valueSearched),step));},saveForm(){return[{isActive:["auto"],content:"save form",trigger:".o_form_button_save:enabled",run:"click",},{content:"wait for save completion",trigger:".o_form_readonly, .o_form_saved",},];},discardForm(){return[{isActive:["auto"],content:"discard the form",trigger:".o_form_button_cancel",run:"click",},{content:"wait for cancellation to complete",trigger:".o_view_controller.o_list_view, .o_form_view > div > div > .o_form_readonly, .o_form_view > div > div > .o_form_saved",},];},waitIframeIsReady(){return{content:"Wait until the iframe is ready",trigger:`iframe[is-ready=true]:iframe html`,};},goToUrl(url){return{isActive:["auto"],content:`Navigate to ${url}`,trigger:"body",run:`goToUrl ${url}`,};},};return __exports;});; /* /web/static/lib/hoot-dom/helpers/dom.js */ odoo.define('@web/../lib/hoot-dom/helpers/dom',['@web/../lib/hoot-dom/hoot_dom_utils','@web/../lib/hoot-dom/helpers/time'],function(require){'use strict';let __exports={};const{HootDomError,getTag,isFirefox,isIterable,parseRegExp}=require("@web/../lib/hoot-dom/hoot_dom_utils");const{waitUntil}=require("@web/../lib/hoot-dom/helpers/time");const{Boolean,document,DOMParser,innerWidth,innerHeight,Map,MutationObserver,Number:{isInteger:$isInteger,isNaN:$isNaN,parseInt:$parseInt,parseFloat:$parseFloat},Object:{keys:$keys,values:$values},RegExp,Set,}=globalThis;const and=(values)=>{const last=values.pop();if(values.length){return[values.join(", "),last].join(" and ");}else{return last;}};const compilePseudoClassRegex=()=>{const customKeys=[...customPseudoClasses.keys()].filter((k)=>k!=="has"&&k!=="not");return new RegExp(`:(${customKeys.join("|")})`);};const elementsMatch=(elements,selector)=>{if(!elements.length){return false;} return parseSelector(selector).some((selectorParts)=>{const[baseSelector,...filters]=selectorParts.at(-1);for(let i=0;imatchFilter(filter,elements,i))){return false;}} return true;});};const ensureElement=(node)=>{if(node){if(isDocument(node)){return node.documentElement;} if(isWindow(node)){return node.document.documentElement;} if(isElement(node)){return node;}} return null;};const extractLayers=(nodes,level,keepInlineTextNodes)=>{const layers=[];for(const node of nodes){if(node.nodeType===Node.COMMENT_NODE){continue;} if(node.nodeType===Node.TEXT_NODE){const textContent=node.nodeValue.replaceAll(/\n/g,"");const trimmedTextContent=textContent.trim();if(trimmedTextContent){const inline=textContent===trimmedTextContent;layers.push({inline,level,value:{textContent:trimmedTextContent}});} continue;} const[open,close]=node.outerHTML.replace(`>${node.innerHTML}<`,">\n<").split("\n");const layer={inline:false,level,value:{open,close}};layers.push(layer);const childLayers=extractLayers(node.childNodes,level+1,false);if(keepInlineTextNodes&&childLayers.length===1&&childLayers[0].inline){layer.value.textContent=childLayers[0].value.textContent;}else{layers.push(...childLayers);}} return layers;};const filterUniqueNodes=(nodesToFilter)=>{const nodes=[];for(const node of nodesToFilter){if(isQueryableNode(node)&&!nodes.includes(node)){nodes.push(node);}} return nodes;};const generateStringFromLayers=(layers,tabSize)=>{const result=[];let layerIndex=0;while(layers.length>0){const layer=layers[layerIndex];const{level,value}=layer;const pad=" ".repeat(tabSize*level);let nextLayerIndex=layerIndex+1;if(value.open){if(value.textContent){result.push(`${pad}${value.open}${value.textContent}${value.close}`);layers.splice(layerIndex,1);nextLayerIndex--;}else{result.push(`${pad}${value.open}`);delete value.open;}}else{if(value.close){result.push(`${pad}${value.close}`);}else if(value.textContent){result.push(`${pad}${value.textContent}`);} layers.splice(layerIndex,1);nextLayerIndex--;} if(nextLayerIndex>=layers.length){layerIndex=nextLayerIndex-1;continue;} const nextLayer=layers[nextLayerIndex];if(nextLayerIndex===0||nextLayer.level>layers[nextLayerIndex-1].level){layerIndex=nextLayerIndex;}else{layerIndex=nextLayerIndex-1;}} return result.join("\n");};const getNodeContent=(node)=>{switch(getTag(node)){case"input":case"option":case"textarea":return getNodeValue(node);case"select":return[...node.selectedOptions].map(getNodeValue).join(",");} return getNodeText(node);};const getStringContent=(string)=>string.match(R_QUOTE_CONTENT)?.[2]||string;const isChar=(char)=>Boolean(char)&&R_CHAR.test(char);const isDocument=(object)=>object?.nodeType===Node.DOCUMENT_NODE;const isElement=(object)=>object?.nodeType===Node.ELEMENT_NODE;const isQueryableNode=(node)=>QUERYABLE_NODE_TYPES.includes(node.nodeType);const isRootElement=(el)=>el&&R_ROOT_ELEMENT.test(el.nodeName||"");const isShadowRoot=(el)=>el.nodeType===Node.DOCUMENT_FRAGMENT_NODE&&Boolean(el.host);const isWindow=(object)=>object?.window===object&&object.constructor.name==="Window";const isWhiteSpace=(char)=>Boolean(char)&&R_HORIZONTAL_WHITESPACE.test(char);const makePatternBasedPseudoClass=(pseudoClass,getContent)=>{return(content)=>{let regex;try{regex=parseRegExp(content);}catch(err){throw selectorError(pseudoClass,err.message);} if(regex instanceof RegExp){return function containsRegExp(node){return regex.test(String(getContent(node)));};}else{const lowerContent=content.toLowerCase();return function containsString(node){return getStringContent(String(getContent(node))).toLowerCase().includes(lowerContent);};}};};const matchFilter=(filter,nodes,index)=>{const node=nodes[index];if(typeof filter==="function"){return filter(node,index,nodes);}else{return node.matches?.(String(filter));}};const parseNumberTuple=(value,propsA,propsB)=>{let result=[];if(value&&typeof value==="object"){if(isIterable(value)){[result[0],result[1]]=[...value];}else{for(const prop of propsA){result[0]??=value[prop];} for(const prop of propsB){result[1]??=value[prop];}}}else{result=[value,value];} return result.map($parseFloat);};const parseSelector=(selector)=>{const addToSelector=(selector)=>{registerChar=false;const index=currentPart.length-1;if(typeof currentPart[index]==="string"){currentPart[index]+=selector;}else{currentPart.push(selector);}};const firstPart=[""];const firstGroup=[firstPart];const groups=[firstGroup];const parens=[0,0];let currentGroup=groups.at(-1);let currentPart=currentGroup.at(-1);let currentPseudo=null;let currentQuote=null;let registerChar=true;for(let i=0;i1){currentGroup.push([""]);currentPart=currentGroup.at(-1);} registerChar=false;} break;} case`'`:case`"`:{if(char===currentQuote){currentQuote=null;}else if(!currentQuote){currentQuote=char;} break;} case">":case"+":case"~":{if(!currentQuote&&!currentPseudo){while(isWhiteSpace(selector[i+1])){i++;} addToSelector(char);} break;} case":":{if(!currentQuote&&!currentPseudo){let pseudo="";while(isChar(selector[i+1])){pseudo+=selector[++i];} if(customPseudoClasses.has(pseudo)){if(selector[i+1]==="("){parens[0]++;i++;registerChar=false;} currentPseudo=[pseudo,""];}else{addToSelector(char+pseudo);}} break;} case"(":{if(!currentQuote){parens[0]++;} break;} case")":{if(!currentQuote){parens[1]++;} break;}} if(currentPseudo){if(parens[0]===parens[1]){const[pseudo,content]=currentPseudo;const makeFilter=customPseudoClasses.get(pseudo);if(pseudo==="iframe"&&!currentPart[0].startsWith("iframe")){currentPart[0]=`iframe${currentPart[0]}`;} currentPart.push(makeFilter(getStringContent(content)));currentPseudo=null;}else if(registerChar){currentPseudo[1]+=selector[i];}}else if(registerChar){addToSelector(selector[i]);}} return groups;};const parseXml=(xmlString,type)=>{const wrapperTag=type==="html"?"body":"templates";const document=parser.parseFromString(`<${wrapperTag}>${xmlString}`,`text/${type}`);if(document.getElementsByTagName("parsererror").length){const trimmed=xmlString.length>80?xmlString.slice(0,80)+"…":xmlString;throw new HootDomError(`error while parsing ${trimmed}: ${getNodeText( document.getElementsByTagName("parsererror")[0] )}`);} return document.getElementsByTagName(wrapperTag)[0].childNodes;};const pixelValueToNumber=(val)=>$parseFloat(val.endsWith("px")?val.slice(0,-2):val);const queryWithCustomSelector=(nodes,selector)=>{const selectorGroups=parseSelector(selector);const foundNodes=[];for(const selectorParts of selectorGroups){let groupNodes=nodes;for(const[partSelector,...filters]of selectorParts){let baseSelector=partSelector;let nodeGetter;switch(baseSelector[0]){case"+":{nodeGetter=NEXT_SIBLING;break;} case">":{nodeGetter=DIRECT_CHILDREN;break;} case"~":{nodeGetter=NEXT_SIBLINGS;break;}} if(nodeGetter){baseSelector=baseSelector.slice(1);} const getNodes=nodeGetter||DESCENDANTS;let currentGroupNodes=groupNodes.flatMap((node)=>getNodes(node,baseSelector));const pseudosReturningNode=new Set();for(const filter of filters){const filteredGroupNodes=[];for(let i=0;i1){const pseudoList=[...pseudosReturningNode];throw selectorError(pseudoList[0],`cannot use multiple pseudo-classes returning nodes (${and(pseudoList)})`);} currentGroupNodes=filteredGroupNodes;} groupNodes=currentGroupNodes;} foundNodes.push(...groupNodes);} return filterUniqueNodes(foundNodes);};const selectorError=(pseudoClass,message)=>new HootDomError(`invalid selector \`:${pseudoClass}\`: ${message}`);const R_CHAR=/[\w-]/;const R_QUOTE_CONTENT=/^\s*(['"])?([^]*?)\1\s*$/;const R_ROOT_ELEMENT=/^(HTML|HEAD|BODY)$/;const R_HORIZONTAL_WHITESPACE=/[\r\t\f \u00a0\u1680\u2000-\u200a\u2028\u2029\u202f\u205f\u3000\ufeff]+/g;const QUERYABLE_NODE_TYPES=[Node.ELEMENT_NODE,Node.DOCUMENT_NODE,Node.DOCUMENT_FRAGMENT_NODE];const parser=new DOMParser();const DIRECT_CHILDREN=(node,selector)=>{const children=[];for(const childNode of node.childNodes){if(childNode.matches?.(selector)){children.push(childNode);}} return children;};const DESCENDANTS=(node,selector)=>[...(node.querySelectorAll?.(selector||"*")||[])];const NEXT_SIBLING=(node,selector)=>{const sibling=node.nextElementSibling;return sibling?.matches?.(selector)?[sibling]:[];};const NEXT_SIBLINGS=(node,selector)=>{const siblings=[];while((node=node.nextElementSibling)){if(node.matches?.(selector)){siblings.push(node);}} return siblings;};const observers=new Map();const currentDimensions={width:innerWidth,height:innerHeight,};let getDefaultRoot=()=>document;const customPseudoClasses=new Map();customPseudoClasses.set("contains",makePatternBasedPseudoClass("contains",getNodeText)).set("displayed",()=>{return function displayed(node){return isNodeDisplayed(node);};}).set("empty",()=>{return function empty(node){return isEmpty(node);};}).set("eq",(content)=>{const index=$parseInt(content);if(!$isInteger(index)){throw selectorError("eq",`expected index to be an integer (got ${content})`);} return function eq(node,i,nodes){return index<0?i===nodes.length+index:i===index;};}).set("first",()=>{return function first(node,i){return i===0;};}).set("focusable",()=>{return function focusable(node){return isNodeFocusable(node);};}).set("has",(content)=>{return function has(node){return Boolean(queryAll(content,{root:node}).length);};}).set("hidden",()=>{return function hidden(node){return!isNodeVisible(node);};}).set("iframe",()=>{return function iframe(node){const doc=node.contentDocument;return doc&&doc.readyState!=="loading"?doc:false;};}).set("last",()=>{return function last(node,i,nodes){return i===nodes.length-1;};}).set("not",(content)=>{return function not(node){return!matches(node,content);};}).set("only",()=>{return function only(node,i,nodes){return nodes.length===1;};}).set("scrollable",()=>{return function scrollable(node){return isNodeScrollable(node);};}).set("selected",()=>{return function selected(node){return Boolean(node.selected);};}).set("shadow",()=>{return function shadow(node){return node.shadowRoot||false;};}).set("value",makePatternBasedPseudoClass("value",getNodeValue)).set("visible",()=>{return function visible(node){return isNodeVisible(node);};});const rCustomPseudoClass=compilePseudoClassRegex();__exports.cleanupDOM=cleanupDOM;function cleanupDOM(){currentDimensions.width=innerWidth;currentDimensions.height=innerHeight;const remainingObservers=observers.size;if(remainingObservers){for(const{observer}of observers.values()){observer.disconnect();} observers.clear();}} __exports.defineRootNode=defineRootNode;function defineRootNode(node){if(typeof node==="function"){getDefaultRoot=node;}else if(node){getDefaultRoot=()=>node;}else{getDefaultRoot=()=>document;}} __exports.getCurrentDimensions=getCurrentDimensions;function getCurrentDimensions(){return currentDimensions;} __exports.getDocument=getDocument;function getDocument(node){node||=getDefaultRoot();return isDocument(node)?node:node.ownerDocument||document;} __exports.getNodeAttribute=getNodeAttribute;function getNodeAttribute(node,attribute){return node.getAttribute?.(attribute)??null;} __exports.getNodeValue=getNodeValue;function getNodeValue(node){switch(node.type){case"checkbox":case"radio":return node.checked;case"file":return[...node.files];case"number":case"range":return node.valueAsNumber;case"date":case"datetime-local":case"month":case"time":case"week":return node.valueAsDate.toISOString();} return node.value;} __exports.getNodeRect=getNodeRect;function getNodeRect(node,options){if(!isElement(node)){return new DOMRect();} const rect=node.getBoundingClientRect();const parentFrame=getParentFrame(node);if(parentFrame){const parentRect=getNodeRect(parentFrame);rect.x-=parentRect.x;rect.y-=parentRect.y;} if(!options?.trimPadding){return rect;} const style=getStyle(node);const{x,y,width,height}=rect;const[pl,pr,pt,pb]=["left","right","top","bottom"].map((side)=>pixelValueToNumber(style.getPropertyValue(`padding-${side}`)));return new DOMRect(x+pl,y+pt,width-(pl+pr),height-(pt+pb));} __exports.getNodeText=getNodeText;function getNodeText(node,options){let content;if(typeof node.innerText==="string"){content=node.innerText;}else{content=node.textContent;} if(options?.raw){return content;} return content.replace(R_HORIZONTAL_WHITESPACE," ").trim();} __exports.getStyle=getStyle;function getStyle(node){return isElement(node)?getComputedStyle(node):null;} __exports.getWindow=getWindow;function getWindow(node){return getDocument(node).defaultView;} __exports.isCheckable=isCheckable;function isCheckable(node){switch(getTag(node)){case"input":return node.type==="checkbox"||node.type==="radio";case"label":return isCheckable(node.control);default:return false;}} __exports.isEmpty=isEmpty;function isEmpty(value){if(!value){return true;} if(typeof value==="object"){if(isNode(value)){return isEmpty(getNodeContent(value));} if(!isIterable(value)){value=$keys(value);} return[...value].length===0;} return false;} __exports.isEventTarget=isEventTarget;function isEventTarget(object){return object&&typeof object.addEventListener==="function";} __exports.isNode=isNode;function isNode(object){return object&&typeof object.nodeType==="number"&&typeof object.nodeName==="string";} __exports.isNodeCssVisible=isNodeCssVisible;function isNodeCssVisible(node){const element=ensureElement(node);if(element===getDefaultRoot()||isRootElement(element)){return true;} const style=getStyle(element);if(style?.visibility==="hidden"||style?.opacity==="0"){return false;} const parent=element.parentNode;return!parent||isNodeCssVisible(isShadowRoot(parent)?parent.host:parent);} __exports.isNodeDisplayed=isNodeDisplayed;function isNodeDisplayed(node){const element=ensureElement(node);if(!isInDOM(element)){return false;} if(isRootElement(element)||element.offsetParent||element.closest("svg")){return true;} return!isFirefox()&&getStyle(element)?.position==="fixed";} __exports.isNodeFocusable=isNodeFocusable;function isNodeFocusable(node,options){return(isNodeDisplayed(node)&&node.matches?.(FOCUSABLE_SELECTOR)&&(!options?.tabbable||node.tabIndex>=0));} __exports.isNodeInViewPort=isNodeInViewPort;function isNodeInViewPort(node){const element=ensureElement(node);const{x,y}=getNodeRect(element);return y>0&&y0&&xnode[sizeProp]){const overflow=getStyle(node).getPropertyValue("overflow");if(/\bauto\b|\bscroll\b/.test(overflow)){return true;}} return false;} __exports.isNodeVisible=isNodeVisible;function isNodeVisible(node){const element=ensureElement(node);if(!isNodeDisplayed(element)||!isNodeCssVisible(element)){return false;} let visible=false;const{width,height}=getNodeRect(element);visible=width>0&&height>0;if(!visible&&getStyle(element)?.display==="contents"){for(const child of element.childNodes){if(isNodeVisible(child)){return true;}}} return visible;} __exports.parseDimensions=parseDimensions;function parseDimensions(dimensions){return parseNumberTuple(dimensions,["width","w"],["height","h"]);} __exports.parsePosition=parsePosition;function parsePosition(position){return parseNumberTuple(position,["x","left","clientX","pageX","screenX"],["y","top","clientY","pageY","screenY"]);} __exports.setDimensions=setDimensions;function setDimensions(width,height){const defaultRoot=getDefaultRoot();if(!$isNaN(width)){currentDimensions.width=width;defaultRoot.style?.setProperty("width",`${width}px`,"important");} if(!$isNaN(height)){currentDimensions.height=height;defaultRoot.style?.setProperty("height",`${height}px`,"important");}} __exports.toSelector=toSelector;function toSelector(node,options){const parts={tag:node.nodeName.toLowerCase(),};if(node.id){parts.id=`#${node.id}`;} if(node.classList?.length){parts.class=`.${[...node.classList].join(".")}`;} return options?.object?parts:$values(parts).join("");} const FOCUSABLE_SELECTOR=__exports.FOCUSABLE_SELECTOR=["a[href]","area[href]","button:enabled","details > summary:first-of-type","iframe","input:enabled","select:enabled","textarea:enabled","[tabindex]","[contenteditable=true]",].join(",");__exports.formatXml=formatXml;function formatXml(value,options){const nodes=parseXml(value,options?.type||"xml");const layers=extractLayers(nodes,0,options?.keepInlineTextNodes??false);return generateStringFromLayers(layers,options?.tabSize??4);} __exports.getActiveElement=getActiveElement;function getActiveElement(node){const document=getDocument(node);const window=getWindow(node);const{activeElement}=document;const{contentDocument,shadowRoot}=activeElement;if(contentDocument&&contentDocument.activeElement!==contentDocument.body){if(contentDocument.activeElement===contentDocument.body){return contentDocument.activeElement}else{return getActiveElement(contentDocument);}} if(shadowRoot){return shadowRoot.activeElement;} if(activeElement===document.body&&window!==window.parent){return getActiveElement(window.parent.document);} return activeElement;} __exports.getFocusableElements=getFocusableElements;function getFocusableElements(options){const parent=queryOne(options?.root||getDefaultRoot());if(typeof parent.querySelectorAll!=="function"){return[];} const byTabIndex={};for(const element of parent.querySelectorAll(FOCUSABLE_SELECTOR)){const{tabIndex}=element;if((options?.tabbable&&tabIndex<0)||!isNodeDisplayed(element)){continue;} if(!byTabIndex[tabIndex]){byTabIndex[tabIndex]=[];} byTabIndex[tabIndex].push(element);} const withTabIndexZero=byTabIndex[0]||[];delete byTabIndex[0];return[...$values(byTabIndex).flat(),...withTabIndexZero];} __exports.getNextFocusableElement=getNextFocusableElement;function getNextFocusableElement(options){const parent=queryOne(options?.root||getDefaultRoot());const focusableEls=getFocusableElements({...options,parent});const index=focusableEls.indexOf(getActiveElement(parent));return focusableEls[index+1]||null;} __exports.getParentFrame=getParentFrame;function getParentFrame(node){const document=getDocument(node);if(!document){return null;} const view=document.defaultView;if(view!==view.parent){for(const iframe of view.parent.document.getElementsByTagName("iframe")){if(iframe.contentWindow===view){return iframe;}}} return null;} __exports.getPreviousFocusableElement=getPreviousFocusableElement;function getPreviousFocusableElement(options){const parent=queryOne(options?.root||getDefaultRoot());const focusableEls=getFocusableElements({...options,parent});const index=focusableEls.indexOf(getActiveElement(parent));return index<0?focusableEls.at(-1):focusableEls[index-1]||null;} __exports.isDisplayed=isDisplayed;function isDisplayed(target){return queryAll(target,{displayed:true}).length>0;} __exports.isEditable=isEditable;function isEditable(node){return(isElement(node)&&!node.matches?.(":disabled")&&["input","textarea"].includes(getTag(node)));} __exports.isFocusable=isFocusable;function isFocusable(target,options){const nodes=queryAll(...arguments);return nodes.length&&nodes.every((node)=>isNodeFocusable(node,options));} __exports.isInDOM=isInDOM;function isInDOM(target){return ensureElement(target)?.isConnected;} __exports.isInViewPort=isInViewPort;function isInViewPort(target){return queryAll(target,{viewPort:true}).length>0;} __exports.isScrollable=isScrollable;function isScrollable(target,axis){const nodes=queryAll(target);return nodes.length&&nodes.every((node)=>isNodeScrollable(node,axis));} __exports.isVisible=isVisible;function isVisible(target){return queryAll(target,{visible:true}).length>0;} __exports.matches=matches;function matches(target,selector){return elementsMatch(queryAll(target),selector);} __exports.observe=observe;function observe(target,callback){if(observers.has(target)){observers.get(target).callbacks.add(callback);}else{const callbacks=new Set([callback]);const observer=new MutationObserver((mutations,observer)=>{for(const callback of callbacks){callback(mutations,observer);}});observer.observe(target,{attributes:true,characterData:true,childList:true,subtree:true,});observers.set(target,{callbacks,observer});} return function disconnect(){if(!observers.has(target)){return;} const{callbacks,observer}=observers.get(target);callbacks.delete(callback);if(!callbacks.size){observer.disconnect();observers.delete(target);}};} __exports.queryAll=queryAll;function queryAll(target,options){if(!target){return[];} if(target.raw){return queryAll(String.raw(...arguments));} const{exact,displayed,root,viewPort,visible}=options||{};let nodes=[];let selector;if(typeof target==="string"){nodes=root?queryAll(root):[getDefaultRoot()];selector=target.trim();}else if(isIterable(target)&&!isNode(target)){nodes=filterUniqueNodes(target);}else{nodes=filterUniqueNodes([target]);} if(selector&&nodes.length){if(rCustomPseudoClass.test(selector)){nodes=queryWithCustomSelector(nodes,selector);}else{nodes=filterUniqueNodes(nodes.flatMap((node)=>DESCENDANTS(node,selector)));}} let prefix,suffix;if(visible+displayed>1){throw new HootDomError(`cannot use more than one visibility modifier ('visible' implies 'displayed')`);} if(viewPort){nodes=nodes.filter(isNodeInViewPort);suffix="in viewport";}else if(visible){nodes=nodes.filter(isNodeVisible);prefix="visible";}else if(displayed){nodes=nodes.filter(isNodeDisplayed);prefix="displayed";} const count=nodes.length;if($isInteger(exact)&&count!==exact){const s=count===1?"":"s";const strPrefix=prefix?`${prefix} `:"";const strSuffix=suffix?` ${suffix}`:"";const strSelector=typeof target==="string"?`(selector: "${target}")`:"";throw new HootDomError(`found ${count} ${strPrefix}node${s}${strSuffix} instead of ${exact} ${strSelector}`);} return nodes;} __exports.queryAttribute=queryAttribute;function queryAttribute(target,attribute,options){return getNodeAttribute(queryOne(target,options),attribute);} __exports.queryAllAttributes=queryAllAttributes;function queryAllAttributes(target,attribute,options){return queryAll(target,options).map((node)=>getNodeAttribute(node,attribute));} __exports.queryAllProperties=queryAllProperties;function queryAllProperties(target,property,options){return queryAll(target,options).map((node)=>node[property]);} __exports.queryAllRects=queryAllRects;function queryAllRects(target,options){return queryAll(...arguments).map(getNodeRect);} __exports.queryAllTexts=queryAllTexts;function queryAllTexts(target,options){return queryAll(...arguments).map((node)=>getNodeText(node,options));} __exports.queryAllValues=queryAllValues;function queryAllValues(target,options){return queryAll(...arguments).map(getNodeValue);} __exports.queryFirst=queryFirst;function queryFirst(target,options){return queryAll(...arguments)[0]||null;} __exports.queryOne=queryOne;function queryOne(target,options){if(target.raw){return queryOne(String.raw(...arguments));} if($isInteger(options?.exact)){throw new HootDomError(`cannot call \`queryOne\` with 'exact'=${options.exact}: did you mean to use \`queryAll\`?`);} return queryAll(target,{...options,exact:1})[0];} __exports.queryRect=queryRect;function queryRect(target,options){return getNodeRect(queryOne(...arguments),options);} __exports.queryText=queryText;function queryText(target,options){return getNodeText(queryOne(...arguments),options);} __exports.queryValue=queryValue;function queryValue(target,options){return getNodeValue(queryOne(...arguments));} __exports.waitFor=waitFor;function waitFor(target,options){return waitUntil(()=>queryFirst(...arguments),{message:`Could not find elements matching "${target}" within %timeout% milliseconds`,...options,});} __exports.waitForNone=waitForNone;function waitForNone(target,options){let count=0;return waitUntil(()=>{count=queryAll(...arguments).length;return!count;},{message:()=>`Could still find ${count} elements matching "${target}" after %timeout% milliseconds`,...options,});} return __exports;});; /* /web/static/lib/hoot-dom/helpers/events.js */ odoo.define('@web/../lib/hoot-dom/helpers/events',['@web/../lib/hoot-dom/hoot_dom_utils','@web/../lib/hoot-dom/helpers/dom','@web/../lib/hoot-dom/helpers/time'],function(require){'use strict';let __exports={};const{HootDomError,getTag,isFirefox,isIterable}=require("@web/../lib/hoot-dom/hoot_dom_utils");const{getActiveElement,getDocument,getNextFocusableElement,getNodeRect,getNodeValue,getParentFrame,getPreviousFocusableElement,getStyle,getWindow,isCheckable,isEditable,isEventTarget,isNode,isNodeFocusable,parseDimensions,parsePosition,queryAll,queryFirst,setDimensions,toSelector,}=require("@web/../lib/hoot-dom/helpers/dom");const{microTick}=require("@web/../lib/hoot-dom/helpers/time");const{AnimationEvent,ClipboardEvent,CompositionEvent,console:{dir:$dir,groupCollapsed:$groupCollapsed,groupEnd:$groupEnd,log:$log},DataTransfer,document,DragEvent,ErrorEvent,Event,FocusEvent,KeyboardEvent,Math:{ceil:$ceil,max:$max,min:$min},MouseEvent,Number:{isInteger:$isInteger,isNaN:$isNaN,parseFloat:$parseFloat},Object:{assign:$assign,values:$values},PointerEvent,PromiseRejectionEvent,String,SubmitEvent,Touch,TouchEvent,TypeError,WheelEvent,}=globalThis;const $createRange=document.createRange.bind(document);const cancelTrustedEvent=(ev)=>{if(ev.isTrusted&&runTime.eventsToIgnore.includes(ev.type)){runTime.eventsToIgnore.splice(runTime.eventsToIgnore.indexOf(ev.type),1);ev.stopPropagation();ev.stopImmediatePropagation();ev.preventDefault();}};const changeSelection=async(target,start,end)=>{if(!isNil(start)&&!isNil(target.selectionStart)){target.selectionStart=start;} if(!isNil(end)&&!isNil(target.selectionEnd)){target.selectionEnd=end;}};const constrainScrollX=(target,x)=>{let{offsetWidth,scrollWidth}=target;const document=getDocument(target);if(target===document||target===document.documentElement){const iframe=getParentFrame(target);if(iframe){({offsetWidth}=iframe);}} const maxScrollLeft=scrollWidth-offsetWidth;const{direction}=getStyle(target);const[min,max]=direction==="rtl"?[-maxScrollLeft,0]:[0,maxScrollLeft];return $min($max(x,min),max);};const constrainScrollY=(target,y)=>{let{offsetHeight,scrollHeight}=target;const document=getDocument(target);if(target===document||target===document.documentElement){const iframe=getParentFrame(target);if(iframe){({offsetHeight}=iframe);}} return $min($max(y,0),scrollHeight-offsetHeight);};const deleteSelection=(target)=>{const{selectionStart,selectionEnd,value}=target;return value.slice(0,selectionStart)+value.slice(selectionEnd);};const dispatchAndIgnore=async({target,events,additionalEvents=[],callback,options})=>{for(const eventType of[...events,...additionalEvents]){runTime.eventsToIgnore.push(eventType);} if(callback){callback(target);} for(const eventType of events){await dispatch(target,eventType,options);}};const dispatchPointerEvent=async(target,eventType,eventInit,{mouse,touch})=>{const pointerEvent=await dispatch(target,eventType,eventInit);let prevented=isPrevented(pointerEvent);if(hasTouch()){if(touch&&runTime.pointerDownTarget){const[touchEventType,touchEventInit]=touch;await dispatch(runTime.pointerDownTarget,touchEventType,touchEventInit||eventInit);}}else{if(mouse&&!prevented){const[mouseEventType,mouseEventInit]=mouse;const mouseEvent=await dispatch(target,mouseEventType,mouseEventInit||eventInit);prevented=isPrevented(mouseEvent);}} return prevented;};const dispatchRelatedEvents=async(events,eventType,eventInit)=>{for(const event of events){if(!event.target||isPrevented(event)){break;} await dispatch(event.target,eventType,eventInit);}};const ensureArray=(value)=>(isIterable(value)?[...value]:[value]);const getCurrentEvents=()=>{const eventType=currentEventTypes.at(-1);if(!eventType){return[];} currentEvents[eventType]||=[];return currentEvents[eventType];};const getDefaultRunTimeValue=()=>({isComposing:false,canStartDrag:false,isDragging:false,lastDragOverCancelled:false,clickCount:0,key:null,pointerDownTarget:null,pointerDownTimeout:0,pointerTarget:null,position:{},previousPointerDownTarget:null,previousPointerTarget:null,touchStartPosition:{},fileInput:null,buttons:0,modifierKeys:{},eventsToIgnore:[],});const getDifferentParents=(el1,el2)=>{if(!el1&&!el2){return[];}else if(!el1&&el2){[el1,el2]=[el2,el1];} const parents=[el2||el1];while(parents[0].parentElement){const parent=parents[0].parentElement;if(el2&&parent.contains(el1)){break;} parents.unshift(parent);} return parents;};const getEventConstructor=(eventType)=>{switch(eventType){case"dblclick":case"mousedown":case"mouseup":case"mousemove":case"mouseover":case"mouseout":return[MouseEvent,mapMouseEvent,BUBBLES|CANCELABLE|VIEW];case"mouseenter":case"mouseleave":return[MouseEvent,mapMouseEvent,VIEW];case"auxclick":case"click":case"contextmenu":case"pointerdown":case"pointerup":case"pointermove":case"pointerover":case"pointerout":return[PointerEvent,mapPointerEvent,BUBBLES|CANCELABLE|VIEW];case"pointerenter":case"pointerleave":case"pointercancel":return[PointerEvent,mapPointerEvent,VIEW];case"blur":case"focus":return[FocusEvent,mapEvent];case"focusin":case"focusout":return[FocusEvent,mapEvent,BUBBLES];case"cut":case"copy":case"paste":return[ClipboardEvent,mapEvent,BUBBLES];case"keydown":case"keyup":return[KeyboardEvent,mapKeyboardEvent,BUBBLES|CANCELABLE|VIEW];case"drag":case"dragend":case"dragenter":case"dragstart":case"dragleave":case"dragover":case"drop":return[DragEvent,mapEvent,BUBBLES];case"beforeinput":return[InputEvent,mapInputEvent,BUBBLES|CANCELABLE|VIEW];case"input":return[InputEvent,mapInputEvent,BUBBLES|VIEW];case"compositionstart":case"compositionend":return[CompositionEvent,mapEvent,BUBBLES];case"select":case"selectionchange":return[Event,mapEvent,BUBBLES];case"touchstart":case"touchend":case"touchmove":return[TouchEvent,mapTouchEvent,BUBBLES|CANCELABLE|VIEW];case"touchcancel":return[TouchEvent,mapTouchEvent,BUBBLES|VIEW];case"resize":return[Event,mapEvent];case"submit":return[SubmitEvent,mapEvent,BUBBLES|CANCELABLE];case"wheel":return[WheelEvent,mapWheelEvent,BUBBLES|VIEW];case"animationcancel":case"animationend":case"animationiteration":case"animationstart":{return[AnimationEvent,mapEvent,BUBBLES|CANCELABLE];} case"error":return[ErrorEvent,mapEvent];case"unhandledrejection":return[PromiseRejectionEvent,mapEvent,CANCELABLE];case"beforeunload":return[Event,mapEvent,CANCELABLE];case"unload":return[Event,mapEvent];default:return[Event,mapEvent,BUBBLES];}};const getFirstCommonParent=(a,b)=>{if(!a||!b||a.ownerDocument!==b.ownerDocument){return null;} const range=document.createRange();range.setStart(a,0);range.setEnd(b,0);if(range.collapsed){range.setStart(b,0);range.setEnd(a,0);} return range.commonAncestorContainer;};const getPosition=(element,options)=>{const{position,relative}=options||{};const isString=typeof position==="string";const[posX,posY]=parsePosition(position);if(!isString&&!relative&&!$isNaN(posX)&&!$isNaN(posY)){return toEventPosition(posX,posY,position);} const{x,y,width,height}=getNodeRect(element);let clientX=x;let clientY=y;if(isString){const positions=position.split("-");if(positions.includes("left")){clientX-=1;}else if(positions.includes("right")){clientX+=$ceil(width)+1;}else{clientX+=width/2;} if(positions.includes("top")){clientY-=1;}else if(positions.includes("bottom")){clientY+=$ceil(height)+1;}else{clientY+=height/2;}}else{if($isNaN(posX)){clientX+=width/2;}else{if(relative){clientX+=posX||0;}else{clientX=posX||0;}} if($isNaN(posY)){clientY+=height/2;}else{if(relative){clientY+=posY||0;}else{clientY=posY||0;}}} return toEventPosition(clientX,clientY,position);};const getStringSelection=(target)=>$isInteger(target.selectionStart)&&$isInteger(target.selectionEnd)&&[target.selectionStart,target.selectionEnd].join(",");const hasTagName=(node,...tagNames)=>tagNames.includes(getTag(node));const hasTouch=()=>globalThis.ontouchstart!==undefined||globalThis.matchMedia("(pointer:coarse)").matches;const isDifferentPosition=(target,options)=>{const previous=runTime.position;const next=isNode(target)?getPosition(target,options):target;for(const key in next){if(previous[key]!==next[key]){return true;}} return false;};const isNil=(value)=>value===null||value===undefined;const isPrevented=(event)=>event&&event.defaultPrevented;const parseKeyStrokes=(keyStrokes,options)=>(isIterable(keyStrokes)?[...keyStrokes]:[keyStrokes]).map((key)=>{const lower=key.toLowerCase();return{...options,key:lower.length===1?key:KEY_ALIASES[lower]||key,};});const redirectSubmit=(ev)=>{if(isPrevented(ev)){return;} ev.preventDefault();const form=ev.target;globalThis.fetch(form.action,{method:form.method,body:new FormData(form,ev.submitter),});};const registerButton=(eventInit,toggle)=>{let value=0;switch(eventInit.button){case btn.LEFT:{value=1;break;} case btn.MIDDLE:{value=4;break;} case btn.RIGHT:{value=2;break;} case btn.BACK:{value=8;break;} case btn.FORWARD:{value=16;break;}} runTime.buttons=$max(runTime.buttons+(toggle?value:-value),0);};const registerFileInput=({target})=>{if(getTag(target)==="input"&&target.type==="file"){runTime.fileInput=target;}else{runTime.fileInput=null;}};const registerForChange=async(target,initialValue,confirmAction)=>{const dispatchChange=()=>target.value!==initialValue&&dispatch(target,"change");confirmAction&&=confirmAction.toLowerCase();if(confirmAction==="auto"){confirmAction=getTag(target)==="input"?"enter":"blur";} if(getTag(target)==="input"){changeTargetListeners.push(on(target,"keydown",(ev)=>{if(isPrevented(ev)||ev.key!=="Enter"){return;} removeChangeTargetListeners();afterNextDispatch=dispatchChange;}));}else if(confirmAction==="enter"){throw new HootDomError(`"enter" confirm action is only supported on elements`);} changeTargetListeners.push(on(target,"blur",()=>{removeChangeTargetListeners();dispatchChange();}),on(target,"change",removeChangeTargetListeners));switch(confirmAction){case"blur":{await _click(getDocument(target).body,{position:{x:0,y:0},});break;} case"enter":{await _press(target,{key:"Enter"});break;} case"tab":{await _press(target,{key:"Tab"});break;}}};const registerSpecialKey=(eventInit,toggle)=>{switch(eventInit.key){case"Alt":{runTime.modifierKeys.altKey=toggle;break;} case"Control":{runTime.modifierKeys.ctrlKey=toggle;break;} case"Meta":{runTime.modifierKeys.metaKey=toggle;break;} case"Shift":{runTime.modifierKeys.shiftKey=toggle;break;}}};const removeChangeTargetListeners=()=>{while(changeTargetListeners.length){changeTargetListeners.pop()();}};const setPointerDownTarget=(target)=>{if(runTime.pointerDownTarget){runTime.previousPointerDownTarget=runTime.pointerDownTarget;} runTime.pointerDownTarget=target;runTime.canStartDrag=false;};const setPointerTarget=async(target,options)=>{runTime.previousPointerTarget=runTime.pointerTarget;runTime.pointerTarget=target;if(runTime.pointerTarget!==runTime.previousPointerTarget&&runTime.canStartDrag){const dragStartEvent=await dispatch(runTime.previousPointerTarget,"dragstart");runTime.isDragging=!isPrevented(dragStartEvent);runTime.canStartDrag=false;} runTime.position=target&&getPosition(target,options);};const setupEvents=(type,options)=>{currentEventTypes.push(type);$assign(currentEventInit,options?.eventInit);return async()=>{for(const eventType in currentEventInit){delete currentEventInit[eventType];} const events=new EventList(getCurrentEvents());const currentType=currentEventTypes.pop();delete currentEvents[currentType];if(!allowLogs){return events;} const groupName=[`${type}: dispatched`,events.length,`events`];$groupCollapsed(...groupName);for(const event of events){const colors=["blue"];const typeList=[event.type];if(event.key){typeList.push(event.key);}else if(event.button){typeList.push(event.button);} [...Array(typeList.length)].forEach(()=>colors.push("orange"));const typeString=typeList.map((t)=>`%c"${t}"%c`).join(", ");let message=`%c${event.constructor.name}%c<${typeString}>`;if(event.__bubbleCount){message+=` (${event.__bubbleCount})`;} const target=event.__originalTarget||event.target;if(isNode(target)){const targetParts=toSelector(target,{object:true});colors.push("blue");if(targetParts.id){colors.push("orange");} if(targetParts.class){colors.push("lightBlue");} const targetString=$values(targetParts).map((part)=>`%c${part}%c`).join("");message+=` @${targetString}`;} const messageColors=colors.flatMap((color)=>[`color: ${LOG_COLORS[color]}; font-weight: normal`,`color: ${LOG_COLORS.reset}`,]);$groupCollapsed(message,...messageColors);$dir(event);$log(target);$groupEnd();} $groupEnd();return events;};};const toEventPosition=(clientX,clientY,position)=>{clientX||=0;clientY||=0;return{clientX,clientY,pageX:position?.pageX??clientX,pageY:position?.pageY??clientY,screenX:position?.screenX??clientX,screenY:position?.screenY??clientY,};};const triggerClick=async(target,pointerInit)=>{if(target.disabled){return;} const eventType=(pointerInit.button??0)===btn.LEFT?"click":"auxclick";const clickEvent=await dispatch(target,eventType,pointerInit);if(isPrevented(clickEvent)){return;} if(isFirefox()){switch(getTag(target)){case"label":{target=target.control;if(target){await triggerClick(target,pointerInit);} break;} case"option":{const parent=target.parentElement;if(parent&&getTag(parent)==="select"){await dispatch(parent,"change");} break;}}}};const triggerDrag=async(target,eventInit)=>{await dispatch(target,"drag",eventInit);const dragOverEvent=await dispatch(target,"dragover",eventInit);runTime.lastDragOverCancelled=isPrevented(dragOverEvent);};const triggerFocus=async(target)=>{const previous=getActiveElement(target);if(previous===target){return;} if(previous!==target.ownerDocument.body){await dispatchAndIgnore({target:previous,events:["blur","focusout"],callback:(el)=>el.blur(),options:{relatedTarget:target},});} if(isNodeFocusable(target)){const previousSelection=getStringSelection(target);await dispatchAndIgnore({target,events:["focus","focusin"],additionalEvents:["select"],callback:(el)=>el.focus(),options:{relatedTarget:previous},});if(previousSelection&&previousSelection===getStringSelection(target)){changeSelection(target,target.value.length,target.value.length);}}};const _clear=async(target,options)=>{const initialValue=target.value;fullClear=true;await _press(target,{ctrlKey:true,key:"a"});await _press(target,{key:"Backspace"});fullClear=false;await registerForChange(target,initialValue,options?.confirm);};const _click=async(target,options)=>{await _pointerDown(target,options);await _pointerUp(target,options);};const _fill=async(target,value,options)=>{const initialValue=target.value;if(getTag(target)==="input"){switch(target.type){case"color":{target.value=String(value);await dispatch(target,"input");await dispatch(target,"change");return;} case"file":{const dataTransfer=new DataTransfer();const files=ensureArray(value);if(files.length>1&&!target.multiple){throw new HootDomError(`input[type="file"] does not support multiple files`);} for(const file of files){if(!(file instanceof File)){throw new TypeError(`file input only accept 'File' objects`);} dataTransfer.items.add(file);} target.files=dataTransfer.files;await dispatch(target,"change");return;} case"range":{const numberValue=$parseFloat(value);if($isNaN(numberValue)){throw new TypeError(`input[type="range"] only accept 'number' values`);} target.value=String(numberValue);await dispatch(target,"input");await dispatch(target,"change");return;}}} if(options?.instantly){globalThis.navigator.clipboard.writeText(value).catch();await _press(target,{ctrlKey:true,key:"v"});}else{if(options?.composition){runTime.isComposing=true;await dispatch(target,"compositionstart");} for(const char of String(value)){const key=char.toLowerCase();await _press(target,{key,shiftKey:key!==char});} if(options?.composition){runTime.isComposing=false;await dispatch(target,"compositionend");}} await registerForChange(target,initialValue,options?.confirm);};const _hover=async(target,options)=>{const isDifferentTarget=target!==runTime.pointerTarget;const previousPosition=runTime.position;await setPointerTarget(target,options);const{previousPointerTarget:previous,pointerTarget:current}=runTime;if(isDifferentTarget&&previous&&(!current||!previous.contains(current))){const leaveEventInit={...previousPosition,relatedTarget:current,};if(runTime.isDragging){await triggerDrag(previous,leaveEventInit);await dispatch(previous,"dragleave",leaveEventInit);}else{await dispatchPointerEvent(previous,"pointermove",leaveEventInit,{mouse:["mousemove"],touch:["touchmove"],});await dispatchPointerEvent(previous,"pointerout",leaveEventInit,{mouse:["mouseout"],});const leaveEvents=await Promise.all(getDifferentParents(current,previous).map((element)=>dispatch(element,"pointerleave",leaveEventInit)));if(!hasTouch()){await dispatchRelatedEvents(leaveEvents,"mouseleave",leaveEventInit);}}} if(current){const enterEventInit={...runTime.position,relatedTarget:previous,};if(runTime.isDragging){if(isDifferentTarget){await dispatch(target,"dragenter",enterEventInit);} await triggerDrag(target,enterEventInit);}else{if(isDifferentTarget){await dispatchPointerEvent(target,"pointerover",enterEventInit,{mouse:["mouseover"],});const enterEvents=await Promise.all(getDifferentParents(previous,current).map((element)=>dispatch(element,"pointerenter",enterEventInit)));if(!hasTouch()){await dispatchRelatedEvents(enterEvents,"mouseenter",enterEventInit);}} await dispatchPointerEvent(target,"pointermove",enterEventInit,{mouse:["mousemove"],touch:["touchmove"],});}}};const _implicitHover=async(target,options)=>{if(runTime.pointerTarget!==target||isDifferentPosition(target,options)){await _hover(target,options);}};const _keyDown=async(target,eventInit)=>{eventInit={...eventInit,...currentEventInit.keydown};registerSpecialKey(eventInit,true);const repeat=typeof eventInit.repeat==="boolean"?eventInit.repeat:runTime.key===eventInit.key;runTime.key=eventInit.key;const keyDownEvent=await dispatch(target,"keydown",{...eventInit,repeat});if(isPrevented(keyDownEvent)){return;} const insertValue=(toInsert,type)=>{const{selectionStart,selectionEnd,value}=target;inputData=toInsert;inputType=type;if(isNil(selectionStart)&&isNil(selectionEnd)){nextValue+=toInsert;}else{nextValue=value.slice(0,selectionStart)+toInsert+value.slice(selectionEnd);if(selectionStart===selectionEnd){nextSelectionStart=nextSelectionEnd=selectionStart+1;}}};const{ctrlKey,key,shiftKey}=keyDownEvent;let inputData=null;let inputType=null;let nextSelectionEnd=null;let nextSelectionStart=null;let nextValue=target.value;let triggerSelect=false;if(isEditable(target)){switch(key){case"ArrowDown":case"ArrowLeft":case"ArrowUp":case"ArrowRight":{const{selectionStart,selectionEnd,value}=target;if(isNil(selectionStart)||isNil(selectionEnd)){break;} const start=key==="ArrowLeft"||key==="ArrowUp";let selectionTarget;if(ctrlKey){selectionTarget=start?0:value.length;}else{selectionTarget=start?selectionStart-1:selectionEnd+1;} nextSelectionStart=nextSelectionEnd=$max($min(selectionTarget,value.length),0);triggerSelect=shiftKey;break;} case"Backspace":{const{selectionStart,selectionEnd,value}=target;if(fullClear){nextValue="";}else if(isNil(selectionStart)||isNil(selectionEnd)){nextValue=value.slice(0,-1);}else if(selectionStart===selectionEnd){nextValue=value.slice(0,selectionStart-1)+value.slice(selectionEnd);}else{nextValue=deleteSelection(target);} inputType="deleteContentBackward";break;} case"Delete":{const{selectionStart,selectionEnd,value}=target;if(fullClear){nextValue="";}else if(isNil(selectionStart)||isNil(selectionEnd)){nextValue=value.slice(1);}else if(selectionStart===selectionEnd){nextValue=value.slice(0,selectionStart)+value.slice(selectionEnd+1);}else{nextValue=deleteSelection(target);} inputType="deleteContentForward";break;} case"Enter":{if(target.tagName==="TEXTAREA"){insertValue("\n","insertLineBreak");} break;} default:{if(key.length===1&&!ctrlKey){insertValue(shiftKey?key.toUpperCase():key.toLowerCase(),runTime.isComposing?"insertCompositionText":"insertText");}}}} switch(key){case"a":{if(ctrlKey){if(isEditable(target)){nextSelectionStart=0;nextSelectionEnd=target.value.length;triggerSelect=true;}else{const selection=globalThis.getSelection();const range=$createRange();range.selectNodeContents(target);selection.removeAllRanges();selection.addRange(range);}} break;} case"c":{if(ctrlKey){const text=globalThis.getSelection().toString();globalThis.navigator.clipboard.writeText(text).catch();await dispatch(target,"copy",{clipboardData:eventInit.dataTransfer||new DataTransfer(),});} break;} case"Enter":{const tag=getTag(target);const parentForm=target.closest("form");if(parentForm&&target.type!=="button"){await dispatch(parentForm,"submit");}else if(!keyDownEvent.repeat&&(tag==="a"||tag==="button"||(tag==="input"&&target.type==="button"))){await dispatch(target,"click",{button:btn.LEFT});} break;} case"Escape":{runTime.isDragging=false;break;} case"Tab":{const next=shiftKey?getPreviousFocusableElement({tabbable:true}):getNextFocusableElement({tabbable:true});if(next){await triggerFocus(next);} break;} case"v":{if(ctrlKey&&isEditable(target)){try{nextValue=await globalThis.navigator.clipboard.readText();}catch(err){} inputType="insertFromPaste";await dispatch(target,"paste",{clipboardData:eventInit.dataTransfer||new DataTransfer(),});} break;} case"x":{if(ctrlKey&&isEditable(target)){const text=globalThis.getSelection().toString();globalThis.navigator.clipboard.writeText(text).catch();nextValue=deleteSelection(target);inputType="deleteByCut";await dispatch(target,"cut",{clipboardData:eventInit.dataTransfer||new DataTransfer(),});} break;}} if(target.value!==nextValue){target.value=nextValue;const inputEventInit={data:inputData,inputType,};const beforeInputEvent=await dispatch(target,"beforeinput",inputEventInit);if(!isPrevented(beforeInputEvent)){await dispatch(target,"input",inputEventInit);}} changeSelection(target,nextSelectionStart,nextSelectionEnd);if(triggerSelect){await dispatchAndIgnore({target,events:["select"],});}};const _keyUp=async(target,eventInit)=>{eventInit={...eventInit,...currentEventInit.keyup};await dispatch(target,"keyup",eventInit);runTime.key=null;registerSpecialKey(eventInit,false);if(eventInit.key===" "&&getTag(target)==="input"&&target.type==="checkbox"){await triggerClick(target,{button:btn.LEFT});}};const _pointerDown=async(target,options)=>{setPointerDownTarget(target);const pointerDownTarget=runTime.pointerDownTarget;const eventInit={...runTime.position,...currentEventInit.pointerdown,button:options?.button||btn.LEFT,};registerButton(eventInit,true);if(pointerDownTarget!==runTime.previousPointerDownTarget){runTime.clickCount=0;} runTime.touchStartPosition={...runTime.position};runTime.touchStartTimeOffset=globalThis.Date.now();const prevented=await dispatchPointerEvent(pointerDownTarget,"pointerdown",eventInit,{mouse:!pointerDownTarget.disabled&&["mousedown",{...eventInit,detail:runTime.clickCount+1},],touch:["touchstart"],});if(prevented){return;} await triggerFocus(target);if(eventInit.button===btn.LEFT&&!hasTouch()&&pointerDownTarget.draggable){runTime.canStartDrag=true;}else if(eventInit.button===btn.RIGHT){await dispatch(target,"contextmenu",eventInit);}};const _pointerUp=async(target,options)=>{const isLongTap=globalThis.Date.now()-runTime.touchStartTimeOffset>LONG_TAP_DELAY;const pointerDownTarget=runTime.pointerDownTarget;const eventInit={...runTime.position,...currentEventInit.pointerup,button:options?.button||btn.LEFT,};registerButton(eventInit,false);if(runTime.isDragging){runTime.isDragging=false;if(runTime.lastDragOverCancelled){await dispatch(target,"drop",eventInit);} await dispatch(target,"dragend",eventInit);return;} const mouseEventInit={...eventInit,detail:runTime.clickCount+1,};await dispatchPointerEvent(target,"pointerup",eventInit,{mouse:!target.disabled&&["mouseup",mouseEventInit],touch:["touchend"],});const touchStartPosition=runTime.touchStartPosition;runTime.touchStartPosition={};if(hasTouch()&&(isDifferentPosition(touchStartPosition)||isLongTap)){return;} let actualTarget;if(hasTouch()){actualTarget=pointerDownTarget===target&⌖}else{actualTarget=getFirstCommonParent(target,pointerDownTarget);} if(actualTarget){await triggerClick(actualTarget,mouseEventInit);if(mouseEventInit.button===btn.LEFT){runTime.clickCount++;if(!hasTouch()&&runTime.clickCount%2===0){await dispatch(actualTarget,"dblclick",mouseEventInit);}}} setPointerDownTarget(null);if(runTime.pointerDownTimeout){globalThis.clearTimeout(runTime.pointerDownTimeout);} runTime.pointerDownTimeout=globalThis.setTimeout(()=>{runTime.clickCount=0;runTime.pointerDownTimeout=0;},DOUBLE_CLICK_DELAY);};const _press=async(target,eventInit)=>{await _keyDown(target,eventInit);await _keyUp(target,eventInit);};const _select=async(target,value)=>{const values=ensureArray(value).map(String);let found=false;for(const option of target.options){option.selected=values.includes(option.value);found||=option.selected;} if(!value){target.selectedIndex=-1;}else if(!found){throw new HootDomError(`error when calling \`select()\`: no option found with value "${values.join(", ")}"`);} await dispatch(target,"change");};const btn={LEFT:0,MIDDLE:1,RIGHT:2,BACK:3,FORWARD:4,};const CAPTURE={capture:true};const DEPRECATED_EVENT_PROPERTIES={keyCode:"key",which:"key",};const DEPRECATED_EVENTS={keypress:"keydown",mousewheel:"wheel",};const DOUBLE_CLICK_DELAY=500;const GLOBAL_TRUSTED_EVENTS_CANCELERS=[["blur",cancelTrustedEvent,CAPTURE],["focus",cancelTrustedEvent,CAPTURE],["focusin",cancelTrustedEvent,CAPTURE],["focusout",cancelTrustedEvent,CAPTURE],["scroll",cancelTrustedEvent,CAPTURE],["scrollend",cancelTrustedEvent,CAPTURE],["select",cancelTrustedEvent,CAPTURE],];const GLOBAL_FILE_INPUT_REGISTERERS=[["click",registerFileInput,CAPTURE],["focus",registerFileInput,CAPTURE],];const GLOBAL_SUBMIT_FORWARDERS=[["submit",redirectSubmit]];const KEY_ALIASES={alt:"Alt",arrowdown:"ArrowDown",arrowleft:"ArrowLeft",arrowright:"ArrowRight",arrowup:"ArrowUp",backspace:"Backspace",control:"Control",delete:"Delete",enter:"Enter",escape:"Escape",meta:"Meta",shift:"Shift",tab:"Tab",caps:"Shift",cmd:"Meta",command:"Meta",ctrl:"Control",del:"Delete",down:"ArrowDown",esc:"Escape",left:"ArrowLeft",right:"ArrowRight",space:" ",up:"ArrowUp",win:"Meta",};const LOG_COLORS={blue:"#5db0d7",orange:"#f29364",lightBlue:"#9bbbdc",reset:"inherit",};const LONG_TAP_DELAY=500;const currentEvents=Object.create(null);const currentEventInit=Object.create(null);const currentEventTypes=[];let afterNextDispatch=null;let allowLogs=false;let fullClear=false;const changeTargetListeners=[];const runTime=getDefaultRunTimeValue();const BUBBLES=0b1;const CANCELABLE=0b10;const VIEW=0b100;const mapEvent=(eventInit)=>eventInit;const mapMouseEvent=(eventInit)=>({button:-1,buttons:runTime.buttons,clientX:eventInit.clientX??eventInit.pageX??eventInit.screenX??0,clientY:eventInit.clientY??eventInit.pageY??eventInit.screenY??0,...runTime.modifierKeys,...eventInit,});const mapPointerEvent=(eventInit)=>({...mapMouseEvent(eventInit),button:btn.LEFT,pointerId:1,pointerType:hasTouch()?"touch":"mouse",...eventInit,});const mapWheelEvent=(eventInit)=>({...mapMouseEvent(eventInit),button:btn.LEFT,...eventInit,});const mapTouchEvent=(eventInit)=>{const touches=eventInit.targetTouches||eventInit.touches||[new Touch({identifier:0,...eventInit})];return{...eventInit,changedTouches:eventInit.changedTouches||touches,target:eventInit.target,targetTouches:eventInit.targetTouches||touches,touches:eventInit.touches||(eventInit.type==="touchend"?[]:touches),};};const mapInputEvent=(eventInit)=>({data:null,isComposing:Boolean(runTime.isComposing),...eventInit,});const mapKeyboardEvent=(eventInit)=>({isComposing:Boolean(runTime.isComposing),...runTime.modifierKeys,...eventInit,});__exports.check=check;async function check(target,options){const finalizeEvents=setupEvents("check",options);const element=queryFirst(await target,options);if(!isCheckable(element)){throw new HootDomError(`cannot call \`check()\`: target should be a checkbox or radio input`);} const checkTarget=getTag(element)==="label"?element.control:element;if(!checkTarget.checked){await _implicitHover(element,options);await _click(element,options);if(!checkTarget.checked){throw new HootDomError(`error when calling \`check()\`: target is not checked after interaction`);}} return finalizeEvents();} __exports.clear=clear;async function clear(options){const finalizeEvents=setupEvents("clear",options);const element=getActiveElement();if(!hasTagName(element,"select")&&!isEditable(element)){throw new HootDomError(`cannot call \`clear()\`: target should be editable or a element`);} if(options?.target){await _implicitHover(element);await _pointerDown(element);} await _select(element,value);if(options?.target){await _pointerUp(element);} return finalizeEvents();} __exports.setInputFiles=setInputFiles;async function setInputFiles(files,options){if(!runTime.fileInput){throw new HootDomError(`cannot call \`setInputFiles()\`: no file input has been interacted with`);} const finalizeEvents=setupEvents("setInputFiles",options);await _fill(runTime.fileInput,files,options);runTime.fileInput=null;return finalizeEvents();} __exports.setInputRange=setInputRange;async function setInputRange(target,value,options){const finalizeEvents=setupEvents("setInputRange",options);const element=queryFirst(await target,options);await _implicitHover(element,options);await _pointerDown(element,options);await _fill(element,value,options);await _pointerUp(element,options);return finalizeEvents();} __exports.setupEventActions=setupEventActions;function setupEventActions(target,options){const eventHandlers=[];if(!options?.allowTrustedEvents){eventHandlers.push(...GLOBAL_TRUSTED_EVENTS_CANCELERS);} if(!options?.noFileInputRegistration){eventHandlers.push(...GLOBAL_FILE_INPUT_REGISTERERS);} if(!options?.allowSubmit){eventHandlers.push(...GLOBAL_SUBMIT_FORWARDERS);} for(const[eventType,handler,options]of eventHandlers){window.addEventListener(eventType,handler,options);} const processedIframes=new WeakSet();const observer=new MutationObserver((mutations)=>{for(const mutation of mutations){if(!mutation.addedNodes){continue;} for(const iframe of target.getElementsByTagName("iframe")){if(processedIframes.has(iframe)){continue;} processedIframes.add(iframe);for(const[eventType,handler,options]of eventHandlers){iframe.contentWindow.addEventListener(eventType,handler,options);}}}});observer.observe(target,{childList:true,subtree:true});return function cleanupEventActions(){observer.disconnect();if(runTime.pointerDownTimeout){globalThis.clearTimeout(runTime.pointerDownTimeout);} removeChangeTargetListeners();for(const[eventType,handler,options]of eventHandlers){window.removeEventListener(eventType,handler,options);} $assign(runTime,getDefaultRunTimeValue());};} __exports.uncheck=uncheck;async function uncheck(target,options){const finalizeEvents=setupEvents("uncheck",options);const element=queryFirst(await target,options);if(!isCheckable(element)){throw new HootDomError(`cannot call \`uncheck()\`: target should be a checkbox or radio input`);} const checkTarget=getTag(element)==="label"?element.control:element;if(checkTarget.checked){await _implicitHover(element,options);await _click(element,options);if(checkTarget.checked){throw new HootDomError(`error when calling \`uncheck()\`: target is still checked after interaction`);}} return finalizeEvents();} __exports.unload=unload;async function unload(options){const finalizeEvents=setupEvents("unload",options);await dispatch(getWindow(),"beforeunload");return finalizeEvents();} const EventList=__exports.EventList=class EventList extends Array{constructor(...args){super(...args.flat());} get(predicate){return this.getAll(predicate)[0]||null;} getAll(predicate){if(typeof predicate!=="function"){const type=predicate;predicate=(ev)=>ev.type===type;} return this.filter(predicate);}} return __exports;});; /* /web/static/lib/hoot-dom/helpers/time.js */ odoo.define('@web/../lib/hoot-dom/helpers/time',['@web/../lib/hoot-dom/hoot_dom_utils'],function(require){'use strict';let __exports={};const{HootDomError}=require("@web/../lib/hoot-dom/hoot_dom_utils");const{cancelAnimationFrame,clearInterval,clearTimeout,Error,Math:{ceil:$ceil,floor:$floor,max:$max,min:$min},parseInt,performance,Promise,requestAnimationFrame,setInterval,setTimeout,}=globalThis;const $performanceNow=performance.now.bind(performance);const animationToId=(id)=>ID_PREFIX.animation+String(id);const getNextTimerValues=()=>{let timerValues=null;for(const[internalId,[callback,init,delay]]of timers.entries()){const timeout=init+delay;if(!timerValues||timeoutNumber(id.slice(ID_PREFIX.animation.length));const idToInterval=(id)=>Number(id.slice(ID_PREFIX.interval.length));const idToTimeout=(id)=>Number(id.slice(ID_PREFIX.timeout.length));const intervalToId=(id)=>ID_PREFIX.interval+String(id);const parseNat=(value)=>{const int=parseInt(value,10);return int>0?int:0;};const now=()=>(freezed?0:$performanceNow())+timeOffset;const timeoutToId=(id)=>ID_PREFIX.timeout+String(id);const ID_PREFIX={animation:"a_",interval:"i_",timeout:"t_",};const timers=new Map();let allowTimers=false;let freezed=false;let frameDelay=1000/60;let nextDummyId=1;let timeOffset=0;__exports.advanceFrame=advanceFrame;function advanceFrame(frameCount){return advanceTime(frameDelay*parseNat(frameCount));} __exports.advanceTime=advanceTime;function advanceTime(ms){ms=parseNat(ms);const targetTime=now()+ms;let remaining=ms;let timerValues;while((timerValues=getNextTimerValues())&&timerValues[0]<=targetTime){const[timeout,handler,id]=timerValues;const diff=timeout-now();if(diff>0){timeOffset+=$min(remaining,diff);remaining=$max(remaining-diff,0);} if(timers.has(id)){handler(timeout);}} if(remaining>0){timeOffset+=remaining;} return animationFrame().then(()=>ms);} __exports.animationFrame=animationFrame;function animationFrame(){return new Promise((resolve)=>requestAnimationFrame(()=>delay().then(resolve)));} __exports.cancelAllTimers=cancelAllTimers;function cancelAllTimers(){for(const id of timers.keys()){if(id.startsWith(ID_PREFIX.animation)){globalThis.cancelAnimationFrame(idToAnimation(id));}else if(id.startsWith(ID_PREFIX.interval)){globalThis.clearInterval(idToInterval(id));}else if(id.startsWith(ID_PREFIX.timeout)){globalThis.clearTimeout(idToTimeout(id));}}} __exports.cleanupTime=cleanupTime;function cleanupTime(){allowTimers=false;freezed=false;cancelAllTimers();return delay();} __exports.delay=delay;function delay(duration){return new Promise((resolve)=>setTimeout(resolve,duration));} __exports.freezeTime=freezeTime;function freezeTime(setFreeze){freezed=setFreeze??!freezed;} __exports.getTimeOffset=getTimeOffset;function getTimeOffset(){return timeOffset;} __exports.isTimeFreezed=isTimeFreezed;function isTimeFreezed(){return freezed;} __exports.microTick=microTick;function microTick(){return new Promise(queueMicrotask);} __exports.mockedCancelAnimationFrame=mockedCancelAnimationFrame;function mockedCancelAnimationFrame(handle){if(!freezed){cancelAnimationFrame(handle);} timers.delete(animationToId(handle));} __exports.mockedClearInterval=mockedClearInterval;function mockedClearInterval(intervalId){if(!freezed){clearInterval(intervalId);} timers.delete(intervalToId(intervalId));} __exports.mockedClearTimeout=mockedClearTimeout;function mockedClearTimeout(timeoutId){if(!freezed){clearTimeout(timeoutId);} timers.delete(timeoutToId(timeoutId));} __exports.mockedRequestAnimationFrame=mockedRequestAnimationFrame;function mockedRequestAnimationFrame(callback){if(!allowTimers){return 0;} const handler=()=>{mockedCancelAnimationFrame(handle);return callback(now());};const animationValues=[handler,now(),frameDelay];const handle=freezed?nextDummyId++:requestAnimationFrame(handler);const internalId=animationToId(handle);timers.set(internalId,animationValues);return handle;} __exports.mockedSetInterval=mockedSetInterval;function mockedSetInterval(callback,ms,...args){if(!allowTimers){return 0;} ms=parseNat(ms);const handler=()=>{if(allowTimers){intervalValues[1]=Math.max(now(),intervalValues[1]+ms);}else{mockedClearInterval(intervalId);} return callback(...args);};const intervalValues=[handler,now(),ms];const intervalId=freezed?nextDummyId++:setInterval(handler,ms);const internalId=intervalToId(intervalId);timers.set(internalId,intervalValues);return intervalId;} __exports.mockedSetTimeout=mockedSetTimeout;function mockedSetTimeout(callback,ms,...args){if(!allowTimers){return 0;} ms=parseNat(ms);const handler=()=>{mockedClearTimeout(timeoutId);return callback(...args);};const timeoutValues=[handler,now(),ms];const timeoutId=freezed?nextDummyId++:setTimeout(handler,ms);const internalId=timeoutToId(timeoutId);timers.set(internalId,timeoutValues);return timeoutId;} __exports.resetTimeOffset=resetTimeOffset;function resetTimeOffset(){timeOffset=0;} __exports.runAllTimers=runAllTimers;function runAllTimers(){if(!timers.size){return 0;} const endts=$max(...[...timers.values()].map(([,init,delay])=>init+delay));return advanceTime($ceil(endts-now()));} __exports.setFrameRate=setFrameRate;function setFrameRate(frameRate){frameRate=parseNat(frameRate);if(frameRate<1||frameRate>1000){throw new Error("frame rate must be an number between 1 and 1000");} frameDelay=1000/frameRate;} __exports.setupTime=setupTime;function setupTime(){allowTimers=true;} __exports.tick=tick;function tick(){return delay();} __exports.waitUntil=waitUntil;function waitUntil(predicate,options){const result=predicate();if(result){return Promise.resolve().then(()=>result);} const timeout=$floor(options?.timeout??200);let handle;let timeoutId;let running=true;return new Promise((resolve,reject)=>{const runCheck=()=>{const result=predicate();if(result){resolve(result);}else if(running){handle=requestAnimationFrame(runCheck);}else{let message=options?.message||`'waitUntil' timed out after %timeout% milliseconds`;if(typeof message==="function"){message=message();} reject(new HootDomError(message.replace("%timeout%",String(timeout))));}};handle=requestAnimationFrame(runCheck);timeoutId=setTimeout(()=>(running=false),timeout);}).finally(()=>{cancelAnimationFrame(handle);clearTimeout(timeoutId);});} const Deferred=__exports.Deferred=class Deferred extends Promise{_resolve;_reject;constructor(executor){let _resolve,_reject;super((resolve,reject)=>{_resolve=resolve;_reject=reject;executor?.(_resolve,_reject);});this._resolve=_resolve;this._reject=_reject;} async reject(reason){return this._reject(reason);} async resolve(value){return this._resolve(value);}} return __exports;});; /* /web/static/lib/hoot-dom/hoot-dom.js */ odoo.define('@web/../lib/hoot-dom/hoot-dom',['@web/../lib/hoot-dom/helpers/dom','@web/../lib/hoot-dom/helpers/events','@web/../lib/hoot-dom/hoot_dom_utils','@web/../lib/hoot-dom/helpers/time'],function(require){'use strict';let __exports={};const dom=require("@web/../lib/hoot-dom/helpers/dom");const events=require("@web/../lib/hoot-dom/helpers/events");const{interactor}=require("@web/../lib/hoot-dom/hoot_dom_utils");{const{formatXml,getActiveElement,getFocusableElements,getNextFocusableElement,getParentFrame,getPreviousFocusableElement,isDisplayed,isEditable,isFocusable,isInDOM,isInViewPort,isScrollable,isVisible,matches,queryAll,queryAllAttributes,queryAllProperties,queryAllRects,queryAllTexts,queryAllValues,queryAttribute,queryFirst,queryOne,queryRect,queryText,queryValue,}=require("@web/../lib/hoot-dom/helpers/dom");Object.assign(__exports,{formatXml,getActiveElement,getFocusableElements,getNextFocusableElement,getParentFrame,getPreviousFocusableElement,isDisplayed,isEditable,isFocusable,isInDOM,isInViewPort,isScrollable,isVisible,matches,queryAll,queryAllAttributes,queryAllProperties,queryAllRects,queryAllTexts,queryAllValues,queryAttribute,queryFirst,queryOne,queryRect,queryText,queryValue,})};{const{on}=require("@web/../lib/hoot-dom/helpers/events");Object.assign(__exports,{on})};{const{advanceFrame,advanceTime,animationFrame,cancelAllTimers,Deferred,delay,freezeTime,microTick,runAllTimers,setFrameRate,tick,waitUntil,}=require("@web/../lib/hoot-dom/helpers/time");Object.assign(__exports,{advanceFrame,advanceTime,animationFrame,cancelAllTimers,Deferred,delay,freezeTime,microTick,runAllTimers,setFrameRate,tick,waitUntil,})};const observe=__exports.observe=interactor("query",dom.observe);const waitFor=__exports.waitFor=interactor("query",dom.waitFor);const waitForNone=__exports.waitForNone=interactor("query",dom.waitForNone);const check=__exports.check=interactor("interaction",events.check);const clear=__exports.clear=interactor("interaction",events.clear);const click=__exports.click=interactor("interaction",events.click);const dblclick=__exports.dblclick=interactor("interaction",events.dblclick);const drag=__exports.drag=interactor("interaction",events.drag);const edit=__exports.edit=interactor("interaction",events.edit);const fill=__exports.fill=interactor("interaction",events.fill);const hover=__exports.hover=interactor("interaction",events.hover);const keyDown=__exports.keyDown=interactor("interaction",events.keyDown);const keyUp=__exports.keyUp=interactor("interaction",events.keyUp);const leave=__exports.leave=interactor("interaction",events.leave);const manuallyDispatchProgrammaticEvent=__exports.manuallyDispatchProgrammaticEvent=interactor("interaction",events.dispatch);const middleClick=__exports.middleClick=interactor("interaction",events.middleClick);const pointerDown=__exports.pointerDown=interactor("interaction",events.pointerDown);const pointerUp=__exports.pointerUp=interactor("interaction",events.pointerUp);const press=__exports.press=interactor("interaction",events.press);const resize=__exports.resize=interactor("interaction",events.resize);const rightClick=__exports.rightClick=interactor("interaction",events.rightClick);const scroll=__exports.scroll=interactor("interaction",events.scroll);const select=__exports.select=interactor("interaction",events.select);const setInputFiles=__exports.setInputFiles=interactor("interaction",events.setInputFiles);const setInputRange=__exports.setInputRange=interactor("interaction",events.setInputRange);const uncheck=__exports.uncheck=interactor("interaction",events.uncheck);const unload=__exports.unload=interactor("interaction",events.unload);return __exports;});odoo.define(`@odoo/hoot-dom`,['@web/../lib/hoot-dom/hoot-dom'],function(require){return require('@web/../lib/hoot-dom/hoot-dom');});; /* /web/static/lib/hoot-dom/hoot_dom_utils.js */ odoo.define('@web/../lib/hoot-dom/hoot_dom_utils',[],function(require){'use strict';let __exports={};const{Boolean,navigator:{userAgent:$userAgent},RegExp,SyntaxError,}=globalThis;const R_REGEX_PATTERN=/^\/(.*)\/([dgimsuvy]+)?$/;const interactionBus=new EventTarget();__exports.addInteractionListener=addInteractionListener;function addInteractionListener(types,callback){for(const type of types){interactionBus.addEventListener(type,callback);} return function removeInteractionListener(){for(const type of types){interactionBus.removeEventListener(type,callback);}};} __exports.dispatchInteraction=dispatchInteraction;function dispatchInteraction(type,name,args,returnValue){interactionBus.dispatchEvent(new CustomEvent(type,{detail:[name,args,returnValue],}));return returnValue;} const makeInteractorFn=(type,fn,name)=>({[name](...args){const result=fn(...args);if(result instanceof Promise){for(let i=0;i(args[i]=result));}} return result.then((promiseResult)=>dispatchInteraction(type,name,args,promiseResult));}else{return dispatchInteraction(type,name,args,result);}},}[name]);__exports.interactor=interactor;function interactor(type,fn){return Object.assign(makeInteractorFn(type,fn,fn.name),{as(alias){return makeInteractorFn(type,fn,alias);},get silent(){return fn;},});} __exports.getTag=getTag;function getTag(node){return node?.nodeName?.toLowerCase()||"";} __exports.isFirefox=isFirefox;function isFirefox(){return/firefox/i.test($userAgent);} __exports.isIterable=isIterable;function isIterable(object){return Boolean(object&&typeof object==="object"&&object[Symbol.iterator]);} __exports.isRegExpFilter=isRegExpFilter;function isRegExpFilter(filter){return R_REGEX_PATTERN.test(filter);} __exports.parseRegExp=parseRegExp;function parseRegExp(value,options){const regexParams=value.match(R_REGEX_PATTERN);if(regexParams){const unified=regexParams[1].replace(/\s+/g,"\\s+");const flag=regexParams[2]||"i";try{return new RegExp(unified,flag);}catch(error){if(error instanceof SyntaxError&&options?.safe){return value;}else{throw error;}}} return value;} __exports.toSelector=toSelector;function toSelector(node,options){const tagName=getTag(node);const id=node.id?`#${node.id}`:"";const classNames=node.classList?[...node.classList].map((className)=>`.${className}`):[];if(options?.raw){return{tagName,id,classNames};}else{return[tagName,id,...classNames].join("");}} const HootDomError=__exports.HootDomError=class HootDomError extends Error{name="HootDomError";} return __exports;});; /* /html_editor/static/src/main/media/media_dialog/document_selector.js */ odoo.define('@html_editor/main/media/media_dialog/document_selector',['@web/core/l10n/translation','@html_editor/main/media/media_dialog/file_selector','@web/core/utils/render'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{Attachment,FileSelector,IMAGE_MIMETYPES}=require("@html_editor/main/media/media_dialog/file_selector");const{renderToElement}=require("@web/core/utils/render");const DocumentAttachment=__exports.DocumentAttachment=class DocumentAttachment extends Attachment{static template="html_editor.DocumentAttachment";} const DocumentSelector=__exports.DocumentSelector=class DocumentSelector extends FileSelector{static mediaSpecificClasses=["o_image"];static mediaSpecificStyles=[];static mediaExtraClasses=[];static tagNames=["A"];static attachmentsListTemplate="html_editor.DocumentsListTemplate";static components={...FileSelector.components,DocumentAttachment,};setup(){super.setup();this.uploadText=_t("Upload a document");this.urlPlaceholder="https://www.odoo.com/mydocument";this.addText=_t("Add URL");this.searchPlaceholder=_t("Search a document");this.allLoadedText=_t("All documents have been loaded");} get attachmentsDomain(){const domain=super.attachmentsDomain;domain.push(["mimetype","not in",IMAGE_MIMETYPES]);domain.unshift("&","|",["url","=",null],"!",["url","=like","/web/assets/%"]);return domain;} async onClickDocument(document){this.selectAttachment(document);await this.props.save();} async fetchAttachments(...args){const attachments=await super.fetchAttachments(...args);if(this.selectInitialMedia()){for(const attachment of attachments){if(`/web/content/${attachment.id}`===this.props.media.getAttribute("href").replace(/[?].*/,"")){this.selectAttachment(attachment);}}} return attachments;} static async createElements(selectedMedia,{orm}){return Promise.all(selectedMedia.map(async(attachment)=>{let url=`/web/content/${encodeURIComponent( attachment.id )}?unique=${encodeURIComponent(attachment.checksum)}&download=true`;if(!attachment.public){let accessToken=attachment.access_token;if(!accessToken){[accessToken]=await orm.call("ir.attachment","generate_access_token",[attachment.id,]);} url+=`&access_token=${encodeURIComponent(accessToken)}`;} return this.renderFileElement(attachment,url);}));} static renderFileElement(attachment,downloadUrl){return renderStaticFileBox(attachment.name,attachment.mimetype,downloadUrl);}} __exports.renderStaticFileBox=renderStaticFileBox;function renderStaticFileBox(filename,mimetype,downloadUrl){const rootSpan=document.createElement("span");rootSpan.classList.add("o_file_box");rootSpan.contentEditable=false;const bannerElement=renderToElement("html_editor.StaticFileBox",{fileModel:{filename,mimetype,downloadUrl},});rootSpan.append(bannerElement);return rootSpan;} return __exports;});; /* /html_editor/static/src/main/media/media_dialog/file_documents_selector.js */ odoo.define('@html_editor/main/media/media_dialog/file_documents_selector',['@html_editor/main/media/media_dialog/document_selector'],function(require){'use strict';let __exports={};const{DocumentSelector}=require("@html_editor/main/media/media_dialog/document_selector");const FileDocumentsSelector=__exports.FileDocumentsSelector=class FileDocumentsSelector extends DocumentSelector{get attachmentsDomain(){const domain=super.attachmentsDomain.map((d)=>{if(d[0]==="mimetype"){return["mimetype","!=",false];} return d;});domain.unshift("&","|",["url","=",null],"&","!",["url","=like","/%/static/%"],"!","|",["url","=ilike","/html_editor/shape/%"],["url","=ilike","/web_editor/shape/%"]);domain.push("!",["name","=like","%.crop"]);return domain;}} return __exports;});; /* /html_editor/static/src/main/media/media_dialog/file_media_dialog.js */ odoo.define('@html_editor/main/media/media_dialog/file_media_dialog',['@web/core/utils/render','@html_editor/main/media/media_dialog/media_dialog','@html_editor/main/media/media_dialog/file_documents_selector','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{renderToElement}=require("@web/core/utils/render");const{MediaDialog}=require("@html_editor/main/media/media_dialog/media_dialog");const{FileDocumentsSelector}=require("@html_editor/main/media/media_dialog/file_documents_selector");const{_t}=require("@web/core/l10n/translation");const FileMediaDialog=__exports.FileMediaDialog=class FileMediaDialog extends MediaDialog{addTabs(){super.addTabs(...arguments);this.addTab({id:"MIXED_FILES",title:_t("Documents"),Component:FileDocumentsSelector,});} async renderMedia([selectedMedia]){let accessToken=selectedMedia.access_token;if(!selectedMedia.public||!accessToken){[accessToken]=await this.orm.call("ir.attachment","generate_access_token",[selectedMedia.id,]);} const dotSplit=selectedMedia.name.split(".");const extension=dotSplit.length>1?dotSplit.pop():undefined;const fileData={access_token:accessToken,checksum:selectedMedia.checksum,extension,filename:selectedMedia.name,id:selectedMedia.id,mimetype:selectedMedia.mimetype,name:selectedMedia.name,type:selectedMedia.type,url:selectedMedia.url||"",};const fileBlock=renderToElement("html_editor.EmbeddedFileBlueprint",{embeddedProps:JSON.stringify({fileData,}),});return[fileBlock];}} return __exports;});; /* /html_editor/static/src/main/media/media_dialog/file_selector.js */ odoo.define('@html_editor/main/media/media_dialog/file_selector',['@web/core/l10n/translation','@web/core/network/rpc','@web/core/utils/hooks','@web/core/confirmation_dialog/confirmation_dialog','@web/core/dialog/dialog','@web/core/utils/concurrency','@web/core/utils/timing','@html_editor/main/media/media_dialog/search_media','@odoo/owl'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{rpc}=require("@web/core/network/rpc");const{useService}=require("@web/core/utils/hooks");const{ConfirmationDialog}=require("@web/core/confirmation_dialog/confirmation_dialog");const{Dialog}=require("@web/core/dialog/dialog");const{KeepLast}=require("@web/core/utils/concurrency");const{useDebounced}=require("@web/core/utils/timing");const{SearchMedia}=require("@html_editor/main/media/media_dialog/search_media");const{Component,xml,useState,useRef,onWillStart,useEffect}=require("@odoo/owl");const IMAGE_MIMETYPES=__exports.IMAGE_MIMETYPES=["image/jpg","image/jpeg","image/jpe","image/png","image/svg+xml","image/gif","image/webp",];const IMAGE_EXTENSIONS=__exports.IMAGE_EXTENSIONS=[".jpg",".jpeg",".jpe",".png",".svg",".gif",".webp"];class RemoveButton extends Component{static template=xml``;static props=["model?","remove"];setup(){this.removeTitle=_t("This file is attached to the current record.");if(this.props.model==="ir.ui.view"){this.removeTitle=_t("This file is a public view attachment.");}} remove(ev){ev.stopPropagation();this.props.remove();}} const AttachmentError=__exports.AttachmentError=class AttachmentError extends Component{static components={Dialog};static template=xml`

The image could not be deleted because it is used in the following pages or views:

`;static props=["views","close"];setup(){this.title=_t("Alert");}} const Attachment=__exports.Attachment=class Attachment extends Component{static template="";static components={RemoveButton,};static props=["*"];setup(){this.dialogs=useService("dialog");} remove(){this.dialogs.add(ConfirmationDialog,{body:_t("Are you sure you want to delete this file?"),confirm:async()=>{const prevented=await rpc("/web_editor/attachment/remove",{ids:[this.props.id],});if(!Object.keys(prevented).length){this.props.onRemoved(this.props.id);}else{this.dialogs.add(AttachmentError,{views:prevented[this.props.id],});}},});}} const FileSelectorControlPanel=__exports.FileSelectorControlPanel=class FileSelectorControlPanel extends Component{static template="html_editor.FileSelectorControlPanel";static components={SearchMedia,};static props={uploadUrl:Function,validateUrl:Function,uploadFiles:Function,changeSearchService:Function,changeShowOptimized:Function,search:Function,accept:{type:String,optional:true},addText:{type:String,optional:true},multiSelect:{type:true,optional:true},needle:{type:String,optional:true},searchPlaceholder:{type:String,optional:true},searchService:{type:String,optional:true},showOptimized:{type:Boolean,optional:true},showOptimizedOption:{type:String,optional:true},uploadText:{type:String,optional:true},urlPlaceholder:{type:String,optional:true},urlWarningTitle:{type:String,optional:true},useMediaLibrary:{type:Boolean,optional:true},useUnsplash:{type:Boolean,optional:true},};setup(){this.state=useState({showUrlInput:false,urlInput:"",isValidUrl:false,isValidFileFormat:false,isValidatingUrl:false,});this.debouncedValidateUrl=useDebounced(this.props.validateUrl,500);this.fileInput=useRef("file-input");} get showSearchServiceSelect(){return this.props.searchService&&this.props.needle;} get enableUrlUploadClick(){return(!this.state.showUrlInput||(this.state.urlInput&&this.state.isValidUrl&&this.state.isValidFileFormat));} async onUrlUploadClick(){if(!this.state.showUrlInput){this.state.showUrlInput=true;}else{await this.props.uploadUrl(this.state.urlInput);this.state.urlInput="";}} async onUrlInput(ev){this.state.isValidatingUrl=true;const{isValidUrl,isValidFileFormat}=await this.debouncedValidateUrl(ev.target.value);this.state.isValidFileFormat=isValidFileFormat;this.state.isValidUrl=isValidUrl;this.state.isValidatingUrl=false;} onClickUpload(){this.fileInput.el.click();} async onChangeFileInput(){const inputFiles=this.fileInput.el.files;if(!inputFiles.length){return;} await this.props.uploadFiles(inputFiles);this.fileInput.el.value="";}} const FileSelector=__exports.FileSelector=class FileSelector extends Component{static template="html_editor.FileSelector";static components={FileSelectorControlPanel,};static props=["*"];setup(){this.notificationService=useService("notification");this.orm=useService("orm");this.uploadService=useService("upload");this.keepLast=new KeepLast();this.loadMoreButtonRef=useRef("load-more-button");this.existingAttachmentsRef=useRef("existing-attachments");this.state=useState({attachments:[],canScrollAttachments:false,canLoadMoreAttachments:false,isFetchingAttachments:false,needle:"",});this.NUMBER_OF_ATTACHMENTS_TO_DISPLAY=30;onWillStart(async()=>{this.state.attachments=await this.fetchAttachments(this.NUMBER_OF_ATTACHMENTS_TO_DISPLAY,0);});this.debouncedOnScroll=useDebounced(this.updateScroll,15);this.debouncedScrollUpdate=useDebounced(this.updateScroll,500);useEffect((modalEl)=>{if(modalEl){modalEl.addEventListener("scroll",this.debouncedOnScroll);return()=>{modalEl.removeEventListener("scroll",this.debouncedOnScroll);};}},()=>[this.props.modalRef.el?.querySelector("main.modal-body")]);useEffect(()=>{this.loadMoreButtonRef.el.classList.add("o_hide_loading");this.state.canScrollAttachments=false;this.debouncedScrollUpdate();},()=>[this.allAttachments.length]);} get canLoadMore(){return this.state.canLoadMoreAttachments;} get hasContent(){return this.state.attachments.length;} get isFetching(){return this.state.isFetchingAttachments;} get selectedAttachmentIds(){return this.props.selectedMedia[this.props.id].filter((media)=>media.mediaType==="attachment").map(({id})=>id);} get attachmentsDomain(){const domain=["&",["res_model","=",this.props.resModel],["res_id","=",this.props.resId||0],];domain.unshift("|",["public","=",true]);domain.push(["name","ilike",this.state.needle]);return domain;} get allAttachments(){return this.state.attachments;} validateUrl(url){const path=url.split("?")[0];const isValidUrl=/^.+\..+$/.test(path);const isValidFileFormat=true;return{isValidUrl,isValidFileFormat,path};} async fetchAttachments(limit,offset){this.state.isFetchingAttachments=true;let attachments=[];try{attachments=await this.orm.call("ir.attachment","search_read",[],{domain:this.attachmentsDomain,fields:["name","mimetype","description","checksum","url","type","res_id","res_model","public","access_token","image_src","image_width","image_height","original_id",],order:"id desc",limit,offset,});attachments.forEach((attachment)=>(attachment.mediaType="attachment"));}catch(e){if(e.exceptionName!=="odoo.exceptions.AccessError"){throw e;}} this.state.canLoadMoreAttachments=attachments.length>=this.NUMBER_OF_ATTACHMENTS_TO_DISPLAY;this.state.isFetchingAttachments=false;return attachments;} async handleLoadMore(){await this.loadMore();} async loadMore(){return this.keepLast.add(this.fetchAttachments(this.NUMBER_OF_ATTACHMENTS_TO_DISPLAY,this.state.attachments.length)).then((newAttachments)=>{this.state.attachments.push(...newAttachments);});} async handleSearch(needle){await this.search(needle);} async search(needle){this.state.attachments=[];this.state.needle=needle;return this.keepLast.add(this.fetchAttachments(this.NUMBER_OF_ATTACHMENTS_TO_DISPLAY,0)).then((attachments)=>{this.state.attachments=attachments;});} async uploadFiles(files){await this.uploadService.uploadFiles(files,{resModel:this.props.resModel,resId:this.props.resId},(attachment)=>this.onUploaded(attachment));} async uploadUrl(url){await fetch(url).then(async(result)=>{const blob=await result.blob();blob.id=new Date().getTime();blob.name=new URL(url).pathname.split("/").findLast((s)=>s);await this.uploadFiles([blob]);}).catch(async()=>{await new Promise((resolve)=>{const imageEl=document.createElement("img");imageEl.onerror=()=>{this.notificationService.add(_t("An error occurred while fetching the entered URL."),{title:_t("Error"),sticky:true,});resolve();};imageEl.onload=()=>{this.uploadService.uploadUrl(url,{resModel:this.props.resModel,resId:this.props.resId,},(attachment)=>this.onUploaded(attachment)).then(resolve);};imageEl.src=url;});});} async onUploaded(attachment){this.state.attachments=[attachment,...this.state.attachments.filter((attach)=>attach.id!==attachment.id),];this.selectAttachment(attachment);if(!this.props.multiSelect){await this.props.save();} if(this.props.onAttachmentChange){this.props.onAttachmentChange(attachment);}} onRemoved(attachmentId){this.state.attachments=this.state.attachments.filter((attachment)=>attachment.id!==attachmentId);} selectAttachment(attachment){this.props.selectMedia({...attachment,mediaType:"attachment"});} selectInitialMedia(){return(this.props.media&&this.constructor.tagNames.includes(this.props.media.tagName)&&!this.selectedAttachmentIds.length);} updateScroll(){const loadMoreTop=this.loadMoreButtonRef.el.getBoundingClientRect().top;const modalEl=this.props.modalRef.el.querySelector("main.modal-body");const modalBottom=modalEl.getBoundingClientRect().bottom;this.state.canScrollAttachments=loadMoreTop>=modalBottom;this.loadMoreButtonRef.el.classList.remove("o_hide_loading");} isAttachmentHidden(attachmentEl){const attachmentBottom=Math.round(attachmentEl.getBoundingClientRect().bottom);const modalEl=this.props.modalRef.el.querySelector("main.modal-body");const modalBottom=modalEl.getBoundingClientRect().bottom;return attachmentBottom>modalBottom;} handleScrollAttachments(){let scrollToEl=this.loadMoreButtonRef.el;const attachmentEls=[...this.existingAttachmentsRef.el.querySelectorAll(".o_existing_attachment_cell"),];const firstHiddenAttachmentEl=attachmentEls.find((el)=>this.isAttachmentHidden(el));if(firstHiddenAttachmentEl){const attachmentBottom=firstHiddenAttachmentEl.getBoundingClientRect().bottom;const attachmentIndex=attachmentEls.indexOf(firstHiddenAttachmentEl);const firstNextRowAttachmentEl=attachmentEls.slice(attachmentIndex).find((el)=>{return el.getBoundingClientRect().bottom>attachmentBottom;});scrollToEl=firstNextRowAttachmentEl||scrollToEl;} scrollToEl.scrollIntoView({block:"end",inline:"nearest",behavior:"smooth"});}} return __exports;});; /* /html_editor/static/src/main/media/media_dialog/icon_selector.js */ odoo.define('@html_editor/main/media/media_dialog/icon_selector',['@html_editor/main/media/media_dialog/search_media','@html_editor/utils/fonts','@odoo/owl'],function(require){'use strict';let __exports={};const{SearchMedia}=require("@html_editor/main/media/media_dialog/search_media");const{fonts}=require("@html_editor/utils/fonts");const{Component,useState}=require("@odoo/owl");const IconSelector=__exports.IconSelector=class IconSelector extends Component{static mediaSpecificClasses=["fa"];static mediaSpecificStyles=["color","background-color"];static mediaExtraClasses=["rounded-circle","rounded","img-thumbnail","shadow",/^text-\S+$/,/^bg-\S+$/,/^fa-\S+$/,];static tagNames=["SPAN","I"];static template="html_editor.IconSelector";static components={SearchMedia,};static props=["*"];setup(){this.state=useState({fonts:this.props.fonts,needle:"",});} get selectedMediaIds(){return this.props.selectedMedia[this.props.id].map(({id})=>id);} search(needle){this.state.needle=needle;if(!this.state.needle){this.state.fonts=this.props.fonts;}else{this.state.fonts=this.props.fonts.map((font)=>{const icons=font.icons.filter((icon)=>icon.alias.indexOf(this.state.needle.toLowerCase())>=0);return{...font,icons};});}} async onClickIcon(font,icon){this.props.selectMedia({...icon,fontBase:font.base,initialIconChanged:this.props.media&&!icon.names.some((name)=>this.props.media.classList.contains(name)),});await this.props.save();} static createElements(selectedMedia){return selectedMedia.map((icon)=>{const iconEl=document.createElement("span");iconEl.classList.add(icon.fontBase,icon.names[0]);return iconEl;});} static initFonts(){fonts.computeFonts();const allFonts=fonts.fontIcons.map(({cssData,base})=>{const uniqueIcons=Array.from(new Map(cssData.map((icon)=>{const alias=icon.names.join(",");const id=`${base}_${alias}`;return[id,{...icon,alias,id}];})).values());return{base,icons:uniqueIcons};});return allFonts;}} return __exports;});; /* /html_editor/static/src/main/media/media_dialog/image_selector.js */ odoo.define('@html_editor/main/media/media_dialog/image_selector',['@odoo/owl','@web/core/l10n/translation','@web/core/network/rpc','@web/core/utils/concurrency','@html_editor/utils/color','@html_editor/utils/formatting','@html_editor/main/media/media_dialog/file_selector'],function(require){'use strict';let __exports={};const{useEffect,useRef,useState}=require("@odoo/owl");const{_t}=require("@web/core/l10n/translation");const{rpc}=require("@web/core/network/rpc");const{KeepLast}=require("@web/core/utils/concurrency");const{DEFAULT_PALETTE}=require("@html_editor/utils/color");const{getCSSVariableValue,getHtmlStyle}=require("@html_editor/utils/formatting");const{Attachment,FileSelector,IMAGE_EXTENSIONS,IMAGE_MIMETYPES}=require("@html_editor/main/media/media_dialog/file_selector");const AutoResizeImage=__exports.AutoResizeImage=class AutoResizeImage extends Attachment{static template="html_editor.AutoResizeImage";setup(){super.setup();this.image=useRef("auto-resize-image");this.container=useRef("auto-resize-image-container");this.state=useState({loaded:false,});useEffect(()=>{this.image.el.addEventListener("load",()=>this.onImageLoaded());return this.image.el.removeEventListener("load",()=>this.onImageLoaded());},()=>[]);} async onImageLoaded(){if(!this.image.el){return;} if(this.props.onLoaded){await this.props.onLoaded(this.image.el);if(!this.image.el){return;}} const aspectRatio=this.image.el.offsetWidth/this.image.el.offsetHeight;const width=aspectRatio*this.props.minRowHeight;this.container.el.style.flexGrow=width;this.container.el.style.flexBasis=`${width}px`;this.state.loaded=true;}} const newLocal="img-fluid";const ImageSelector=__exports.ImageSelector=class ImageSelector extends FileSelector{static mediaSpecificClasses=["img",newLocal,"o_we_custom_image"];static mediaSpecificStyles=[];static mediaExtraClasses=["rounded-circle","rounded","img-thumbnail","shadow","w-25","w-50","w-75","w-100",];static tagNames=["IMG"];static attachmentsListTemplate="html_editor.ImagesListTemplate";static components={...FileSelector.components,AutoResizeImage,};setup(){super.setup();this.keepLastLibraryMedia=new KeepLast();this.state.libraryMedia=[];this.state.libraryResults=null;this.state.isFetchingLibrary=false;this.state.searchService="all";this.state.showOptimized=false;this.NUMBER_OF_MEDIA_TO_DISPLAY=10;this.uploadText=_t("Upload an image");this.urlPlaceholder="https://www.odoo.com/logo.png";this.addText=_t("Add URL");this.searchPlaceholder=_t("Search an image");this.urlWarningTitle=_t("Uploaded image's format is not supported. Try with: "+IMAGE_EXTENSIONS.join(", "));this.allLoadedText=_t("All images have been loaded");this.showOptimizedOption=this.env.debug;this.MIN_ROW_HEIGHT=128;this.fileMimetypes=IMAGE_MIMETYPES.join(",");} get canLoadMore(){if(this.state.searchService==="media-library"){return(this.state.libraryResults&&this.state.libraryMedia.lengthmedia.mediaType==="libraryMedia").map(({id})=>id);} get allAttachments(){return[...super.allAttachments,...this.state.libraryMedia];} get attachmentsDomain(){const domain=super.attachmentsDomain;domain.push(["mimetype","in",IMAGE_MIMETYPES]);if(!this.props.useMediaLibrary){domain.push("|",["url","=",false],"!","|",["url","=ilike","/html_editor/shape/%"],["url","=ilike","/web_editor/shape/%"],);} domain.push("!",["name","=like","%.crop"]);domain.push("|",["type","=","binary"],"!",["url","=like","/%/static/%"]);if(!this.env.debug){const subDomain=[false];const originalId=this.props.media&&this.props.media.dataset.originalId;if(originalId){subDomain.push(originalId);} domain.push(["original_id","in",subDomain]);} return domain;} async uploadFiles(files){await this.uploadService.uploadFiles(files,{resModel:this.props.resModel,resId:this.props.resId,isImage:true},(attachment)=>this.onUploaded(attachment));} async validateUrl(...args){const{isValidUrl,path}=super.validateUrl(...args);const isValidFileFormat=isValidUrl&&(await new Promise((resolve)=>{const img=new Image();img.src=path;img.onload=()=>resolve(true);img.onerror=()=>resolve(false);}));return{isValidFileFormat,isValidUrl};} isInitialMedia(attachment){if(this.props.media.dataset.originalSrc){return this.props.media.dataset.originalSrc===attachment.image_src;} return this.props.media.getAttribute("src")===attachment.image_src;} async fetchAttachments(limit,offset){const attachments=await super.fetchAttachments(limit,offset);const primaryColors={};const htmlStyle=getHtmlStyle(document);for(let color=1;color<=5;color++){primaryColors[color]=getCSSVariableValue("o-color-"+color,htmlStyle);} return attachments.map((attachment)=>{if(attachment.image_src.startsWith("/")){const newURL=new URL(attachment.image_src,window.location.origin);if(attachment.image_src.startsWith("/html_editor/shape/")||attachment.image_src.startsWith("/web_editor/shape/")){newURL.searchParams.forEach((value,key)=>{const match=key.match(/^c([1-5])$/);if(match){newURL.searchParams.set(key,primaryColors[match[1]]);}});}else{newURL.searchParams.set("height",2*this.MIN_ROW_HEIGHT);} attachment.thumbnail_src=newURL.pathname+newURL.search;} if(this.selectInitialMedia()&&this.isInitialMedia(attachment)){this.selectAttachment(attachment);} return attachment;});} async fetchLibraryMedia(offset){if(!this.state.needle){return{media:[],results:null};} this.state.isFetchingLibrary=true;try{const response=await rpc("/web_editor/media_library_search",{query:this.state.needle,offset:offset,},{silent:true,});this.state.isFetchingLibrary=false;const media=(response.media||[]).slice(0,this.NUMBER_OF_MEDIA_TO_DISPLAY);media.forEach((record)=>(record.mediaType="libraryMedia"));return{media,results:response.results};}catch{console.error(`Couldn't reach API endpoint.`);this.state.isFetchingLibrary=false;return{media:[],results:null};}} async loadMore(...args){await super.loadMore(...args);if(!this.props.useMediaLibrary||this.state.searchService!=="media-library"){return;} return this.keepLastLibraryMedia.add(this.fetchLibraryMedia(this.state.libraryMedia.length)).then(({media})=>{this.state.libraryMedia.push(...media);});} async search(...args){await super.search(...args);if(!this.props.useMediaLibrary){return;} if(!this.state.needle){this.state.searchService="all";} this.state.libraryMedia=[];this.state.libraryResults=0;return this.keepLastLibraryMedia.add(this.fetchLibraryMedia(0)).then(({media,results})=>{this.state.libraryMedia=media;this.state.libraryResults=results;});} async onClickAttachment(attachment){this.selectAttachment(attachment);if(!this.props.multiSelect){await this.props.save();}} async onClickMedia(media){this.props.selectMedia({...media,mediaType:"libraryMedia"});if(!this.props.multiSelect){await this.props.save();}} static async createElements(selectedMedia,{orm}){const toSave=Object.fromEntries(selectedMedia.filter((media)=>media.mediaType==="libraryMedia").map((media)=>[media.id,{query:media.query||"",is_dynamic_svg:!!media.isDynamicSVG,dynamic_colors:media.dynamicColors,},]));let savedMedia=[];if(Object.keys(toSave).length!==0){savedMedia=await rpc("/html_editor/save_library_media",{media:toSave});} const selected=selectedMedia.filter((media)=>media.mediaType==="attachment").concat(savedMedia).map((attachment)=>{if(attachment.image_src&&(attachment.image_src.startsWith("/html_editor/shape/")||attachment.image_src.startsWith("/web_editor/shape/"))){const colorCustomizedURL=new URL(attachment.image_src,window.location.origin);const htmlStyle=getHtmlStyle(document);colorCustomizedURL.searchParams.forEach((value,key)=>{const match=key.match(/^c([1-5])$/);if(match){colorCustomizedURL.searchParams.set(key,getCSSVariableValue(`o-color-${match[1]}`,htmlStyle));}});attachment.image_src=colorCustomizedURL.pathname+colorCustomizedURL.search;} return attachment;});return Promise.all(selected.map(async(attachment)=>{const imageEl=document.createElement("img");let src=attachment.image_src;if(!attachment.public&&!attachment.url){let accessToken=attachment.access_token;if(!accessToken){[accessToken]=await orm.call("ir.attachment","generate_access_token",[attachment.id,]);} src+=`?access_token=${encodeURIComponent(accessToken)}`;} imageEl.src=src;imageEl.alt=attachment.description||"";return imageEl;}));} async onImageLoaded(imgEl,attachment){this.debouncedScrollUpdate();if(attachment.mediaType==="libraryMedia"&&!imgEl.src.startsWith("blob")){await this.onLibraryImageLoaded(imgEl,attachment);}} async onLibraryImageLoaded(imgEl,media){const mediaUrl=imgEl.src;try{const response=await fetch(mediaUrl);if(response.headers.get("content-type")==="image/svg+xml"){let svg=await response.text();const dynamicColors={};const combinedColorsRegex=new RegExp(Object.values(DEFAULT_PALETTE).join("|"),"gi");const htmlStyle=getHtmlStyle(document);svg=svg.replace(combinedColorsRegex,(match)=>{const colorId=Object.keys(DEFAULT_PALETTE).find((key)=>DEFAULT_PALETTE[key]===match.toUpperCase());const colorKey="c"+colorId;dynamicColors[colorKey]=getCSSVariableValue("o-color-"+colorId,htmlStyle);return dynamicColors[colorKey];});const fileName=mediaUrl.split("/").pop();const file=new File([svg],fileName,{type:"image/svg+xml",});imgEl.src=URL.createObjectURL(file);if(Object.keys(dynamicColors).length){media.isDynamicSVG=true;media.dynamicColors=dynamicColors;}}}catch{console.error("CORS is misconfigured on the API server, image will be treated as non-dynamic.");}}} return __exports;});; /* /html_editor/static/src/main/media/media_dialog/media_dialog.js */ odoo.define('@html_editor/main/media/media_dialog/media_dialog',['@web/core/l10n/translation','@web/core/utils/hooks','@web/core/dialog/dialog','@web/core/notebook/notebook','@html_editor/main/media/media_dialog/image_selector','@html_editor/main/media/media_dialog/icon_selector','@html_editor/main/media/media_dialog/video_selector','@odoo/owl'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{useService,useChildRef}=require("@web/core/utils/hooks");const{Dialog}=require("@web/core/dialog/dialog");const{Notebook}=require("@web/core/notebook/notebook");const{ImageSelector}=require("@html_editor/main/media/media_dialog/image_selector");const{IconSelector}=require("@html_editor/main/media/media_dialog/icon_selector");const{VideoSelector}=require("@html_editor/main/media/media_dialog/video_selector");const{Component,useState,useRef,useEffect}=require("@odoo/owl");const TABS=__exports.TABS={IMAGES:{id:"IMAGES",title:_t("Images"),Component:ImageSelector,sequence:10,},ICONS:{id:"ICONS",title:_t("Icons"),Component:IconSelector,sequence:20,},VIDEOS:{id:"VIDEOS",title:_t("Videos"),Component:VideoSelector,sequence:30,},};const DEFAULT_SEQUENCE=50;const sequence=(tab)=>tab.sequence??DEFAULT_SEQUENCE;const MediaDialog=__exports.MediaDialog=class MediaDialog extends Component{static template="html_editor.MediaDialog";static defaultProps={useMediaLibrary:true,};static components={Dialog,Notebook,};static props=["*"];setup(){this.size="xl";this.contentClass="o_select_media_dialog h-100";this.title=_t("Select a media");this.modalRef=useChildRef();this.orm=useService("orm");this.notificationService=useService("notification");this.selectedMedia=useState({});this.addButtonRef=useRef("add-button");this.initialIconClasses=[];this.tabs={...TABS};this.notebookPages=[];this.addDefaultTabs();this.addExtraTabs();this.notebookPages.sort((a,b)=>sequence(a)-sequence(b));this.errorMessages={};this.state=useState({activeTab:this.initialActiveTab,});useEffect((nbSelectedAttachments)=>{this.addButtonRef.el.toggleAttribute("disabled",!nbSelectedAttachments);},()=>[this.selectedMedia[this.state.activeTab].length]);} get initialActiveTab(){if(this.props.activeTab){return this.props.activeTab;} if(this.props.media){const correspondingTab=Object.keys(this.tabs).find((id)=>this.tabs[id].Component.tagNames.includes(this.props.media.tagName));if(correspondingTab){return correspondingTab;}} return this.notebookPages[0].id;} addTab(tab,additionalProps={}){this.selectedMedia[tab.id]=[];this.notebookPages.push({...tab,props:{...tab.props,...additionalProps,id:tab.id,resModel:this.props.resModel,resId:this.props.resId,media:this.props.media,selectedMedia:this.selectedMedia,selectMedia:(...args)=>this.selectMedia(...args,tab.id,additionalProps.multiSelect),save:this.save.bind(this),onAttachmentChange:this.props.onAttachmentChange,errorMessages:(errorMessage)=>(this.errorMessages[tab.id]=errorMessage),modalRef:this.modalRef,},});} addTabs(){this.addDefaultTabs();} addDefaultTabs(){const onlyImages=this.props.onlyImages||(this.props.media&&this.props.media.parentElement&&(this.props.media.parentElement.dataset.oeField==="image"||this.props.media.parentElement.dataset.oeType==="image"));const noIcons=onlyImages||this.props.noIcons;const noVideos=onlyImages||this.props.noVideos;if(!this.props.noImages){this.addTab(TABS.IMAGES,{useMediaLibrary:this.props.useMediaLibrary,multiSelect:this.props.multiImages,});} if(!noIcons){const fonts=TABS.ICONS.Component.initFonts();this.addTab(TABS.ICONS,{fonts,});if(this.props.media&&TABS.ICONS.Component.tagNames.includes(this.props.media.tagName)){const classes=this.props.media.className.split(/\s+/);const mediaFont=fonts.find((font)=>classes.includes(font.base));if(mediaFont){const selectedIcon=mediaFont.icons.find((icon)=>icon.names.some((name)=>classes.includes(name)));if(selectedIcon){this.initialIconClasses.push(...selectedIcon.names);this.selectMedia(selectedIcon,TABS.ICONS.id);}}}} if(!noVideos){this.addTab(TABS.VIDEOS,{vimeoPreviewIds:this.props.vimeoPreviewIds,isForBgVideo:this.props.isForBgVideo,});}} addExtraTabs(){for(const tab of this.props.extraTabs||[]){this.addTab(tab);this.tabs[tab.id]=tab;}} async renderMedia(selectedMedia){const elements=await this.tabs[this.state.activeTab].Component.createElements(selectedMedia,{orm:this.orm});elements.forEach((element)=>{if(this.props.media){element.classList.add(...this.props.media.classList);const style=this.props.media.getAttribute("style");if(style){element.setAttribute("style",style);} if(this.state.activeTab===this.tabs.IMAGES.id){if(this.props.media.dataset.shape){element.dataset.shape=this.props.media.dataset.shape;} if(this.props.media.dataset.shapeColors){element.dataset.shapeColors=this.props.media.dataset.shapeColors;} if(this.props.media.dataset.shapeFlip){element.dataset.shapeFlip=this.props.media.dataset.shapeFlip;} if(this.props.media.dataset.shapeRotate){element.dataset.shapeRotate=this.props.media.dataset.shapeRotate;} if(this.props.media.dataset.hoverEffect){element.dataset.hoverEffect=this.props.media.dataset.hoverEffect;} if(this.props.media.dataset.hoverEffectColor){element.dataset.hoverEffectColor=this.props.media.dataset.hoverEffectColor;} if(this.props.media.dataset.hoverEffectStrokeWidth){element.dataset.hoverEffectStrokeWidth=this.props.media.dataset.hoverEffectStrokeWidth;} if(this.props.media.dataset.hoverEffectIntensity){element.dataset.hoverEffectIntensity=this.props.media.dataset.hoverEffectIntensity;}}} for(const otherTab of Object.keys(this.tabs).filter((key)=>key!==this.state.activeTab)){for(const property of this.tabs[otherTab].Component.mediaSpecificStyles){element.style.removeProperty(property);} element.classList.remove(...this.tabs[otherTab].Component.mediaSpecificClasses);const extraClassesToRemove=[];for(const name of this.tabs[otherTab].Component.mediaExtraClasses){if(typeof name==="string"){extraClassesToRemove.push(name);}else{for(const className of element.classList){if(className.match(name)){extraClassesToRemove.push(className);}}}} element.classList.remove(...extraClassesToRemove.filter((candidateName)=>{for(const name of this.tabs[this.state.activeTab].Component.mediaExtraClasses){if(typeof name==="string"){if(candidateName===name){return false;}}else{for(const className of element.classList){if(className.match(candidateName)){return false;}}}} return true;}));} element.classList.remove(...this.initialIconClasses);element.classList.remove("o_modified_image_to_save");element.classList.remove("oe_edited_link");element.classList.add(...this.tabs[this.state.activeTab].Component.mediaSpecificClasses);});return elements;} selectMedia(media,tabId,multiSelect){if(multiSelect){const isMediaSelected=this.selectedMedia[tabId].map(({id})=>id).includes(media.id);if(!isMediaSelected){this.selectedMedia[tabId].push(media);}else{this.selectedMedia[tabId]=this.selectedMedia[tabId].filter((m)=>m.id!==media.id);}}else{this.selectedMedia[tabId]=[media];}} async save(){if(this.errorMessages[this.state.activeTab]){this.notificationService.add(this.errorMessages[this.state.activeTab],{type:"danger",});return;} const selectedMedia=this.selectedMedia[this.state.activeTab];const saveSelectedMedia=selectedMedia.length&&(this.state.activeTab!==this.tabs.ICONS.id||selectedMedia[0].initialIconChanged||!this.props.media);if(saveSelectedMedia){const elements=await this.renderMedia(selectedMedia);if(this.props.multiImages){this.props.save(elements);}else{this.props.save(elements[0]);}} this.props.close();} onTabChange(tab){this.state.activeTab=tab;}} return __exports;});; /* /html_editor/static/src/main/media/media_dialog/search_media.js */ odoo.define('@html_editor/main/media/media_dialog/search_media',['@web/core/utils/timing','@web/core/utils/hooks','@odoo/owl'],function(require){'use strict';let __exports={};const{useDebounced}=require("@web/core/utils/timing");const{useAutofocus}=require("@web/core/utils/hooks");const{Component,xml,useEffect,useState}=require("@odoo/owl");const SearchMedia=__exports.SearchMedia=class SearchMedia extends Component{static template=xml`
`;static props=["searchPlaceholder","search","needle"];setup(){useAutofocus({mobile:true});this.debouncedSearch=useDebounced(this.props.search,1000);this.state=useState({input:this.props.needle||"",});useEffect((input)=>{if(this.hasRendered){this.debouncedSearch(input);}else{this.hasRendered=true;}},()=>[this.state.input]);}} return __exports;});; /* /html_editor/static/src/main/media/media_dialog/upload_progress_toast/upload_progress_toast.js */ odoo.define('@html_editor/main/media/media_dialog/upload_progress_toast/upload_progress_toast',['@web/core/utils/hooks','@odoo/owl'],function(require){'use strict';let __exports={};const{useService}=require("@web/core/utils/hooks");const{Component,useState}=require("@odoo/owl");const ProgressBar=__exports.ProgressBar=class ProgressBar extends Component{static template="html_editor.ProgressBar";static props={progress:{type:Number,optional:true},hasError:{type:Boolean,optional:true},uploaded:{type:Boolean,optional:true},name:String,size:{type:String,optional:true},errorMessage:{type:String,optional:true},};static defaultProps={progress:0,hasError:false,uploaded:false,size:"",errorMessage:"",};get progress(){return Math.round(this.props.progress);}} const UploadProgressToast=__exports.UploadProgressToast=class UploadProgressToast extends Component{static template="html_editor.UploadProgressToast";static components={ProgressBar,};static props={close:Function,};setup(){this.uploadService=useService("upload");this.state=useState(this.uploadService.progressToast);}} return __exports;});; /* /html_editor/static/src/main/media/media_dialog/upload_progress_toast/upload_service.js */ odoo.define('@html_editor/main/media/media_dialog/upload_progress_toast/upload_service',['@web/core/network/rpc','@web/core/registry','@html_editor/main/media/media_dialog/upload_progress_toast/upload_progress_toast','@web/core/l10n/translation','@web/core/utils/files','@web/core/utils/numbers','@web/core/utils/urls','@web/core/utils/strings','@odoo/owl'],function(require){'use strict';let __exports={};const{rpc}=require("@web/core/network/rpc");const{registry}=require("@web/core/registry");const{UploadProgressToast}=require("@html_editor/main/media/media_dialog/upload_progress_toast/upload_progress_toast");const{_t}=require("@web/core/l10n/translation");const{checkFileSize}=require("@web/core/utils/files");const{humanNumber}=require("@web/core/utils/numbers");const{getDataURLFromFile}=require("@web/core/utils/urls");const{sprintf}=require("@web/core/utils/strings");const{reactive}=require("@odoo/owl");const AUTOCLOSE_DELAY=__exports.AUTOCLOSE_DELAY=3000;const AUTOCLOSE_DELAY_LONG=__exports.AUTOCLOSE_DELAY_LONG=8000;const uploadService=__exports.uploadService={dependencies:["notification"],start(env,{notification}){let fileId=0;const progressToast=reactive({files:{},isVisible:false,});registry.category("main_components").add("UploadProgressToast",{Component:UploadProgressToast,props:{close:()=>(progressToast.isVisible=false),},});const addFile=(file)=>{progressToast.files[file.id]=file;progressToast.isVisible=true;return progressToast.files[file.id];};const deleteFile=(fileId)=>{delete progressToast.files[fileId];if(!Object.keys(progressToast.files).length){progressToast.isVisible=false;}};return{get progressToast(){return progressToast;},get fileId(){return fileId;},addFile,deleteFile,incrementId(){fileId++;},uploadUrl:async(url,{resModel,resId},onUploaded)=>{const attachment=await rpc("/html_editor/attachment/add_url",{url,res_model:resModel,res_id:resId,});await onUploaded(attachment);},uploadFiles:async(files,{resModel,resId,isImage},onUploaded)=>{const sortedFiles=Array.from(files).sort((a,b)=>a.size-b.size);for(const file of sortedFiles){let fileSize=file.size;if(!checkFileSize(fileSize,notification)){return null;} if(!fileSize){fileSize="";}else{fileSize=humanNumber(fileSize)+"B";} const id=++fileId;file.progressToastId=id;addFile({id,name:file.name,size:fileSize,});} for(const sortedFile of sortedFiles){const file=progressToast.files[sortedFile.progressToastId];let dataURL;try{dataURL=await getDataURLFromFile(sortedFile);}catch{deleteFile(file.id);env.services.notification.add(sprintf(_t('Could not load the file "%s".'),sortedFile.name),{type:"danger"});continue;} try{const xhr=new XMLHttpRequest();xhr.upload.addEventListener("progress",(ev)=>{const rpcComplete=(ev.loaded/ev.total)*100;file.progress=rpcComplete;});xhr.upload.addEventListener("load",function(){file.progress=100;});const attachment=await rpc("/html_editor/attachment/add_data",{name:file.name,data:dataURL.split(",")[1],res_id:resId,res_model:resModel,is_image:!!isImage,width:0,quality:0,},{xhr});if(attachment.error){file.hasError=true;file.errorMessage=attachment.error;}else{if(attachment.mimetype==="image/webp"){const image=document.createElement("img");image.src=`data:image/webp;base64,${dataURL.split(",")[1]}`;await new Promise((resolve)=>image.addEventListener("load",resolve));const canvas=document.createElement("canvas");canvas.width=image.width;canvas.height=image.height;const ctx=canvas.getContext("2d");ctx.fillStyle="rgb(255, 255, 255)";ctx.fillRect(0,0,canvas.width,canvas.height);ctx.drawImage(image,0,0);const altDataURL=canvas.toDataURL("image/jpeg",0.75);await rpc("/html_editor/attachment/add_data",{name:file.name.replace(/\.webp$/,".jpg"),data:altDataURL.split(",")[1],res_id:attachment.id,res_model:"ir.attachment",is_image:true,width:0,quality:0,},{xhr});} file.uploaded=true;await onUploaded(attachment);} const message_autoclose_delay=file.hasError?AUTOCLOSE_DELAY_LONG:AUTOCLOSE_DELAY;setTimeout(()=>deleteFile(file.id),message_autoclose_delay);}catch(error){file.hasError=true;setTimeout(()=>deleteFile(file.id),AUTOCLOSE_DELAY_LONG);throw error;}}},};},};registry.category("services").add("upload",uploadService);return __exports;});; /* /html_editor/static/src/main/media/media_dialog/video_selector.js */ odoo.define('@html_editor/main/media/media_dialog/video_selector',['@web/core/l10n/translation','@web/core/network/rpc','@web/core/utils/hooks','@web/core/utils/timing','@odoo/owl'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{rpc}=require("@web/core/network/rpc");const{useAutofocus,useService}=require("@web/core/utils/hooks");const{debounce}=require("@web/core/utils/timing");const{Component,useState,useRef,onMounted,onWillStart}=require("@odoo/owl");class VideoOption extends Component{static template="html_editor.VideoOption";static props={description:{type:String,optional:true},label:{type:String,optional:true},onChangeOption:Function,value:{type:Boolean,optional:true},};} class VideoIframe extends Component{static template="html_editor.VideoIframe";static props={src:{type:String},};} const VideoSelector=__exports.VideoSelector=class VideoSelector extends Component{static mediaSpecificClasses=["media_iframe_video"];static mediaSpecificStyles=[];static mediaExtraClasses=[];static tagNames=["IFRAME","DIV"];static template="html_editor.VideoSelector";static components={VideoIframe,VideoOption,};static props={selectMedia:Function,errorMessages:Function,vimeoPreviewIds:{type:Array,optional:true},isForBgVideo:{type:Boolean,optional:true},media:{type:Object,optional:true},"*":true,};static defaultProps={vimeoPreviewIds:[],isForBgVideo:false,};setup(){this.http=useService("http");this.PLATFORMS={youtube:"youtube",dailymotion:"dailymotion",vimeo:"vimeo",youku:"youku",};this.OPTIONS={autoplay:{label:_t("Autoplay"),description:_t("Videos are muted when autoplay is enabled"),platforms:[this.PLATFORMS.youtube,this.PLATFORMS.dailymotion,this.PLATFORMS.vimeo,],urlParameter:"autoplay=1",},loop:{label:_t("Loop"),platforms:[this.PLATFORMS.youtube,this.PLATFORMS.vimeo],urlParameter:"loop=1",},hide_controls:{label:_t("Hide player controls"),platforms:[this.PLATFORMS.youtube,this.PLATFORMS.dailymotion,this.PLATFORMS.vimeo,],urlParameter:"controls=0",},hide_fullscreen:{label:_t("Hide fullscreen button"),platforms:[this.PLATFORMS.youtube],urlParameter:"fs=0",isHidden:()=>this.state.options.filter((option)=>option.id==="hide_controls")[0].value,},hide_dm_logo:{label:_t("Hide Dailymotion logo"),platforms:[this.PLATFORMS.dailymotion],urlParameter:"ui-logo=0",},hide_dm_share:{label:_t("Hide sharing button"),platforms:[this.PLATFORMS.dailymotion],urlParameter:"sharing-enable=0",},};this.state=useState({options:[],src:"",urlInput:"",platform:null,vimeoPreviews:[],errorMessage:"",});this.urlInputRef=useRef("url-input");onWillStart(async()=>{if(this.props.media){const src=this.props.media.dataset.oeExpression||this.props.media.dataset.src||(this.props.media.tagName==="IFRAME"&&this.props.media.getAttribute("src"))||"";if(src){this.state.urlInput=src;await this.updateVideo();this.state.options=this.state.options.map((option)=>{const{urlParameter}=this.OPTIONS[option.id];return{...option,value:src.indexOf(urlParameter)>=0};});}}});onMounted(async()=>{await Promise.all(this.props.vimeoPreviewIds.map(async(videoId)=>{const{thumbnail_url:thumbnailSrc}=await this.http.get(`https://vimeo.com/api/oembed.json?url=http%3A//vimeo.com/${encodeURIComponent( videoId )}`);this.state.vimeoPreviews.push({id:videoId,thumbnailSrc,src:`https://player.vimeo.com/video/${encodeURIComponent(videoId)}`,});}));});useAutofocus();this.onChangeUrl=debounce((ev)=>this.updateVideo(ev.target.value),500);} get shownOptions(){if(this.props.isForBgVideo){return[];} return this.state.options.filter((option)=>!this.OPTIONS[option.id].isHidden||!this.OPTIONS[option.id].isHidden());} async onChangeOption(optionId){this.state.options=this.state.options.map((option)=>{if(option.id===optionId){return{...option,value:!option.value};} return option;});await this.updateVideo();} async onClickSuggestion(src){this.state.urlInput=src;await this.updateVideo();} async updateVideo(){if(!this.state.urlInput){this.state.src="";this.state.urlInput="";this.state.options=[];this.state.platform=null;this.state.errorMessage="";this.props.selectMedia({});return;} const embedMatch=this.state.urlInput.match(/(src|href)=["']?([^"']+)?/);if(embedMatch&&embedMatch[2].length>0&&embedMatch[2].indexOf("instagram")){embedMatch[1]=embedMatch[2];} const url=embedMatch?embedMatch[1]:this.state.urlInput;const options={};if(this.props.isForBgVideo){Object.keys(this.OPTIONS).forEach((key)=>{options[key]=true;});}else{for(const option of this.shownOptions){options[option.id]=option.value;}} const{embed_url:src,video_id:videoId,params,platform,}=await this._getVideoURLData(url,options);if(!src){this.state.errorMessage=_t("The provided url is not valid");}else if(!platform){this.state.errorMessage=_t("The provided url does not reference any supported video");}else{this.state.errorMessage="";} this.props.errorMessages(this.state.errorMessage);const newOptions=[];if(platform&&platform!==this.state.platform){Object.keys(this.OPTIONS).forEach((key)=>{if(this.OPTIONS[key].platforms.includes(platform)){const{label,description}=this.OPTIONS[key];newOptions.push({id:key,label,description});}});} this.state.src=src;this.props.selectMedia({id:src,src,platform,videoId,params,});if(platform!==this.state.platform){this.state.platform=platform;this.state.options=newOptions;}} async _getVideoURLData(url,options){return await rpc("/web_editor/video_url/data",{video_url:url,...options,});} static createElements(selectedMedia){return selectedMedia.map((video)=>{const div=document.createElement("div");div.dataset.oeExpression=video.src;div.innerHTML='
'+'
'+'';div.querySelector("iframe").src=video.src;return div;});}} return __exports;});; /* /html_editor/static/src/utils/base_container.js */ odoo.define('@html_editor/utils/base_container',[],function(require){'use strict';let __exports={};const BASE_CONTAINER_CLASS=__exports.BASE_CONTAINER_CLASS="o-paragraph";const SUPPORTED_BASE_CONTAINER_NAMES=__exports.SUPPORTED_BASE_CONTAINER_NAMES=["P","DIV"];__exports.getBaseContainerSelector=getBaseContainerSelector;function getBaseContainerSelector(nodeName){if(!nodeName){return baseContainerGlobalSelector;} nodeName=SUPPORTED_BASE_CONTAINER_NAMES.includes(nodeName)?nodeName:"P";let suffix="";if(nodeName!=="P"){suffix=`.${BASE_CONTAINER_CLASS}`;} return`${nodeName}${suffix}`;} const baseContainerGlobalSelector=__exports.baseContainerGlobalSelector=SUPPORTED_BASE_CONTAINER_NAMES.map((name)=>getBaseContainerSelector(name)).join(",");__exports.createBaseContainer=createBaseContainer;function createBaseContainer(nodeName,document){if(!document&&window){document=window.document;} nodeName=nodeName&&SUPPORTED_BASE_CONTAINER_NAMES.includes(nodeName)?nodeName:"P";const el=document.createElement(nodeName);if(nodeName!=="P"){el.className=BASE_CONTAINER_CLASS;} return el;} return __exports;});; /* /html_editor/static/src/utils/blocks.js */ odoo.define('@html_editor/utils/blocks',['@html_editor/utils/dom_traversal'],function(require){'use strict';let __exports={};const{closestPath,findNode}=require("@html_editor/utils/dom_traversal");const blockTagNames=["ADDRESS","ARTICLE","ASIDE","BLOCKQUOTE","DETAILS","DIALOG","DD","DIV","DL","DT","FIELDSET","FIGCAPTION","FIGURE","FOOTER","FORM","H1","H2","H3","H4","H5","H6","HEADER","HGROUP","HR","LI","MAIN","NAV","OL","P","PRE","SECTION","TABLE","UL","SELECT","OPTION","TR","TD","TBODY","THEAD","TH",];const computedStyles=new WeakMap();__exports.isBlock=isBlock;function isBlock(node){if(!node||node.nodeType!==Node.ELEMENT_NODE){return false;} const tagName=node.nodeName.toUpperCase();if(tagName==="BR"){return false;} if(!node.isConnected){return blockTagNames.includes(tagName);} let style=computedStyles.get(node);if(!style){style=node.ownerDocument.defaultView.getComputedStyle(node);computedStyles.set(node,style);} if(style.display){return!style.display.includes("inline")&&style.display!=="contents";} return blockTagNames.includes(tagName);} __exports.closestBlock=closestBlock;function closestBlock(node){return findNode(closestPath(node),(node)=>isBlock(node));} return __exports;});; /* /html_editor/static/src/utils/color.js */ odoo.define('@html_editor/utils/color',['@html_editor/utils/dom_traversal'],function(require){'use strict';let __exports={};const{closestElement}=require("@html_editor/utils/dom_traversal");const COLOR_PALETTE_COMPATIBILITY_COLOR_NAMES=__exports.COLOR_PALETTE_COMPATIBILITY_COLOR_NAMES=["primary","secondary","alpha","beta","gamma","delta","epsilon","success","info","warning","danger",];const DEFAULT_PALETTE=__exports.DEFAULT_PALETTE={1:"#3AADAA",2:"#7C6576",3:"#F6F6F6",4:"#FFFFFF",5:"#383E45",};const EDITOR_COLOR_CSS_VARIABLES=__exports.EDITOR_COLOR_CSS_VARIABLES=[...COLOR_PALETTE_COMPATIBILITY_COLOR_NAMES];for(let i=1;i<=5;i++){EDITOR_COLOR_CSS_VARIABLES.push(`o-color-${i}`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-bg`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-bg-gradient`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-headings`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-text`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-btn-primary`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-btn-primary-text`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-btn-secondary`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-btn-secondary-text`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-btn-primary-border`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-btn-secondary-border`);} for(let i=100;i<=900;i+=100){EDITOR_COLOR_CSS_VARIABLES.push(`${i}`);} __exports.rgbToHex=rgbToHex;function rgbToHex(rgb="",node=null){if(rgb.startsWith("#")){return rgb;}else if(rgb.startsWith("rgba")){const values=rgb.match(/[\d.]{1,5}/g)||[];const alpha=parseFloat(values.pop());let bgRgbValues=[];if(node){let bgColor=getComputedStyle(node).backgroundColor;if(bgColor.startsWith("rgba")){bgColor=rgbToHex(bgColor,node.parentElement);} if(bgColor&&bgColor.startsWith("#")){bgRgbValues=(bgColor.match(/[\da-f]{2}/gi)||[]).map((val)=>parseInt(val,16));}else if(bgColor&&bgColor.startsWith("rgb")){bgRgbValues=(bgColor.match(/[\d.]{1,5}/g)||[]).map((val)=>parseInt(val));}} bgRgbValues=bgRgbValues.length?bgRgbValues:[255,255,255];return("#"+ values.map((value,index)=>{const converted=Math.floor(alpha*parseInt(value)+(1-alpha)*bgRgbValues[index]);const hex=parseInt(converted).toString(16);return hex.length===1?"0"+hex:hex;}).join(""));}else{return("#"+ (rgb.match(/\d{1,3}/g)||[]).map((x)=>{x=parseInt(x).toString(16);return x.length===1?"0"+x:x;}).join(""));}} __exports.isColorCombinationName=isColorCombinationName;function isColorCombinationName(name){const number=parseInt(name);return!isNaN(number)&&number%100!==0;} __exports.isColorGradient=isColorGradient;function isColorGradient(value){return value&&value.includes("-gradient(");} const TEXT_CLASSES_REGEX=__exports.TEXT_CLASSES_REGEX=/\btext-[^\s]*\b/;const BG_CLASSES_REGEX=__exports.BG_CLASSES_REGEX=/\bbg-[^\s]*\b/;__exports.hasColor=hasColor;function hasColor(element,mode){const style=element.style;const parent=element.parentNode;const classRegex=mode==="color"?TEXT_CLASSES_REGEX:BG_CLASSES_REGEX;if(isColorGradient(style["background-image"])){if(element.classList.contains("text-gradient")){if(mode==="color"){return true;}}else{if(mode!=="color"){return true;}}} return((style[mode]&&style[mode]!=="inherit"&&(!parent||style[mode]!==parent.style[mode]))||(classRegex.test(element.className)&&(!parent||getComputedStyle(element)[mode]!==getComputedStyle(parent)[mode])));} __exports.hasAnyNodesColor=hasAnyNodesColor;function hasAnyNodesColor(nodes,mode){for(const node of nodes){if(hasColor(closestElement(node),mode)){return true;}} return false;} return __exports;});; /* /html_editor/static/src/utils/content_types.js */ odoo.define('@html_editor/utils/content_types',[],function(require){'use strict';let __exports={};const CTYPES=__exports.CTYPES={CONTENT:1,SPACE:2,BLOCK_OUTSIDE:4,BLOCK_INSIDE:8,BR:16,};__exports.ctypeToString=ctypeToString;function ctypeToString(ctype){return Object.keys(CTYPES).find((key)=>CTYPES[key]===ctype);} const CTGROUPS=__exports.CTGROUPS={INLINE:CTYPES.CONTENT|CTYPES.SPACE,BLOCK:CTYPES.BLOCK_OUTSIDE|CTYPES.BLOCK_INSIDE,BR:CTYPES.BR,};return __exports;});; /* /html_editor/static/src/utils/dom.js */ odoo.define('@html_editor/utils/dom',['@html_editor/utils/blocks','@html_editor/utils/dom_info','@html_editor/utils/selection','@html_editor/utils/dom_traversal','@html_editor/utils/position','@html_editor/utils/base_container'],function(require){'use strict';let __exports={};const{closestBlock,isBlock}=require("@html_editor/utils/blocks");const{isParagraphRelatedElement,isShrunkBlock,isVisible}=require("@html_editor/utils/dom_info");const{callbacksForCursorUpdate}=require("@html_editor/utils/selection");const{isEmptyBlock,isPhrasingContent}=require("@html_editor/utils/dom_info");const{childNodes}=require("@html_editor/utils/dom_traversal");const{childNodeIndex,DIRECTIONS}=require("@html_editor/utils/position");const{baseContainerGlobalSelector,createBaseContainer,}=require("@html_editor/utils/base_container");__exports.makeContentsInline=makeContentsInline;function makeContentsInline(node){const document=node.ownerDocument;let childIndex=0;for(const child of node.childNodes){if(isBlock(child)){if(childIndex&&isParagraphRelatedElement(child)){child.before(document.createElement("br"));} for(const grandChild of child.childNodes){child.before(grandChild);makeContentsInline(grandChild);} child.remove();} childIndex+=1;}} __exports.wrapInlinesInBlocks=wrapInlinesInBlocks;function wrapInlinesInBlocks(element,{baseContainerNodeName="P",cursors={update:()=>{}}}={}){const wrapInBlock=(node,cursors)=>{const block=isPhrasingContent(node)?createBaseContainer(baseContainerNodeName,node.ownerDocument):node.ownerDocument.createElement("DIV");cursors.update(callbacksForCursorUpdate.append(block,node));cursors.update(callbacksForCursorUpdate.before(node,block));if(node.nextSibling){const sibling=node.nextSibling;node.remove();sibling.before(block);}else{const parent=node.parentElement;node.remove();parent.append(block);} block.append(node);return block;};const appendToCurrentBlock=(currentBlock,node,cursors)=>{if(currentBlock.matches(baseContainerGlobalSelector)&&!isPhrasingContent(node)){const block=currentBlock.ownerDocument.createElement("DIV");cursors.update(callbacksForCursorUpdate.before(currentBlock,block));currentBlock.before(block);for(const child of childNodes(currentBlock)){cursors.update(callbacksForCursorUpdate.append(block,child));block.append(child);} cursors.update(callbacksForCursorUpdate.remove(currentBlock));currentBlock.remove();currentBlock=block;} cursors.update(callbacksForCursorUpdate.append(currentBlock,node));currentBlock.append(node);return currentBlock;};const removeNode=(node,cursors)=>{cursors.update(callbacksForCursorUpdate.remove(node));node.remove();};const children=childNodes(element);const visibleNodes=new Set(children.filter(isVisible));let currentBlock;let shouldBreakLine=true;for(const node of children){if(isBlock(node)){shouldBreakLine=true;}else if(!visibleNodes.has(node)){removeNode(node,cursors);}else if(node.nodeName==="BR"){if(shouldBreakLine){wrapInBlock(node,cursors);}else{removeNode(node,cursors);shouldBreakLine=true;}}else if(shouldBreakLine){currentBlock=wrapInBlock(node,cursors);shouldBreakLine=false;}else{currentBlock=appendToCurrentBlock(currentBlock,node,cursors);}}} __exports.unwrapContents=unwrapContents;function unwrapContents(node){const contents=childNodes(node);for(const child of contents){node.parentNode.insertBefore(child,node);} node.parentNode.removeChild(node);return contents;} __exports.setTagName=setTagName;function setTagName(el,newTagName){const document=el.ownerDocument;if(el.tagName===newTagName){return el;} const newEl=document.createElement(newTagName);while(el.firstChild){newEl.append(el.firstChild);} if(el.tagName==="LI"){el.append(newEl);}else{for(const attribute of el.attributes){newEl.setAttribute(attribute.name,attribute.value);} el.parentNode.replaceChild(newEl,el);} return newEl;} __exports.removeClass=removeClass;function removeClass(element,...classNames){const classNamesSet=new Set(classNames);if([...element.classList].every((className)=>classNamesSet.has(className))){element.removeAttribute("class");}else{element.classList.remove(...classNames);}} __exports.fillEmpty=fillEmpty;function fillEmpty(el){const document=el.ownerDocument;const fillers={...fillShrunkPhrasingParent(el)};if(!isBlock(el)&&!isVisible(el)&&!el.hasAttribute("data-oe-zws-empty-inline")){const zws=document.createTextNode("\u200B");el.appendChild(zws);el.setAttribute("data-oe-zws-empty-inline","");fillers.zws=zws;const previousSibling=el.previousSibling;if(previousSibling&&previousSibling.nodeName==="BR"){previousSibling.remove();}} return fillers;} __exports.fillShrunkPhrasingParent=fillShrunkPhrasingParent;function fillShrunkPhrasingParent(el){const document=el.ownerDocument;const fillers={};const blockEl=closestBlock(el);if(isShrunkBlock(blockEl)){const br=document.createElement("br");blockEl.appendChild(br);fillers.br=br;} return fillers;} __exports.cleanTrailingBR=cleanTrailingBR;function cleanTrailingBR(el,predicates=[]){const candidate=el?.lastChild;if(candidate?.nodeName==="BR"&&candidate.previousSibling?.nodeName!=="BR"&&!isEmptyBlock(el)&&!predicates.some((predicate)=>predicate(candidate))){candidate.remove();return candidate;}} __exports.toggleClass=toggleClass;function toggleClass(node,className){node.classList.toggle(className);if(!node.className){node.removeAttribute("class");}} __exports.cleanTextNode=cleanTextNode;function cleanTextNode(node,char,cursors){const removedIndexes=[];node.textContent=node.textContent.replaceAll(char,(_,offset)=>{removedIndexes.push(offset);return"";});cursors?.update((cursor)=>{if(cursor.node===node){cursor.offset-=removedIndexes.filter((index)=>cursor.offset>index).length;}});} __exports.splitTextNode=splitTextNode;function splitTextNode(textNode,offset,originalNodeSide=DIRECTIONS.RIGHT){const document=textNode.ownerDocument;let parentOffset=childNodeIndex(textNode);if(offset>0){parentOffset++;if(offset"){return true;} return false;} __exports.isEmptyTextNode=isEmptyTextNode;function isEmptyTextNode(node){return node.nodeType===Node.TEXT_NODE&&node.nodeValue.length===0;} __exports.isBold=isBold;function isBold(node){const fontWeight=+getComputedStyle(closestElement(node)).fontWeight;return fontWeight>500||fontWeight>+getComputedStyle(closestBlock(node)).fontWeight;} __exports.isItalic=isItalic;function isItalic(node){return getComputedStyle(closestElement(node)).fontStyle==="italic";} __exports.isUnderline=isUnderline;function isUnderline(node){let parent=closestElement(node);while(parent){if(getComputedStyle(parent).textDecorationLine.includes("underline")){return true;} parent=parent.parentElement;} return false;} __exports.isStrikeThrough=isStrikeThrough;function isStrikeThrough(node){let parent=closestElement(node);while(parent){if(getComputedStyle(parent).textDecorationLine.includes("line-through")){return true;} parent=parent.parentElement;} return false;} __exports.isFontSize=isFontSize;function isFontSize(node,props){const element=closestElement(node);return getComputedStyle(element)["font-size"]===props.size;} __exports.hasClass=hasClass;function hasClass(node,props){const element=closestElement(node);return element.classList.contains(props.className);} __exports.isDirectionSwitched=isDirectionSwitched;function isDirectionSwitched(node,editable){const defaultDirection=editable.getAttribute("dir")||"ltr";return getComputedStyle(closestElement(node)).direction!==defaultDirection;} __exports.isRow=isRow;function isRow(node){return["TH","TD"].includes(node.tagName);} __exports.isZWS=isZWS;function isZWS(node){return node&&node.textContent==="\u200B";} __exports.isInPre=isInPre;function isInPre(node){const element=node.nodeType===Node.TEXT_NODE?node.parentElement:node;return(!!element&&(!!element.closest("pre")||getComputedStyle(element).getPropertyValue("white-space")==="pre"));} const ZERO_WIDTH_CHARS=__exports.ZERO_WIDTH_CHARS=["\u200b","\ufeff"];const whitespace=__exports.whitespace=`[^\\S\\u00A0\\u0009\\ufeff]`;const whitespaceRegex=new RegExp(`^${whitespace}*$`);__exports.isWhitespace=isWhitespace;function isWhitespace(value){const str=typeof value==="string"?value:value.nodeValue;return whitespaceRegex.test(str);} const visibleCharRegex=/[^\s\u200b]|[\u00A0\u0009]$/;__exports.isVisibleTextNode=isVisibleTextNode;function isVisibleTextNode(testedNode){if(!testedNode||!testedNode.length||testedNode.nodeType!==Node.TEXT_NODE){return false;} if(isProtected(testedNode)){return true;} if(visibleCharRegex.test(testedNode.textContent)||(isInPre(testedNode)&&isWhitespace(testedNode))){return true;} if(ZERO_WIDTH_CHARS.includes(testedNode.textContent)){return false;} let preceding;let following;let foundTestedNode;const currentNodeParentBlock=closestBlock(testedNode);if(!currentNodeParentBlock){return false;} const nodeIterator=document.createNodeIterator(currentNodeParentBlock);for(let node=nodeIterator.nextNode();node;node=nodeIterator.nextNode()){if(node.nodeType===Node.TEXT_NODE){if(foundTestedNode){following=node;break;}else if(testedNode===node){foundTestedNode=true;}else{preceding=node;}}else if(isBlock(node)){if(foundTestedNode){break;}else{preceding=null;}}else if(foundTestedNode&&!isWhitespace(node)){following=node;break;}} while(following&&!visibleCharRegex.test(following.textContent)){following=following.nextSibling;} if(!(preceding&&following)||currentNodeParentBlock!==closestBlock(preceding)||currentNodeParentBlock!==closestBlock(following)){return false;} return visibleCharRegex.test(preceding.textContent);} const selfClosingElementTags=["BR","IMG","INPUT","T","HR"];__exports.isSelfClosingElement=isSelfClosingElement;function isSelfClosingElement(node){return node&&selfClosingElementTags.includes(node.nodeName);} __exports.isVisible=isVisible;function isVisible(node){return(!!node&&((node.nodeType===Node.TEXT_NODE&&isVisibleTextNode(node))||isSelfClosingElement(node)||isMediaElement(node)||hasVisibleContent(node)||isProtecting(node)));} __exports.hasVisibleContent=hasVisibleContent;function hasVisibleContent(node){return(node?childNodes(node):[]).some((n)=>isVisible(n));} __exports.isButton=isButton;function isButton(node){if(!node||node.nodeType!==Node.ELEMENT_NODE){return false;} return node.nodeName==="BUTTON"||node.classList.contains("btn");} __exports.isZwnbsp=isZwnbsp;function isZwnbsp(node){return node?.nodeType===Node.TEXT_NODE&&node.textContent==="\ufeff";} __exports.isTangible=isTangible;function isTangible(node){return isVisible(node)||isZwnbsp(node)||hasTangibleContent(node);} __exports.hasTangibleContent=hasTangibleContent;function hasTangibleContent(node){return(node?childNodes(node):[]).some((n)=>isTangible(n));} const isNotEditableNode=__exports.isNotEditableNode=(node)=>node.getAttribute&&node.getAttribute("contenteditable")&&node.getAttribute("contenteditable").toLowerCase()==="false";const iconTags=["I","SPAN"];const iconClasses=["fa","fab","fad","far","oi"];const ICON_SELECTOR=__exports.ICON_SELECTOR=iconTags.map((tag)=>{return iconClasses.map((cls)=>{return`${tag}.${cls}`;}).join(", ");}).join(", ");__exports.isIconElement=isIconElement;function isIconElement(node){return!!(node&&iconTags.includes(node.nodeName)&&iconClasses.some((cls)=>node.classList.contains(cls)));} __exports.isMediaElement=isMediaElement;function isMediaElement(node){return(isIconElement(node)||(node.classList&&(node.classList.contains("o_image")||node.classList.contains("media_iframe_video"))));} const phrasingTagNames=new Set(["ABBR","AUDIO","B","BDI","BDO","BR","BUTTON","CANVAS","CITE","CODE","DATA","DATALIST","DFN","EM","EMBED","I","IFRAME","IMG","INPUT","KBD","LABEL","MARK","MATH","METER","NOSCRIPT","OBJECT","OUTPUT","PICTURE","PROGRESS","Q","RUBY","S","SAMP","SCRIPT","SELECT","SLOT","SMALL","SPAN","STRONG","SUB","SUP","SVG","TEMPLATE","TEXTAREA","TIME","U","VAR","VIDEO","WBR","FONT","A","AREA","DEL","INS","LINK","MAP","META",]);__exports.isPhrasingContent=isPhrasingContent;function isPhrasingContent(node){if(node&&(node.nodeType===Node.TEXT_NODE||(node.nodeType===Node.ELEMENT_NODE&&phrasingTagNames.has(node.tagName)))){return true;} return false;} __exports.containsAnyInline=containsAnyInline;function containsAnyInline(element){if(!element){return false;} let child=element.firstChild;while(child){if((!isBlock(child)&&child.nodeType===Node.ELEMENT_NODE)||(child.nodeType===Node.TEXT_NODE&&child.textContent.trim()!=="")){return true;} child=child.nextSibling;} return false;} __exports.containsAnyNonPhrasingContent=containsAnyNonPhrasingContent;function containsAnyNonPhrasingContent(element){if(!element){return false;} let child=element.firstChild;while(child){if(!isPhrasingContent(child)){return true;} child=child.nextSibling;} return false;} __exports.isProtected=isProtected;function isProtected(node){if(!node){return false;} const candidate=node.parentElement?closestElement(node.parentElement,"[data-oe-protected]"):null;if(!candidate||candidate.dataset.oeProtected==="false"){return false;} return true;} __exports.isProtecting=isProtecting;function isProtecting(node){if(!node){return false;} return(node.nodeType===Node.ELEMENT_NODE&&node.dataset.oeProtected!=="false"&&node.dataset.oeProtected!==undefined);} __exports.isUnprotecting=isUnprotecting;function isUnprotecting(node){if(!node){return false;} return node.nodeType===Node.ELEMENT_NODE&&node.dataset.oeProtected==="false";} const paragraphRelatedElements=__exports.paragraphRelatedElements=["P","H1","H2","H3","H4","H5","H6"];__exports.allowsParagraphRelatedElements=allowsParagraphRelatedElements;function allowsParagraphRelatedElements(node){return isBlock(node)&&!isParagraphRelatedElement(node);} const phrasingContent=__exports.phrasingContent=new Set(["#text",...phrasingTagNames]);const flowContent=new Set([...phrasingContent,...paragraphRelatedElements,"DIV","HR"]);const listItem=__exports.listItem=new Set(["LI"]);const listContainers=new Set(["UL","OL"]);const allowedContent={BLOCKQUOTE:flowContent,DIV:flowContent,H1:phrasingContent,H2:phrasingContent,H3:phrasingContent,H4:phrasingContent,H5:phrasingContent,H6:phrasingContent,HR:new Set(),LI:flowContent,OL:listItem,UL:listItem,P:phrasingContent,PRE:flowContent,TD:flowContent,TR:new Set(["TD"]),};__exports.isParagraphRelatedElement=isParagraphRelatedElement;function isParagraphRelatedElement(node){if(!node){return false;} return(paragraphRelatedElements.includes(node.nodeName)||(node.nodeType===Node.ELEMENT_NODE&&node.matches(baseContainerGlobalSelector)));} const paragraphRelatedElementsSelector=__exports.paragraphRelatedElementsSelector=[...paragraphRelatedElements,baseContainerGlobalSelector,].join(",");__exports.isListItemElement=isListItemElement;function isListItemElement(node){return[...listItem].includes(node.nodeName);} const listItemElementSelector=__exports.listItemElementSelector=[...listItem].join(",");__exports.isListElement=isListElement;function isListElement(node){return[...listContainers].includes(node.nodeName);} const listElementSelector=__exports.listElementSelector=[...listContainers].join(",");__exports.isAllowedContent=isAllowedContent;function isAllowedContent(parentBlock,nodes){let allowedContentSet=allowedContent[parentBlock.nodeName];if(!allowedContentSet){return true;} if(parentBlock.matches(baseContainerGlobalSelector)){allowedContentSet=phrasingContent;} return nodes.every((node)=>allowedContentSet.has(node.nodeName));} __exports.isEmptyBlock=isEmptyBlock;function isEmptyBlock(blockEl){if(!blockEl||blockEl.nodeType!==Node.ELEMENT_NODE){return false;} if(visibleCharRegex.test(blockEl.textContent)){return false;} if(blockEl.querySelectorAll("br").length>=2){return false;} if(isProtecting(blockEl)||isProtected(blockEl)){return false;} const nodes=blockEl.querySelectorAll("*");for(const node of nodes){if(node.nodeName!="BR"&&(isSelfClosingElement(node)||isMediaElement(node)||isProtecting(node))){return false;}} return isBlock(blockEl);} __exports.isShrunkBlock=isShrunkBlock;function isShrunkBlock(blockEl){return isEmptyBlock(blockEl)&&!blockEl.querySelector("br")&&!isSelfClosingElement(blockEl);} __exports.isEditorTab=isEditorTab;function isEditorTab(node){return node&&node.nodeName==="SPAN"&&node.classList.contains("oe-tabs");} __exports.getDeepestPosition=getDeepestPosition;function getDeepestPosition(node,offset){let direction=DIRECTIONS.RIGHT;let next=node;while(next){if(isTangible(next)||(isZWS(next)&&isContentEditable(next))){if(next!==node){[node,offset]=[next,direction?0:nodeSize(next)];} const childrenNodes=childNodes(node);direction=offsetn?.nodeType===Node.ELEMENT_NODE)){return false;} if(node.nodeName!==node2.nodeName){return false;} for(const name of new Set([...node.getAttributeNames(),...node2.getAttributeNames()])){if(node.getAttribute(name)!==node2.getAttribute(name)){return false;}} if([node,node2].some((n)=>hasPseudoElementContent(n,":before")||hasPseudoElementContent(n,":after"))){return false;} if(isBlock(node)){return false;} const nodeStyle=getComputedStyle(node);const node2Style=getComputedStyle(node2);return(!+nodeStyle.padding.replace(NOT_A_NUMBER,"")&&!+node2Style.padding.replace(NOT_A_NUMBER,"")&&!+nodeStyle.margin.replace(NOT_A_NUMBER,"")&&!+node2Style.margin.replace(NOT_A_NUMBER,""));} __exports.isTextNode=isTextNode;function isTextNode(node){return node.nodeType===Node.TEXT_NODE;} __exports.isElement=isElement;function isElement(node){return node.nodeType===Node.ELEMENT_NODE;} __exports.isContentEditable=isContentEditable;function isContentEditable(node){const element=isTextNode(node)?node.parentElement:node;return element&&element.isContentEditable;} __exports.isContentEditableAncestor=isContentEditableAncestor;function isContentEditableAncestor(node){if(node.nodeType!==Node.ELEMENT_NODE){return false;} return node.isContentEditable&&node.matches("[contenteditable]");} return __exports;});; /* /html_editor/static/src/utils/dom_state.js */ odoo.define('@html_editor/utils/dom_state',['@html_editor/utils/blocks','@html_editor/utils/content_types','@html_editor/utils/dom_info','@html_editor/utils/dom_traversal','@html_editor/utils/position'],function(require){'use strict';let __exports={};const{isBlock}=require("@html_editor/utils/blocks");const{CTGROUPS,CTYPES,ctypeToString}=require("@html_editor/utils/content_types");const{isInPre,isVisible,isWhitespace,whitespace}=require("@html_editor/utils/dom_info");const{PATH_END_REASONS,ancestors,closestElement,closestPath,createDOMPathGenerator,}=require("@html_editor/utils/dom_traversal");const{DIRECTIONS,leftPos,rightPos}=require("@html_editor/utils/position");const prepareUpdateLockedEditables=new Set();__exports.prepareUpdate=prepareUpdate;function prepareUpdate(...args){const closestRoot=args.length&&ancestors(args[0]).find((ancestor)=>ancestor.classList.contains("odoo-editor-editable"));const isPrepareUpdateLocked=closestRoot&&prepareUpdateLockedEditables.has(closestRoot);const hash=(Math.random()+1).toString(36).substring(7);const options={allowReenter:true,label:hash,debug:false,...(args.length&&args[args.length-1]instanceof Object?args.pop():{}),};if(options.debug){console.log("%cPreparing%c update: "+ options.label+ (options.label===hash?"":` (${hash})`)+"%c"+ (isPrepareUpdateLocked?" LOCKED":""),"color: cyan;","color: white;","color: red; font-weight: bold;");} if(isPrepareUpdateLocked){return()=>{if(options.debug){console.log("%cRestoring%c update: "+ options.label+ (options.label===hash?"":` (${hash})`)+"%c LOCKED","color: lightgreen;","color: white;","color: red; font-weight: bold;");}};} if(!options.allowReenter&&closestRoot){prepareUpdateLockedEditables.add(closestRoot);} const positions=[...args];const restoreData=[];let el,offset;while(positions.length){offset=positions.pop();el=positions.pop();const left=getState(el,offset,DIRECTIONS.LEFT);const right=getState(el,offset,DIRECTIONS.RIGHT,left.cType);if(options.debug){const editable=el&&closestElement(el,".odoo-editor-editable");const oldEditableHTML=(editable&&editable.innerHTML.replaceAll(" ","_").replaceAll("\u200B","ZWS"))||"";left.oldEditableHTML=oldEditableHTML;right.oldEditableHTML=oldEditableHTML;} restoreData.push(left,right);} return function restoreStates(){if(options.debug){console.log("%cRestoring%c update: "+ options.label+ (options.label===hash?"":` (${hash})`),"color: lightgreen;","color: white;");} for(const data of restoreData){restoreState(data,options.debug);} if(!options.allowReenter&&closestRoot){prepareUpdateLockedEditables.delete(closestRoot);}};} const leftLeafOnlyNotBlockPath=__exports.leftLeafOnlyNotBlockPath=createDOMPathGenerator(DIRECTIONS.LEFT,{leafOnly:true,stopTraverseFunction:isBlock,stopFunction:isBlock,});const rightLeafOnlyNotBlockPath=createDOMPathGenerator(DIRECTIONS.RIGHT,{leafOnly:true,stopTraverseFunction:isBlock,stopFunction:isBlock,});__exports.getState=getState;function getState(el,offset,direction,leftCType){const leftDOMPath=leftLeafOnlyNotBlockPath;const rightDOMPath=rightLeafOnlyNotBlockPath;let domPath;let inverseDOMPath;const whitespaceAtStartRegex=new RegExp("^"+whitespace+"+");const whitespaceAtEndRegex=new RegExp(whitespace+"+$");const reasons=[];if(direction===DIRECTIONS.LEFT){domPath=leftDOMPath(el,offset,reasons);inverseDOMPath=rightDOMPath(el,offset);}else{domPath=rightDOMPath(el,offset,reasons);inverseDOMPath=leftDOMPath(el,offset);} const boundaryNode=inverseDOMPath.next().value;let cType=undefined;let lastSpace=null;for(const node of domPath){if(node.nodeType===Node.TEXT_NODE){const value=node.nodeValue;if(direction===DIRECTIONS.LEFT){if(!isWhitespace(value)){if(lastSpace){cType=CTYPES.SPACE;}else{const rightLeaf=rightLeafOnlyNotBlockPath(node).next().value;const hasContentRight=rightLeaf&&!whitespaceAtStartRegex.test(rightLeaf.textContent);cType=!hasContentRight&&whitespaceAtEndRegex.test(node.textContent)?CTYPES.SPACE:CTYPES.CONTENT;} break;} if(value.length){lastSpace=node;}}else{leftCType=leftCType||getState(el,offset,DIRECTIONS.LEFT).cType;if(whitespaceAtStartRegex.test(value)){const leftLeaf=leftLeafOnlyNotBlockPath(node).next().value;const hasContentLeft=leftLeaf&&!whitespaceAtEndRegex.test(leftLeaf.textContent);const rct=!isWhitespace(value)?CTYPES.CONTENT:getState(...rightPos(node),DIRECTIONS.RIGHT).cType;cType=leftCType&CTYPES.CONTENT&&rct&(CTYPES.CONTENT|CTYPES.BR)&&!hasContentLeft?CTYPES.SPACE:rct;break;} if(!isWhitespace(value)){cType=CTYPES.CONTENT;break;}}}else if(node.nodeName==="BR"){cType=CTYPES.BR;break;}else if(isVisible(node)){cType=CTYPES.CONTENT;break;}} if(cType===undefined){cType=reasons.includes(PATH_END_REASONS.BLOCK_HIT)?CTYPES.BLOCK_OUTSIDE:CTYPES.BLOCK_INSIDE;} return{node:boundaryNode,direction:direction,cType:cType,};} const priorityRestoreStateRules=[[{cType1:CTYPES.CONTENT,cType2:CTYPES.SPACE|CTGROUPS.BLOCK},{spaceVisibility:true},],[{direction:DIRECTIONS.LEFT,cType1:CTGROUPS.INLINE,cType2:CTGROUPS.BR},{spaceVisibility:true},],[{direction:DIRECTIONS.RIGHT,cType1:CTGROUPS.CONTENT,cType2:CTGROUPS.BR},{spaceVisibility:true},],[{direction:DIRECTIONS.RIGHT,cType1:CTGROUPS.BR,cType2:CTYPES.SPACE|CTGROUPS.BLOCK},{spaceVisibility:true},],[{cType1:CTYPES.SPACE},{spaceVisibility:false},],[{direction:DIRECTIONS.LEFT,cType1:CTGROUPS.BR},{spaceVisibility:false},],[{cType1:CTGROUPS.BLOCK,cType2:CTGROUPS.INLINE|CTGROUPS.BR},{spaceVisibility:false},],[{direction:DIRECTIONS.RIGHT,cType1:CTGROUPS.INLINE,cType2:CTGROUPS.BLOCK},{brVisibility:true},],[{direction:DIRECTIONS.RIGHT,cType1:CTGROUPS.BLOCK,cType2:CTGROUPS.INLINE|CTGROUPS.BR,},{brVisibility:false},],[{direction:DIRECTIONS.LEFT,cType1:CTGROUPS.BR|CTGROUPS.BLOCK,cType2:CTGROUPS.INLINE,},{brVisibility:false,extraBRRemovalCondition:(brNode)=>isFakeLineBreak(brNode)},],];function restoreStateRuleHashCode(direction,cType1,cType2){return`${direction}-${cType1}-${cType2}`;} const allRestoreStateRules=(function(){const map=new Map();const keys=["direction","cType1","cType2"];for(const direction of Object.values(DIRECTIONS)){for(const cType1 of Object.values(CTYPES)){for(const cType2 of Object.values(CTYPES)){const rule={direction:direction,cType1:cType1,cType2:cType2};const matchedRules=[];for(const entry of priorityRestoreStateRules){let priority=0;for(const key of keys){const entryKeyValue=entry[0][key];if(entryKeyValue!==undefined){if(typeof entryKeyValue==="boolean"?rule[key]===entryKeyValue:rule[key]&entryKeyValue){priority++;}else{priority=-1;break;}}} if(priority>=0){matchedRules.push([priority,entry[1]]);}} const finalRule={};for(let p=0;p<=keys.length;p++){for(const entry of matchedRules){if(entry[0]===p){Object.assign(finalRule,entry[1]);}}} const hashCode=restoreStateRuleHashCode(direction,cType1,cType2);map.set(hashCode,finalRule);}}} return map;})();__exports.restoreState=restoreState;function restoreState(prevStateData,debug=false){const{node,direction,cType:cType1,oldEditableHTML}=prevStateData;if(!node||!node.parentNode){return;} const[el,offset]=direction===DIRECTIONS.LEFT?leftPos(node):rightPos(node);const{cType:cType2}=getState(el,offset,direction);const ruleHashCode=restoreStateRuleHashCode(direction,cType1,cType2);const rule=allRestoreStateRules.get(ruleHashCode);if(debug){const editable=closestElement(node,".odoo-editor-editable");console.log("%c"+ node.textContent.replaceAll(" ","_").replaceAll("\u200B","ZWS")+"\n"+"%c"+ (direction===DIRECTIONS.LEFT?"left":"right")+"\n"+"%c"+ ctypeToString(cType1)+"\n"+"%c"+ ctypeToString(cType2)+"\n"+"%c"+"BEFORE: "+ (oldEditableHTML||"(unavailable)")+"\n"+"%c"+"AFTER: "+ (editable?editable.innerHTML.replaceAll(" ","_").replaceAll("\u200B","ZWS"):"(unavailable)")+"\n","color: white; display: block; width: 100%;","color: "+ (direction===DIRECTIONS.LEFT?"magenta":"lightgreen")+"; display: block; width: 100%;","color: pink; display: block; width: 100%;","color: lightblue; display: block; width: 100%;","color: white; display: block; width: 100%;","color: white; display: block; width: 100%;",rule);} if(Object.values(rule).filter((x)=>x!==undefined).length){const inverseDirection=direction===DIRECTIONS.LEFT?DIRECTIONS.RIGHT:DIRECTIONS.LEFT;enforceWhitespace(el,offset,inverseDirection,rule);} return rule;} __exports.isFakeLineBreak=isFakeLineBreak;function isFakeLineBreak(brEl){return!(getState(...rightPos(brEl),DIRECTIONS.RIGHT).cType&(CTYPES.CONTENT|CTGROUPS.BR));} __exports.enforceWhitespace=enforceWhitespace;function enforceWhitespace(el,offset,direction,rule){const document=el.ownerDocument;let domPath,whitespaceAtEdgeRegex;if(direction===DIRECTIONS.LEFT){domPath=leftLeafOnlyNotBlockPath(el,offset);whitespaceAtEdgeRegex=new RegExp(whitespace+"+$");}else{domPath=rightLeafOnlyNotBlockPath(el,offset);whitespaceAtEdgeRegex=new RegExp("^"+whitespace+"+");} const invisibleSpaceTextNodes=[];let foundVisibleSpaceTextNode=null;for(const node of domPath){if(node.nodeName==="BR"){if(rule.brVisibility===undefined){break;} if(rule.brVisibility){node.before(document.createElement("br"));}else{if(!rule.extraBRRemovalCondition||rule.extraBRRemovalCondition(node)){node.remove();}} break;}else if(node.nodeType===Node.TEXT_NODE&&!isInPre(node)){if(whitespaceAtEdgeRegex.test(node.nodeValue)){if(!isWhitespace(node)){foundVisibleSpaceTextNode=node;break;}else{invisibleSpaceTextNodes.push(node);}}else if(!isWhitespace(node)){break;}}else{break;}} if(rule.spaceVisibility===undefined){return;} if(!rule.spaceVisibility){for(const node of invisibleSpaceTextNodes){node.nodeValue="";const ancestorPath=closestPath(node.parentNode);let toRemove=null;for(const pNode of ancestorPath){if(toRemove){toRemove.remove();} if(pNode.childNodes.length===1&&!isBlock(pNode)){pNode.after(node);toRemove=pNode;}else{break;}}}} const spaceNode=foundVisibleSpaceTextNode||invisibleSpaceTextNodes[0];if(spaceNode){let spaceVisibility=rule.spaceVisibility;if(spaceVisibility&&!foundVisibleSpaceTextNode&&getState(...rightPos(spaceNode),DIRECTIONS.RIGHT).cType&CTGROUPS.BLOCK&&getState(...leftPos(spaceNode),DIRECTIONS.LEFT).cType!==CTYPES.CONTENT){spaceVisibility=false;} spaceNode.nodeValue=spaceNode.nodeValue.replace(whitespaceAtEdgeRegex,spaceVisibility?"\u00A0":"");}} __exports.observeMutations=observeMutations;function observeMutations(target,observerOptions){const records=[];const observerCallback=(mutations)=>records.push(...mutations);const observer=new MutationObserver(observerCallback);observer.observe(target,observerOptions);return()=>{observerCallback(observer.takeRecords());observer.disconnect();return records;};} return __exports;});; /* /html_editor/static/src/utils/dom_traversal.js */ odoo.define('@html_editor/utils/dom_traversal',['@html_editor/utils/position'],function(require){'use strict';let __exports={};const{DIRECTIONS}=require("@html_editor/utils/position");const closestPath=__exports.closestPath=function*(node){while(node){yield node;node=node.parentNode;}};__exports.findNode=findNode;function findNode(domPath,findCallback=()=>true,stopCallback=()=>false){for(const node of domPath){if(findCallback(node)){return node;} if(stopCallback(node)){break;}} return null;} __exports.findUpTo=findUpTo;function findUpTo(node,limitAncestor,predicate){while(node!==limitAncestor){if(predicate(node)){return node;} node=node.parentElement;} return null;} __exports.findFurthest=findFurthest;function findFurthest(node,limitAncestor,predicate){const nodes=[];while(node!==limitAncestor){nodes.push(node);node=node.parentNode;} return nodes.findLast(predicate);} __exports.closestElement=closestElement;function closestElement(node,predicate="*"){let element=node.nodeType===Node.ELEMENT_NODE?node:node.parentElement;const editable=element?.closest(".odoo-editor-editable");if(typeof predicate==="function"){while(element&&!predicate(element)){element=element.parentElement;}}else{element=element?.closest(predicate);} if((editable&&editable.contains(element))||!node.isConnected){return element;} return null;} __exports.ancestors=ancestors;function ancestors(node,editable){const result=[];while(node&&node.parentElement&&node!==editable){result.push(node.parentElement);node=node.parentElement;} return result;} __exports.children=children;function children(elem){const children=[];let child=elem.firstElementChild;while(child){children.push(child);child=child.nextElementSibling;} return children;} __exports.childNodes=childNodes;function childNodes(node){const childNodes=[];let child=node.firstChild;while(child){childNodes.push(child);child=child.nextSibling;} return childNodes;} __exports.descendants=descendants;function descendants(node,posterity=[]){let child=node.firstChild;while(child){posterity.push(child);descendants(child,posterity);child=child.nextSibling;} return posterity;} const PATH_END_REASONS=__exports.PATH_END_REASONS={NO_NODE:0,BLOCK_OUT:1,BLOCK_HIT:2,OUT_OF_SCOPE:3,};__exports.createDOMPathGenerator=createDOMPathGenerator;function createDOMPathGenerator(direction,{leafOnly=false,inScope=false,stopTraverseFunction,stopFunction}={}){const nextDeepest=direction===DIRECTIONS.LEFT?(node)=>lastLeaf(node.previousSibling,stopTraverseFunction):(node)=>firstLeaf(node.nextSibling,stopTraverseFunction);const firstNode=direction===DIRECTIONS.LEFT?(node,offset)=>lastLeaf(node.childNodes[offset-1],stopTraverseFunction):(node,offset)=>firstLeaf(node.childNodes[offset],stopTraverseFunction);return function*(node,offset,reasons=[]){let movedUp=false;let currentNode=firstNode(node,offset);if(!currentNode){movedUp=true;currentNode=node;} while(currentNode){if(stopFunction&&stopFunction(currentNode)){reasons.push(movedUp?PATH_END_REASONS.BLOCK_OUT:PATH_END_REASONS.BLOCK_HIT);break;} if(inScope&¤tNode===node){reasons.push(PATH_END_REASONS.OUT_OF_SCOPE);break;} if(!(leafOnly&&movedUp)){yield currentNode;} movedUp=false;let nextNode=nextDeepest(currentNode);if(!nextNode){movedUp=true;nextNode=currentNode.parentNode;} currentNode=nextNode;} reasons.push(PATH_END_REASONS.NO_NODE);};} __exports.lastLeaf=lastLeaf;function lastLeaf(node,stopTraverseFunction){while(node&&node.lastChild&&!(stopTraverseFunction&&stopTraverseFunction(node))){node=node.lastChild;} return node;} __exports.firstLeaf=firstLeaf;function firstLeaf(node,stopTraverseFunction){while(node&&node.firstChild&&!(stopTraverseFunction&&stopTraverseFunction(node))){node=node.firstChild;} return node;} __exports.getAdjacentPreviousSiblings=getAdjacentPreviousSiblings;function getAdjacentPreviousSiblings(node,predicate=(n)=>!!n){let previous=node.previousSibling;const list=[];while(previous&&predicate(previous)){list.push(previous);previous=previous.previousSibling;} return list;} __exports.getAdjacentNextSiblings=getAdjacentNextSiblings;function getAdjacentNextSiblings(node,predicate=(n)=>!!n){let next=node.nextSibling;const list=[];while(next&&predicate(next)){list.push(next);next=next.nextSibling;} return list;} __exports.getAdjacents=getAdjacents;function getAdjacents(node,predicate=(n)=>!!n){const previous=getAdjacentPreviousSiblings(node,predicate);const next=getAdjacentNextSiblings(node,predicate);return predicate(node)?[...previous.reverse(),node,...next]:[];} __exports.getCommonAncestor=getCommonAncestor;function getCommonAncestor(nodes,root=undefined){const pathsToRoot=nodes.map((node)=>[node,...ancestors(node,root)]);let candidate=pathsToRoot[0]?.at(-1);if(root&&candidate!==root){return null;} let commonAncestor=null;while(candidate&&pathsToRoot.every((path)=>path.at(-1)===candidate)){commonAncestor=candidate;pathsToRoot.forEach((path)=>path.pop());candidate=pathsToRoot[0].at(-1);} return commonAncestor;} const selectElements=__exports.selectElements=function*(root,selector){if(root.matches(selector)){yield root;} for(const elem of root.querySelectorAll(selector)){yield elem;}};return __exports;});; /* /html_editor/static/src/utils/drag_and_drop.js */ odoo.define('@html_editor/utils/drag_and_drop',['@web/core/utils/draggable_hook_builder','@web/core/utils/objects','@odoo/owl','@web/core/utils/timing','@web/core/utils/ui'],function(require){'use strict';let __exports={};const{makeDraggableHook}=require("@web/core/utils/draggable_hook_builder");const{pick}=require("@web/core/utils/objects");const{reactive}=require("@odoo/owl");const{throttleForAnimation}=require("@web/core/utils/timing");const{closest,touching}=require("@web/core/utils/ui");__exports.useNativeDraggable=useNativeDraggable;function useNativeDraggable(hookParams,initialParams){const setupFunctions=new Map();const cleanupFunctions=[];const currentParams={...initialParams};const setupHooks={wrapState:reactive,throttle:throttleForAnimation,addListener:(el,type,callback,options)=>{el.addEventListener(type,callback,options);cleanupFunctions.push(()=>el.removeEventListener(type,callback));},setup:(setupFn,depsFn)=>setupFunctions.set(setupFn,depsFn),teardown:(cleanupFn)=>{cleanupFunctions.push(cleanupFn);},};const el=initialParams.ref.el;el.classList.add("o_draggable");cleanupFunctions.push(()=>el.classList.remove("o_draggable"));const draggableState=makeDraggableHook({setupHooks,...hookParams})(currentParams);draggableState.enable=true;const draggableComponent={state:draggableState,update:(newParams)=>{Object.assign(currentParams,newParams);setupFunctions.forEach((depsFn,setupFn)=>setupFn(...depsFn()));},destroy:()=>{cleanupFunctions.forEach((cleanupFn)=>cleanupFn());},};draggableComponent.update({});return draggableComponent;} function updateElementPosition(el,{x,y},styleFn,offset={x:0,y:0}){return styleFn(el,{top:`${y - offset.y}px`,left:`${x - offset.x}px`});} const dragAndDropHookParams={name:"useDragAndDrop",acceptedParams:{dropzones:[Function],scrollingElement:[Object,Function],helper:[Function],extraWindow:[Object,Function],},edgeScrolling:{enabled:true},onComputeParams({ctx,params}){ctx.followCursor=false;ctx.scrollingElement=params.scrollingElement;ctx.getHelper=params.helper;ctx.getDropZones=params.dropzones;},onWillStartDrag:({ctx})=>{ctx.current.container=ctx.scrollingElement;ctx.current.helperOffset={x:0,y:0};},onDragStart:({ctx,addStyle,addCleanup})=>{ctx.current.element=ctx.getHelper({...ctx.current,...ctx.pointer});ctx.current.helper=ctx.current.element;ctx.current.helper.style.position="fixed";ctx.current.helper.classList.remove("o_dragged");ctx.current.helper.style.cursor=ctx.cursor;ctx.current.helper.style.pointerEvents="auto";const frameElement=ctx.current.helper.ownerDocument.defaultView.frameElement;if(frameElement){addStyle(frameElement,{pointerEvents:"auto"});} addCleanup(()=>ctx.current.helper.remove());updateElementPosition(ctx.current.helper,ctx.pointer,addStyle,ctx.current.helperOffset);return pick(ctx.current,"element","helper");},onDrag:({ctx,addStyle,callHandler})=>{ctx.current.helper.classList.add("o_draggable_dragging");updateElementPosition(ctx.current.helper,ctx.pointer,addStyle,ctx.current.helperOffset);let helperRect=ctx.current.helper.getBoundingClientRect();helperRect={x:helperRect.x,y:helperRect.y,width:helperRect.width,height:helperRect.height,};const dropzoneEl=closest(touching(ctx.getDropZones(),helperRect),helperRect);if(ctx.current.dropzone?.el&&ctx.current.dropzone.el.classList.contains("oe_grid_zone")){ctx.current.dropzone.rect=ctx.current.dropzone.el.getBoundingClientRect();} if(ctx.current.dropzone&&(ctx.current.dropzone.el===dropzoneEl||(!dropzoneEl&&touching([ctx.current.helper],ctx.current.dropzone.rect).length>0))){return pick(ctx.current,"element","dropzone","helper");} if(ctx.current.dropzone&&dropzoneEl!==ctx.current.dropzone.el){callHandler("dropzoneOut",{dropzone:ctx.current.dropzone});delete ctx.current.dropzone;} if(dropzoneEl){const rect=DOMRect.fromRect(dropzoneEl.getBoundingClientRect());ctx.current.dropzone={el:dropzoneEl,rect:{x:rect.x,y:rect.y,width:rect.width,height:rect.height,},};callHandler("dropzoneOver",{dropzone:ctx.current.dropzone});} return pick(ctx.current,"element","dropzone","helper");},onDragEnd({ctx}){return pick(ctx.current,"element","dropzone","helper");},};__exports.useDragAndDrop=useDragAndDrop;function useDragAndDrop(initialParams){return useNativeDraggable(dragAndDropHookParams,initialParams);} return __exports;});; /* /html_editor/static/src/utils/fonts.js */ odoo.define('@html_editor/utils/fonts',[],function(require){'use strict';let __exports={};const fonts=__exports.fonts={cacheCssSelectors:{},getCssSelectors:function(filter){if(this.cacheCssSelectors[filter]){return this.cacheCssSelectors[filter];} this.cacheCssSelectors[filter]=[];var sheets=document.styleSheets;for(var i=0;i{data.cssData=self.getCssSelectors(data.parser);data.alias=data.cssData.map((x)=>x.names).flat();});this.computedFonts=true;}},};return __exports;});; /* /html_editor/static/src/utils/formatting.js */ odoo.define('@html_editor/utils/formatting',['@web/core/utils/colors','@html_editor/utils/dom','@html_editor/utils/dom_info','@html_editor/utils/dom_traversal'],function(require){'use strict';let __exports={};const{normalizeCSSColor}=require("@web/core/utils/colors");const{removeClass}=require("@html_editor/utils/dom");const{isBold,isDirectionSwitched,isItalic,isStrikeThrough,isUnderline}=require("@html_editor/utils/dom_info");const{closestElement}=require("@html_editor/utils/dom_traversal");const FONT_SIZE_CLASSES=__exports.FONT_SIZE_CLASSES=["display-1-fs","display-2-fs","display-3-fs","display-4-fs","h1-fs","h2-fs","h3-fs","h4-fs","h5-fs","h6-fs","base-fs","small","o_small-fs",];const TEXT_STYLE_CLASSES=__exports.TEXT_STYLE_CLASSES=["display-1","display-2","display-3","display-4","lead"];const formatsSpecs=__exports.formatsSpecs={italic:{tagName:"em",isFormatted:isItalic,isTag:(node)=>["EM","I"].includes(node.tagName),hasStyle:(node)=>Boolean(node.style&&node.style["font-style"]),addStyle:(node)=>(node.style["font-style"]="italic"),addNeutralStyle:(node)=>(node.style["font-style"]="normal"),removeStyle:(node)=>removeStyle(node,"font-style"),},bold:{tagName:"strong",isFormatted:isBold,isTag:(node)=>["STRONG","B"].includes(node.tagName),hasStyle:(node)=>Boolean(node.style&&node.style["font-weight"]),addStyle:(node)=>(node.style["font-weight"]="bolder"),addNeutralStyle:(node)=>{node.style["font-weight"]="normal";},removeStyle:(node)=>removeStyle(node,"font-weight"),},underline:{tagName:"u",isFormatted:isUnderline,isTag:(node)=>node.tagName==="U",hasStyle:(node)=>node.style&&(node.style["text-decoration"].includes("underline")||node.style["text-decoration-line"].includes("underline")),addStyle:(node)=>(node.style["text-decoration-line"]+=" underline"),removeStyle:(node)=>removeStyle(node,node.style["text-decoration"].includes("underline")?"text-decoration":"text-decoration-line","underline"),},strikeThrough:{tagName:"s",isFormatted:isStrikeThrough,isTag:(node)=>node.tagName==="S",hasStyle:(node)=>node.style&&(node.style["text-decoration"].includes("line-through")||node.style["text-decoration-line"].includes("line-through")),addStyle:(node)=>(node.style["text-decoration-line"]+=" line-through"),removeStyle:(node)=>removeStyle(node,node.style["text-decoration"].includes("line-through")?"text-decoration":"text-decoration-line","line-through"),},fontSize:{isFormatted:(node)=>closestElement(node)?.style["font-size"],hasStyle:(node)=>node.style&&node.style["font-size"],addStyle:(node,props)=>{node.style["font-size"]=props.size;removeClass(node,...FONT_SIZE_CLASSES);},removeStyle:(node)=>removeStyle(node,"font-size"),},setFontSizeClassName:{isFormatted:(node)=>FONT_SIZE_CLASSES.find((cls)=>closestElement(node)?.classList?.contains(cls)),hasStyle:(node,props)=>FONT_SIZE_CLASSES.find((cls)=>node.classList.contains(cls)),addStyle:(node,props)=>{node.style.removeProperty("font-size");node.classList.add(props.className);},removeStyle:(node)=>removeClass(node,...FONT_SIZE_CLASSES,...TEXT_STYLE_CLASSES),},switchDirection:{isFormatted:isDirectionSwitched,},};function removeStyle(node,styleName,item){if(item){const newStyle=node.style[styleName].split(" ").filter((x)=>x!==item).join(" ");node.style[styleName]=newStyle||null;}else{node.style[styleName]=null;} if(node.getAttribute("style")===""){node.removeAttribute("style");}} __exports.getCSSVariableValue=getCSSVariableValue;function getCSSVariableValue(key,htmlStyle){let value=htmlStyle.getPropertyValue(`--${key}`).trim();value=normalizeCSSColor(value);return value.replace(/"/g,"'");} const CSS_UNITS_CONVERSION={"s-ms":()=>1000,"ms-s":()=>0.001,"rem-px":(htmlStyle)=>parseFloat(htmlStyle["font-size"]),"px-rem":(htmlStyle)=>1/parseFloat(htmlStyle["font-size"]),"%-px":()=>-1,"px-%":()=>-1,};__exports.convertNumericToUnit=convertNumericToUnit;function convertNumericToUnit(value,unitFrom,unitTo,htmlStyle){if(Math.abs(value) `.${className}`)}, ${styleClassesRelatedToFontSize.map((className) => `.${className}`)}, ${tagNameRelatedToFontSize} `);let remValue;const htmlStyle=getHtmlStyle(document);if(closestFontSizedEl){const useFontSizeInput=closestFontSizedEl.style.fontSize;if(useFontSizeInput){return parseFloat(getComputedStyle(closestStartContainerEl).fontSize);} const fontSizeClass=FONT_SIZE_CLASSES.find((className)=>closestFontSizedEl.classList.contains(className));let fsName;if(fontSizeClass){fsName=fontSizeClass.substring(0,fontSizeClass.length-3);}else{fsName=styleClassesRelatedToFontSize.find((className)=>closestFontSizedEl.classList.contains(className))||closestFontSizedEl.tagName.toLowerCase();} remValue=parseFloat(getCSSVariableValue(`${fsName}-font-size`,htmlStyle));} const pxValue=remValue&&convertNumericToUnit(remValue,"rem","px",htmlStyle);return pxValue||parseFloat(getComputedStyle(closestStartContainerEl).fontSize);} return __exports;});; /* /html_editor/static/src/utils/html.js */ odoo.define('@html_editor/utils/html',[],function(require){'use strict';let __exports={};__exports.parseHTML=parseHTML;function parseHTML(document,html){const fragment=document.createDocumentFragment();const parser=new document.defaultView.DOMParser();const parsedDocument=parser.parseFromString(html,"text/html");fragment.replaceChildren(...parsedDocument.body.childNodes);return fragment;} __exports.normalizeHTML=normalizeHTML;function normalizeHTML(content,cleanup=()=>{}){const parser=new document.defaultView.DOMParser();const body=parser.parseFromString(content,"text/html").body;cleanup(body);return body.innerHTML;} return __exports;});; /* /html_editor/static/src/utils/image.js */ odoo.define('@html_editor/utils/image',['@html_editor/utils/color'],function(require){'use strict';let __exports={};const{isColorGradient}=require("@html_editor/utils/color");__exports.backgroundImageCssToParts=backgroundImageCssToParts;function backgroundImageCssToParts(css){const parts={};css=css||"";if(css.startsWith("url(")){const urlEnd=css.indexOf(")")+1;parts.url=css.substring(0,urlEnd).trim();const commaPos=css.indexOf(",",urlEnd);css=commaPos>0?css.substring(commaPos+1):"";} if(isColorGradient(css)){parts.gradient=css.trim();} return parts;} __exports.backgroundImagePartsToCss=backgroundImagePartsToCss;function backgroundImagePartsToCss(parts){let css=parts.url||"";if(parts.gradient){css+=(css?", ":"")+parts.gradient;} return css||"none";} return __exports;});; /* /html_editor/static/src/utils/image_processing.js */ odoo.define('@html_editor/utils/image_processing',['@web/core/network/rpc','@web/core/utils/objects','@html_editor/utils/perspective_utils'],function(require){'use strict';let __exports={};const{rpc}=require("@web/core/network/rpc");const{pick}=require("@web/core/utils/objects");const{getAffineApproximation,getProjective}=require("@html_editor/utils/perspective_utils");const cropperDataFields=__exports.cropperDataFields=["x","y","width","height","rotate","scaleX","scaleY"];const isGif=__exports.isGif=(mimetype)=>mimetype==="image/gif";const _applyAll=(result,filter,filters)=>{filters.forEach((f)=>{if(f[0]==="blend"){const cv=f[1];const ctx=result.getContext("2d");ctx.globalCompositeOperation=f[2];ctx.globalAlpha=f[3];ctx.drawImage(cv,0,0);ctx.globalCompositeOperation="source-over";ctx.globalAlpha=1.0;}else{filter.addFilter(...f);}});};let applyAll;const glFilters={blur:(filter)=>filter.addFilter("blur",10),1977:(filter,cv)=>{const ctx=cv.getContext("2d");ctx.fillStyle="rgb(243, 106, 188)";ctx.fillRect(0,0,cv.width,cv.height);applyAll(filter,[["blend",cv,"screen",0.3],["brightness",0.1],["contrast",0.1],["saturation",0.3],]);},aden:(filter,cv)=>{const ctx=cv.getContext("2d");ctx.fillStyle="rgb(66, 10, 14)";ctx.fillRect(0,0,cv.width,cv.height);applyAll(filter,[["blend",cv,"darken",0.2],["brightness",0.2],["contrast",-0.1],["saturation",-0.15],["hue",20],]);},brannan:(filter,cv)=>{const ctx=cv.getContext("2d");ctx.fillStyle="rgb(161, 44, 191)";ctx.fillRect(0,0,cv.width,cv.height);applyAll(filter,[["blend",cv,"lighten",0.31],["sepia",0.5],["contrast",0.4],]);},earlybird:(filter,cv)=>{const ctx=cv.getContext("2d");const gradient=ctx.createRadialGradient(cv.width/2,cv.height/2,0,cv.width/2,cv.height/2,Math.hypot(cv.width,cv.height)/2);gradient.addColorStop(0.2,"#D0BA8E");gradient.addColorStop(1,"#1D0210");ctx.fillStyle=gradient;ctx.fillRect(0,0,cv.width,cv.height);applyAll(filter,[["blend",cv,"overlay",0.2],["sepia",0.2],["contrast",-0.1],]);},inkwell:(filter,cv)=>{applyAll(filter,[["sepia",0.3],["brightness",0.1],["contrast",-0.1],["desaturateLuminance"],]);},maven:(filter,cv)=>{applyAll(filter,[["sepia",0.25],["brightness",-0.05],["contrast",-0.05],["saturation",0.5],]);},toaster:(filter,cv)=>{const ctx=cv.getContext("2d");const gradient=ctx.createRadialGradient(cv.width/2,cv.height/2,0,cv.width/2,cv.height/2,Math.hypot(cv.width,cv.height)/2);gradient.addColorStop(0,"#0F4E80");gradient.addColorStop(1,"#3B003B");ctx.fillStyle=gradient;ctx.fillRect(0,0,cv.width,cv.height);applyAll(filter,[["blend",cv,"screen",0.5],["brightness",-0.1],["contrast",0.5],]);},walden:(filter,cv)=>{const ctx=cv.getContext("2d");ctx.fillStyle="#CC4400";ctx.fillRect(0,0,cv.width,cv.height);applyAll(filter,[["blend",cv,"screen",0.3],["sepia",0.3],["brightness",0.1],["saturation",0.6],["hue",350],]);},valencia:(filter,cv)=>{const ctx=cv.getContext("2d");ctx.fillStyle="#3A0339";ctx.fillRect(0,0,cv.width,cv.height);applyAll(filter,[["blend",cv,"exclusion",0.5],["sepia",0.08],["brightness",0.08],["contrast",0.08],]);},xpro:(filter,cv)=>{const ctx=cv.getContext("2d");const gradient=ctx.createRadialGradient(cv.width/2,cv.height/2,0,cv.width/2,cv.height/2,Math.hypot(cv.width,cv.height)/2);gradient.addColorStop(0.4,"#E0E7E6");gradient.addColorStop(1,"#2B2AA1");ctx.fillStyle=gradient;ctx.fillRect(0,0,cv.width,cv.height);applyAll(filter,[["blend",cv,"color-burn",0.7],["sepia",0.3],]);},custom:(filter,cv,filterOptions)=>{const options=Object.assign({blend:"normal",filterColor:"",blur:"0",desaturateLuminance:"0",saturation:"0",contrast:"0",brightness:"0",sepia:"0",},JSON.parse(filterOptions||"{}"));const filters=[];if(options.filterColor){const ctx=cv.getContext("2d");ctx.fillStyle=options.filterColor;ctx.fillRect(0,0,cv.width,cv.height);filters.push(["blend",cv,options.blend,1]);} delete options.blend;delete options.filterColor;filters.push(...Object.entries(options).map(([filter,amount])=>[filter,parseInt(amount)/100]));applyAll(filter,filters);},};__exports.applyModifications=applyModifications;async function applyModifications(img,cropper,dataOptions={}){const data=Object.assign({glFilter:"",filter:"#0000",quality:"75",forceModification:false,},img.dataset,dataOptions);let{width,height,resizeWidth,quality,filter,mimetype,originalSrc,glFilter,filterOptions,forceModification,perspective,svgAspectRatio,imgAspectRatio,}=data;[width,height,resizeWidth]=[width,height,resizeWidth].map((s)=>parseFloat(s));quality=parseInt(quality);if(isGif(mimetype)&&!forceModification){return await _loadImageDataURL(originalSrc);} const container=document.createElement("div");const original=await loadImage(originalSrc);originalSrc=original.getAttribute("src");container.appendChild(original);let croppedImg=cropper.getCroppedCanvas(width,height);if(imgAspectRatio){document.createElement("div").appendChild(croppedImg);imgAspectRatio=imgAspectRatio.split(":");imgAspectRatio=parseFloat(imgAspectRatio[0])/parseFloat(imgAspectRatio[1]);const croppedCropper=await activateCropper(croppedImg,imgAspectRatio,{y:0});croppedImg=croppedCropper.cropper("getCroppedCanvas");croppedCropper.destroy();} const result=document.createElement("canvas");result.width=resizeWidth||croppedImg.width;result.height=perspective?result.width/svgAspectRatio:(croppedImg.height*result.width)/croppedImg.width;const ctx=result.getContext("2d");ctx.imageSmoothingQuality="high";ctx.mozImageSmoothingEnabled=true;ctx.webkitImageSmoothingEnabled=true;ctx.msImageSmoothingEnabled=true;ctx.imageSmoothingEnabled=true;if(perspective){const points=JSON.parse(perspective);const divisions=10;const w=croppedImg.width,h=croppedImg.height;const project=getProjective(w,h,[[(result.width/100)*points[0][0],(result.height/100)*points[0][1]],[(result.width/100)*points[1][0],(result.height/100)*points[1][1]],[(result.width/100)*points[2][0],(result.height/100)*points[2][1]],[(result.width/100)*points[3][0],(result.height/100)*points[3][1]],]);for(let i=0;i=newSize?dataURL:await _loadImageDataURL(originalSrc);} __exports.loadImage=loadImage;function loadImage(src,img=new Image()){const handleImage=(source,resolve,reject)=>{img.addEventListener("load",()=>resolve(img),{once:true});img.addEventListener("error",reject,{once:true});img.src=source;};const placeholderHref="/web/image/__odoo__unknown__src__/";return new Promise((resolve,reject)=>{fetch(src).then((response)=>{if(!response.ok){src=placeholderHref;} handleImage(src,resolve,reject);}).catch((error)=>{src=placeholderHref;handleImage(src,resolve,reject);});});} const imageCache=new Map();function _loadImageObjectURL(src){return _updateImageData(src);} function _loadImageDataURL(src){return _updateImageData(src,"dataURL");} async function _updateImageData(src,key="objectURL"){const currentImageData=imageCache.get(src);if(currentImageData&¤tImageData[key]){return currentImageData[key];} let value="";const blob=await fetch(src).then((res)=>res.blob());if(key==="dataURL"){value=await createDataURL(blob);}else{value=URL.createObjectURL(blob);} imageCache.set(src,Object.assign(currentImageData||{},{[key]:value,size:blob.size}));return value;} function _getImageSizeFromCache(src){return imageCache.get(src).size;} __exports.activateCropper=activateCropper;async function activateCropper(image,aspectRatio,dataset){const oldSrc=image.src;const newSrc=await _loadImageObjectURL(image.getAttribute("src"));image.src=newSrc;const cropper=new Cropper(image,{viewMode:2,dragMode:"move",autoCropArea:1.0,aspectRatio:aspectRatio,data:Object.fromEntries(Object.entries(pick(dataset,...cropperDataFields)).map(([key,value])=>[key,parseFloat(value),])),minContainerWidth:1,minContainerHeight:1,});if(oldSrc===newSrc&&image.complete){return;} return cropper;} __exports.loadImageInfo=loadImageInfo;async function loadImageInfo(img,attachmentSrc=""){const src=attachmentSrc||img.getAttribute("src");if((img.dataset.originalSrc&&img.dataset.mimetypeBeforeConversion)||!src){return;} let docHref=img.ownerDocument.defaultView.location.href;if(docHref.startsWith("about:")){docHref=window.location.href;} const srcUrl=new URL(src,docHref);const relativeSrc=srcUrl.pathname;const{original}=await rpc("/html_editor/get_image_info",{src:relativeSrc});if(original&&original.image_src&&!/\/web\/image\/\d+-redirect\//.test(original.image_src)){if(!img.dataset.mimetype){img.dataset.mimetype=original.mimetype;} img.dataset.originalId=original.id;img.dataset.originalSrc=original.image_src;img.dataset.mimetypeBeforeConversion=original.mimetype;}} __exports.createDataURL=createDataURL;function createDataURL(blob){return new Promise((resolve,reject)=>{const reader=new FileReader();reader.addEventListener("load",()=>resolve(reader.result));reader.addEventListener("abort",reject);reader.addEventListener("error",reject);reader.readAsDataURL(blob);});} __exports.getDataURLBinarySize=getDataURLBinarySize;function getDataURLBinarySize(dataURL){return(dataURL.split(",")[1].length/4)*3;} return __exports;});; /* /html_editor/static/src/utils/list.js */ odoo.define('@html_editor/utils/list',['@html_editor/utils/dom'],function(require){'use strict';let __exports={};const{removeClass,setTagName}=require("@html_editor/utils/dom");__exports.getListMode=getListMode;function getListMode(pnode){if(!["UL","OL"].includes(pnode.tagName)){return;} if(pnode.tagName==="OL"){return"OL";} return pnode.classList.contains("o_checklist")?"CL":"UL";} __exports.switchListMode=switchListMode;function switchListMode(list,newMode){if(getListMode(list)===newMode){return;} const newTag=newMode==="CL"?"UL":newMode;const newList=setTagName(list,newTag);newList.style.removeProperty("list-style");for(const li of newList.children){if(li.style.listStyle!=="none"){li.style.listStyle=null;if(!li.style.all){li.removeAttribute("style");}}} removeClass(newList,"o_checklist");if(newMode==="CL"){newList.classList.add("o_checklist");} return newList;} __exports.convertList=convertList;function convertList(node,newMode){if(!["UL","OL","LI"].includes(node.tagName)){return;} const listMode=getListMode(node);if(listMode&&newMode!==listMode){node=switchListMode(node,newMode);} for(const child of node.children){convertList(child,newMode);} return node;} return __exports;});; /* /html_editor/static/src/utils/perspective_utils.js */ odoo.define('@html_editor/utils/perspective_utils',[],function(require){'use strict';let __exports={};__exports.transform=transform;function transform([[a,b,c],[d,e,f],[g,h,i]],[x,y]){let z=g*x+h*y+i;return[(a*x+b*y+c)/z,(d*x+e*y+f)/z];} function invert([[a,b,c],[d,e,f],[g,h,i]]){const determinant=a*e*i-a*f*h-b*d*i+b*f*g+c*d*h-c*e*g;return[[(e*i-h*f)/determinant,(h*c-b*i)/determinant,(b*f-e*c)/determinant],[(g*f-d*i)/determinant,(a*i-g*c)/determinant,(d*c-a*f)/determinant],[(d*h-g*e)/determinant,(g*b-a*h)/determinant,(a*e-d*b)/determinant],];} function multiply(a,b){const[[a0,a1,a2],[a3,a4,a5],[a6,a7,a8]]=a;const[[b0,b1,b2],[b3,b4,b5],[b6,b7,b8]]=b;return[[a0*b0+a1*b3+a2*b6,a0*b1+a1*b4+a2*b7,a0*b2+a1*b5+a2*b8],[a3*b0+a4*b3+a5*b6,a3*b1+a4*b4+a5*b7,a3*b2+a4*b5+a5*b8],[a6*b0+a7*b3+a8*b6,a6*b1+a7*b4+a8*b7,a6*b2+a7*b5+a8*b8],];} __exports.getProjective=getProjective;function getProjective(width,height,[[x0,y0],[x1,y1],[x2,y2],[x3,y3]]){const denominator=x3*(y1-y2)+x1*(y2-y3)+x2*(y3-y1);const a=(x0*(y2-y3)+x2*(y3-y0)+x3*(y0-y2))/denominator;const b=(x0*(y3-y1)+x3*(y1-y0)+x1*(y0-y3))/denominator;const c=(x0*(y1-y2)+x1*(y2-y0)+x2*(y0-y1))/denominator;const reverse=invert([[width,-width,0],[0,-height,height],[1,-1,1]]);const forward=[[a*x1,b*x2,c*x3],[a*y1,b*y2,c*y3],[a,b,c]];return multiply(forward,reverse);} __exports.getAffineApproximation=getAffineApproximation;function getAffineApproximation(projective,[[x0,y0],[x1,y1],[x2,y2]]){const a=transform(projective,[x0,y0]);const b=transform(projective,[x1,y1]);const c=transform(projective,[x2,y2]);return multiply([[a[0],b[0],c[0]],[a[1],b[1],c[1]],[1,1,1]],invert([[x0,x1,x2],[y0,y1,y2],[1,1,1]]),);} return __exports;});; /* /html_editor/static/src/utils/position.js */ odoo.define('@html_editor/utils/position',[],function(require){'use strict';let __exports={};const DIRECTIONS=__exports.DIRECTIONS={LEFT:false,RIGHT:true,};__exports.leftPos=leftPos;function leftPos(node){return[node.parentElement,childNodeIndex(node)];} __exports.rightPos=rightPos;function rightPos(node){return[node.parentElement,childNodeIndex(node)+1];} __exports.boundariesOut=boundariesOut;function boundariesOut(node){const index=childNodeIndex(node);return[node.parentElement,index,node.parentElement,index+1];} __exports.boundariesIn=boundariesIn;function boundariesIn(node){return[node,0,node,nodeSize(node)];} __exports.startPos=startPos;function startPos(node){return[node,0];} __exports.endPos=endPos;function endPos(node){return[node,nodeSize(node)];} __exports.childNodeIndex=childNodeIndex;function childNodeIndex(node){let i=0;while(node.previousSibling){i++;node=node.previousSibling;} return i;} __exports.nodeSize=nodeSize;function nodeSize(node){const isTextNode=node.nodeType===Node.TEXT_NODE;if(isTextNode){return node.length;}else{const child=node.lastChild;return child?childNodeIndex(child)+1:0;}} return __exports;});; /* /html_editor/static/src/utils/regex.js */ odoo.define('@html_editor/utils/regex',[],function(require){'use strict';let __exports={};const tldWhitelist=['com','net','org','ac','ad','ae','af','ag','ai','al','am','an','ao','aq','ar','as','at','au','aw','ax','az','ba','bb','bd','be','bf','bg','bh','bi','bj','bl','bm','bn','bo','br','bq','bs','bt','bv','bw','by','bz','ca','cc','cd','cf','cg','ch','ci','ck','cl','cm','cn','co','cr','cs','cu','cv','cw','cx','cy','cz','dd','de','dj','dk','dm','do','dz','ec','ee','eg','eh','er','es','et','eu','fi','fj','fk','fm','fo','fr','ga','gb','gd','ge','gf','gg','gh','gi','gl','gm','gn','gp','gq','gr','gs','gt','gu','gw','gy','hk','hm','hn','hr','ht','hu','id','ie','il','im','in','io','iq','ir','is','it','je','jm','jo','jp','ke','kg','kh','ki','km','kn','kp','kr','kw','ky','kz','la','lb','lc','li','lk','lr','ls','lt','lu','lv','ly','ma','mc','md','me','mf','mg','mh','mk','ml','mm','mn','mo','mp','mq','mr','ms','mt','mu','mv','mw','mx','my','mz','na','nc','ne','nf','ng','ni','nl','no','np','nr','nu','nz','om','pa','pe','pf','pg','ph','pk','pl','pm','pn','pr','ps','pt','pw','py','qa','re','ro','rs','ru','rw','sa','sb','sc','sd','se','sg','sh','si','sj','sk','sl','sm','sn','so','sr','ss','st','su','sv','sx','sy','sz','tc','td','tf','tg','th','tj','tk','tl','tm','tn','to','tp','tr','tt','tv','tw','tz','ua','ug','uk','um','us','uy','uz','va','vc','ve','vg','vi','vn','vu','wf','ws','ye','yt','yu','za','zm','zr','zw','co\\.uk'];const urlRegexBase=`|(?:www.))[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-zA-Z][a-zA-Z0-9]{1,62}|(?:[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.(?:${tldWhitelist.join('|')})\\b))(?:(?:[/?#])[^\\s]*[^!.,})\\]'"\\s]|(?:[^!(){}.,[\\]'"\\s]+))?`;const httpCapturedRegex=`(https?:\\/\\/)`;const URL_REGEX=__exports.URL_REGEX=new RegExp(`((?:(?:${httpCapturedRegex}${urlRegexBase})`,'i');return __exports;});; /* /html_editor/static/src/utils/resource.js */ odoo.define('@html_editor/utils/resource',[],function(require){'use strict';let __exports={};const resourceSequenceSymbol=__exports.resourceSequenceSymbol=Symbol("resourceSequence");__exports.withSequence=withSequence;function withSequence(sequenceNumber,object){return{[resourceSequenceSymbol]:sequenceNumber,object,};} return __exports;});; /* /html_editor/static/src/utils/sanitize.js */ odoo.define('@html_editor/utils/sanitize',['@html_editor/utils/dom_info','@html_editor/utils/dom','@odoo/owl'],function(require){'use strict';let __exports={};const{containsAnyInline}=require("@html_editor/utils/dom_info");const{wrapInlinesInBlocks}=require("@html_editor/utils/dom");const{markup}=require("@odoo/owl");__exports.initElementForEdition=initElementForEdition;function initElementForEdition(element,options={}){if(element?.nodeType===Node.ELEMENT_NODE&&containsAnyInline(element)&&!options.allowInlineAtRoot){wrapInlinesInBlocks(element,{baseContainerNodeName:"DIV",});}} __exports.fixInvalidHTML=fixInvalidHTML;function fixInvalidHTML(content){if(!content){return content;} const regex=/<\s*(a|strong|t)[^<]*?\/\s*>/g;return content.replace(regex,(match,g0)=>match.replace(/\/\s*>/,`>`));} let Markup=null;__exports.instanceofMarkup=instanceofMarkup;function instanceofMarkup(value){if(!Markup){Markup=markup("").constructor;} return value instanceof Markup;} return __exports;});; /* /html_editor/static/src/utils/selection.js */ odoo.define('@html_editor/utils/selection',['@html_editor/utils/blocks','@html_editor/utils/dom_info','@html_editor/utils/dom_state','@html_editor/utils/dom_traversal','@html_editor/utils/position'],function(require){'use strict';let __exports={};const{closestBlock,isBlock}=require("@html_editor/utils/blocks");const{getDeepestPosition,isContentEditable,isNotEditableNode,isSelfClosingElement,nextLeaf,previousLeaf,}=require("@html_editor/utils/dom_info");const{isFakeLineBreak}=require("@html_editor/utils/dom_state");const{closestElement,createDOMPathGenerator}=require("@html_editor/utils/dom_traversal");const{DIRECTIONS,childNodeIndex,endPos,leftPos,nodeSize,rightPos,startPos,}=require("@html_editor/utils/position");__exports.getCursorDirection=getCursorDirection;function getCursorDirection(anchorNode,anchorOffset,focusNode,focusOffset){if(anchorNode===focusNode){if(anchorOffset===focusOffset){return false;} return anchorOffsetselection.intersectsNode(node)));}} const leftLeafOnlyInScopeNotBlockEditablePath=createDOMPathGenerator(DIRECTIONS.LEFT,{leafOnly:true,inScope:true,stopTraverseFunction:(node)=>isNotEditableNode(node)||isBlock(node),stopFunction:(node)=>isNotEditableNode(node)||isBlock(node),});const rightLeafOnlyInScopeNotBlockEditablePath=createDOMPathGenerator(DIRECTIONS.RIGHT,{leafOnly:true,inScope:true,stopTraverseFunction:(node)=>isNotEditableNode(node)||isBlock(node),stopFunction:(node)=>isNotEditableNode(node)||isBlock(node),});__exports.normalizeSelfClosingElement=normalizeSelfClosingElement;function normalizeSelfClosingElement(node,offset){if(isSelfClosingElement(node)){[node,offset]=rightPos(node);} return[node,offset];} __exports.normalizeNotEditableNode=normalizeNotEditableNode;function normalizeNotEditableNode(node,offset,position="right"){const editable=closestElement(node,".odoo-editor-editable");let closest=closestElement(node);while(closest&&closest!==editable&&!closest.isContentEditable){[node,offset]=position==="right"?rightPos(node):leftPos(node);closest=node;} return[node,offset];} __exports.normalizeCursorPosition=normalizeCursorPosition;function normalizeCursorPosition(node,offset,position="right"){[node,offset]=normalizeSelfClosingElement(node,offset);[node,offset]=normalizeNotEditableNode(node,offset,position);return[node,offset];} __exports.normalizeFakeBR=normalizeFakeBR;function normalizeFakeBR(node,offset){const prevNode=node.nodeType===Node.ELEMENT_NODE&&node.childNodes[offset-1];if(prevNode&&prevNode.nodeName==="BR"&&isFakeLineBreak(prevNode)){offset--;} return[node,offset];} __exports.normalizeDeepCursorPosition=normalizeDeepCursorPosition;function normalizeDeepCursorPosition(node,offset){let el;let elOffset;if(node.nodeType===Node.ELEMENT_NODE){el=node;elOffset=offset;}else if(node.nodeType===Node.TEXT_NODE){if(offset===0){el=node.parentNode;elOffset=childNodeIndex(node);}else if(offset===node.length){el=node.parentNode;elOffset=childNodeIndex(node)+1;}} if(el){const leftInlineNode=leftLeafOnlyInScopeNotBlockEditablePath(el,elOffset).next().value;let leftVisibleEmpty=false;if(leftInlineNode){leftVisibleEmpty=isSelfClosingElement(leftInlineNode)||!isContentEditable(leftInlineNode);[node,offset]=leftVisibleEmpty?rightPos(leftInlineNode):endPos(leftInlineNode);} if(!leftInlineNode||leftVisibleEmpty){const rightInlineNode=rightLeafOnlyInScopeNotBlockEditablePath(el,elOffset).next().value;if(rightInlineNode){const closest=closestElement(rightInlineNode);const rightVisibleEmpty=isSelfClosingElement(rightInlineNode)||!closest||!closest.isContentEditable;if(!(leftVisibleEmpty&&rightVisibleEmpty)){[node,offset]=rightVisibleEmpty?leftPos(rightInlineNode):startPos(rightInlineNode);}}}} return[node,offset];} function updateCursorBeforeMove(destParent,destIndex,node,cursor){if(cursor.node===destParent&&cursor.offset>=destIndex){cursor.offset+=1;}else if(cursor.node===node.parentNode){const childIndex=childNodeIndex(node);if(cursor.offset===childIndex){[cursor.node,cursor.offset]=[destParent,destIndex];}else if(cursor.offset>childIndex){cursor.offset-=1;}}} function updateCursorBeforeRemove(node,cursor){if(node.contains(cursor.node)){[cursor.node,cursor.offset]=[node.parentNode,childNodeIndex(node)];}else if(cursor.node===node.parentNode&&cursor.offset>childNodeIndex(node)){cursor.offset-=1;}} function updateCursorBeforeUnwrap(node,cursor){if(cursor.node===node){[cursor.node,cursor.offset]=[node.parentNode,cursor.offset+childNodeIndex(node)];}else if(cursor.node===node.parentNode&&cursor.offset>childNodeIndex(node)){cursor.offset+=nodeSize(node)-1;}} function updateCursorBeforeMergeIntoPreviousSibling(node,cursor){if(cursor.node===node){cursor.node=node.previousSibling;cursor.offset+=node.previousSibling.childNodes.length;}else if(cursor.node===node.parentNode){const childIndex=childNodeIndex(node);if(cursor.offset===childIndex){cursor.node=node.previousSibling;cursor.offset=node.previousSibling.childNodes.length;}else if(cursor.offset>childIndex){cursor.offset--;}}} const callbacksForCursorUpdate=__exports.callbacksForCursorUpdate={remove:(node)=>(cursor)=>updateCursorBeforeRemove(node,cursor),before:(ref,node)=>(cursor)=>updateCursorBeforeMove(ref.parentNode,childNodeIndex(ref),node,cursor),after:(ref,node)=>(cursor)=>updateCursorBeforeMove(ref.parentNode,childNodeIndex(ref)+1,node,cursor),append:(to,node)=>(cursor)=>updateCursorBeforeMove(to,to.childNodes.length,node,cursor),prepend:(to,node)=>(cursor)=>updateCursorBeforeMove(to,0,node,cursor),unwrap:(node)=>(cursor)=>updateCursorBeforeUnwrap(node,cursor),merge:(node)=>(cursor)=>updateCursorBeforeMergeIntoPreviousSibling(node,cursor),};__exports.getAdjacentCharacter=getAdjacentCharacter;function getAdjacentCharacter(selection,side,editable){let{focusNode,focusOffset}=selection;[focusNode,focusOffset]=getDeepestPosition(focusNode,focusOffset);const originalBlock=closestBlock(focusNode);let adjacentCharacter;while(!adjacentCharacter&&focusNode){if(side==="previous"){adjacentCharacter=focusOffset>0&&focusNode.textContent[focusOffset-1];}else{adjacentCharacter=focusNode.textContent[focusOffset];} if(!adjacentCharacter){if(side==="previous"){focusNode=previousLeaf(focusNode,editable);focusOffset=focusNode&&nodeSize(focusNode);}else{focusNode=nextLeaf(focusNode,editable);focusOffset=0;} const characterIndex=side==="previous"?focusOffset-1:focusOffset;adjacentCharacter=focusNode&&focusNode.textContent[characterIndex];}} if(!focusNode||!isContentEditable(focusNode)||closestBlock(focusNode)!==originalBlock){return undefined;} return adjacentCharacter;} return __exports;});; /* /html_editor/static/src/utils/table.js */ odoo.define('@html_editor/utils/table',['@html_editor/utils/dom_traversal'],function(require){'use strict';let __exports={};const{closestElement}=require("@html_editor/utils/dom_traversal");__exports.getRowIndex=getRowIndex;function getRowIndex(trOrTd){const tr=closestElement(trOrTd,"tr");return tr.rowIndex;} __exports.getColumnIndex=getColumnIndex;function getColumnIndex(td){return td.cellIndex;} return __exports;});; /* /html_editor/static/src/utils/url.js */ odoo.define('@html_editor/utils/url',[],function(require){'use strict';let __exports={};__exports.checkURL=checkURL;function checkURL(url,hostnameList){if(url){let potentialURL;try{potentialURL=new URL(url);}catch{return false;} if(hostnameList.includes(potentialURL.hostname)){return`https://${potentialURL.hostname}${potentialURL.pathname}`;}} return false;} __exports.isImageUrl=isImageUrl;function isImageUrl(url){const urlFileExtention=url.split(".").pop();return["jpg","jpeg","png","gif","svg","webp"].includes(urlFileExtention.toLowerCase());} __exports.getVideoUrl=getVideoUrl;function getVideoUrl(platform,videoId,params){let url;switch(platform){case"youtube":url=new URL(`https://www.youtube.com/embed/${videoId}`);break;case"vimeo":url=new URL(`https://player.vimeo.com/video/${videoId}`);break;case"dailymotion":url=new URL(`https://www.dailymotion.com/embed/video/${videoId}`);break;case"instagram":url=new URL(`https://www.instagram.com/p/${videoId}/embed`);break;case"youku":url=new URL(`https://player.youku.com/embed/${videoId}`);break;default:throw new Error(`Unsupported platform: ${platform}`);} url.search=new URLSearchParams(params);return url;} return __exports;});; /* /web_unsplash/static/src/media_dialog/image_selector_patch.js */ odoo.define('@web_unsplash/media_dialog/image_selector_patch',['@web/core/l10n/translation','@web/core/utils/patch','@web/core/utils/concurrency','@web/core/network/rpc','@web/core/utils/hooks','@html_editor/main/media/media_dialog/image_selector','@web_unsplash/unsplash_error/unsplash_error','@odoo/owl'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{patch}=require("@web/core/utils/patch");const{KeepLast}=require("@web/core/utils/concurrency");const{rpc}=require("@web/core/network/rpc");const{useService}=require("@web/core/utils/hooks");const{ImageSelector}=require("@html_editor/main/media/media_dialog/image_selector");const{UnsplashError}=require("@web_unsplash/unsplash_error/unsplash_error");const{useState}=require("@odoo/owl");patch(ImageSelector.prototype,{setup(){super.setup();this.unsplash=useService("unsplash");this.keepLastUnsplash=new KeepLast();this.unsplashState=useState({unsplashRecords:[],isFetchingUnsplash:false,isMaxed:false,unsplashError:null,useUnsplash:true,});this.NUMBER_OF_RECORDS_TO_DISPLAY=30;this.errorMessages={key_not_found:{title:_t("Setup Unsplash to access royalty free photos."),subtitle:"",},401:{title:_t("Unauthorized Key"),subtitle:_t("Please check your Unsplash access key and application ID."),},403:{title:_t("Search is temporarily unavailable"),subtitle:_t("The max number of searches is exceeded. Please retry in an hour or extend to a better account."),},};},get canLoadMore(){if(this.state.searchService==="all"){return(super.canLoadMore||(this.state.needle&&!this.unsplashState.isMaxed&&!this.unsplashState.unsplashError));}else if(this.state.searchService==="unsplash"){return(this.state.needle&&!this.unsplashState.isMaxed&&!this.unsplashState.unsplashError);} return super.canLoadMore;},get hasContent(){if(this.state.searchService==="all"){return super.hasContent||!!this.unsplashState.unsplashRecords.length;}else if(this.state.searchService==="unsplash"){return!!this.unsplashState.unsplashRecords.length;} return super.hasContent;},get errorTitle(){if(this.errorMessages[this.unsplashState.unsplashError]){return this.errorMessages[this.unsplashState.unsplashError].title;} return _t("Something went wrong");},get errorSubtitle(){if(this.errorMessages[this.unsplashState.unsplashError]){return this.errorMessages[this.unsplashState.unsplashError].subtitle;} return _t("Please check your internet connection or contact administrator.");},get selectedRecordIds(){return this.props.selectedMedia[this.props.id].filter((media)=>media.mediaType==="unsplashRecord").map(({id})=>id);},get isFetching(){return super.isFetching||this.unsplashState.isFetchingUnsplash;},get combinedRecords(){function alternate(a,b){return[a.map((v,i)=>(iexisting.id);const newImages=images.filter((record)=>!existingIds.includes(record.id));const records=newImages.map((record)=>{const url=new URL(record.urls.regular);url.searchParams.set("h",2*this.MIN_ROW_HEIGHT);url.searchParams.delete("w");return Object.assign({},record,{url:url.toString(),mediaType:"unsplashRecord",});});return{isMaxed,records};}catch(e){this.unsplashState.isFetchingUnsplash=false;if(e==="no_access"){this.unsplashState.useUnsplash=false;}else{this.unsplashState.unsplashError=e;} return{records:[],isMaxed:true};}},async loadMore(...args){await super.loadMore(...args);return this.keepLastUnsplash.add(this.fetchUnsplashRecords(this.unsplashState.unsplashRecords.length)).then(({records,isMaxed})=>{this.unsplashState.unsplashRecords.push(...records);this.unsplashState.isMaxed=isMaxed;});},async search(...args){await super.search(...args);await this.searchUnsplash();},async searchUnsplash(){if(!this.state.needle){this.unsplashState.unsplashError=false;this.unsplashState.unsplashRecords=[];this.unsplashState.isMaxed=false;} return this.keepLastUnsplash.add(this.fetchUnsplashRecords(0)).then(({records,isMaxed})=>{this.unsplashState.unsplashRecords=records;this.unsplashState.isMaxed=isMaxed;});},async onClickRecord(media){this.props.selectMedia({...media,mediaType:"unsplashRecord",query:this.state.needle});if(!this.props.multiSelect){await this.props.save();}},async submitCredentials(key,appId){this.unsplashState.unsplashError=null;await rpc("/web_unsplash/save_unsplash",{key,appId});await this.searchUnsplash();},});ImageSelector.components={...ImageSelector.components,UnsplashError,};return __exports;});; /* /web_unsplash/static/src/media_dialog/media_dialog_patch.js */ odoo.define('@web_unsplash/media_dialog/media_dialog_patch',['@html_editor/main/media/media_dialog/media_dialog','@web/core/utils/patch','@web/core/utils/hooks'],function(require){'use strict';let __exports={};const{MediaDialog,TABS}=require("@html_editor/main/media/media_dialog/media_dialog");const{patch}=require("@web/core/utils/patch");const{useService}=require("@web/core/utils/hooks");patch(MediaDialog.prototype,{setup(){super.setup();this.unsplashService=useService("unsplash");},async save(){const selectedImages=this.selectedMedia[TABS.IMAGES.id];if(selectedImages){const unsplashRecords=selectedImages.filter((media)=>media.mediaType==="unsplashRecord");if(unsplashRecords.length){await this.unsplashService.uploadUnsplashRecords(unsplashRecords,{resModel:this.props.resModel,resId:this.props.resId},(attachments)=>{this.selectedMedia[TABS.IMAGES.id]=this.selectedMedia[TABS.IMAGES.id].filter((media)=>media.mediaType!=="unsplashRecord");this.selectedMedia[TABS.IMAGES.id]=this.selectedMedia[TABS.IMAGES.id].concat(attachments.map((attachment)=>({...attachment,mediaType:"attachment",})));});}} return super.save(...arguments);},});return __exports;});; /* /web_unsplash/static/src/unsplash_credentials/unsplash_credentials.js */ odoo.define('@web_unsplash/unsplash_credentials/unsplash_credentials',['@odoo/owl'],function(require){'use strict';let __exports={};const{Component,useState}=require("@odoo/owl");const UnsplashCredentials=__exports.UnsplashCredentials=class UnsplashCredentials extends Component{static template="web_unsplash.UnsplashCredentials";static props={submitCredentials:Function,hasCredentialsError:Boolean,};setup(){this.state=useState({key:"",appId:"",hasKeyError:this.props.hasCredentialsError,hasAppIdError:this.props.hasCredentialsError,});} submitCredentials(){if(this.state.key===""){this.state.hasKeyError=true;}else if(this.state.appId===""){this.state.hasAppIdError=true;}else{this.props.submitCredentials(this.state.key,this.state.appId);}}} return __exports;});; /* /web_unsplash/static/src/unsplash_error/unsplash_error.js */ odoo.define('@web_unsplash/unsplash_error/unsplash_error',['@odoo/owl','@web_unsplash/unsplash_credentials/unsplash_credentials'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const{UnsplashCredentials}=require("@web_unsplash/unsplash_credentials/unsplash_credentials");const UnsplashError=__exports.UnsplashError=class UnsplashError extends Component{static template="web_unsplash.UnsplashError";static components={UnsplashCredentials,};static props={title:String,subtitle:String,showCredentials:Boolean,submitCredentials:{type:Function,optional:true},hasCredentialsError:{type:Boolean,optional:true},};} return __exports;});; /* /web_unsplash/static/src/unsplash_service.js */ odoo.define('@web_unsplash/unsplash_service',['@web/core/network/rpc','@web/core/registry','@web/core/l10n/translation','@html_editor/main/media/media_dialog/upload_progress_toast/upload_service'],function(require){'use strict';let __exports={};const{rpc}=require("@web/core/network/rpc");const{registry}=require("@web/core/registry");const{_t}=require("@web/core/l10n/translation");const{AUTOCLOSE_DELAY}=require("@html_editor/main/media/media_dialog/upload_progress_toast/upload_service");const unsplashService=__exports.unsplashService={dependencies:["upload"],async start(env,{upload}){const _cache={};return{async uploadUnsplashRecords(records,{resModel,resId},onUploaded){upload.incrementId();const file=upload.addFile({id:upload.fileId,name:records.length>1?_t("Uploading %(count)s '%(query)s' images.",{count:records.length,query:records[0].query,}):_t("Uploading '%s' image.",records[0].query),});try{const urls={};for(const record of records){const _1920Url=new URL(record.urls.regular);_1920Url.searchParams.set("w","1920");urls[record.id]={url:_1920Url.href,download_url:record.links.download_location,description:record.alt_description,};} const xhr=new XMLHttpRequest();xhr.upload.addEventListener("progress",(ev)=>{const rpcComplete=(ev.loaded/ev.total)*100;file.progress=rpcComplete;});xhr.upload.addEventListener("load",function(){file.progress=100;});const attachments=await rpc("/web_unsplash/attachment/add",{res_id:resId,res_model:resModel,unsplashurls:urls,query:records[0].query,},{xhr});if(attachments.error){file.hasError=true;file.errorMessage=attachments.error;}else{file.uploaded=true;await onUploaded(attachments);} setTimeout(()=>upload.deleteFile(file.id),AUTOCLOSE_DELAY);}catch(error){file.hasError=true;setTimeout(()=>upload.deleteFile(file.id),AUTOCLOSE_DELAY);throw error;}},async getImages(query,offset=0,pageSize=30,orientation){const from=offset;const to=offset+pageSize;let cachedData=orientation?_cache[query+orientation]:_cache[query];if(cachedData&&(cachedData.images.length>=to||(cachedData.totalImages!==0&&cachedData.totalImagescachedData.totalImages,};} cachedData=await this._fetchImages(query,orientation);return{images:cachedData.images.slice(from,to),isMaxed:to>cachedData.totalImages,};},async _fetchImages(query,orientation){const key=orientation?query+orientation:query;if(!_cache[key]){_cache[key]={images:[],maxPages:0,totalImages:0,pageCached:0,};} const cachedData=_cache[key];const payload={query:query,page:cachedData.pageCached+1,per_page:30,};if(orientation){payload.orientation=orientation;} const result=await rpc("/web_unsplash/fetch_images",payload);if(result.error){return Promise.reject(result.error);} cachedData.pageCached++;cachedData.images.push(...result.results);cachedData.maxPages=result.total_pages;cachedData.totalImages=result.total;return cachedData;},};},};registry.category("services").add("unsplash",unsplashService);return __exports;});; /* /web_editor/static/src/components/media_dialog/document_selector.js */ odoo.define('@web_editor/components/media_dialog/document_selector',['@web/core/l10n/translation','@web_editor/components/media_dialog/file_selector'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{Attachment,FileSelector,IMAGE_MIMETYPES}=require("@web_editor/components/media_dialog/file_selector");const DocumentAttachment=__exports.DocumentAttachment=class DocumentAttachment extends Attachment{static template="web_editor.DocumentAttachment";} const DocumentSelector=__exports.DocumentSelector=class DocumentSelector extends FileSelector{static mediaSpecificClasses=["o_image"];static mediaSpecificStyles=[];static mediaExtraClasses=[];static tagNames=["A"];static attachmentsListTemplate="web_editor.DocumentsListTemplate";static components={...FileSelector.components,DocumentAttachment,};setup(){super.setup();this.uploadText=_t("Upload a document");this.urlPlaceholder="https://www.odoo.com/mydocument";this.addText=_t("Add URL");this.searchPlaceholder=_t("Search a document");this.allLoadedText=_t("All documents have been loaded");} get attachmentsDomain(){const domain=super.attachmentsDomain;domain.push(['mimetype','not in',IMAGE_MIMETYPES]);domain.unshift('&','|',['url','=',null],'!',['url','=like','/web/assets/%']);return domain;} async onClickDocument(document){this.selectAttachment(document);await this.props.save();} async fetchAttachments(...args){const attachments=await super.fetchAttachments(...args);if(this.selectInitialMedia()){for(const attachment of attachments){if(`/web/content/${attachment.id}`===this.props.media.getAttribute('href').replace(/[?].*/,'')){this.selectAttachment(attachment);}}} return attachments;} static async createElements(selectedMedia,{orm}){return Promise.all(selectedMedia.map(async attachment=>{const linkEl=document.createElement('a');let href=`/web/content/${encodeURIComponent(attachment.id)}?unique=${encodeURIComponent(attachment.checksum)}&download=true`;if(!attachment.public){let accessToken=attachment.access_token;if(!accessToken){[accessToken]=await orm.call('ir.attachment','generate_access_token',[attachment.id],);} href+=`&access_token=${encodeURIComponent(accessToken)}`;} linkEl.href=href;linkEl.title=attachment.name;linkEl.dataset.mimetype=attachment.mimetype;return linkEl;}));}} return __exports;});; /* /web_editor/static/src/components/media_dialog/file_selector.js */ odoo.define('@web_editor/components/media_dialog/file_selector',['@web/core/l10n/translation','@web/core/network/rpc','@web/core/utils/hooks','@web/core/confirmation_dialog/confirmation_dialog','@web/core/dialog/dialog','@web/core/utils/concurrency','@web/core/utils/timing','@web_editor/components/media_dialog/search_media','@odoo/owl'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{rpc}=require("@web/core/network/rpc");const{useService}=require('@web/core/utils/hooks');const{ConfirmationDialog}=require('@web/core/confirmation_dialog/confirmation_dialog');const{Dialog}=require('@web/core/dialog/dialog');const{KeepLast}=require("@web/core/utils/concurrency");const{useDebounced}=require("@web/core/utils/timing");const{SearchMedia}=require("@web_editor/components/media_dialog/search_media");const{Component,xml,useState,useRef,onWillStart,useEffect}=require("@odoo/owl");const IMAGE_MIMETYPES=__exports.IMAGE_MIMETYPES=['image/jpg','image/jpeg','image/jpe','image/png','image/svg+xml','image/gif','image/webp'];const IMAGE_EXTENSIONS=__exports.IMAGE_EXTENSIONS=['.jpg','.jpeg','.jpe','.png','.svg','.gif','.webp'];class RemoveButton extends Component{static template=xml``;static props=["model?","remove"];setup(){this.removeTitle=_t("This file is attached to the current record.");if(this.props.model==='ir.ui.view'){this.removeTitle=_t("This file is a public view attachment.");}} remove(ev){ev.stopPropagation();this.props.remove();}} const AttachmentError=__exports.AttachmentError=class AttachmentError extends Component{static components={Dialog};static template=xml`

The image could not be deleted because it is used in the following pages or views:

`;static props=["views","close"];setup(){this.title=_t("Alert");}} const Attachment=__exports.Attachment=class Attachment extends Component{static template="";static components={RemoveButton,};static props=["*"];setup(){this.dialogs=useService('dialog');} remove(){this.dialogs.add(ConfirmationDialog,{body:_t("Are you sure you want to delete this file?"),confirm:async()=>{const prevented=await rpc('/web_editor/attachment/remove',{ids:[this.props.id],});if(!Object.keys(prevented).length){this.props.onRemoved(this.props.id);}else{this.dialogs.add(AttachmentError,{views:prevented[this.props.id],});}},});}} const FileSelectorControlPanel=__exports.FileSelectorControlPanel=class FileSelectorControlPanel extends Component{static template="web_editor.FileSelectorControlPanel";static components={SearchMedia,};static props={uploadUrl:Function,validateUrl:Function,uploadFiles:Function,changeSearchService:Function,changeShowOptimized:Function,search:Function,accept:{type:String,optional:true},addText:{type:String,optional:true},multiSelect:{type:true,optional:true},needle:{type:String,optional:true},searchPlaceholder:{type:String,optional:true},searchService:{type:String,optional:true},showOptimized:{type:Boolean,optional:true},showOptimizedOption:{type:String,optional:true},uploadText:{type:String,optional:true},urlPlaceholder:{type:String,optional:true},urlWarningTitle:{type:String,optional:true},useMediaLibrary:{type:Boolean,optional:true},useUnsplash:{type:Boolean,optional:true},};setup(){this.state=useState({showUrlInput:false,urlInput:'',isValidUrl:false,isValidFileFormat:false,isValidatingUrl:false,});this.debouncedValidateUrl=useDebounced(this.props.validateUrl,500);this.fileInput=useRef('file-input');} get showSearchServiceSelect(){return this.props.searchService&&this.props.needle;} get enableUrlUploadClick(){return!this.state.showUrlInput||(this.state.urlInput&&this.state.isValidUrl&&this.state.isValidFileFormat);} async onUrlUploadClick(){if(!this.state.showUrlInput){this.state.showUrlInput=true;}else{await this.props.uploadUrl(this.state.urlInput);this.state.urlInput='';}} async onUrlInput(ev){this.state.isValidatingUrl=true;const{isValidUrl,isValidFileFormat}=await this.debouncedValidateUrl(ev.target.value);this.state.isValidFileFormat=isValidFileFormat;this.state.isValidUrl=isValidUrl;this.state.isValidatingUrl=false;} onClickUpload(){this.fileInput.el.click();} async onChangeFileInput(){const inputFiles=this.fileInput.el.files;if(!inputFiles.length){return;} await this.props.uploadFiles(inputFiles);const fileInputEl=this.fileInput.el;if(fileInputEl){fileInputEl.value="";}}} const FileSelector=__exports.FileSelector=class FileSelector extends Component{static template="web_editor.FileSelector";static components={FileSelectorControlPanel,};static props=["*"];setup(){this.notificationService=useService("notification");this.orm=useService('orm');this.uploadService=useService('upload');this.keepLast=new KeepLast();this.loadMoreButtonRef=useRef('load-more-button');this.existingAttachmentsRef=useRef("existing-attachments");this.state=useState({attachments:[],canScrollAttachments:false,canLoadMoreAttachments:false,isFetchingAttachments:false,needle:'',});this.NUMBER_OF_ATTACHMENTS_TO_DISPLAY=30;onWillStart(async()=>{this.state.attachments=await this.fetchAttachments(this.NUMBER_OF_ATTACHMENTS_TO_DISPLAY,0);});this.debouncedOnScroll=useDebounced(this.updateScroll,15);this.debouncedScrollUpdate=useDebounced(this.updateScroll,500);useEffect((modalEl)=>{if(modalEl){modalEl.addEventListener("scroll",this.debouncedOnScroll);return()=>{modalEl.removeEventListener("scroll",this.debouncedOnScroll);};}},()=>[this.props.modalRef.el?.querySelector("main.modal-body")]);useEffect(()=>{this.loadMoreButtonRef.el.classList.add("o_hide_loading");this.state.canScrollAttachments=false;this.debouncedScrollUpdate();},()=>[this.allAttachments.length]);} get canLoadMore(){return this.state.canLoadMoreAttachments;} get hasContent(){return this.state.attachments.length;} get isFetching(){return this.state.isFetchingAttachments;} get selectedAttachmentIds(){return this.props.selectedMedia[this.props.id].filter(media=>media.mediaType==='attachment').map(({id})=>id);} get attachmentsDomain(){const domain=['&',['res_model','=',this.props.resModel],['res_id','=',this.props.resId||0]];domain.unshift('|',['public','=',true]);domain.push(['name','ilike',this.state.needle]);return domain;} get allAttachments(){return this.state.attachments;} validateUrl(url){const path=url.split('?')[0];const isValidUrl=/^.+\..+$/.test(path);const isValidFileFormat=true;return{isValidUrl,isValidFileFormat,path};} async fetchAttachments(limit,offset){this.state.isFetchingAttachments=true;let attachments=[];try{attachments=await this.orm.call('ir.attachment','search_read',[],{domain:this.attachmentsDomain,fields:['name','mimetype','description','checksum','url','type','res_id','res_model','public','access_token','image_src','image_width','image_height','original_id'],order:'id desc',limit,offset,});attachments.forEach(attachment=>attachment.mediaType='attachment');}catch(e){if(e.exceptionName!=='odoo.exceptions.AccessError'){throw e;}} this.state.canLoadMoreAttachments=attachments.length>=this.NUMBER_OF_ATTACHMENTS_TO_DISPLAY;this.state.isFetchingAttachments=false;return attachments;} async handleLoadMore(){await this.loadMore();} async loadMore(){return this.keepLast.add(this.fetchAttachments(this.NUMBER_OF_ATTACHMENTS_TO_DISPLAY,this.state.attachments.length)).then((newAttachments)=>{this.state.attachments.push(...newAttachments);});} async handleSearch(needle){await this.search(needle);} async search(needle){this.state.attachments=[];this.state.needle=needle;return this.keepLast.add(this.fetchAttachments(this.NUMBER_OF_ATTACHMENTS_TO_DISPLAY,0)).then((attachments)=>{this.state.attachments=attachments;});} async uploadFiles(files){await this.uploadService.uploadFiles(files,{resModel:this.props.resModel,resId:this.props.resId},attachment=>this.onUploaded(attachment));} async uploadUrl(url){await this.uploadService.uploadUrl(url,{resModel:this.props.resModel,resId:this.props.resId,},attachment=>this.onUploaded(attachment));} async onUploaded(attachment){this.state.attachments=[attachment,...this.state.attachments.filter(attach=>attach.id!==attachment.id)];this.selectAttachment(attachment);if(!this.props.multiSelect){await this.props.save();} if(this.props.onAttachmentChange){this.props.onAttachmentChange(attachment);}} onRemoved(attachmentId){this.state.attachments=this.state.attachments.filter(attachment=>attachment.id!==attachmentId);} selectAttachment(attachment){this.props.selectMedia({...attachment,mediaType:'attachment'});} selectInitialMedia(){return this.props.media&&this.constructor.tagNames.includes(this.props.media.tagName)&&!this.selectedAttachmentIds.length;} updateScroll(){const loadMoreTop=this.loadMoreButtonRef.el.getBoundingClientRect().top;const modalEl=this.props.modalRef.el.querySelector("main.modal-body");const modalBottom=modalEl.getBoundingClientRect().bottom;this.state.canScrollAttachments=loadMoreTop>=modalBottom;this.loadMoreButtonRef.el.classList.remove("o_hide_loading");} isAttachmentHidden(attachmentEl){const attachmentBottom=Math.round(attachmentEl.getBoundingClientRect().bottom);const modalEl=this.props.modalRef.el.querySelector("main.modal-body");const modalBottom=modalEl.getBoundingClientRect().bottom;return attachmentBottom>modalBottom;} handleScrollAttachments(){let scrollToEl=this.loadMoreButtonRef.el;const attachmentEls=[...this.existingAttachmentsRef.el.querySelectorAll(".o_existing_attachment_cell")];const firstHiddenAttachmentEl=attachmentEls.find(el=>this.isAttachmentHidden(el));if(firstHiddenAttachmentEl){const attachmentBottom=firstHiddenAttachmentEl.getBoundingClientRect().bottom;const attachmentIndex=attachmentEls.indexOf(firstHiddenAttachmentEl);const firstNextRowAttachmentEl=attachmentEls.slice(attachmentIndex).find(el=>{return el.getBoundingClientRect().bottom>attachmentBottom;}) scrollToEl=firstNextRowAttachmentEl||scrollToEl;} scrollToEl.scrollIntoView({block:"end",inline:"nearest",behavior:"smooth"});}} return __exports;});; /* /web_editor/static/src/components/media_dialog/icon_selector.js */ odoo.define('@web_editor/components/media_dialog/icon_selector',['@web_editor/js/wysiwyg/fonts','@web_editor/components/media_dialog/search_media','@odoo/owl'],function(require){'use strict';let __exports={};const fonts=require('@web_editor/js/wysiwyg/fonts')[Symbol.for("default")];const{SearchMedia}=require("@web_editor/components/media_dialog/search_media");const{Component,useState}=require("@odoo/owl");const IconSelector=__exports.IconSelector=class IconSelector extends Component{static mediaSpecificClasses=["fa"];static mediaSpecificStyles=["color","background-color","border-width","border-color","border-style"];static mediaExtraClasses=["rounded-circle","rounded","img-thumbnail","shadow","border",/^text-\S+$/,/^bg-\S+$/,/^fa-\S+$/,];static tagNames=["SPAN","I"];static template="web_editor.IconSelector";static components={SearchMedia,};static props=["*"];setup(){this.state=useState({fonts:this.props.fonts,needle:'',});} get selectedMediaIds(){return this.props.selectedMedia[this.props.id].map(({id})=>id);} search(needle){this.state.needle=needle;if(!this.state.needle){this.state.fonts=this.props.fonts;}else{this.state.fonts=this.props.fonts.map(font=>{const icons=font.icons.filter(icon=>icon.alias.indexOf(this.state.needle)>=0);return{...font,icons};});}} async onClickIcon(font,icon){this.props.selectMedia({...icon,fontBase:font.base,initialIconChanged:this.props.media&&!icon.names.some(name=>this.props.media.classList.contains(name)),});await this.props.save();} static createElements(selectedMedia){return selectedMedia.map(icon=>{const iconEl=document.createElement('span');iconEl.classList.add(icon.fontBase,icon.names[0]);return iconEl;});} static initFonts(){fonts.computeFonts();const allFonts=fonts.fontIcons.map(({cssData,base})=>{const uniqueIcons=Array.from(new Map(cssData.map(icon=>{const alias=icon.names.join(',');const id=`${base}_${alias}`;return[id,{...icon,alias,id}];})).values());return{base,icons:uniqueIcons};});return allFonts;}} return __exports;});; /* /web_editor/static/src/components/media_dialog/image_selector.js */ odoo.define('@web_editor/components/media_dialog/image_selector',['@web/core/l10n/translation','@web/core/network/rpc','@web_editor/js/common/utils','@web_editor/components/media_dialog/file_selector','@web/core/utils/concurrency','@odoo/owl'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{rpc}=require("@web/core/network/rpc");const weUtils=require('@web_editor/js/common/utils')[Symbol.for("default")];const{Attachment,FileSelector,IMAGE_MIMETYPES,IMAGE_EXTENSIONS}=require("@web_editor/components/media_dialog/file_selector");const{KeepLast}=require("@web/core/utils/concurrency");const{useRef,useState,useEffect}=require("@odoo/owl");const AutoResizeImage=__exports.AutoResizeImage=class AutoResizeImage extends Attachment{static template="web_editor.AutoResizeImage";setup(){super.setup();this.image=useRef('auto-resize-image');this.container=useRef('auto-resize-image-container');this.state=useState({loaded:false,});useEffect(()=>{this.image.el.addEventListener('load',()=>this.onImageLoaded());return this.image.el.removeEventListener('load',()=>this.onImageLoaded());},()=>[]);} async onImageLoaded(){if(!this.image.el){return;} if(this.props.onLoaded){await this.props.onLoaded(this.image.el);if(!this.image.el){return;}} const aspectRatio=this.image.el.offsetWidth/this.image.el.offsetHeight;const width=aspectRatio*this.props.minRowHeight;this.container.el.style.flexGrow=width;this.container.el.style.flexBasis=`${width}px`;this.state.loaded=true;}} const newLocal="img-fluid";const ImageSelector=__exports.ImageSelector=class ImageSelector extends FileSelector{static mediaSpecificClasses=["img",newLocal,"o_we_custom_image"];static mediaSpecificStyles=[];static mediaExtraClasses=["rounded-circle","rounded","img-thumbnail","shadow","w-25","w-50","w-75","w-100",];static tagNames=["IMG"];static attachmentsListTemplate="web_editor.ImagesListTemplate";static components={...FileSelector.components,AutoResizeImage,};setup(){super.setup();this.keepLastLibraryMedia=new KeepLast();this.state.libraryMedia=[];this.state.libraryResults=null;this.state.isFetchingLibrary=false;this.state.searchService='all';this.state.showOptimized=false;this.NUMBER_OF_MEDIA_TO_DISPLAY=10;this.uploadText=_t("Upload an image");this.urlPlaceholder="https://www.odoo.com/logo.png";this.addText=_t("Add URL");this.searchPlaceholder=_t("Search an image");this.urlWarningTitle=_t("Uploaded image's format is not supported. Try with: "+IMAGE_EXTENSIONS.join(', '));this.allLoadedText=_t("All images have been loaded");this.showOptimizedOption=this.env.debug;this.MIN_ROW_HEIGHT=128;this.fileMimetypes=IMAGE_MIMETYPES.join(',');this.isImageField=!!(this.props.media&&this.props.media.closest("[data-oe-type=image]"))||!!this.env.addFieldImage;} get canLoadMore(){if(this.state.searchService==='media-library'){return this.state.libraryResults&&this.state.libraryMedia.lengthmedia.mediaType==='libraryMedia').map(({id})=>id);} get allAttachments(){return[...super.allAttachments,...this.state.libraryMedia];} get attachmentsDomain(){const domain=super.attachmentsDomain;domain.push(['mimetype','in',IMAGE_MIMETYPES]);if(!this.props.useMediaLibrary){domain.push("|",["url","=",false],"!","|",["url","=ilike","/html_editor/shape/%"],["url","=ilike","/web_editor/shape/%"],);} domain.push('!',['name','=like','%.crop']);domain.push('|',['type','=','binary'],'!',['url','=like','/%/static/%']);if(!this.env.debug){const subDomain=[false];const originalId=this.props.media&&this.props.media.dataset.originalId;if(originalId){subDomain.push(originalId);} domain.push(['original_id','in',subDomain]);} return domain;} async uploadFiles(files){await this.uploadService.uploadFiles(files,{resModel:this.props.resModel,resId:this.props.resId,isImage:true},(attachment)=>this.onUploaded(attachment));} async uploadUrl(url){await fetch(url).then(async result=>{const blob=await result.blob();blob.id=new Date().getTime();blob.name=new URL(url,window.location.href).pathname.split("/").findLast(s=>s);await this.uploadFiles([blob]);}).catch(async()=>{await new Promise(resolve=>{const imageEl=document.createElement("img");imageEl.onerror=()=>{this.notificationService.add(_t("An error occurred while fetching the entered URL."),{title:_t("Error"),sticky:true,});resolve();};imageEl.onload=()=>{const urlPathname=new URL(url,window.location.href).pathname;const imageExtension=IMAGE_EXTENSIONS.find(format=>urlPathname.endsWith(format));if(this.isImageField&&imageExtension===".webp"){this.notificationService.add(_t("You can not replace a field by this image. If you want to use this image, first save it on your computer and then upload it here."),{title:_t("Error"),sticky:true,});return resolve();} super.uploadUrl(url).then(resolve);};imageEl.src=url;});});} async validateUrl(...args){const{isValidUrl,path}=super.validateUrl(...args);const isValidFileFormat=isValidUrl&&await new Promise(resolve=>{const img=new Image();img.src=path;img.onload=()=>resolve(true);img.onerror=()=>resolve(false);});return{isValidUrl,isValidFileFormat};} isInitialMedia(attachment){if(this.props.media.dataset.originalSrc){return this.props.media.dataset.originalSrc===attachment.image_src;} return this.props.media.getAttribute('src')===attachment.image_src;} async fetchAttachments(limit,offset){const attachments=await super.fetchAttachments(limit,offset);if(this.isImageField){for(const attachment of attachments){if(attachment.mimetype==="image/webp"&&await weUtils.isSrcCorsProtected(attachment.image_src)){attachment.unselectable=true;}}} const primaryColors={};for(let color=1;color<=5;color++){primaryColors[color]=weUtils.getCSSVariableValue('o-color-'+color);} return attachments.map(attachment=>{if(attachment.image_src.startsWith('/')){const newURL=new URL(attachment.image_src,window.location.origin);if(attachment.image_src.startsWith('/html_editor/shape/')||attachment.image_src.startsWith('/web_editor/shape/')){newURL.searchParams.forEach((value,key)=>{const match=key.match(/^c([1-5])$/);if(match){newURL.searchParams.set(key,primaryColors[match[1]]);}});}else{newURL.searchParams.set('height',2*this.MIN_ROW_HEIGHT);} attachment.thumbnail_src=newURL.pathname+newURL.search;} if(this.selectInitialMedia()&&this.isInitialMedia(attachment)){this.selectAttachment(attachment);} return attachment;});} async fetchLibraryMedia(offset){if(!this.state.needle){return{media:[],results:null};} this.state.isFetchingLibrary=true;try{const response=await rpc('/web_editor/media_library_search',{'query':this.state.needle,'offset':offset,},{silent:true,});this.state.isFetchingLibrary=false;const media=(response.media||[]).slice(0,this.NUMBER_OF_MEDIA_TO_DISPLAY);media.forEach(record=>record.mediaType='libraryMedia');return{media,results:response.results};}catch{console.error(`Couldn't reach API endpoint.`);this.state.isFetchingLibrary=false;return{media:[],results:null};}} async loadMore(...args){await super.loadMore(...args);if(!this.props.useMediaLibrary||this.state.searchService!=='media-library'){return;} return this.keepLastLibraryMedia.add(this.fetchLibraryMedia(this.state.libraryMedia.length)).then(({media})=>{this.state.libraryMedia.push(...media);});} async search(...args){await super.search(...args);if(!this.props.useMediaLibrary){return;} if(!this.state.needle){this.state.searchService='all';} this.state.libraryMedia=[];this.state.libraryResults=0;return this.keepLastLibraryMedia.add(this.fetchLibraryMedia(0)).then(({media,results})=>{this.state.libraryMedia=media;this.state.libraryResults=results;});} async onClickAttachment(attachment){if(attachment.unselectable){this.notificationService.add(_t("You can not replace a field by this image. If you want to use this image, first save it on your computer and then upload it here."),{title:_t("Error"),sticky:true,});return;} this.selectAttachment(attachment);if(!this.props.multiSelect){await this.props.save();}} async onClickMedia(media){this.props.selectMedia({...media,mediaType:'libraryMedia'});if(!this.props.multiSelect){await this.props.save();}} static async createElements(selectedMedia,{orm}){const toSave=Object.fromEntries(selectedMedia.filter(media=>media.mediaType==='libraryMedia').map(media=>[media.id,{query:media.query||'',is_dynamic_svg:!!media.isDynamicSVG,dynamic_colors:media.dynamicColors,}]));let savedMedia=[];if(Object.keys(toSave).length!==0){savedMedia=await rpc('/web_editor/save_library_media',{media:toSave});} const selected=selectedMedia.filter(media=>media.mediaType==='attachment').concat(savedMedia).map(attachment=>{if(attachment.image_src&&(attachment.image_src.startsWith('/html_editor/shape/')||attachment.image_src.startsWith('/web_editor/shape/'))){const colorCustomizedURL=new URL(attachment.image_src,window.location.origin);colorCustomizedURL.searchParams.forEach((value,key)=>{const match=key.match(/^c([1-5])$/);if(match){colorCustomizedURL.searchParams.set(key,weUtils.getCSSVariableValue(`o-color-${match[1]}`));}});attachment.image_src=colorCustomizedURL.pathname+colorCustomizedURL.search;} return attachment;});return Promise.all(selected.map(async(attachment)=>{const imageEl=document.createElement('img');let src=attachment.image_src;if(!attachment.public&&!attachment.url){let accessToken=attachment.access_token;if(!accessToken){[accessToken]=await orm.call('ir.attachment','generate_access_token',[attachment.id],);} src+=`?access_token=${encodeURIComponent(accessToken)}`;} imageEl.src=src;imageEl.alt=attachment.description||'';return imageEl;}));} async onImageLoaded(imgEl,attachment){this.debouncedScrollUpdate();if(attachment.mediaType==='libraryMedia'&&!imgEl.src.startsWith('blob')){await this.onLibraryImageLoaded(imgEl,attachment);}} async onLibraryImageLoaded(imgEl,media){const mediaUrl=imgEl.src;try{const response=await fetch(mediaUrl);const contentType=response.headers.get("content-type");if(contentType&&contentType.startsWith("image/svg+xml")){let svg=await response.text();const dynamicColors={};const combinedColorsRegex=new RegExp(Object.values(weUtils.DEFAULT_PALETTE).join('|'),'gi');svg=svg.replace(combinedColorsRegex,match=>{const colorId=Object.keys(weUtils.DEFAULT_PALETTE).find(key=>weUtils.DEFAULT_PALETTE[key]===match.toUpperCase());const colorKey='c'+colorId dynamicColors[colorKey]=weUtils.getCSSVariableValue('o-color-'+colorId);return dynamicColors[colorKey];});const fileName=mediaUrl.split('/').pop();const file=new File([svg],fileName,{type:"image/svg+xml",});imgEl.src=URL.createObjectURL(file);if(Object.keys(dynamicColors).length){media.isDynamicSVG=true;media.dynamicColors=dynamicColors;}}}catch{console.error('CORS is misconfigured on the API server, image will be treated as non-dynamic.');}}} return __exports;});; /* /web_editor/static/src/components/media_dialog/media_dialog.js */ odoo.define('@web_editor/components/media_dialog/media_dialog',['@web/core/l10n/translation','@web/core/utils/hooks','@web/core/utils/concurrency','@web/core/dialog/dialog','@web/core/notebook/notebook','@web_editor/components/media_dialog/image_selector','@web_editor/components/media_dialog/document_selector','@web_editor/components/media_dialog/icon_selector','@web_editor/components/media_dialog/video_selector','@odoo/owl'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{useService,useChildRef}=require('@web/core/utils/hooks');const{Mutex}=require("@web/core/utils/concurrency");const{Dialog}=require('@web/core/dialog/dialog');const{Notebook}=require('@web/core/notebook/notebook');const{ImageSelector}=require("@web_editor/components/media_dialog/image_selector");const{DocumentSelector}=require("@web_editor/components/media_dialog/document_selector");const{IconSelector}=require("@web_editor/components/media_dialog/icon_selector");const{VideoSelector}=require("@web_editor/components/media_dialog/video_selector");const{Component,useState,useRef,useEffect}=require("@odoo/owl");const TABS=__exports.TABS={IMAGES:{id:'IMAGES',title:_t("Images"),Component:ImageSelector,},DOCUMENTS:{id:'DOCUMENTS',title:_t("Documents"),Component:DocumentSelector,},ICONS:{id:'ICONS',title:_t("Icons"),Component:IconSelector,},VIDEOS:{id:'VIDEOS',title:_t("Videos"),Component:VideoSelector,},};const MediaDialog=__exports.MediaDialog=class MediaDialog extends Component{static template="web_editor.MediaDialog";static defaultProps={useMediaLibrary:true,};static components={...Object.keys(TABS).map((key)=>TABS[key].Component),Dialog,Notebook,};static props=["*"];setup(){this.size='xl';this.contentClass='o_select_media_dialog h-100';this.modalRef=useChildRef();this.orm=useService('orm');this.notificationService=useService('notification');this.mutex=new Mutex();this.tabs=[];this.selectedMedia=useState({});this.addButtonRef=useRef('add-button');this.initialIconClasses=[];this.addTabs();this.errorMessages={};this.state=useState({activeTab:this.initialActiveTab,});useEffect((nbSelectedAttachments)=>{this.addButtonRef.el.toggleAttribute("disabled",!nbSelectedAttachments);},()=>[this.selectedMedia[this.state.activeTab].length]);} get initialActiveTab(){if(this.props.activeTab){return this.props.activeTab;} if(this.props.media){const correspondingTab=Object.keys(TABS).find(id=>TABS[id].Component.tagNames.includes(this.props.media.tagName));if(correspondingTab){return correspondingTab;}} return this.tabs[0].id;} addTab(tab,additionalProps={}){this.selectedMedia[tab.id]=[];this.tabs.push({...tab,props:{...tab.props,...additionalProps,id:tab.id,resModel:this.props.resModel,resId:this.props.resId,media:this.props.media,multiImages:this.props.multiImages,selectedMedia:this.selectedMedia,selectMedia:(...args)=>this.selectMedia(...args,tab.id,additionalProps.multiSelect),save:this.save.bind(this),onAttachmentChange:this.props.onAttachmentChange,errorMessages:(errorMessage)=>this.errorMessages[tab.id]=errorMessage,modalRef:this.modalRef,},});} addTabs(){const onlyImages=this.props.onlyImages||this.props.multiImages||(this.props.media&&this.props.media.parentElement&&(this.props.media.parentElement.dataset.oeField==='image'||this.props.media.parentElement.dataset.oeType==='image'));const noDocuments=onlyImages||this.props.noDocuments;const noIcons=onlyImages||this.props.noIcons;const noVideos=onlyImages||this.props.noVideos;if(!this.props.noImages){this.addTab(TABS.IMAGES,{useMediaLibrary:this.props.useMediaLibrary,multiSelect:this.props.multiImages,});} if(!noDocuments){this.addTab(TABS.DOCUMENTS);} if(!noIcons){const fonts=TABS.ICONS.Component.initFonts();this.addTab(TABS.ICONS,{fonts,});if(this.props.media&&TABS.ICONS.Component.tagNames.includes(this.props.media.tagName)){const classes=this.props.media.className.split(/\s+/);const mediaFont=fonts.find(font=>classes.includes(font.base));if(mediaFont){const selectedIcon=mediaFont.icons.find(icon=>icon.names.some(name=>classes.includes(name)));if(selectedIcon){this.initialIconClasses.push(...selectedIcon.names);this.selectMedia(selectedIcon,TABS.ICONS.id);}}}} if(!noVideos){this.addTab(TABS.VIDEOS,{vimeoPreviewIds:this.props.vimeoPreviewIds,isForBgVideo:this.props.isForBgVideo,});}} async renderMedia(selectedMedia){const elements=await this.mutex.exec(async()=>await TABS[this.state.activeTab].Component.createElements(selectedMedia,{orm:this.orm}));elements.forEach(element=>{if(this.props.media){element.classList.add(...this.props.media.classList);const style=this.props.media.getAttribute('style');if(style){element.setAttribute('style',style);} if(this.state.activeTab===TABS.IMAGES.id){if(this.props.media.dataset.shape){element.dataset.shape=this.props.media.dataset.shape;} if(this.props.media.dataset.shapeColors){element.dataset.shapeColors=this.props.media.dataset.shapeColors;} if(this.props.media.dataset.shapeFlip){element.dataset.shapeFlip=this.props.media.dataset.shapeFlip;} if(this.props.media.dataset.shapeRotate){element.dataset.shapeRotate=this.props.media.dataset.shapeRotate;} if(this.props.media.dataset.hoverEffect){element.dataset.hoverEffect=this.props.media.dataset.hoverEffect;} if(this.props.media.dataset.hoverEffectColor){element.dataset.hoverEffectColor=this.props.media.dataset.hoverEffectColor;} if(this.props.media.dataset.hoverEffectStrokeWidth){element.dataset.hoverEffectStrokeWidth=this.props.media.dataset.hoverEffectStrokeWidth;} if(this.props.media.dataset.hoverEffectIntensity){element.dataset.hoverEffectIntensity=this.props.media.dataset.hoverEffectIntensity;} if(this.props.media.dataset.shapeAnimationSpeed){element.dataset.shapeAnimationSpeed=this.props.media.dataset.shapeAnimationSpeed;}}else if([TABS.VIDEOS.id,TABS.DOCUMENTS.id].includes(this.state.activeTab)){const parentEl=this.props.media.parentElement;if(parentEl&&parentEl.tagName==="A"&&parentEl.children.length===1&&this.props.media.tagName==="IMG"){parentEl.replaceWith(parentEl.firstElementChild);}}} for(const otherTab of Object.keys(TABS).filter(key=>key!==this.state.activeTab)){for(const property of TABS[otherTab].Component.mediaSpecificStyles){element.style.removeProperty(property);} element.classList.remove(...TABS[otherTab].Component.mediaSpecificClasses);const extraClassesToRemove=[];for(const name of TABS[otherTab].Component.mediaExtraClasses){if(typeof(name)==='string'){extraClassesToRemove.push(name);}else{for(const className of element.classList){if(className.match(name)){extraClassesToRemove.push(className);}}}} element.classList.remove(...extraClassesToRemove.filter(candidateName=>{for(const name of TABS[this.state.activeTab].Component.mediaExtraClasses){if(typeof(name)==='string'){if(candidateName===name){return false;}}else{for(const className of element.classList){if(className.match(candidateName)){return false;}}}} return true;}));} element.classList.remove(...this.initialIconClasses);element.classList.remove('o_modified_image_to_save');element.classList.remove('oe_edited_link');element.classList.add(...TABS[this.state.activeTab].Component.mediaSpecificClasses);});return elements;} selectMedia(media,tabId,multiSelect){if(multiSelect){const isMediaSelected=this.selectedMedia[tabId].map(({id})=>id).includes(media.id);if(!isMediaSelected){this.selectedMedia[tabId].push(media);}else{this.selectedMedia[tabId]=this.selectedMedia[tabId].filter(m=>m.id!==media.id);}}else{this.selectedMedia[tabId]=[media];}} async save(){if(this.errorMessages[this.state.activeTab]){this.notificationService.add(this.errorMessages[this.state.activeTab],{type:'danger',});return;} const selectedMedia=this.selectedMedia[this.state.activeTab];const saveSelectedMedia=selectedMedia.length&&(this.state.activeTab!==TABS.ICONS.id||selectedMedia[0].initialIconChanged||!this.props.media);if(saveSelectedMedia){const elements=await this.renderMedia(selectedMedia);if(this.props.multiImages){await this.props.save(elements);}else{await this.props.save(elements[0]);}} this.props.close();} onTabChange(tab){this.state.activeTab=tab;}} return __exports;});; /* /web_editor/static/src/components/media_dialog/search_media.js */ odoo.define('@web_editor/components/media_dialog/search_media',['@web/core/utils/timing','@web/core/utils/hooks','@odoo/owl'],function(require){'use strict';let __exports={};const{useDebounced}=require('@web/core/utils/timing');const{useAutofocus}=require('@web/core/utils/hooks');const{Component,xml,useEffect,useState}=require("@odoo/owl");const SearchMedia=__exports.SearchMedia=class SearchMedia extends Component{static template=xml`
`;static props=["searchPlaceholder","search","needle"];setup(){useAutofocus();this.debouncedSearch=useDebounced(this.props.search,1000);this.state=useState({input:this.props.needle||'',});useEffect((input)=>{if(this.hasRendered){this.debouncedSearch(input);}else{this.hasRendered=true;}},()=>[this.state.input]);}} return __exports;});; /* /web_editor/static/src/components/media_dialog/video_selector.js */ odoo.define('@web_editor/components/media_dialog/video_selector',['@web/core/l10n/translation','@web/core/network/rpc','@web/core/utils/hooks','@web/core/utils/timing','@odoo/owl'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{rpc}=require("@web/core/network/rpc");const{useAutofocus,useService}=require('@web/core/utils/hooks');const{debounce}=require('@web/core/utils/timing');const{Component,useState,useRef,onMounted,onWillStart}=require("@odoo/owl");class VideoOption extends Component{static template="web_editor.VideoOption";static props={description:{type:String,optional:true},label:{type:String,optional:true},onChangeOption:Function,value:{type:Boolean,optional:true},};} class VideoIframe extends Component{static template="web_editor.VideoIframe";static props={src:{type:String},};} const VideoSelector=__exports.VideoSelector=class VideoSelector extends Component{static mediaSpecificClasses=["media_iframe_video"];static mediaSpecificStyles=[];static mediaExtraClasses=[];static tagNames=["IFRAME","DIV"];static template="web_editor.VideoSelector";static components={VideoIframe,VideoOption,};static props={selectMedia:Function,errorMessages:Function,vimeoPreviewIds:{type:Array,optional:true},isForBgVideo:{type:Boolean,optional:true},media:{type:Object,optional:true},"*":true,};static defaultProps={vimeoPreviewIds:[],isForBgVideo:false,};setup(){this.http=useService('http');this.PLATFORMS={youtube:'youtube',dailymotion:'dailymotion',vimeo:'vimeo',youku:'youku',};this.OPTIONS={autoplay:{label:_t("Autoplay"),description:_t("Videos are muted when autoplay is enabled"),platforms:[this.PLATFORMS.youtube,this.PLATFORMS.dailymotion,this.PLATFORMS.vimeo],urlParameter:'autoplay=1',},loop:{label:_t("Loop"),platforms:[this.PLATFORMS.youtube,this.PLATFORMS.vimeo],urlParameter:'loop=1',},hide_controls:{label:_t("Hide player controls"),platforms:[this.PLATFORMS.youtube,this.PLATFORMS.dailymotion,this.PLATFORMS.vimeo],urlParameter:'controls=0',},hide_fullscreen:{label:_t("Hide fullscreen button"),platforms:[this.PLATFORMS.youtube],urlParameter:'fs=0',isHidden:()=>this.state.options.filter(option=>option.id==='hide_controls')[0].value,},hide_dm_logo:{label:_t("Hide Dailymotion logo"),platforms:[this.PLATFORMS.dailymotion],urlParameter:'ui-logo=0',},hide_dm_share:{label:_t("Hide sharing button"),platforms:[this.PLATFORMS.dailymotion],urlParameter:'sharing-enable=0',},};this.state=useState({options:[],src:'',urlInput:'',platform:null,vimeoPreviews:[],errorMessage:'',});this.urlInputRef=useRef('url-input');onWillStart(async()=>{if(this.props.media){const src=this.props.media.dataset.oeExpression||this.props.media.dataset.src||(this.props.media.tagName==='IFRAME'&&this.props.media.getAttribute('src'))||'';if(src){this.state.urlInput=src;await this.updateVideo();this.state.options=this.state.options.map((option)=>{const{urlParameter}=this.OPTIONS[option.id];return{...option,value:src.indexOf(urlParameter)>=0};});}}});onMounted(async()=>this.prepareVimeoPreviews());useAutofocus();this.onChangeUrl=debounce((ev)=>this.updateVideo(ev.target.value),500);} get shownOptions(){if(this.props.isForBgVideo){return[];} return this.state.options.filter(option=>!this.OPTIONS[option.id].isHidden||!this.OPTIONS[option.id].isHidden());} async onChangeOption(optionId){this.state.options=this.state.options.map(option=>{if(option.id===optionId){return{...option,value:!option.value};} return option;});await this.updateVideo();} async onClickSuggestion(src){this.state.urlInput=src;await this.updateVideo();} async updateVideo(){if(!this.state.urlInput){this.state.src='';this.state.urlInput='';this.state.options=[];this.state.platform=null;this.state.errorMessage='';this.props.selectMedia({});return;} const embedMatch=this.state.urlInput.match(/(src|href)=["']?([^"']+)?/);if(embedMatch&&embedMatch[2].length>0&&embedMatch[2].indexOf('instagram')){embedMatch[1]=embedMatch[2];} const url=embedMatch?embedMatch[1]:this.state.urlInput;const options={};if(this.props.isForBgVideo){Object.keys(this.OPTIONS).forEach(key=>{options[key]=true;});}else{for(const option of this.shownOptions){options[option.id]=option.value;}} const{embed_url:src,video_id:videoId,params,platform}=await this._getVideoURLData(url,options);if(!src){this.state.errorMessage=_t("The provided url is not valid");}else if(!platform){this.state.errorMessage=_t("The provided url does not reference any supported video");}else{this.state.errorMessage='';} this.props.errorMessages(this.state.errorMessage);const newOptions=[];if(platform&&platform!==this.state.platform){Object.keys(this.OPTIONS).forEach(key=>{if(this.OPTIONS[key].platforms.includes(platform)){const{label,description}=this.OPTIONS[key];newOptions.push({id:key,label,description});}});} this.state.src=src;this.props.selectMedia({id:src,src,platform,videoId,params});if(platform!==this.state.platform){this.state.platform=platform;this.state.options=newOptions;}} async _getVideoURLData(url,options){return await rpc('/web_editor/video_url/data',{video_url:url,...options,});} static createElements(selectedMedia){return selectedMedia.map(video=>{const div=document.createElement('div');div.dataset.oeExpression=video.src;div.innerHTML=`
`;div.querySelector('iframe').src=video.src;return div;});} async prepareVimeoPreviews(){return Promise.all(this.props.vimeoPreviewIds.map(async(videoId)=>{const{thumbnail_url:thumbnailSrc}=await this.http.get(`https://vimeo.com/api/oembed.json?url=http%3A//vimeo.com/${encodeURIComponent(videoId)}`);this.state.vimeoPreviews.push({id:videoId,thumbnailSrc,src:`https://player.vimeo.com/video/${encodeURIComponent(videoId)}`});}));}} return __exports;});; /* /web_editor/static/src/components/upload_progress_toast/upload_progress_toast.js */ odoo.define('@web_editor/components/upload_progress_toast/upload_progress_toast',['@web/core/utils/hooks','@odoo/owl'],function(require){'use strict';let __exports={};const{useService}=require('@web/core/utils/hooks');const{Component,useState}=require("@odoo/owl");const ProgressBar=__exports.ProgressBar=class ProgressBar extends Component{static template="web_editor.ProgressBar";static props={progress:{type:Number,optional:true},hasError:{type:Boolean,optional:true},uploaded:{type:Boolean,optional:true},name:String,size:{type:String,optional:true},errorMessage:{type:String,optional:true},};static defaultProps={progress:0,hasError:false,uploaded:false,size:"",errorMessage:"",};get progress(){return Math.round(this.props.progress);}} const UploadProgressToast=__exports.UploadProgressToast=class UploadProgressToast extends Component{static template="web_editor.UploadProgressToast";static components={ProgressBar,};static props={close:Function,};setup(){this.uploadService=useService('upload');this.state=useState(this.uploadService.progressToast);}} return __exports;});; /* /web_editor/static/src/components/upload_progress_toast/upload_service.js */ odoo.define('@web_editor/components/upload_progress_toast/upload_service',['@web/core/network/rpc','@web/core/registry','@web_editor/components/upload_progress_toast/upload_progress_toast','@web/core/l10n/translation','@web/core/utils/files','@web/core/utils/numbers','@web/core/utils/urls','@web/core/utils/strings','@odoo/owl'],function(require){'use strict';let __exports={};const{rpc}=require('@web/core/network/rpc');const{registry}=require('@web/core/registry');const{UploadProgressToast}=require("@web_editor/components/upload_progress_toast/upload_progress_toast");const{_t}=require("@web/core/l10n/translation");const{checkFileSize}=require("@web/core/utils/files");const{humanNumber}=require("@web/core/utils/numbers");const{getDataURLFromFile}=require("@web/core/utils/urls");const{sprintf}=require("@web/core/utils/strings");const{reactive}=require("@odoo/owl");const AUTOCLOSE_DELAY=__exports.AUTOCLOSE_DELAY=3000;const AUTOCLOSE_DELAY_LONG=__exports.AUTOCLOSE_DELAY_LONG=8000;const uploadService=__exports.uploadService={dependencies:['notification'],start(env,{notification}){let fileId=0;const progressToast=reactive({files:{},isVisible:false,});registry.category('main_components').add('UploadProgressToast',{Component:UploadProgressToast,props:{close:()=>progressToast.isVisible=false,}});const addFile=(file)=>{progressToast.files[file.id]=file;progressToast.isVisible=true;return progressToast.files[file.id];};const deleteFile=(fileId)=>{delete progressToast.files[fileId];if(!Object.keys(progressToast.files).length){progressToast.isVisible=false;}};return{get progressToast(){return progressToast;},get fileId(){return fileId;},addFile,deleteFile,incrementId(){fileId++;},uploadUrl:async(url,{resModel,resId},onUploaded)=>{const attachment=await rpc('/web_editor/attachment/add_url',{url,'res_model':resModel,'res_id':resId,});await onUploaded(attachment);},uploadFiles:async(files,{resModel,resId,isImage},onUploaded)=>{const sortedFiles=Array.from(files).sort((a,b)=>a.size-b.size);for(const file of sortedFiles){let fileSize=file.size;if(!checkFileSize(fileSize,notification)){return null;} if(!fileSize){fileSize="";}else{fileSize=humanNumber(fileSize)+"B";} const id=++fileId;file.progressToastId=id;addFile({id,name:file.name,size:fileSize,});} for(const sortedFile of sortedFiles){const file=progressToast.files[sortedFile.progressToastId];let dataURL;try{dataURL=await getDataURLFromFile(sortedFile);}catch{deleteFile(file.id);env.services.notification.add(sprintf(_t('Could not load the file "%s".'),sortedFile.name),{type:'danger'});continue} try{const xhr=new XMLHttpRequest();xhr.upload.addEventListener('progress',ev=>{const rpcComplete=ev.loaded/ev.total*100;file.progress=rpcComplete;});xhr.upload.addEventListener('load',function(){file.progress=100;});const attachment=await rpc('/web_editor/attachment/add_data',{'name':file.name,'data':dataURL.split(',')[1],'res_id':resId,'res_model':resModel,'is_image':!!isImage,'width':0,'quality':0,},{xhr});if(attachment.error){file.hasError=true;file.errorMessage=attachment.error;}else{if(attachment.mimetype==='image/webp'){const image=document.createElement('img');image.src=`data:image/webp;base64,${dataURL.split(',')[1]}`;await new Promise(resolve=>image.addEventListener('load',resolve));const canvas=document.createElement('canvas');canvas.width=image.width;canvas.height=image.height;const ctx=canvas.getContext('2d');ctx.fillStyle='rgb(255, 255, 255)';ctx.fillRect(0,0,canvas.width,canvas.height);ctx.drawImage(image,0,0);const altDataURL=canvas.toDataURL('image/jpeg',0.75);await rpc('/web_editor/attachment/add_data',{'name':file.name.replace(/\.webp$/,'.jpg'),'data':altDataURL.split(',')[1],'res_id':attachment.id,'res_model':'ir.attachment','is_image':true,'width':0,'quality':0,},{xhr});} file.uploaded=true;await onUploaded(attachment);} let message_autoclose_delay=file.hasError?AUTOCLOSE_DELAY_LONG:AUTOCLOSE_DELAY;setTimeout(()=>deleteFile(file.id),message_autoclose_delay);}catch(error){file.hasError=true;setTimeout(()=>deleteFile(file.id),AUTOCLOSE_DELAY_LONG);throw error;}}}};},};return __exports;});; /* /website/static/src/components/media_dialog/file_documents_selector.js */ odoo.define('@website/components/media_dialog/file_documents_selector',['@web/core/utils/patch','@html_editor/main/media/media_dialog/file_documents_selector'],function(require){'use strict';let __exports={};const{patch}=require("@web/core/utils/patch");const{FileDocumentsSelector}=require("@html_editor/main/media/media_dialog/file_documents_selector");patch(FileDocumentsSelector.prototype,{get attachmentsDomain(){const domain=super.attachmentsDomain;domain.push("|",["url","=",false],"!",["url","=like","/web/image/website.%"]);domain.push(["key","=",false]);return domain;},});return __exports;});; /* /website/static/src/components/media_dialog/image_selector.js */ odoo.define('@website/components/media_dialog/image_selector',['@web/core/utils/patch','@web_editor/components/media_dialog/image_selector','@html_editor/main/media/media_dialog/image_selector'],function(require){'use strict';let __exports={};const{patch}=require("@web/core/utils/patch");const{ImageSelector}=require('@web_editor/components/media_dialog/image_selector');const{ImageSelector:HtmlImageSelector}=require("@html_editor/main/media/media_dialog/image_selector");patch(ImageSelector.prototype,{get attachmentsDomain(){const domain=super.attachmentsDomain;domain.push('|',['url','=',false],'!',['url','=like','/web/image/website.%']);domain.push(['key','=',false]);return domain;}});patch(HtmlImageSelector.prototype,{get attachmentsDomain(){const domain=super.attachmentsDomain;domain.push('|',['url','=',false],'!',['url','=like','/web/image/website.%']);domain.push(['key','=',false]);return domain;}});return __exports;});; /* /web_unsplash/static/src/media_dialog_legacy/image_selector.js */ odoo.define('@web_unsplash/media_dialog_legacy/image_selector',['@web/core/l10n/translation','@web/core/utils/patch','@web/core/utils/concurrency','@web_editor/components/media_dialog/media_dialog','@web_editor/components/media_dialog/image_selector','@web/core/network/rpc','@web/core/utils/hooks','@web_unsplash/unsplash_error/unsplash_error'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{patch}=require("@web/core/utils/patch");const{KeepLast}=require("@web/core/utils/concurrency");const{MediaDialog,TABS}=require("@web_editor/components/media_dialog/media_dialog");const{ImageSelector}=require("@web_editor/components/media_dialog/image_selector");const{rpc}=require("@web/core/network/rpc");const{useService}=require("@web/core/utils/hooks");const{UnsplashError}=require("@web_unsplash/unsplash_error/unsplash_error");patch(ImageSelector.prototype,{setup(){super.setup();this.unsplash=useService('unsplash');this.keepLastUnsplash=new KeepLast();this.state.unsplashRecords=[];this.state.isFetchingUnsplash=false;this.state.isMaxed=false;this.state.unsplashError=null;this.state.useUnsplash=true;this.NUMBER_OF_RECORDS_TO_DISPLAY=30;this.errorMessages={'key_not_found':{title:_t("Setup Unsplash to access royalty free photos."),subtitle:"",},401:{title:_t("Unauthorized Key"),subtitle:_t("Please check your Unsplash access key and application ID."),},403:{title:_t("Search is temporarily unavailable"),subtitle:_t("The max number of searches is exceeded. Please retry in an hour or extend to a better account."),},};},get canLoadMore(){if(this.state.searchService==='all'){return super.canLoadMore||this.state.needle&&!this.state.isMaxed&&!this.state.unsplashError;}else if(this.state.searchService==='unsplash'){return this.state.needle&&!this.state.isMaxed&&!this.state.unsplashError;} return super.canLoadMore;},get hasContent(){if(this.state.searchService==='all'){return super.hasContent||!!this.state.unsplashRecords.length;}else if(this.state.searchService==='unsplash'){return!!this.state.unsplashRecords.length;} return super.hasContent;},get errorTitle(){if(this.errorMessages[this.state.unsplashError]){return this.errorMessages[this.state.unsplashError].title;} return _t("Something went wrong");},get errorSubtitle(){if(this.errorMessages[this.state.unsplashError]){return this.errorMessages[this.state.unsplashError].subtitle;} return _t("Please check your internet connection or contact administrator.");},get selectedRecordIds(){return this.props.selectedMedia[this.props.id].filter(media=>media.mediaType==='unsplashRecord').map(({id})=>id);},get isFetching(){return super.isFetching||this.state.isFetchingUnsplash;},get combinedRecords(){function alternate(a,b){return[a.map((v,i)=>iexisting.id);const newImages=images.filter(record=>!existingIds.includes(record.id));const records=newImages.map(record=>{const url=new URL(record.urls.regular);url.searchParams.set('h',2*this.MIN_ROW_HEIGHT);url.searchParams.delete('w');return Object.assign({},record,{url:url.toString(),mediaType:'unsplashRecord',});});return{isMaxed,records};}catch(e){this.state.isFetchingUnsplash=false;if(e==='no_access'){this.state.useUnsplash=false;}else{this.state.unsplashError=e;} return{records:[],isMaxed:true};}},async loadMore(...args){await super.loadMore(...args);return this.keepLastUnsplash.add(this.fetchUnsplashRecords(this.state.unsplashRecords.length)).then(({records,isMaxed})=>{this.state.unsplashRecords.push(...records);this.state.isMaxed=isMaxed;});},async search(...args){await super.search(...args);await this.searchUnsplash();},async searchUnsplash(){if(!this.state.needle){this.state.unsplashError=false;this.state.unsplashRecords=[];this.state.isMaxed=false;} return this.keepLastUnsplash.add(this.fetchUnsplashRecords(0)).then(({records,isMaxed})=>{this.state.unsplashRecords=records;this.state.isMaxed=isMaxed;});},async onClickRecord(media){this.props.selectMedia({...media,mediaType:'unsplashRecord',query:this.state.needle});if(!this.props.multiSelect){await this.props.save();}},async submitCredentials(key,appId){this.state.unsplashError=null;await rpc('/web_unsplash/save_unsplash',{key,appId});await this.searchUnsplash();},});ImageSelector.components={...ImageSelector.components,UnsplashError,};patch(MediaDialog.prototype,{setup(){super.setup();this.unsplashService=useService('unsplash');},async save(){const selectedImages=this.selectedMedia[TABS.IMAGES.id];if(selectedImages){const unsplashRecords=selectedImages.filter(media=>media.mediaType==='unsplashRecord');if(unsplashRecords.length){await this.unsplashService.uploadUnsplashRecords(unsplashRecords,{resModel:this.props.resModel,resId:this.props.resId},(attachments)=>{this.selectedMedia[TABS.IMAGES.id]=this.selectedMedia[TABS.IMAGES.id].filter(media=>media.mediaType!=='unsplashRecord');this.selectedMedia[TABS.IMAGES.id]=this.selectedMedia[TABS.IMAGES.id].concat(attachments.map(attachment=>({...attachment,mediaType:'attachment'})));});}} return super.save(...arguments);},});return __exports;});; /* /web_editor/static/src/js/common/browser_extensions.js */ odoo.define('@web_editor/js/common/browser_extensions',[],function(require){'use strict';let __exports={};const originalGetRangeAt=Selection.prototype.getRangeAt;Selection.prototype.getRangeAt=function(){let range=originalGetRangeAt.apply(this,arguments);if(range.startContainer&&!Object.getPrototypeOf(range.startContainer)){range=document.createRange();range.setStart(this.anchorNode,0);range.setEnd(this.focusNode,0);} return range;};return __exports;});; /* /web_editor/static/src/js/common/column_layout_mixin.js */ odoo.define('@web_editor/js/common/column_layout_mixin',[],function(require){'use strict';let __exports={};const ColumnLayoutMixin=__exports.ColumnLayoutMixin={_getNbColumns(columnEls,isMobile){if(!columnEls){return 0;} if(this._areColsCustomized(columnEls,isMobile)){return"custom";} const resolutionModifier=isMobile?"":"lg-";const colRegex=new RegExp(`(?:^|\\s+)col-${resolutionModifier}(\\d{1,2})(?!\\S)`);const colSize=parseInt(columnEls[0].className.match(colRegex)?.[1]||12);const offsetSize=this._getFirstItem(columnEls,isMobile).classList.contains(`offset-${resolutionModifier}1`)?1:0;return Math.floor((12-offsetSize)/colSize);},_getFirstItem(columnEls,isMobile){return isMobile&&[...columnEls].find(el=>el.style.order==="0")||columnEls[0];},_addMobileOrders(columnEls){for(let i=0;iparseInt(columnEl.className.match(colRegex)?.[1]||12)===colSize);if(!allColsSizesEqual){return true;} const offsetRegex=new RegExp(`(?:^|\\s+)offset-${resolutionModifier}[1-9][0-1]?(?!\\S)`);const nbOffsets=[...columnEls].filter((columnEl)=>columnEl.className.match(offsetRegex)).length;if(nbOffsets===0){return false;} if(nbOffsets===1&&colSize===2&&this._getFirstItem(columnEls,isMobile).className.match(`offset-${resolutionModifier}1`)){return false;} return true;},_fillRemovedItemGap(parentEl,itemOrder){[...parentEl.children].forEach(el=>{const elOrder=parseInt(el.style.order);if(elOrder>itemOrder){el.style.order=elOrder-1;}});},};return __exports;});; /* /web_editor/static/src/js/common/grid_layout_utils.js */ odoo.define('@web_editor/js/common/grid_layout_utils',['@web/core/utils/render','@web_editor/js/editor/odoo-editor/src/utils/utils'],function(require){'use strict';let __exports={};const{renderToElement}=require("@web/core/utils/render");const{descendants,preserveCursor}=require("@web_editor/js/editor/odoo-editor/src/utils/utils");const rowSize=__exports.rowSize=50;const additionalRowLimit=__exports.additionalRowLimit=10;const defaultGridPadding=10;__exports._getGridProperties=_getGridProperties;function _getGridProperties(rowEl){const style=window.getComputedStyle(rowEl);const rowGap=parseFloat(style.rowGap);const columnGap=parseFloat(style.columnGap);const columnSize=(rowEl.clientWidth-11*columnGap)/12;return{rowGap:rowGap,rowSize:rowSize,columnGap:columnGap,columnSize:columnSize};} __exports._setElementToMaxZindex=_setElementToMaxZindex;function _setElementToMaxZindex(element,rowEl){const childrenEls=[...rowEl.children].filter(el=>el!==element&&!el.classList.contains("o_we_grid_preview"));element.style.zIndex=Math.max(...childrenEls.map(el=>el.style.zIndex))+1;} __exports._addBackgroundGrid=_addBackgroundGrid;function _addBackgroundGrid(rowEl,gridHeight){const gridProp=_getGridProperties(rowEl);const rowCount=Math.max(rowEl.dataset.rowCount,gridHeight);const backgroundGrid=renderToElement('web_editor.background_grid',{rowCount:rowCount+1,rowGap:gridProp.rowGap,rowSize:gridProp.rowSize,columnGap:gridProp.columnGap,columnSize:gridProp.columnSize,});rowEl.prepend(backgroundGrid);return rowEl.firstElementChild;} __exports._resizeGrid=_resizeGrid;function _resizeGrid(rowEl){const columnEls=[...rowEl.children].filter(c=>c.classList.contains('o_grid_item'));rowEl.dataset.rowCount=Math.max(...columnEls.map(el=>el.style.gridRowEnd))-1;} __exports._gridCleanUp=_gridCleanUp;function _gridCleanUp(rowEl,columnEl){columnEl.style.removeProperty('position');columnEl.style.removeProperty('top');columnEl.style.removeProperty('left');columnEl.style.removeProperty('height');columnEl.style.removeProperty('width');rowEl.style.removeProperty('position');} __exports._toggleGridMode=_toggleGridMode;function _toggleGridMode(containerEl){let rowEl=containerEl.querySelector(':scope > .row');const outOfRowEls=[...containerEl.children].filter(el=>!el.classList.contains('row'));const avoidRollback=(el)=>{for(const node of descendants(el)){node.ouid=undefined;}};const restoreCursor=!rowEl||outOfRowEls.length>0?preserveCursor(containerEl.ownerDocument):()=>{};if(rowEl&&outOfRowEls.length>0){const columnEl=document.createElement('div');columnEl.classList.add('col-lg-12');for(let i=outOfRowEls.length-1;i>=0;i--){columnEl.prepend(outOfRowEls[i]);} avoidRollback(columnEl);rowEl.prepend(columnEl);} if(!rowEl){rowEl=document.createElement('div');rowEl.classList.add('row');const columnEl=document.createElement('div');columnEl.classList.add('col-lg-12');const containerChildren=containerEl.children;for(let i=containerChildren.length-1;i>=0;i--){columnEl.prepend(containerChildren[i]);} avoidRollback(columnEl);rowEl.appendChild(columnEl);containerEl.appendChild(rowEl);} restoreCursor();const columnEls=rowEl.children;const columnSize=(rowEl.clientWidth)/12;rowEl.style.position='relative';const rowCount=_placeColumns(columnEls,rowSize,0,columnSize,0)-1;rowEl.style.removeProperty('position');rowEl.dataset.rowCount=rowCount;const classesToRemove=[...rowEl.classList].filter(c=>{return/^align-items/.test(c);});rowEl.classList.remove(...classesToRemove);rowEl.classList.add('o_grid_mode');} function _placeColumns(columnEls,rowSize,rowGap,columnSize,columnGap){let maxRowEnd=0;const columnSpans=[];let zIndex=1;const imageColumns=[];for(const columnEl of columnEls){let isImageColumn=_checkIfImageColumn(columnEl);const imageEl=columnEl.querySelector('img');const hasBackgroundColor=columnEl.classList.contains("o_cc");const isImageWithoutPadding=isImageColumn&&!hasBackgroundColor;const style=window.getComputedStyle(columnEl);const borderLeft=parseFloat(style.borderLeft);const columnLeft=isImageWithoutPadding&&!borderLeft?imageEl.offsetLeft:columnEl.offsetLeft;const paddingLeft=parseFloat(style.paddingLeft);let width=isImageWithoutPadding?parseFloat(imageEl.scrollWidth):parseFloat(columnEl.scrollWidth)-(hasBackgroundColor?0:2*paddingLeft);const borderX=borderLeft+parseFloat(style.borderRight);width+=borderX+(hasBackgroundColor||isImageColumn?0:2*defaultGridPadding);let columnSpan=Math.round((width+columnGap)/(columnSize+columnGap));if(columnSpan<1){columnSpan=1;} const columnStart=Math.round(columnLeft/(columnSize+columnGap))+1;const columnEnd=columnStart+columnSpan;const borderTop=parseFloat(style.borderTop);const columnTop=isImageWithoutPadding&&!borderTop?imageEl.offsetTop:columnEl.offsetTop;const paddingTop=parseFloat(style.paddingTop);const paddingBottom=parseFloat(style.paddingBottom);const rowOffsetTop=Math.floor((paddingTop+rowGap)/(rowSize+rowGap));let height=isImageWithoutPadding?parseFloat(imageEl.scrollHeight):parseFloat(columnEl.scrollHeight)-(hasBackgroundColor?0:paddingTop+paddingBottom);const borderY=borderTop+parseFloat(style.borderBottom);height+=borderY+(hasBackgroundColor||isImageColumn?0:2*defaultGridPadding);const rowSpan=Math.ceil((height+rowGap)/(rowSize+rowGap));const rowStart=Math.round(columnTop/(rowSize+rowGap))+1+(hasBackgroundColor||isImageWithoutPadding?0:rowOffsetTop);const rowEnd=rowStart+rowSpan;columnEl.style.gridArea=`${rowStart} / ${columnStart} / ${rowEnd} / ${columnEnd}`;columnEl.classList.add('o_grid_item');columnEl.classList.add('g-col-lg-'+columnSpan,'g-height-'+rowSpan);columnEl.style.zIndex=zIndex++;if(hasBackgroundColor){columnEl.style.setProperty("--grid-item-padding-y",`${paddingTop}px`);columnEl.style.setProperty("--grid-item-padding-x",`${paddingLeft}px`);} _reloadLazyImages(columnEl);maxRowEnd=Math.max(rowEnd,maxRowEnd);columnSpans.push(columnSpan);imageColumns.push(isImageColumn);} for(const[i,columnEl]of[...columnEls].entries()){const regex=/^(((pt|pb)\d{1,3}$)|col-lg-|offset-lg-)/;const toRemove=[...columnEl.classList].filter(c=>{return regex.test(c);});columnEl.classList.remove(...toRemove);columnEl.classList.add('col-lg-'+columnSpans[i]);if(imageColumns[i]){_convertImageColumn(columnEl);}} return maxRowEnd;} __exports._reloadLazyImages=_reloadLazyImages;function _reloadLazyImages(columnEl){const imageEls=columnEl.querySelectorAll('img');for(const imageEl of imageEls){const src=imageEl.getAttribute("src");imageEl.src='';imageEl.src=src;}} __exports._convertColumnToGrid=_convertColumnToGrid;function _convertColumnToGrid(rowEl,columnEl,columnWidth,columnHeight){if(_checkIfImageColumn(columnEl)){_convertImageColumn(columnEl);} const paddingX=parseFloat(rowEl.style.getPropertyValue("--grid-item-padding-x"))||defaultGridPadding;const paddingY=parseFloat(rowEl.style.getPropertyValue("--grid-item-padding-y"))||defaultGridPadding;columnWidth+=2*paddingX;columnHeight+=2*paddingY;const gridProp=_getGridProperties(rowEl);const columnColCount=Math.round((columnWidth+gridProp.columnGap)/(gridProp.columnSize+gridProp.columnGap));const columnRowCount=Math.ceil((columnHeight+gridProp.rowGap)/(gridProp.rowSize+gridProp.rowGap));const regex=/^(pt|pb|col-|offset-)/;const toRemove=[...columnEl.classList].filter(c=>regex.test(c));columnEl.classList.remove(...toRemove);columnEl.classList.add('g-col-lg-'+columnColCount,'g-height-'+columnRowCount,'col-lg-'+columnColCount);columnEl.classList.add('o_grid_item');return{columnColCount:columnColCount,columnRowCount:columnRowCount};} __exports._convertToNormalColumn=_convertToNormalColumn;function _convertToNormalColumn(columnEl){const gridSizeClasses=columnEl.className.match(/(g-col-lg|g-height)-[0-9]+/g);columnEl.classList.remove("o_grid_item","o_grid_item_image","o_grid_item_image_contain",...gridSizeClasses);columnEl.style.removeProperty("z-index");columnEl.style.removeProperty("--grid-item-padding-x");columnEl.style.removeProperty("--grid-item-padding-y");columnEl.style.removeProperty("grid-area");} __exports._checkIfImageColumn=_checkIfImageColumn;function _checkIfImageColumn(columnEl){let isImageColumn=false;const imageEls=columnEl.querySelectorAll(":scope > img, :scope > a > img");const columnChildrenEls=[...columnEl.children].filter(el=>el.nodeName!=='BR');if(imageEls.length===1&&columnChildrenEls.length===1){const textNodeEls=[...columnEl.childNodes].filter(el=>el.nodeType===Node.TEXT_NODE);const areTextNodesEmpty=[...textNodeEls].every(textNodeEl=>textNodeEl.nodeValue.trim()==='');isImageColumn=areTextNodesEmpty;} return isImageColumn;} function _convertImageColumn(columnEl){columnEl.querySelectorAll('br').forEach(el=>el.remove());const textNodeEls=[...columnEl.childNodes].filter(el=>el.nodeType===Node.TEXT_NODE);textNodeEls.forEach(el=>el.remove());const imageEl=columnEl.querySelector('img');columnEl.classList.add('o_grid_item_image');imageEl.style.removeProperty('width');} return __exports;});; /* /web_editor/static/src/js/common/scrolling.js */ odoo.define('@web_editor/js/common/scrolling',['@web/core/utils/scrolling'],function(require){'use strict';let __exports={};const{getScrollingElement}=require("@web/core/utils/scrolling");function isScrollable(element){if(!element){return false;} const overflowY=window.getComputedStyle(element).overflowY;return overflowY==='auto'||overflowY==='scroll'||(overflowY==='visible'&&element===element.ownerDocument.scrollingElement);} __exports.closestScrollable=closestScrollable;function closestScrollable(element){const document=element.ownerDocument||window.document;while(element&&element!==document.scrollingElement){if(element instanceof Document){return null;} if(isScrollable(element)){return element;} element=element.parentElement;} return element||document.scrollingElement;} function scrollFixedOffset(doc=document){let size=0;const elements=doc.querySelectorAll('.o_top_fixed_element');elements.forEach(el=>{size+=el.offsetHeight;});return size;} __exports.scrollTo=scrollTo;function scrollTo(el,options={}){if(!el){throw new Error("The scrollTo function was called without any given element");} if(typeof el==='string'){el=document.querySelector(el);} const isTopOrBottomHidden=(el==="top"||el==="bottom");const scrollable=isTopOrBottomHidden?document.scrollingElement:(options.scrollable||closestScrollable(el.parentElement));const scrollDocument=scrollable.ownerDocument;const isInOneDocument=isTopOrBottomHidden||scrollDocument===el.ownerDocument;const iframe=!isInOneDocument&&Array.from(scrollable.querySelectorAll('iframe')).find(node=>node.contentDocument.contains(el));const topLevelScrollable=getScrollingElement(scrollDocument);function _computeScrollTop(){if(el==='#top'||el.id==='top'){return 0;} if(el==='#bottom'||el.id==='bottom'){return scrollable.scrollHeight-scrollable.clientHeight;} el.classList.add("o_check_scroll_position");let offsetTop=el.getBoundingClientRect().top+window.scrollY;el.classList.remove("o_check_scroll_position");if(el.classList.contains('d-none')){el.classList.remove('d-none');offsetTop=el.getBoundingClientRect().top+window.scrollY;el.classList.add('d-none');} const isDocScrollingEl=scrollable===el.ownerDocument.scrollingElement;let elPosition=offsetTop-(scrollable.getBoundingClientRect().top+window.scrollY-(isDocScrollingEl?0:scrollable.scrollTop));if(!isInOneDocument&&iframe){elPosition+=iframe.getBoundingClientRect().top+window.scrollY;} let offset=options.forcedOffset;if(offset===undefined){offset=(scrollable===topLevelScrollable?scrollFixedOffset(scrollDocument):0)+(options.extraOffset||0);} return Math.max(0,elPosition-offset);} return new Promise(resolve=>{const start=scrollable.scrollTop;const duration=options.duration||600;const startTime=performance.now();function animateScroll(currentTime){const elapsedTime=currentTime-startTime;const progress=Math.min(elapsedTime/duration,1);const easeInOutQuad=progress<0.5?2*progress*progress:1-Math.pow(-2*progress+2,2)/2;const change=_computeScrollTop()-start;const newScrollTop=start+change*easeInOutQuad;scrollable.scrollTop=newScrollTop;if(elapsedTimeeditableWindow=ew;let editableDocument=document;const _setEditableDocument=(ed)=>editableDocument=ed;const COLOR_PALETTE_COMPATIBILITY_COLOR_NAMES=['primary','secondary','alpha','beta','gamma','delta','epsilon','success','info','warning','danger'];const EDITOR_COLOR_CSS_VARIABLES=[...COLOR_PALETTE_COMPATIBILITY_COLOR_NAMES];for(let i=1;i<=5;i++){EDITOR_COLOR_CSS_VARIABLES.push(`o-color-${i}`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-bg`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-bg-gradient`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-headings`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-text`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-btn-primary`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-btn-primary-text`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-btn-secondary`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-btn-secondary-text`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-btn-primary-border`);EDITOR_COLOR_CSS_VARIABLES.push(`o-cc${i}-btn-secondary-border`);} for(let i=100;i<=900;i+=100){EDITOR_COLOR_CSS_VARIABLES.push(`${i}`);} const CSS_SHORTHANDS={'border-width':['border-top-width','border-right-width','border-bottom-width','border-left-width'],'border-radius':['border-top-left-radius','border-top-right-radius','border-bottom-right-radius','border-bottom-left-radius'],'border-color':['border-top-color','border-right-color','border-bottom-color','border-left-color'],'border-style':['border-top-style','border-right-style','border-bottom-style','border-left-style'],'padding':['padding-top','padding-right','padding-bottom','padding-left'],};const CSS_UNITS_CONVERSION={'s-ms':()=>1000,'ms-s':()=>0.001,'rem-px':()=>_computePxByRem(),'px-rem':()=>_computePxByRem(true),'%-px':()=>-1,'px-%':()=>-1,};const DEFAULT_PALETTE={'1':'#3AADAA','2':'#7C6576','3':'#F6F6F6','4':'#FFFFFF','5':'#383E45',};const BACKGROUND_IMAGE_ATTRIBUTES=new Set(["originalId","originalSrc","mimetype","resizeWidth","glFilter","quality","bgSrc","filterOptions","mimetypeBeforeConversion",]);function _computePxByRem(toRem){if(editableDocument.PX_BY_REM===undefined){const htmlStyle=editableWindow.getComputedStyle(editableDocument.documentElement);editableDocument.PX_BY_REM=parseFloat(htmlStyle['font-size']);} return toRem?(1/editableDocument.PX_BY_REM):editableDocument.PX_BY_REM;} function _convertValueToUnit(value,unitTo,cssProp,$target){const m=_getNumericAndUnit(value);if(!m){return NaN;} const numValue=parseFloat(m[0]);const valueUnit=m[1];return _convertNumericToUnit(numValue,valueUnit,unitTo,cssProp,$target);} function _convertNumericToUnit(value,unitFrom,unitTo,cssProp,$target){if(Math.abs(value)index?parts1[index]:'auto';const part2=parts2&&parts2.length>index?parts2[index]:'auto';if(!_areCssValuesEqual(part1,part2,pseudoPartProp,$target)){return false;}} return true;} if(value1.startsWith('var(--')){value1=_getCSSVariableValue(value1.substring(6,value1.length-1));} if(value2.startsWith('var(--')){value2=_getCSSVariableValue(value2.substring(6,value2.length-1));} if(value1===value2){return true;} const color1=normalizeCSSColor(value1);const color2=normalizeCSSColor(value2);if(color1===color2){return true;} const value1IsGradient=_isColorGradient(value1);const value2IsGradient=_isColorGradient(value2);if(value1IsGradient!==value2IsGradient){return false;} if(value1IsGradient){const temp1El=document.createElement('div');temp1El.style.backgroundImage=value1;document.body.appendChild(temp1El);value1=getComputedStyle(temp1El).backgroundImage;document.body.removeChild(temp1El);const temp2El=document.createElement('div');temp2El.style.backgroundImage=value2;document.body.appendChild(temp2El);value2=getComputedStyle(temp2El).backgroundImage;document.body.removeChild(temp2El);return value1===value2;} if(cssProp==='box-shadow'){const temp1El=document.createElement('div');temp1El.style.boxShadow=value1;document.body.appendChild(temp1El);value1=getComputedStyle(temp1El).boxShadow;document.body.removeChild(temp1El);const temp2El=document.createElement('div');temp2El.style.boxShadow=value2;document.body.appendChild(temp2El);value2=getComputedStyle(temp2El).boxShadow;document.body.removeChild(temp2El);return value1===value2;} const data=_getNumericAndUnit(value1);if(!data){return false;} const numValue1=data[0];const numValue2=_convertValueToUnit(value2,data[1],cssProp,$target);return(Math.abs(numValue1-numValue2){if(isBgPrefix&&_isColorCombinationName(c)){hasCCClasses=true;return`o_cc${c}`;} return(prefix+c);});if(hasCCClasses){classes.push('o_cc');} return classes;} function _getCSSVariableValue(key,htmlStyle){if(htmlStyle===undefined){htmlStyle=editableWindow.getComputedStyle(editableWindow.document.documentElement);} let value=htmlStyle.getPropertyValue(`--${key}`).trim();value=normalizeCSSColor(value);return value.replace(/"/g,"'");} function _normalizeColor(color){if(isCSSColor(color)){return color;} return _getCSSVariableValue(color);} function _getBgImageURL(el){const parts=_backgroundImageCssToParts($(el).css('background-image'));const string=parts.url||'';const match=string.match(/^url\((['"])(.*?)\1\)$/);if(!match){return'';} const matchedURL=match[2];const fullURL=new URL(matchedURL,window.location.origin);if(fullURL.origin===window.location.origin){return fullURL.href.slice(fullURL.origin.length);} return matchedURL;} function _backgroundImageCssToParts(css){const parts={};css=css||'';if(css.startsWith('url(')){const urlEnd=css.indexOf(')')+1;parts.url=css.substring(0,urlEnd).trim();const commaPos=css.indexOf(',',urlEnd);css=commaPos>0?css.substring(commaPos+1):'';} if(_isColorGradient(css)){parts.gradient=css.trim();} return parts;} function _backgroundImagePartsToCss(parts){let css=parts.url||'';if(parts.gradient){css+=(css?', ':'')+parts.gradient;} return css||'none';} function _isColorGradient(value){return value&&value.includes('-gradient(');} function _generateHTMLId(){return`o${Math.random().toString(36).substring(2, 15)}`;} function _getColorClass(el,colorNames,prefix){const prefixedColorNames=_computeColorClasses(colorNames,prefix);return el.classList.value.split(' ').filter(cl=>prefixedColorNames.includes(cl)).join(' ');} function _addBackgroundImageAttributes(...newAttributes){BACKGROUND_IMAGE_ATTRIBUTES.add(...newAttributes);} function _isBackgroundImageAttribute(attribute){return BACKGROUND_IMAGE_ATTRIBUTES.has(attribute);} function _shouldEditableMediaBeEditable(mediaEl){const parentEl=mediaEl.parentElement;const nonEditableAncestorRootEl=parentEl&&parentEl.closest('[contenteditable="false"]');return nonEditableAncestorRootEl&&nonEditableAncestorRootEl.parentElement&&nonEditableAncestorRootEl.parentElement.isContentEditable;} function _isMobileView(targetEl){const mobileViewThreshold=MEDIAS_BREAKPOINTS[SIZES.LG].minWidth;const clientWidth=targetEl.ownerDocument.defaultView?.frameElement?.clientWidth||targetEl.ownerDocument.documentElement.clientWidth;return clientWidth&&clientWidthfalse).catch(()=>true);} return isCorsProtected;} async function _isSrcCorsProtected(src){const dummyImg=document.createElement("img");dummyImg.src=src;return _isImageCorsProtected(dummyImg);} __exports[Symbol.for("default")]={COLOR_PALETTE_COMPATIBILITY_COLOR_NAMES:COLOR_PALETTE_COMPATIBILITY_COLOR_NAMES,CSS_SHORTHANDS:CSS_SHORTHANDS,CSS_UNITS_CONVERSION:CSS_UNITS_CONVERSION,DEFAULT_PALETTE:DEFAULT_PALETTE,EDITOR_COLOR_CSS_VARIABLES:EDITOR_COLOR_CSS_VARIABLES,computePxByRem:_computePxByRem,convertValueToUnit:_convertValueToUnit,convertNumericToUnit:_convertNumericToUnit,getNumericAndUnit:_getNumericAndUnit,areCssValuesEqual:_areCssValuesEqual,isColorCombinationName:_isColorCombinationName,isColorGradient:_isColorGradient,computeColorClasses:_computeColorClasses,getCSSVariableValue:_getCSSVariableValue,normalizeColor:_normalizeColor,getBgImageURL:_getBgImageURL,backgroundImageCssToParts:_backgroundImageCssToParts,backgroundImagePartsToCss:_backgroundImagePartsToCss,generateHTMLId:_generateHTMLId,getColorClass:_getColorClass,setEditableWindow:_setEditableWindow,setEditableDocument:_setEditableDocument,addBackgroundImageAttributes:_addBackgroundImageAttributes,isBackgroundImageAttribute:_isBackgroundImageAttribute,shouldEditableMediaBeEditable:_shouldEditableMediaBeEditable,isMobileView:_isMobileView,getLinkLabel:_getLinkLabel,forwardToThumbnail:_forwardToThumbnail,isImageCorsProtected:_isImageCorsProtected,isSrcCorsProtected:_isSrcCorsProtected,};return __exports;});; /* /web_editor/static/src/js/common/wysiwyg_utils.js */ odoo.define('@web_editor/js/common/wysiwyg_utils',[],function(require){'use strict';let __exports={};__exports.isImg=isImg;function isImg(node){return(node&&(node.nodeName==="IMG"||(node.className&&node.className.match(/(^|\s)(media_iframe_video|o_image|fa)(\s|$)/i))));} __exports.ancestors=ancestors;function ancestors(node,stopElement){if(!node||!node.parentElement||node===stopElement)return[];return[node.parentElement,...ancestors(node.parentElement,stopElement)];} return __exports;});; /* /web_editor/static/src/js/core/owl_utils.js */ odoo.define('@web_editor/js/core/owl_utils',['@odoo/owl','@web/core/templates','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{App,Component,useState,xml}=require("@odoo/owl");const{getTemplate}=require("@web/core/templates");const{_t}=require("@web/core/l10n/translation");const rootTemplate=xml``;__exports.attachComponent=attachComponent;async function attachComponent(parent,element,componentClass,props={}){class Root extends Component{static template=rootTemplate;static components={SubComp:componentClass};static props=["*"];state=useState(props);} const env=Component.env;const app=new App(Root,{env,getTemplate,dev:env.debug,translatableAttributes:["data-tooltip"],translateFn:_t,});if(parent.__parentedMixin){parent.__parentedChildren.push({get $el(){return $(app.root.el);},destroy(){app.destroy();},});} const originalValidateTarget=App.validateTarget;App.validateTarget=()=>{};const mountPromise=app.mount(element);App.validateTarget=originalValidateTarget;const component=await mountPromise;const subComp=Object.values(component.__owl__.children)[0].component;return{component:subComp,destroy(){app.destroy();},update(props){Object.assign(component.state,props);},};} return __exports;});; /* /web_editor/static/src/js/editor/odoo-editor/src/utils/utils.js */ odoo.define('@web_editor/js/editor/odoo-editor/src/utils/utils',[],function(require){'use strict';let __exports={};const DIRECTIONS=__exports.DIRECTIONS={LEFT:false,RIGHT:true,};const CTYPES=__exports.CTYPES={CONTENT:1,SPACE:2,BLOCK_OUTSIDE:4,BLOCK_INSIDE:8,BR:16,};__exports.ctypeToString=ctypeToString;function ctypeToString(ctype){return Object.keys(CTYPES).find((key)=>CTYPES[key]===ctype);} const CTGROUPS=__exports.CTGROUPS={INLINE:CTYPES.CONTENT|CTYPES.SPACE,BLOCK:CTYPES.BLOCK_OUTSIDE|CTYPES.BLOCK_INSIDE,BR:CTYPES.BR,};const tldWhitelist=['com','net','org','ac','ad','ae','af','ag','ai','al','am','an','ao','aq','ar','as','at','au','aw','ax','az','ba','bb','bd','be','bf','bg','bh','bi','bj','bl','bm','bn','bo','br','bq','bs','bt','bv','bw','by','bz','ca','cc','cd','cf','cg','ch','ci','ck','cl','cm','cn','co','cr','cs','cu','cv','cw','cx','cy','cz','dd','de','dj','dk','dm','do','dz','ec','ee','eg','eh','er','es','et','eu','fi','fj','fk','fm','fo','fr','ga','gb','gd','ge','gf','gg','gh','gi','gl','gm','gn','gp','gq','gr','gs','gt','gu','gw','gy','hk','hm','hn','hr','ht','hu','id','ie','il','im','in','io','iq','ir','is','it','je','jm','jo','jp','ke','kg','kh','ki','km','kn','kp','kr','kw','ky','kz','la','lb','lc','li','lk','lr','ls','lt','lu','lv','ly','ma','mc','md','me','mf','mg','mh','mk','ml','mm','mn','mo','mp','mq','mr','ms','mt','mu','mv','mw','mx','my','mz','na','nc','ne','nf','ng','ni','nl','no','np','nr','nu','nz','om','pa','pe','pf','pg','ph','pk','pl','pm','pn','pr','ps','pt','pw','py','qa','re','ro','rs','ru','rw','sa','sb','sc','sd','se','sg','sh','si','sj','sk','sl','sm','sn','so','sr','ss','st','su','sv','sx','sy','sz','tc','td','tf','tg','th','tj','tk','tl','tm','tn','to','tp','tr','tt','tv','tw','tz','ua','ug','uk','um','us','uy','uz','va','vc','ve','vg','vi','vn','vu','wf','ws','ye','yt','yu','za','zm','zr','zw','co\\.uk'];const urlRegexBase=`|(?:www.))[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-zA-Z][a-zA-Z0-9]{1,62}|(?:[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.(?:${tldWhitelist.join('|')})\\b))(?:(?:[/?#])[^\\s]*[^!.,})\\]'"\\s]|(?:[^!(){}.,[\\]'"\\s]+))?`;const httpCapturedRegex=`(https?:\\/\\/)`;const URL_REGEX=__exports.URL_REGEX=new RegExp(`((?:(?:${httpCapturedRegex}${urlRegexBase})`,'i');const YOUTUBE_URL_GET_VIDEO_ID=__exports.YOUTUBE_URL_GET_VIDEO_ID=/^(?:(?:https?:)?\/\/)?(?:(?:www|m)\.)?(?:youtube\.com|youtu\.be)(?:\/(?:[\w-]+\?v=|embed\/|v\/)?)([^\s?&#]+)(?:\S+)?$/i;const EMAIL_REGEX=__exports.EMAIL_REGEX=/^(mailto:)?[\w-.]+@(?:[\w-]+\.)+[\w-]{2,4}$/i;const PHONE_REGEX=__exports.PHONE_REGEX=/^(tel:(?:\/\/)?)?\+?[\d\s.\-()\/]{3,25}$/;const PROTECTED_BLOCK_TAG=__exports.PROTECTED_BLOCK_TAG=['TR','TD','TABLE','TBODY','UL','OL','LI'];const FONT_SIZE_CLASSES=__exports.FONT_SIZE_CLASSES=["display-1-fs","display-2-fs","display-3-fs","display-4-fs","h1-fs","h2-fs","h3-fs","h4-fs","h5-fs","h6-fs","base-fs","o_small-fs","small","o_small_twelve-fs","o_small_ten-fs","o_small_eight-fs"];const TEXT_STYLE_CLASSES=__exports.TEXT_STYLE_CLASSES=["display-1","display-2","display-3","display-4","lead","o_small","small"];const ZWNBSP_CHAR='\ufeff';const ZERO_WIDTH_CHARS=__exports.ZERO_WIDTH_CHARS=['\u200b',ZWNBSP_CHAR];const ZERO_WIDTH_CHARS_REGEX=__exports.ZERO_WIDTH_CHARS_REGEX=new RegExp(`[${ZERO_WIDTH_CHARS.join('')}]`,'g');__exports.leftPos=leftPos;function leftPos(node){return[node.parentNode,childNodeIndex(node)];} __exports.rightPos=rightPos;function rightPos(node){return[node.parentNode,childNodeIndex(node)+1];} __exports.boundariesOut=boundariesOut;function boundariesOut(node){const index=childNodeIndex(node);return[node.parentNode,index,node.parentNode,index+1];} __exports.startPos=startPos;function startPos(node){return[node,0];} __exports.endPos=endPos;function endPos(node){return[node,nodeSize(node)];} __exports.boundariesIn=boundariesIn;function boundariesIn(node){return[node,0,node,nodeSize(node)];} __exports.childNodeIndex=childNodeIndex;function childNodeIndex(node){let i=0;while(node.previousSibling){i++;node=node.previousSibling;} return i;} __exports.nodeSize=nodeSize;function nodeSize(node){const isTextNode=node.nodeType===Node.TEXT_NODE;return isTextNode?node.length:node.childNodes.length;} const closestPath=__exports.closestPath=function*(node){while(node){yield node;node=node.parentNode;}};const PATH_END_REASONS={NO_NODE:0,BLOCK_OUT:1,BLOCK_HIT:2,OUT_OF_SCOPE:3,};__exports.createDOMPathGenerator=createDOMPathGenerator;function createDOMPathGenerator(direction,{leafOnly=false,inScope=false,stopTraverseFunction,stopFunction}={},){const nextDeepest=direction===DIRECTIONS.LEFT?node=>lastLeaf(node.previousSibling,stopTraverseFunction):node=>firstLeaf(node.nextSibling,stopTraverseFunction);const firstNode=direction===DIRECTIONS.LEFT?(node,offset)=>lastLeaf(node.childNodes[offset-1],stopTraverseFunction):(node,offset)=>firstLeaf(node.childNodes[offset],stopTraverseFunction);return function*(node,offset,reasons=[]){let movedUp=false;let currentNode=firstNode(node,offset);if(!currentNode){movedUp=true;currentNode=node;} while(currentNode){if(stopFunction&&stopFunction(currentNode)){reasons.push(movedUp?PATH_END_REASONS.BLOCK_OUT:PATH_END_REASONS.BLOCK_HIT);break;} if(inScope&¤tNode===node){reasons.push(PATH_END_REASONS.OUT_OF_SCOPE);break;} if(!(leafOnly&&movedUp)){yield currentNode;} movedUp=false;let nextNode=nextDeepest(currentNode);if(!nextNode){movedUp=true;nextNode=currentNode.parentNode;} currentNode=nextNode;} reasons.push(PATH_END_REASONS.NO_NODE);};} __exports.findNode=findNode;function findNode(domPath,findCallback=()=>true,stopCallback=()=>false){for(const node of domPath){if(findCallback(node)){return node;} if(stopCallback(node)){break;}} return null;} __exports.getFurthestUneditableParent=getFurthestUneditableParent;function getFurthestUneditableParent(node,parentLimit){if(node===parentLimit||(parentLimit&&!parentLimit.contains(node))){return undefined;} let parent=node&&node.parentElement;let nonEditableElement;while(parent&&(!parentLimit||parent!==parentLimit)){if(!parent.isContentEditable){nonEditableElement=parent;} if(parent.oid==="root"){break;} parent=parent.parentElement;} return nonEditableElement;} __exports.closestElement=closestElement;function closestElement(node,predicate="*"){if(!node)return null;let element=node.nodeType===Node.ELEMENT_NODE?node:node.parentElement;if(typeof predicate==='function'){while(element&&!predicate(element)){element=element.parentElement;}}else{element=element?.closest(predicate);} return element?.closest('.odoo-editor-editable')&&element;} __exports.ancestors=ancestors;function ancestors(node,editable){if(!node||!node.parentElement||node===editable)return[];return[node.parentElement,...ancestors(node.parentElement,editable)];} __exports.descendants=descendants;function descendants(node){const posterity=[];for(const child of(node.childNodes||[])){posterity.push(child,...descendants(child));} return posterity;} __exports.closestBlock=closestBlock;function closestBlock(node){return findNode(closestPath(node),node=>isBlock(node));} __exports.lastLeaf=lastLeaf;function lastLeaf(node,stopTraverseFunction){while(node&&node.lastChild&&!(stopTraverseFunction&&stopTraverseFunction(node))){node=node.lastChild;} return node;} __exports.firstLeaf=firstLeaf;function firstLeaf(node,stopTraverseFunction){while(node&&node.firstChild&&!(stopTraverseFunction&&stopTraverseFunction(node))){node=node.firstChild;} return node;} __exports.previousLeaf=previousLeaf;function previousLeaf(node,editable,skipInvisible=false){let ancestor=node;while(ancestor&&!ancestor.previousSibling&&ancestor!==editable){ancestor=ancestor.parentElement;} if(ancestor&&ancestor!==editable){if(skipInvisible&&!isVisible(ancestor.previousSibling)){return previousLeaf(ancestor.previousSibling,editable,skipInvisible);}else{const last=lastLeaf(ancestor.previousSibling);if(skipInvisible&&!isVisible(last)){return previousLeaf(last,editable,skipInvisible);}else{return last;}}}} __exports.nextLeaf=nextLeaf;function nextLeaf(node,editable,skipInvisible=false){let ancestor=node;while(ancestor&&!ancestor.nextSibling&&ancestor!==editable){ancestor=ancestor.parentElement;} if(ancestor&&ancestor!==editable){if(skipInvisible&&ancestor.nextSibling&&!isVisible(ancestor.nextSibling)){return nextLeaf(ancestor.nextSibling,editable,skipInvisible);}else{const first=firstLeaf(ancestor.nextSibling);if(skipInvisible&&!isVisible(first)){return nextLeaf(first,editable,skipInvisible);}else{return first;}}}} __exports.getAdjacentPreviousSiblings=getAdjacentPreviousSiblings;function getAdjacentPreviousSiblings(node,predicate=n=>!!n){let previous=node.previousSibling;const list=[];while(previous&&predicate(previous)){list.push(previous);previous=previous.previousSibling;} return list;} __exports.getAdjacentNextSiblings=getAdjacentNextSiblings;function getAdjacentNextSiblings(node,predicate=n=>!!n){let next=node.nextSibling;const list=[];while(next&&predicate(next)){list.push(next);next=next.nextSibling;} return list;} __exports.getAdjacents=getAdjacents;function getAdjacents(node,predicate=n=>!!n){const previous=getAdjacentPreviousSiblings(node,predicate);const next=getAdjacentNextSiblings(node,predicate);return predicate(node)?[...previous.reverse(),node,...next]:[];} __exports.hasTableSelection=hasTableSelection;function hasTableSelection(editable){return!!editable.querySelector('.o_selected_table');} __exports.hasValidSelection=hasValidSelection;function hasValidSelection(editable){return hasTableSelection(editable)||editable.ownerDocument.getSelection().rangeCount>0;} __exports.getNormalizedCursorPosition=getNormalizedCursorPosition;function getNormalizedCursorPosition(node,offset,full=true){const editable=closestElement(node,'.odoo-editor-editable');let closest=closestElement(node);while(closest&&closest!==editable&&(isSelfClosingElement(node)||!closest.isContentEditable)){[node,offset]=offset||!nodeSize(node)?rightPos(node):leftPos(node);closest=closestElement(node);} offset=Math.min(Math.max(offset,0),nodeSize(node));if(full){let el;let elOffset;if(node.nodeType===Node.ELEMENT_NODE){el=node;elOffset=offset;}else if(node.nodeType===Node.TEXT_NODE){if(offset===0){el=node.parentNode;elOffset=childNodeIndex(node);}else if(offset===node.length){el=node.parentNode;elOffset=childNodeIndex(node)+1;}} if(el){const leftInlineNode=leftLeafOnlyInScopeNotBlockEditablePath(el,elOffset).next().value;let leftVisibleEmpty=false;if(leftInlineNode){leftVisibleEmpty=isSelfClosingElement(leftInlineNode)||!closestElement(leftInlineNode).isContentEditable;[node,offset]=leftVisibleEmpty?rightPos(leftInlineNode):endPos(leftInlineNode);} if(!leftInlineNode||leftVisibleEmpty){const rightInlineNode=rightLeafOnlyInScopeNotBlockEditablePath(el,elOffset).next().value;if(rightInlineNode){const closest=closestElement(rightInlineNode);const rightVisibleEmpty=isSelfClosingElement(rightInlineNode)||!closest||!closest.isContentEditable;if(!(leftVisibleEmpty&&rightVisibleEmpty)){[node,offset]=rightVisibleEmpty?leftPos(rightInlineNode):startPos(rightInlineNode);}}}}} const prevNode=node.nodeType===Node.ELEMENT_NODE&&node.childNodes[offset-1];if(prevNode&&prevNode.nodeName==='BR'&&isFakeLineBreak(prevNode)){offset--;} return[node,offset];} __exports.insertSelectionChars=insertSelectionChars;function insertSelectionChars(anchorNode,anchorOffset,focusNode,focusOffset,startChar='[',endChar=']'){if(anchorNode===focusNode&&anchorOffset<=focusOffset){focusOffset+=(focusNode.nodeType===Node.TEXT_NODE?startChar.length:1);} insertCharsAt(startChar,anchorNode,anchorOffset);insertCharsAt(endChar,focusNode,focusOffset);} __exports.logSelection=logSelection;function logSelection(root,options={}){const sel=options.selection||root.ownerDocument.getSelection();if(!root.contains(sel.anchorNode)||!root.contains(sel.focusNode)){console.warn('The selection is not contained in the root.');return;} let anchorClone,focusClone;const cloneTree=node=>{const clone=node.cloneNode();if(options.includeOids){clone.oid=node.oid;} anchorClone=anchorClone||(node===sel.anchorNode&&clone);focusClone=focusClone||(node===sel.focusNode&&clone);for(const child of node.childNodes||[]){clone.append(cloneTree(child));} return clone;} const rootClone=cloneTree(root);insertSelectionChars(anchorClone,sel.anchorOffset,focusClone,sel.focusOffset,'%c[%c','%c]%c');rootClone.removeAttribute('data-last-history-steps');if(options.doFormat){const formatHtml=(node,spaces=0)=>{node.before(document.createTextNode('\n'+' '.repeat(spaces)));for(const child of[...node.childNodes]){formatHtml(child,spaces+4);} if(node.nodeType!==Node.TEXT_NODE){node.appendChild(document.createTextNode('\n'+' '.repeat(spaces)));} if(options.includeOids){if(node.nodeType===Node.TEXT_NODE){node.textContent+=` (${node.oid})`;}else{node.setAttribute('oid',node.oid);}}} formatHtml(rootClone);} const selectionCharacterStyle='color: #75bfff; font-weight: 700;';const defaultStyle='color: inherit; font-weight: inherit;';console.log(makeZeroWidthCharactersVisible(rootClone.outerHTML),selectionCharacterStyle,defaultStyle,selectionCharacterStyle,defaultStyle,);} __exports.ensureFocus=ensureFocus;function ensureFocus(element){const activeElement=element.ownerDocument.activeElement;if(activeElement!==element&&(!element.contains(activeElement)||!activeElement.isContentEditable)){element.focus();}} __exports.setSelection=setSelection;function setSelection(anchorNode,anchorOffset,focusNode=anchorNode,focusOffset=anchorOffset,normalize=true,){if(!anchorNode||!anchorNode.parentElement||!anchorNode.parentElement.closest('body')||!focusNode||!focusNode.parentElement||!focusNode.parentElement.closest('body')){return null;} const document=anchorNode.ownerDocument;const seemsCollapsed=anchorNode===focusNode&&anchorOffset===focusOffset;[anchorNode,anchorOffset]=getNormalizedCursorPosition(anchorNode,anchorOffset,normalize);[focusNode,focusOffset]=seemsCollapsed?[anchorNode,anchorOffset]:getNormalizedCursorPosition(focusNode,focusOffset,normalize);const direction=getCursorDirection(anchorNode,anchorOffset,focusNode,focusOffset);const sel=document.getSelection();if(!sel){return null;} try{const range=new Range();if(direction===DIRECTIONS.RIGHT){range.setStart(anchorNode,anchorOffset);range.collapse(true);}else{range.setEnd(anchorNode,anchorOffset);range.collapse(false);} sel.removeAllRanges();sel.addRange(range);sel.extend(focusNode,focusOffset);}catch(e){if(e.name!=='NS_ERROR_FAILURE'){throw e;}} return[anchorNode,anchorOffset,focusNode,focusOffset];} __exports.setCursorStart=setCursorStart;function setCursorStart(node,normalize=true){const pos=startPos(node);return setSelection(...pos,...pos,normalize);} __exports.setCursorEnd=setCursorEnd;function setCursorEnd(node,normalize=true){const pos=endPos(node);return setSelection(...pos,...pos,normalize);} __exports.getCursorDirection=getCursorDirection;function getCursorDirection(anchorNode,anchorOffset,focusNode,focusOffset){if(anchorNode===focusNode){if(anchorOffset===focusOffset)return false;return anchorOffsettraversedNodes.add(descendant));}}else if(!(node===range.endContainer&&range.endOffset===0&&!range.collapsed&&node.previousSibling&&node.previousSibling.nodeName==="BR")){traversedNodes.add(node);}}} if(node){for(const descendant of descendants(node)){if(descendant.parentElement===node&&childNodeIndex(descendant)>=range.endOffset){break;} traversedNodes.add(descendant);}} return[...traversedNodes];} __exports.getSelectedNodes=getSelectedNodes;function getSelectedNodes(editable){const selectedTableCells=editable.querySelectorAll('.o_selected_td');const document=editable.ownerDocument;const sel=document.getSelection();if(!sel.rangeCount&&!selectedTableCells.length){return[];} const range=sel.getRangeAt(0);return[...new Set(getTraversedNodes(editable).flatMap(node=>{const td=closestElement(node,'.o_selected_td');if(td){return descendants(td);}else if(range.isPointInRange(node,0)&&range.isPointInRange(node,nodeSize(node))){return node;}else{return[];}},))];} __exports.getDeepRange=getDeepRange;function getDeepRange(editable,{range,sel,splitText,select,correctTripleClick}={}){sel=sel||editable.parentElement&&editable.ownerDocument.getSelection();if(sel&&sel.isCollapsed&&sel.anchorNode&&sel.anchorNode.nodeName==="BR"){setSelection(sel.anchorNode.parentElement,childNodeIndex(sel.anchorNode));} range=range?range.cloneRange():sel&&sel.rangeCount&&sel.getRangeAt(0).cloneRange();if(!range)return;let start=range.startContainer;let startOffset=range.startOffset;let end=range.endContainer;let endOffset=range.endOffset;const isBackwards=!range.collapsed&&start===sel.focusNode&&startOffset===sel.focusOffset;[start,startOffset]=getDeepestPosition(start,startOffset);[end,endOffset]=getDeepestPosition(end,endOffset);if(splitText){const isInSingleContainer=start===end;if(end.nodeType===Node.TEXT_NODE&&endOffset!==0&&endOffset!==end.textContent.length){const endParent=end.parentNode;const splitOffset=splitTextNode(end,endOffset);end=endParent.childNodes[splitOffset-1]||endParent.firstChild;if(isInSingleContainer){start=end;} endOffset=end.textContent.length;} if(start.nodeType===Node.TEXT_NODE&&startOffset!==0&&startOffset!==start.textContent.length){splitTextNode(start,startOffset);startOffset=0;if(isInSingleContainer){endOffset=start.textContent.length;}}} const endLeaf=firstLeaf(end);const beforeEnd=endLeaf.previousSibling;const isInsideColumn=closestElement(end,'.o_text_columns') if(correctTripleClick&&!endOffset&&(start!==end||startOffset!==endOffset)&&(!beforeEnd||(beforeEnd.nodeType===Node.TEXT_NODE&&!isVisibleTextNode(beforeEnd)&&!isZWS(beforeEnd)))&&!closestElement(endLeaf,'table')&&!isInsideColumn){const previous=previousLeaf(endLeaf,editable,true);if(previous&&closestElement(previous).isContentEditable){[end,endOffset]=[previous,nodeSize(previous)];}} if(select){if(isBackwards){[start,end,startOffset,endOffset]=[end,start,endOffset,startOffset];range.setEnd(start,startOffset);range.collapse(false);}else{range.setStart(start,startOffset);range.collapse(true);} sel.removeAllRanges();sel.addRange(range);try{sel.extend(end,endOffset);}catch{} range=sel.getRangeAt(0);}else{range.setStart(start,startOffset);range.setEnd(end,endOffset);} return range;} __exports.getAdjacentCharacter=getAdjacentCharacter;function getAdjacentCharacter(editable,side){let{focusNode,focusOffset}=editable.ownerDocument.getSelection();const originalBlock=closestBlock(focusNode);let adjacentCharacter;while(!adjacentCharacter&&focusNode){if(side==='previous'){adjacentCharacter=focusOffset>0&&focusNode.textContent[focusOffset-1];}else{adjacentCharacter=focusNode.textContent[focusOffset];} if(!adjacentCharacter){if(side==='previous'){focusNode=previousLeaf(focusNode,editable);focusOffset=focusNode&&nodeSize(focusNode);}else{focusNode=nextLeaf(focusNode,editable);focusOffset=0;} const characterIndex=side==='previous'?focusOffset-1:focusOffset;adjacentCharacter=focusNode&&focusNode.textContent[characterIndex];}} return closestBlock(focusNode)===originalBlock?adjacentCharacter:undefined;} __exports.isZwnbsp=isZwnbsp;function isZwnbsp(node){return node.nodeType===Node.TEXT_NODE&&node.textContent==='\ufeff';} function isTangible(node){return isVisible(node)||isZwnbsp(node)||hasTangibleContent(node);} function hasTangibleContent(node){return[...(node?.childNodes||[])].some(n=>isTangible(n));} __exports.getDeepestPosition=getDeepestPosition;function getDeepestPosition(node,offset){let direction=DIRECTIONS.RIGHT;let next=node;while(next){if(isTangible(next)||isZWS(next)){if(next!==node){[node,offset]=[next,direction?0:nodeSize(next)];} direction=offset{replace=replace||new Map();cursorPos[0]=replace.get(cursorPos[0])||cursorPos[0];cursorPos[2]=replace.get(cursorPos[2])||cursorPos[2];return setSelection(...cursorPos,false);};} __exports.isSelectionInSelectors=isSelectionInSelectors;function isSelectionInSelectors(selector){let anchor=document.getSelection().anchorNode;if(anchor&&anchor.nodeType&&anchor.nodeType!==Node.ELEMENT_NODE){anchor=anchor.parentElement;} if(anchor&&closestElement(anchor,selector)){return true;} return false;} __exports.getOffsetAndCharSize=getOffsetAndCharSize;function getOffsetAndCharSize(nodeValue,offset,direction){const splittedNodeValue=[...nodeValue];let charSize=1;let newOffset=offset;let currentSize=0;for(const item of splittedNodeValue){currentSize+=item.length;if(currentSize>=offset){newOffset=direction==DIRECTIONS.LEFT?currentSize:currentSize-item.length;charSize=item.length;break;}} return[newOffset,charSize];} const formatsSpecs=__exports.formatsSpecs={italic:{tagName:'em',isFormatted:isItalic,isTag:(node)=>['EM','I'].includes(node.tagName),hasStyle:(node)=>Boolean(node.style&&node.style['font-style']),addStyle:(node)=>node.style['font-style']='italic',addNeutralStyle:(node)=>node.style['font-style']='normal',removeStyle:(node)=>removeStyle(node,'font-style'),},bold:{tagName:'strong',isFormatted:isBold,isTag:(node)=>['STRONG','B'].includes(node.tagName),hasStyle:(node)=>Boolean(node.style&&node.style['font-weight']),addStyle:(node)=>node.style['font-weight']='bolder',addNeutralStyle:(node)=>{node.style['font-weight']='normal'},removeStyle:(node)=>removeStyle(node,'font-weight'),},underline:{tagName:'u',isFormatted:isUnderline,isTag:(node)=>node.tagName==='U',hasStyle:(node)=>node.style&&node.style['text-decoration-line'].includes('underline'),addStyle:(node)=>node.style['text-decoration-line']+=' underline',removeStyle:(node)=>removeStyle(node,'text-decoration-line','underline'),},strikeThrough:{tagName:'s',isFormatted:isStrikeThrough,isTag:(node)=>node.tagName==='S',hasStyle:(node)=>node.style&&node.style['text-decoration-line'].includes('line-through'),addStyle:(node)=>node.style['text-decoration-line']+=' line-through',removeStyle:(node)=>removeStyle(node,'text-decoration-line','line-through'),},fontSize:{isFormatted:isFontSize,hasStyle:(node)=>node.style&&node.style['font-size'],addStyle:(node,props)=>{node.style['font-size']=props.size;node.classList.remove(...FONT_SIZE_CLASSES);},removeStyle:(node)=>removeStyle(node,'font-size'),},setFontSizeClassName:{isFormatted:hasClass,hasStyle:(node,props)=>FONT_SIZE_CLASSES.find(cls=>node.classList.contains(cls)),addStyle:(node,props)=>node.classList.add(props.className),removeStyle:(node)=>{node.classList.remove(...FONT_SIZE_CLASSES,...TEXT_STYLE_CLASSES);if(node.classList.length===0){node.removeAttribute("class");}},},switchDirection:{isFormatted:isDirectionSwitched,}} const removeStyle=(node,styleName,item)=>{if(item){const newStyle=node.style[styleName].split(' ').filter(x=>x!==item).join(' ');node.style[styleName]=newStyle||null;}else{node.style[styleName]=null;} if(node.getAttribute('style')===''){node.removeAttribute('style');}};const getOrCreateSpan=(node,ancestors)=>{const span=ancestors.find((element)=>element.tagName==='SPAN'&&element.isConnected);const lastInlineAncestor=ancestors.findLast((element)=>!isBlock(element)&&element.isConnected);if(span){return span;}else{const span=document.createElement('span');if(lastInlineAncestor){lastInlineAncestor.after(span);span.append(lastInlineAncestor);}else{node.after(span);span.append(node);} return span;}} const removeFormat=(node,formatSpec)=>{node=closestElement(node);if(formatSpec.hasStyle(node)){formatSpec.removeStyle(node);if(['SPAN','FONT'].includes(node.tagName)&&!node.getAttributeNames().length){return unwrapContents(node);}} if(formatSpec.isTag&&formatSpec.isTag(node)){const attributesNames=node.getAttributeNames().filter((name)=>{return name!=='data-oe-zws-empty-inline';});if(attributesNames.length){const newNode=document.createElement('span');while(node.firstChild){newNode.appendChild(node.firstChild);} for(let index=node.attributes.length-1;index>=0;--index){newNode.attributes.setNamedItem(node.attributes[index].cloneNode());} node.parentNode.replaceChild(newNode,node);}else{unwrapContents(node);}}} const formatSelection=__exports.formatSelection=(editor,formatName,{applyStyle,formatProps}={})=>{const selection=editor.document.getSelection();let direction let wasCollapsed;if(editor.editable.querySelector('.o_selected_td')){direction=DIRECTIONS.RIGHT;}else{if(!selection.rangeCount)return;wasCollapsed=selection.getRangeAt(0).collapsed;direction=getCursorDirection(selection.anchorNode,selection.anchorOffset,selection.focusNode,selection.focusOffset);} getDeepRange(editor.editable,{splitText:true,select:true,correctTripleClick:true});if(typeof applyStyle==='undefined'){applyStyle=!isSelectionFormat(editor.editable,formatName);} let zws;if(wasCollapsed){if(selection.anchorNode.nodeType===Node.TEXT_NODE&&selection.anchorNode.textContent==='\u200b'){zws=selection.anchorNode;selection.getRangeAt(0).selectNode(zws);}else{zws=insertAndSelectZws(selection);} getDeepRange(editor.editable,{splitText:true,select:true,correctTripleClick:true});} const selectedNodes=getSelectedNodes(editor.editable).filter((n)=>((n.nodeType===Node.TEXT_NODE&&(isVisibleTextNode(n)||isZWS(n)))||n.nodeName==="BR")&&closestElement(n).isContentEditable);const selectedFieldNodes=new Set(getSelectedNodes(editor.editable).map(n=>closestElement(n,"*[t-field],*[t-out],*[t-esc]")).filter(Boolean));const formatSpec=formatsSpecs[formatName];for(const node of selectedNodes){const inlineAncestors=[];let currentNode=node;let parentNode=node.parentElement;while(parentNode&&!isBlock(parentNode)&&!isUnbreakable(parentNode)&&!isUnbreakable(currentNode)&&(parentNode.classList.length===0||[...parentNode.classList].every(cls=>FONT_SIZE_CLASSES.includes(cls)))){const isUselessZws=parentNode.tagName==='SPAN'&&parentNode.hasAttribute('data-oe-zws-empty-inline')&&parentNode.getAttributeNames().length===1;if(isUselessZws){unwrapContents(parentNode);}else{const newLastAncestorInlineFormat=splitAroundUntil(currentNode,parentNode);removeFormat(newLastAncestorInlineFormat,formatSpec);if(newLastAncestorInlineFormat.isConnected){inlineAncestors.push(newLastAncestorInlineFormat);currentNode=newLastAncestorInlineFormat;}} parentNode=currentNode.parentElement;} const isFormatted=formatName==="setFontSizeClassName"&&!formatProps?hasAnyFontSizeClass:formatSpec.isFormatted;const firstBlockOrClassHasFormat=isFormatted(parentNode,formatProps);if(firstBlockOrClassHasFormat&&!applyStyle){formatSpec.addNeutralStyle&&formatSpec.addNeutralStyle(getOrCreateSpan(node,inlineAncestors));}else if(!firstBlockOrClassHasFormat&&applyStyle){const tag=formatSpec.tagName&&document.createElement(formatSpec.tagName);if(tag){node.after(tag);tag.append(node);if(!isFormatted(tag,formatProps)){tag.after(node);tag.remove();formatSpec.addStyle(getOrCreateSpan(node,inlineAncestors),formatProps);}}else if(formatName!=='fontSize'||formatProps.size!==undefined){formatSpec.addStyle(getOrCreateSpan(node,inlineAncestors),formatProps);}}} for(const selectedFieldNode of selectedFieldNodes){if(applyStyle){formatSpec.addStyle(selectedFieldNode,formatProps);}else{formatSpec.removeStyle(selectedFieldNode);}} if(zws){const siblings=[...zws.parentElement.childNodes];if(!isBlock(zws.parentElement)&&selectedNodes.includes(siblings[0])&&selectedNodes.includes(siblings[siblings.length-1])){zws.parentElement.setAttribute('data-oe-zws-empty-inline','');}else{const span=document.createElement('span');span.setAttribute('data-oe-zws-empty-inline','');zws.before(span);span.append(zws);}} if(selectedNodes.length===1&&selectedNodes[0].textContent==='\u200B'){setSelection(selectedNodes[0],0);}else if(selectedNodes.length){const firstNode=selectedNodes[0];const lastNode=selectedNodes[selectedNodes.length-1];if(direction===DIRECTIONS.RIGHT){setSelection(firstNode,0,lastNode,lastNode.length,false);}else{setSelection(lastNode,lastNode.length,firstNode,0,false);}}} const isLinkEligibleForZwnbsp=__exports.isLinkEligibleForZwnbsp=(editable,link)=>{return link.parentElement.isContentEditable&&link.isContentEditable&&editable.contains(link)&&!([link,...link.querySelectorAll('*')].some(el=>el.nodeName==='IMG'||isBlock(el))||link.matches('nav a, a.nav-link'));} const padLinkWithZws=__exports.padLinkWithZws=(editable,link)=>{if(!isLinkEligibleForZwnbsp(editable,link)){return;} const selection=editable.ownerDocument.getSelection()||{};const{anchorOffset,focusOffset}=selection;let extraAnchorOffset=0;let extraFocusOffset=0;if(!link.textContent.startsWith('\uFEFF')){if(selection.anchorNode===link&&anchorOffset){extraAnchorOffset+=1;} if(selection.focusNode===link&&focusOffset){extraFocusOffset+=1;} link.prepend(document.createTextNode('\uFEFF'));} if(!link.textContent.endsWith('\uFEFF')){if(selection.anchorNode===link&&anchorOffset+extraAnchorOffset===nodeSize(link)){extraAnchorOffset+=1;} if(selection.focusNode===link&&focusOffset+extraFocusOffset===nodeSize(link)){extraFocusOffset+=1;} link.append(document.createTextNode('\uFEFF'));} const linkIndex=childNodeIndex(link);if(!(link.previousSibling&&link.previousSibling.textContent.endsWith('\uFEFF'))){if(selection.anchorNode===link.parentElement&&anchorOffset+extraAnchorOffset>linkIndex){extraAnchorOffset+=1;} if(selection.focusNode===link.parentElement&&focusOffset+extraFocusOffset>linkIndex){extraFocusOffset+=1;} link.before(document.createTextNode('\uFEFF'));} if(!(link.nextSibling&&link.nextSibling.textContent.startsWith('\uFEFF'))){if(selection.anchorNode===link.parentElement&&anchorOffset+extraAnchorOffset>linkIndex+1){extraAnchorOffset+=1;} if(selection.focusNode===link.parentElement&&focusOffset+extraFocusOffset>linkIndex+1){extraFocusOffset+=1;} link.after(document.createTextNode('\uFEFF'));} if(extraAnchorOffset||extraFocusOffset){setSelection(selection.anchorNode,anchorOffset+extraAnchorOffset,selection.focusNode,focusOffset+extraFocusOffset,);}} const blockTagNames=['ADDRESS','ARTICLE','ASIDE','BLOCKQUOTE','DETAILS','DIALOG','DD','DIV','DL','DT','FIELDSET','FIGCAPTION','FIGURE','FOOTER','FORM','H1','H2','H3','H4','H5','H6','HEADER','HGROUP','HR','LI','MAIN','NAV','OL','P','PRE','SECTION','TABLE','UL','SELECT','OPTION','TR','TD','TBODY','THEAD','TH',];const computedStyles=new WeakMap();__exports.isBlock=isBlock;function isBlock(node){if(!node||node.nodeType!==Node.ELEMENT_NODE){return false;} const tagName=node.nodeName.toUpperCase();if(tagName.startsWith('JW-')||(tagName==='T'&&node.getAttribute('t-esc')===null&&node.getAttribute('t-out')===null&&node.getAttribute('t-raw')===null)){return true;} if(tagName==='BR'){return false;} if(!node.isConnected){return blockTagNames.includes(tagName);} let style=computedStyles.get(node);if(!style){style=node.ownerDocument.defaultView?.getComputedStyle(node);computedStyles.set(node,style);} if(style?.display){return!style.display.includes('inline')&&style.display!=='contents';} return blockTagNames.includes(tagName);} __exports.isBold=isBold;function isBold(node){const fontWeight=+getComputedStyle(closestElement(node)).fontWeight;return fontWeight>500||fontWeight>+getComputedStyle(closestBlock(node)).fontWeight;} __exports.isItalic=isItalic;function isItalic(node){return getComputedStyle(closestElement(node)).fontStyle==='italic';} __exports.isUnderline=isUnderline;function isUnderline(node){let parent=closestElement(node);while(parent){if(getComputedStyle(parent).textDecorationLine.includes('underline')){return true;} parent=parent.parentElement;} return false;} __exports.isStrikeThrough=isStrikeThrough;function isStrikeThrough(node){let parent=closestElement(node);while(parent){if(getComputedStyle(parent).textDecorationLine.includes('line-through')){return true;} parent=parent.parentElement;} return false;} __exports.isFontSize=isFontSize;function isFontSize(node,props){const element=closestElement(node);return getComputedStyle(element)['font-size']===props.size;} __exports.hasClass=hasClass;function hasClass(node,props){const element=closestElement(node);return element.classList.contains(props.className);} __exports.hasAnyFontSizeClass=hasAnyFontSizeClass;function hasAnyFontSizeClass(node){return FONT_SIZE_CLASSES.find((cls)=>node?.classList?.contains(cls));} __exports.isDirectionSwitched=isDirectionSwitched;function isDirectionSwitched(node,editable){const defaultDirection=editable.getAttribute('dir');return getComputedStyle(closestElement(node)).direction!==defaultDirection;} __exports.isSelectionFormat=isSelectionFormat;function isSelectionFormat(editable,format){const selectedNodes=getTraversedNodes(editable).filter((n)=>n.nodeType===Node.TEXT_NODE&&n.nodeValue.replaceAll(ZWNBSP_CHAR,'').length);const isFormatted=format==="setFontSizeClassName"?hasAnyFontSizeClass:formatsSpecs[format].isFormatted;return selectedNodes.length&&selectedNodes.every(n=>isFormatted(n,editable));} __exports.isUnbreakable=isUnbreakable;function isUnbreakable(node){if(!node||node.nodeType===Node.TEXT_NODE){return false;} if(node.nodeType!==Node.ELEMENT_NODE){return true;} return(isUnremovable(node)||['TABLE','THEAD','TBODY','TFOOT','TR','TH','TD','SECTION','DIV'].includes(node.tagName)||node.hasAttribute('t')||(node.nodeType===Node.ELEMENT_NODE&&(node.nodeName==='T'||node.getAttribute('t-if')||node.getAttribute('t-esc')||node.getAttribute('t-elif')||node.getAttribute('t-else')||node.getAttribute('t-foreach')||node.getAttribute('t-value')||node.getAttribute('t-out')||node.getAttribute('t-raw'))||node.getAttribute('t-field'))||node.matches(".oe_unbreakable, a.btn, a[role='tab'], a[role='button'], li.nav-item"));} __exports.isUnremovable=isUnremovable;function isUnremovable(node){return((node.nodeType!==Node.COMMENT_NODE&&node.nodeType!==Node.ELEMENT_NODE&&node.nodeType!==Node.TEXT_NODE)||node.oid==='root'||(node.nodeType===Node.ELEMENT_NODE&&(node.classList.contains('o_editable')||node.getAttribute('t-set')||node.getAttribute('t-call')))||(node.classList&&node.classList.contains('oe_unremovable'))||(node.nodeName==='SPAN'&&node.parentElement&&node.parentElement.getAttribute('data-oe-type')==='monetary')||(node.ownerDocument&&node.ownerDocument.defaultWindow&&!ancestors(node).find(ancestor=>ancestor.oid==='root')));} __exports.containsUnbreakable=containsUnbreakable;function containsUnbreakable(node){if(!node){return false;} return isUnbreakable(node)||containsUnbreakable(node.firstChild);} const iconTags=['I','SPAN'];const iconClasses=['fa','fab','fad','far','oi'];__exports.isIconElement=isIconElement;function isIconElement(node){return!!(node&&iconTags.includes(node.nodeName)&&iconClasses.some(cls=>node.classList.contains(cls)));} const ICON_SELECTOR=__exports.ICON_SELECTOR=iconTags.map(tag=>{return iconClasses.map(cls=>{return`${tag}.${cls}`;}).join(', ');}).join(', ');__exports.isZWS=isZWS;function isZWS(node){return(node&&node.textContent==='\u200B');} __exports.isEditorTab=isEditorTab;function isEditorTab(node){return(node&&(node.nodeName==='SPAN')&&node.classList.contains('oe-tabs'));} __exports.isMediaElement=isMediaElement;function isMediaElement(node){return(isIconElement(node)||(node.classList&&(node.classList.contains('o_image')||node.classList.contains('media_iframe_video'))));} __exports.isProtected=isProtected;function isProtected(node){const closestProtectedElement=closestElement(node,'[data-oe-protected]');if(closestProtectedElement){return["","true"].includes(closestProtectedElement.dataset.oeProtected);} return false;} const VOID_ELEMENT_NAMES=['AREA','BASE','BR','COL','EMBED','HR','IMG','INPUT','KEYGEN','LINK','META','PARAM','SOURCE','TRACK','WBR'];__exports.isArtificialVoidElement=isArtificialVoidElement;function isArtificialVoidElement(node){return isMediaElement(node)||node.nodeName==='HR';} __exports.isNotAllowedContent=isNotAllowedContent;function isNotAllowedContent(node){return isArtificialVoidElement(node)||VOID_ELEMENT_NAMES.includes(node.nodeName);} __exports.containsUnremovable=containsUnremovable;function containsUnremovable(node){if(!node){return false;} return isUnremovable(node)||containsUnremovable(node.firstChild);} __exports.getInSelection=getInSelection;function getInSelection(document,selector){const selection=document.getSelection();const range=selection&&!!selection.rangeCount&&selection.getRangeAt(0);if(range){const selectorInStartAncestors=closestElement(range.startContainer,selector);if(selectorInStartAncestors){return selectorInStartAncestors;}else{const commonElementAncestor=closestElement(range.commonAncestorContainer);return commonElementAncestor&&[...commonElementAncestor.querySelectorAll(selector)].find(node=>range.intersectsNode(node),);}}} __exports.getRowIndex=getRowIndex;function getRowIndex(trOrTd){const tr=closestElement(trOrTd,'tr');const trParent=tr&&tr.parentElement;if(!trParent){return-1;} const trSiblings=[...trParent.children].filter(child=>child.nodeName==='TR');return trSiblings.findIndex(child=>child===tr);} __exports.getColumnIndex=getColumnIndex;function getColumnIndex(td){const tdParent=td.parentElement;if(!tdParent){return-1;} const tdSiblings=[...tdParent.children].filter(child=>child.nodeName==='TD'||child.nodeName==='TH');return tdSiblings.findIndex(child=>child===td);} const paragraphRelatedElements=__exports.paragraphRelatedElements=['P','H1','H2','H3','H4','H5','H6','PRE','BLOCKQUOTE',];__exports.allowsParagraphRelatedElements=allowsParagraphRelatedElements;function allowsParagraphRelatedElements(node){return isBlock(node)&&!['P','H1','H2','H3','H4','H5','H6'].includes(node.nodeName);} __exports.makeContentsInline=makeContentsInline;function makeContentsInline(node){let childIndex=0;for(const child of node.childNodes){if(isBlock(child)){if(childIndex&¶graphRelatedElements.includes(child.nodeName)){child.before(document.createElement('br'));} for(const grandChild of child.childNodes){child.before(grandChild);makeContentsInline(grandChild);} child.remove();} childIndex+=1;}} __exports.getOuid=getOuid;function getOuid(node,optimize=false){while(node&&!isUnbreakable(node)){if(node.ouid&&optimize)return node.ouid;node=node.parentNode;} return node&&node.oid;} __exports.isHtmlContentSupported=isHtmlContentSupported;function isHtmlContentSupported(node){return!closestElement(node,'[data-oe-model]:not([data-oe-field="arch"]):not([data-oe-type="html"]),[data-oe-translation-id]',true);} const selfClosingElementTags=['BR','IMG','INPUT'];__exports.isSelfClosingElement=isSelfClosingElement;function isSelfClosingElement(node){return node&&selfClosingElementTags.includes(node.nodeName);} __exports.isInPre=isInPre;function isInPre(node){const element=node.nodeType===Node.TEXT_NODE?node.parentElement:node;return(!!element&&(!!element.closest('pre')||getComputedStyle(element).getPropertyValue('white-space')==='pre'));} const whitespace=`[^\\S\\u00A0\\u0009\\ufeff]`;const whitespaceRegex=new RegExp(`^${whitespace}*$`);__exports.isWhitespace=isWhitespace;function isWhitespace(value){const str=typeof value==='string'?value:value.nodeValue;return whitespaceRegex.test(str);} __exports.isVisible=isVisible;function isVisible(node){return!!node&&((node.nodeType===Node.TEXT_NODE&&isVisibleTextNode(node))||(node.nodeType===Node.ELEMENT_NODE&&(node.getAttribute("t-esc")||node.getAttribute("t-out")))||isSelfClosingElement(node)||isIconElement(node)||hasVisibleContent(node));} __exports.hasVisibleContent=hasVisibleContent;function hasVisibleContent(node){return[...(node?.childNodes||[])].some(n=>isVisible(n));} __exports.isButton=isButton;function isButton(node){if(!node||node.nodeType!==Node.ELEMENT_NODE){return false;} return node.nodeName==="BUTTON"||node.classList.contains("btn");} const visibleCharRegex=/[^\s\u200b]|[\u00A0\u0009]$/;__exports.isVisibleTextNode=isVisibleTextNode;function isVisibleTextNode(testedNode){if(!testedNode||!testedNode.length||testedNode.nodeType!==Node.TEXT_NODE){return false;} if(visibleCharRegex.test(testedNode.textContent)||(isInPre(testedNode)&&isWhitespace(testedNode))){return true;} if(ZERO_WIDTH_CHARS.includes(testedNode.textContent)){return false;} let preceding;let following;let foundTestedNode;const currentNodeParentBlock=closestBlock(testedNode);if(!currentNodeParentBlock){return false;} const nodeIterator=document.createNodeIterator(currentNodeParentBlock);for(let node=nodeIterator.nextNode();node;node=nodeIterator.nextNode()){if(node.nodeType===Node.TEXT_NODE){if(foundTestedNode){following=node;break;}else if(testedNode===node){foundTestedNode=true;}else{preceding=node;}}else if(isBlock(node)){if(foundTestedNode){break;}else{preceding=null;}}else if(foundTestedNode&&!isWhitespace(node)){following=node;break;}} while(following&&!visibleCharRegex.test(following.textContent)){following=following.nextSibling;} if(!(preceding&&following)||currentNodeParentBlock!==closestBlock(preceding)||currentNodeParentBlock!==closestBlock(following)){return false;} return visibleCharRegex.test(preceding.textContent);} __exports.parentsGet=parentsGet;function parentsGet(node,root=undefined){const parents=[];while(node){parents.unshift(node);if(node===root){break;} node=node.parentNode;} return parents;} __exports.commonParentGet=commonParentGet;function commonParentGet(node1,node2,root=undefined){if(!node1||!node2){return null;} const n1p=parentsGet(node1,root);const n2p=parentsGet(node2,root);while(n1p.length>1&&n1p[1]===n2p[1]){n1p.shift();n2p.shift();} return n1p[0]===n2p[0]?n1p[0]:null;} __exports.getListMode=getListMode;function getListMode(pnode){if(!["UL","OL"].includes(pnode.tagName))return;if(pnode.tagName=='OL')return'OL';return pnode.classList.contains('o_checklist')?'CL':'UL';} __exports.createList=createList;function createList(mode){const node=document.createElement(mode=='OL'?'OL':'UL');if(mode=='CL'){node.classList.add('o_checklist');} return node;} __exports.insertListAfter=insertListAfter;function insertListAfter(afterNode,mode,content=[]){const list=createList(mode);afterNode.after(list);list.append(...content.map(c=>{const li=document.createElement('LI');li.append(...[].concat(c));return li;}),);return list;} __exports.toggleList=toggleList;function toggleList(node,mode,offset=0){let pnode=node.closest('ul, ol');if(!pnode)return;const listMode=getListMode(pnode)+mode;if(['OLCL','ULCL'].includes(listMode)){pnode.classList.add('o_checklist');for(let li=pnode.firstElementChild;li!==null;li=li.nextElementSibling){if(li.style.listStyle!=='none'){li.style.listStyle=null;if(!li.style.all)li.removeAttribute('style');}} pnode=setTagName(pnode,'UL');}else if(['CLOL','CLUL'].includes(listMode)){toggleClass(pnode,'o_checklist');pnode=setTagName(pnode,mode);}else if(['OLUL','ULOL'].includes(listMode)){pnode=setTagName(pnode,mode);}else{let currNode=node;while(currNode){currNode=currNode.oShiftTab(offset);} return;} return pnode;} __exports.convertList=convertList;function convertList(node,toMode){if(!["UL","OL","LI"].includes(node.nodeName))return;const listMode=getListMode(node);if(listMode&&toMode!==listMode){node=toggleList(node,toMode);} for(const child of node.childNodes){convertList(child,toMode);} return node;} __exports.toggleClass=toggleClass;function toggleClass(node,className){node.classList.toggle(className);if(!node.className){node.removeAttribute('class');}} __exports.makeZeroWidthCharactersVisible=makeZeroWidthCharactersVisible;function makeZeroWidthCharactersVisible(text){return text.replaceAll('\u200B','//ZWSP//').replaceAll('\uFEFF','//ZWNBSP//');} __exports.isFakeLineBreak=isFakeLineBreak;function isFakeLineBreak(brEl){return!(getState(...rightPos(brEl),DIRECTIONS.RIGHT).cType&(CTYPES.CONTENT|CTGROUPS.BR));} __exports.isEmptyBlock=isEmptyBlock;function isEmptyBlock(blockEl){if(!blockEl||blockEl.nodeType!==Node.ELEMENT_NODE){return false;} if(isIconElement(blockEl)||visibleCharRegex.test(blockEl.textContent)){return false;} if(blockEl.querySelectorAll('br').length>=2){return false;} const nodes=blockEl.querySelectorAll('*');for(const node of nodes){if(node.nodeName!='BR'&&(isSelfClosingElement(node)||isIconElement(node))){return false;}} return true;} __exports.isShrunkBlock=isShrunkBlock;function isShrunkBlock(blockEl){return(isEmptyBlock(blockEl)&&!blockEl.querySelector('br')&&blockEl.nodeName!=="IMG");} __exports.isColorGradient=isColorGradient;function isColorGradient(value){return value&&value.includes('-gradient(');} __exports.getFontSizeDisplayValue=getFontSizeDisplayValue;function getFontSizeDisplayValue(sel,getCSSVariableValue,convertNumericToUnit){const tagNameRelatedToFontSize=["h1","h2","h3","h4","h5","h6"];const styleClassesRelatedToFontSize=["display-1","display-2","display-3","display-4","lead"];const closestStartContainerEl=closestElement(sel.getRangeAt(0).startContainer);const closestFontSizedEl=closestStartContainerEl.closest(` [style*='font-size'], ${FONT_SIZE_CLASSES.map(className => `.${className}`)}, ${styleClassesRelatedToFontSize.map(className => `.${className}`)}, ${tagNameRelatedToFontSize} `);let remValue;if(closestFontSizedEl){const useFontSizeInput=closestFontSizedEl.style.fontSize;if(useFontSizeInput){return parseFloat(getComputedStyle(closestStartContainerEl).fontSize);} const fontSizeClass=FONT_SIZE_CLASSES.find(className=>closestFontSizedEl.classList.contains(className));let fsName;if(fontSizeClass){fsName=fontSizeClass.substring(0,fontSizeClass.length-3);}else{fsName=styleClassesRelatedToFontSize.find(className=>closestFontSizedEl.classList.contains(className))||closestFontSizedEl.tagName.toLowerCase();} remValue=parseFloat(getCSSVariableValue(`${fsName}-font-size`));} const pxValue=remValue&&convertNumericToUnit(remValue,"rem","px");return pxValue||parseFloat(getComputedStyle(closestStartContainerEl).fontSize);} __exports.splitTextNode=splitTextNode;function splitTextNode(textNode,offset,originalNodeSide=DIRECTIONS.RIGHT){let parentOffset=childNodeIndex(textNode);if(offset>0){parentOffset++;if(offsetstartValue.length){throw new Error(`Invalid ${chars} insertion in text node`);} node.nodeValue=startValue.slice(0,offset)+chars+startValue.slice(offset);}else{if(offset<0||offset>node.childNodes.length){throw new Error(`Invalid ${chars} insertion in non-text node`);} const textNode=document.createTextNode(chars);if(offsetfragment.appendChild(node));const posRightNode=destinationEl.childNodes[destinationOffset];if(posRightNode){destinationEl.insertBefore(fragment,posRightNode);}else{destinationEl.appendChild(fragment);} restoreDestination();restoreMoved();} if(!nodeSize(sourceEl)){const restoreOrigin=prepareUpdate(...boundariesOut(sourceEl));sourceEl.remove();restoreOrigin();} const firstNode=nodes.find(node=>!!node.parentNode);return firstNode?leftPos(firstNode):[destinationEl,destinationOffset];} __exports.resetOuids=resetOuids;function resetOuids(node){node.ouid=undefined;for(const descendant of descendants(node)){descendant.ouid=undefined;}} const prepareUpdateLockedEditables=new Set();__exports.prepareUpdate=prepareUpdate;function prepareUpdate(...args){const closestRoot=args.length&&ancestors(args[0]).find(ancestor=>ancestor.oid==='root');const isPrepareUpdateLocked=closestRoot&&prepareUpdateLockedEditables.has(closestRoot);const hash=(Math.random()+1).toString(36).substring(7);const options={allowReenter:true,label:hash,debug:false,...(args.length&&args[args.length-1]instanceof Object?args.pop():{}),};if(options.debug){console.log('%cPreparing%c update: '+options.label+ (options.label===hash?'':` (${hash})`)+'%c'+(isPrepareUpdateLocked?' LOCKED':''),'color: cyan;','color: white;','color: red; font-weight: bold;',);} if(isPrepareUpdateLocked){return()=>{if(options.debug){console.log('%cRestoring%c update: '+options.label+ (options.label===hash?'':` (${hash})`)+'%c LOCKED','color: lightgreen;','color: white;','color: red; font-weight: bold;',);}};} if(!options.allowReenter&&closestRoot){prepareUpdateLockedEditables.add(closestRoot);} const positions=[...args];const restoreData=[];let el,offset;while(positions.length){offset=positions.pop();el=positions.pop();const left=getState(el,offset,DIRECTIONS.LEFT);const right=getState(el,offset,DIRECTIONS.RIGHT,left.cType);if(options.debug){const editable=el&&closestElement(el,'.odoo-editor-editable');const oldEditableHTML=editable&&makeZeroWidthCharactersVisible(editable.innerHTML).replaceAll(' ','_')||'';left.oldEditableHTML=oldEditableHTML;right.oldEditableHTML=oldEditableHTML;} restoreData.push(left,right);} return function restoreStates(){if(options.debug){console.log('%cRestoring%c update: '+options.label+ (options.label===hash?'':` (${hash})`),'color: lightgreen;','color: white;',);} for(const data of restoreData){restoreState(data,options.debug);} if(!options.allowReenter&&closestRoot){prepareUpdateLockedEditables.delete(closestRoot);}};} __exports.getState=getState;function getState(el,offset,direction,leftCType){const leftDOMPath=leftLeafOnlyNotBlockPath;const rightDOMPath=rightLeafOnlyNotBlockPath;let domPath;let inverseDOMPath;const whitespaceAtStartRegex=new RegExp('^'+whitespace+'+');const whitespaceAtEndRegex=new RegExp(whitespace+'+$');const reasons=[];if(direction===DIRECTIONS.LEFT){domPath=leftDOMPath(el,offset,reasons);inverseDOMPath=rightDOMPath(el,offset);}else{domPath=rightDOMPath(el,offset,reasons);inverseDOMPath=leftDOMPath(el,offset);} const boundaryNode=inverseDOMPath.next().value;let cType=undefined;let lastSpace=null;for(const node of domPath){if(node.nodeType===Node.TEXT_NODE){const value=node.nodeValue.replaceAll('\ufeff','');if(direction===DIRECTIONS.LEFT){if(!isWhitespace(value)){if(lastSpace){cType=CTYPES.SPACE;}else{const rightLeaf=rightLeafOnlyNotBlockPath(node).next().value;const hasContentRight=rightLeaf&&!whitespaceAtStartRegex.test(rightLeaf.textContent);cType=!hasContentRight&&whitespaceAtEndRegex.test(node.textContent)?CTYPES.SPACE:CTYPES.CONTENT;} break;} if(value.length){lastSpace=node;}}else{leftCType=leftCType||getState(el,offset,DIRECTIONS.LEFT).cType;if(whitespaceAtStartRegex.test(value)){const leftLeaf=leftLeafOnlyNotBlockPath(node).next().value;const hasContentLeft=leftLeaf&&!whitespaceAtEndRegex.test(leftLeaf.textContent);const rct=!isWhitespace(value)?CTYPES.CONTENT:getState(...rightPos(node),DIRECTIONS.RIGHT).cType;cType=leftCType&CTYPES.CONTENT&&rct&(CTYPES.CONTENT|CTYPES.BR)&&!hasContentLeft?CTYPES.SPACE:rct;break;} if(!isWhitespace(value)){cType=CTYPES.CONTENT;break;}}}else if(node.nodeName==='BR'){cType=CTYPES.BR;break;}else if(isVisible(node)){cType=CTYPES.CONTENT;break;}} if(cType===undefined){cType=reasons.includes(PATH_END_REASONS.BLOCK_HIT)?CTYPES.BLOCK_OUTSIDE:CTYPES.BLOCK_INSIDE;} return{node:boundaryNode,direction:direction,cType:cType,};} const priorityRestoreStateRules=[[{cType1:CTYPES.CONTENT,cType2:CTYPES.SPACE|CTGROUPS.BLOCK},{spaceVisibility:true},],[{direction:DIRECTIONS.LEFT,cType1:CTGROUPS.INLINE,cType2:CTGROUPS.BR},{spaceVisibility:true},],[{direction:DIRECTIONS.RIGHT,cType1:CTGROUPS.CONTENT,cType2:CTGROUPS.BR},{spaceVisibility:true},],[{direction:DIRECTIONS.RIGHT,cType1:CTGROUPS.BR,cType2:CTYPES.SPACE|CTGROUPS.BLOCK},{spaceVisibility:true},],[{cType1:CTYPES.SPACE},{spaceVisibility:false},],[{direction:DIRECTIONS.LEFT,cType1:CTGROUPS.BR},{spaceVisibility:false},],[{cType1:CTGROUPS.BLOCK,cType2:CTGROUPS.INLINE|CTGROUPS.BR},{spaceVisibility:false},],[{direction:DIRECTIONS.RIGHT,cType1:CTGROUPS.INLINE,cType2:CTGROUPS.BLOCK},{brVisibility:true},],[{direction:DIRECTIONS.RIGHT,cType1:CTGROUPS.BLOCK,cType2:CTGROUPS.INLINE|CTGROUPS.BR,},{brVisibility:false},],[{direction:DIRECTIONS.LEFT,cType1:CTGROUPS.BR|CTGROUPS.BLOCK,cType2:CTGROUPS.INLINE,},{brVisibility:false,extraBRRemovalCondition:brNode=>isFakeLineBreak(brNode)},],];function restoreStateRuleHashCode(direction,cType1,cType2){return`${direction}-${cType1}-${cType2}`;} const allRestoreStateRules=(function(){const map=new Map();const keys=['direction','cType1','cType2'];for(const direction of Object.values(DIRECTIONS)){for(const cType1 of Object.values(CTYPES)){for(const cType2 of Object.values(CTYPES)){const rule={direction:direction,cType1:cType1,cType2:cType2};const matchedRules=[];for(const entry of priorityRestoreStateRules){let priority=0;for(const key of keys){const entryKeyValue=entry[0][key];if(entryKeyValue!==undefined){if(typeof entryKeyValue==='boolean'?rule[key]===entryKeyValue:rule[key]&entryKeyValue){priority++;}else{priority=-1;break;}}} if(priority>=0){matchedRules.push([priority,entry[1]]);}} const finalRule={};for(let p=0;p<=keys.length;p++){for(const entry of matchedRules){if(entry[0]===p){Object.assign(finalRule,entry[1]);}}} const hashCode=restoreStateRuleHashCode(direction,cType1,cType2);map.set(hashCode,finalRule);}}} return map;})();__exports.restoreState=restoreState;function restoreState(prevStateData,debug=false){const{node,direction,cType:cType1,oldEditableHTML}=prevStateData;if(!node||!node.parentNode){return;} const[el,offset]=direction===DIRECTIONS.LEFT?leftPos(node):rightPos(node);const{cType:cType2}=getState(el,offset,direction);const ruleHashCode=restoreStateRuleHashCode(direction,cType1,cType2);const rule=allRestoreStateRules.get(ruleHashCode);if(debug){const editable=closestElement(node,'.odoo-editor-editable');console.log('%c'+makeZeroWidthCharactersVisible(node.textContent).replaceAll(' ','_')+'\n'+'%c'+(direction===DIRECTIONS.LEFT?'left':'right')+'\n'+'%c'+ctypeToString(cType1)+'\n'+'%c'+ctypeToString(cType2)+'\n'+'%c'+'BEFORE: '+(oldEditableHTML||'(unavailable)')+'\n'+'%c'+'AFTER: '+(editable?makeZeroWidthCharactersVisible(editable.innerHTML).replaceAll(' ','_'):'(unavailable)')+'\n','color: white; display: block; width: 100%;','color: '+(direction===DIRECTIONS.LEFT?'magenta':'lightgreen')+'; display: block; width: 100%;','color: pink; display: block; width: 100%;','color: lightblue; display: block; width: 100%;','color: white; display: block; width: 100%;','color: white; display: block; width: 100%;',rule,);} if(Object.values(rule).filter(x=>x!==undefined).length){const inverseDirection=direction===DIRECTIONS.LEFT?DIRECTIONS.RIGHT:DIRECTIONS.LEFT;enforceWhitespace(el,offset,inverseDirection,rule);} return rule;} __exports.enforceWhitespace=enforceWhitespace;function enforceWhitespace(el,offset,direction,rule){let domPath,whitespaceAtEdgeRegex;if(direction===DIRECTIONS.LEFT){domPath=leftLeafOnlyNotBlockPath(el,offset);whitespaceAtEdgeRegex=new RegExp(whitespace+'+$');}else{domPath=rightLeafOnlyNotBlockPath(el,offset);whitespaceAtEdgeRegex=new RegExp('^'+whitespace+'+');} const invisibleSpaceTextNodes=[];let foundVisibleSpaceTextNode=null;for(const node of domPath){if(node.nodeName==='BR'){if(rule.brVisibility===undefined){break;} if(rule.brVisibility){node.before(document.createElement('br'));}else{if(!rule.extraBRRemovalCondition||rule.extraBRRemovalCondition(node)){node.remove();}} break;}else if(node.nodeType===Node.TEXT_NODE&&!isInPre(node)){if(whitespaceAtEdgeRegex.test(node.nodeValue)){if(!isWhitespace(node)){foundVisibleSpaceTextNode=node;break;}else{invisibleSpaceTextNodes.push(node);}}else if(!isWhitespace(node)){break;}}else{break;}} if(rule.spaceVisibility===undefined){return;} if(!rule.spaceVisibility){for(const node of invisibleSpaceTextNodes){node.nodeValue='';const ancestorPath=closestPath(node.parentNode);let toRemove=null;for(const pNode of ancestorPath){if(toRemove){toRemove.remove();} if(pNode.childNodes.length===1&&!isBlock(pNode)){pNode.after(node);toRemove=pNode;}else{break;}}}} const spaceNode=foundVisibleSpaceTextNode||invisibleSpaceTextNodes[0];if(spaceNode){let spaceVisibility=rule.spaceVisibility;if(spaceVisibility&&!foundVisibleSpaceTextNode&&getState(...rightPos(spaceNode),DIRECTIONS.RIGHT).cType&CTGROUPS.BLOCK&&getState(...leftPos(spaceNode),DIRECTIONS.LEFT).cType!==CTYPES.CONTENT){spaceVisibility=false;} spaceNode.nodeValue=spaceNode.nodeValue.replace(whitespaceAtEdgeRegex,spaceVisibility?'\u00A0':'');}} __exports.rgbToHex=rgbToHex;function rgbToHex(rgb='',node=null){if(rgb.startsWith('#')){return rgb;}else if(rgb.startsWith('rgba')){const values=rgb.match(/[\d\.]{1,5}/g)||[];const alpha=parseFloat(values.pop());let bgRgbValues=[];if(node){let bgColor=getComputedStyle(node).backgroundColor;if(bgColor.startsWith('rgba')){bgColor=rgbToHex(bgColor,node.parentElement);} if(bgColor&&bgColor.startsWith('#')){bgRgbValues=(bgColor.match(/[\da-f]{2}/gi)||[]).map(val=>parseInt(val,16));}else if(bgColor&&bgColor.startsWith('rgb')){bgRgbValues=(bgColor.match(/[\d\.]{1,5}/g)||[]).map(val=>parseInt(val));}} bgRgbValues=bgRgbValues.length?bgRgbValues:[255,255,255];return('#'+ values.map((value,index)=>{const converted=Math.floor(alpha*parseInt(value)+(1-alpha)*bgRgbValues[index]);const hex=parseInt(converted).toString(16);return hex.length===1?'0'+hex:hex;}).join(''));}else{return('#'+ (rgb.match(/\d{1,3}/g)||[]).map(x=>{x=parseInt(x).toString(16);return x.length===1?'0'+x:x;}).join(''));}} __exports.parseHTML=parseHTML;function parseHTML(document,html){const fragment=document.createDocumentFragment();const parser=new document.defaultView.DOMParser();const parsedDocument=parser.parseFromString(html,'text/html');fragment.replaceChildren(...parsedDocument.body.childNodes);return fragment;} __exports.pxToFloat=pxToFloat;function pxToFloat(sizeString){return parseFloat(sizeString.replace('px',''));} __exports.getRangePosition=getRangePosition;function getRangePosition(el,document,options={}){const selection=document.getSelection();if(!selection.rangeCount)return;const range=selection.getRangeAt(0);const isRtl=options.direction==='rtl';const marginRight=options.marginRight||20;const marginBottom=options.marginBottom||20;const marginTop=options.marginTop||10;const marginLeft=options.marginLeft||10;let offset;if(range.endOffset-1>0){const clonedRange=range.cloneRange();clonedRange.setStart(range.endContainer,range.endOffset-1);clonedRange.setEnd(range.endContainer,range.endOffset);const rect=clonedRange.getBoundingClientRect();offset={height:rect.height,left:rect.left+rect.width,top:rect.top};clonedRange.detach();} if(!offset||offset.height===0){const clonedRange=range.cloneRange();const shadowCaret=document.createTextNode('|');clonedRange.insertNode(shadowCaret);clonedRange.selectNode(shadowCaret);const rect=clonedRange.getBoundingClientRect();offset={height:rect.height,left:rect.left,top:rect.top};shadowCaret.remove();clonedRange.detach();} if(isRtl){offset.right=offset.left-el.offsetWidth;const leftMove=Math.max(0,offset.right+el.offsetWidth+marginLeft-window.innerWidth);if(leftMove&&offset.right-leftMove>marginRight){offset.right-=leftMove;}else if(offset.right-leftMovemarginLeft){offset.left-=leftMove;}else if(offset.left-leftMovewindow.innerHeight&&offset.top-el.offsetHeight-marginBottom>0){offset.top-=el.offsetHeight;}else{offset.top+=offset.height;} if(offset){offset.top+=window.scrollY;offset.left+=window.scrollX;if(isRtl){offset.right+=window.scrollX;}} if(isRtl){offset.right=window.innerWidth-offset.right-el.offsetWidth;} return offset;} const isNotEditableNode=__exports.isNotEditableNode=node=>node.getAttribute&&node.getAttribute('contenteditable')&&node.getAttribute('contenteditable').toLowerCase()==='false';const isRoot=__exports.isRoot=node=>node.oid==="root";const leftLeafFirstPath=__exports.leftLeafFirstPath=createDOMPathGenerator(DIRECTIONS.LEFT);const leftLeafOnlyNotBlockPath=__exports.leftLeafOnlyNotBlockPath=createDOMPathGenerator(DIRECTIONS.LEFT,{leafOnly:true,stopTraverseFunction:isBlock,stopFunction:node=>isBlock(node)||isRoot(node),});const leftLeafOnlyInScopeNotBlockEditablePath=__exports.leftLeafOnlyInScopeNotBlockEditablePath=createDOMPathGenerator(DIRECTIONS.LEFT,{leafOnly:true,inScope:true,stopTraverseFunction:node=>isNotEditableNode(node)||isBlock(node),stopFunction:node=>isNotEditableNode(node)||isBlock(node)||isRoot(node),});const rightLeafOnlyNotBlockPath=__exports.rightLeafOnlyNotBlockPath=createDOMPathGenerator(DIRECTIONS.RIGHT,{leafOnly:true,stopTraverseFunction:isBlock,stopFunction:node=>isBlock(node)||isRoot(node),});const rightLeafOnlyPathNotBlockNotEditablePath=__exports.rightLeafOnlyPathNotBlockNotEditablePath=createDOMPathGenerator(DIRECTIONS.RIGHT,{leafOnly:true,stopFunction:node=>isRoot(node),});const rightLeafOnlyInScopeNotBlockEditablePath=__exports.rightLeafOnlyInScopeNotBlockEditablePath=createDOMPathGenerator(DIRECTIONS.RIGHT,{leafOnly:true,inScope:true,stopTraverseFunction:node=>isNotEditableNode(node)||isBlock(node),stopFunction:node=>isNotEditableNode(node)||isBlock(node)||isRoot(node),});const rightLeafOnlyNotBlockNotEditablePath=__exports.rightLeafOnlyNotBlockNotEditablePath=createDOMPathGenerator(DIRECTIONS.RIGHT,{leafOnly:true,stopTraverseFunction:node=>isNotEditableNode(node)||isBlock(node),stopFunction:node=>isBlock(node)&&!isNotEditableNode(node)||isRoot(node),});__exports.peek=peek;function peek(arr){return arr[arr.length-1];} __exports.isMacOS=isMacOS;function isMacOS(){return window.navigator.userAgent.includes('Mac');} __exports.cleanZWS=cleanZWS;function cleanZWS(node){[node,...descendants(node)].filter(node=>node.nodeType===Node.TEXT_NODE&&node.nodeValue.includes('\u200B')).forEach((node)=>{node.nodeValue=node.nodeValue.replace(/\u200B/g,"");if(node.nodeValue===""){node.remove();}});} return __exports;});; /* /web_editor/static/src/js/wysiwyg/fonts.js */ odoo.define('@web_editor/js/wysiwyg/fonts',[],function(require){'use strict';let __exports={};const fonts=__exports.fonts={cacheCssSelectors:{},getCssSelectors:function(filter){if(this.cacheCssSelectors[filter]){return this.cacheCssSelectors[filter];} this.cacheCssSelectors[filter]=[];var sheets=document.styleSheets;for(var i=0;i{data.cssData=self.getCssSelectors(data.parser);data.alias=data.cssData.map((x)=>x.names).flat();});this.computedFonts=true;}},};__exports[Symbol.for("default")]=fonts;return __exports;});; /* /web_editor/static/src/js/frontend/loadWysiwygFromTextarea.js */ odoo.define('@web_editor/js/frontend/loadWysiwygFromTextarea',['@web/core/assets','@web/core/ensure_jquery','@web_editor/js/core/owl_utils'],function(require){'use strict';let __exports={};const{loadBundle}=require("@web/core/assets");const{ensureJQuery}=require("@web/core/ensure_jquery");const{attachComponent}=require("@web_editor/js/core/owl_utils");__exports.loadWysiwygFromTextarea=loadWysiwygFromTextarea;async function loadWysiwygFromTextarea(parent,textarea,options){var loading=textarea.nextElementSibling;if(loading&&!loading.classList.contains('o_wysiwyg_loading')){loading=null;} const $textarea=$(textarea);const currentOptions=Object.assign({},options);currentOptions.value=currentOptions.value||$textarea.val()||'';if(!currentOptions.value.trim()){currentOptions.value='


';} await ensureJQuery();await loadBundle("web_editor.assets_wysiwyg");const{Wysiwyg}=await odoo.loader.modules.get('@web_editor/js/wysiwyg/wysiwyg');let wysiwyg;class LegacyWysiwyg extends Wysiwyg{constructor(...args){super(...args);wysiwyg=this;}} const $wysiwygWrapper=$textarea.closest('.o_wysiwyg_textarea_wrapper');const $form=$textarea.closest('form');$textarea.hide();$form.append($textarea);$wysiwygWrapper.html('');const wysiwygWrapper=$wysiwygWrapper[0];await attachComponent(parent,wysiwygWrapper,LegacyWysiwyg,{options:currentOptions,editingValue:currentOptions.value,});$form.find('.note-editable').data('wysiwyg',wysiwyg);$form.find('.note-editable').find('img.o_we_selected_image').removeClass('o_we_selected_image');let b64imagesPending=true;$form.on('click','button[type=submit]',(ev)=>{if(b64imagesPending){ev.preventDefault();wysiwyg.savePendingImages().finally(()=>{b64imagesPending=false;ev.currentTarget.click();});}else{$form.find('.note-editable').find('img.o_we_selected_image').removeClass('o_we_selected_image');$form.find('.note-editable').find('img.float-start').removeClass('float-start');$textarea.val(wysiwyg.getValue());}});return wysiwyg;};return __exports;});; /* /auth_signup/static/src/js/reset_password.js */ odoo.define('@auth_signup/js/reset_password',['@web/legacy/js/public/public_widget'],function(require){'use strict';let __exports={};const publicWidget=require("@web/legacy/js/public/public_widget")[Symbol.for("default")];publicWidget.registry.ResetPasswordForm=publicWidget.Widget.extend({selector:'.oe_reset_password_form',events:{'submit':'_onSubmit',},_onSubmit:function(){var $btn=this.$('.oe_login_buttons > button[type="submit"]');if($btn.prop("disabled")){return;} $btn.attr('disabled','disabled');$btn.prepend(' ');},});return __exports;});; /* /auth_signup/static/src/js/signup.js */ odoo.define('@auth_signup/js/signup',['@web/legacy/js/public/public_widget'],function(require){'use strict';let __exports={};const publicWidget=require("@web/legacy/js/public/public_widget")[Symbol.for("default")];publicWidget.registry.SignUpForm=publicWidget.Widget.extend({selector:'.oe_signup_form',events:{'submit':'_onSubmit',},_onSubmit:function(){var $btn=this.$('.oe_login_buttons > button[type="submit"]');if($btn.prop("disabled")){return;} $btn.attr('disabled','disabled');$btn.prepend(' ');},});return __exports;});; /* /portal/static/src/js/portal.js */ odoo.define('@portal/js/portal',['@web/legacy/js/public/public_widget','@web/core/network/rpc'],function(require){'use strict';let __exports={};const publicWidget=require("@web/legacy/js/public/public_widget")[Symbol.for("default")];const{rpc}=require("@web/core/network/rpc");publicWidget.registry.portalDetails=publicWidget.Widget.extend({selector:'.o_portal_details',events:{'change select[name="country_id"]':'_onCountryChange',},start:function(){var def=this._super.apply(this,arguments);this.$state=this.$('select[name="state_id"]');this.$stateOptions=this.$state.filter(':enabled').find('option:not(:first)');this._adaptAddressForm();return def;},_adaptAddressForm:function(){var $country=this.$('select[name="country_id"]');var countryID=($country.val()||0);this.$stateOptions.detach();var $displayedState=this.$stateOptions.filter('[data-country_id='+countryID+']');var nb=$displayedState.appendTo(this.$state).removeClass('d-none').show().length;this.$state.parent().toggle(nb>=1);},_onCountryChange:function(){this._adaptAddressForm();},});__exports[Symbol.for("default")]=publicWidget.registry.portalDetails;const PortalHomeCounters=__exports.PortalHomeCounters=publicWidget.Widget.extend({selector:'.o_portal_my_home',start:function(){var def=this._super.apply(this,arguments);this._updateCounters();return def;},_getCountersAlwaysDisplayed(){return[];},async _updateCounters(elem){const needed=Object.values(this.el.querySelectorAll('[data-placeholder_count]')).map(documentsCounterEl=>documentsCounterEl.dataset['placeholder_count']);const numberRpc=Math.min(Math.ceil(needed.length/5),3);const counterByRpc=Math.ceil(needed.length/numberRpc);const countersAlwaysDisplayed=this._getCountersAlwaysDisplayed();const proms=[...Array(Math.min(numberRpc,needed.length)).keys()].map(async i=>{const documentsCountersData=await rpc("/my/counters",{counters:needed.slice(i*counterByRpc,(i+1)*counterByRpc)});Object.keys(documentsCountersData).forEach(counterName=>{const documentsCounterEl=this.el.querySelector(`[data-placeholder_count='${counterName}']`);documentsCounterEl.textContent=documentsCountersData[counterName];if(documentsCountersData[counterName]!==0||countersAlwaysDisplayed.includes(counterName)){documentsCounterEl.closest('.o_portal_index_card').classList.remove('d-none');}});return documentsCountersData;});return Promise.all(proms).then((results)=>{this.el.querySelector('.o_portal_doc_spinner').remove();});},});publicWidget.registry.PortalHomeCounters=PortalHomeCounters;publicWidget.registry.portalSearchPanel=publicWidget.Widget.extend({selector:'.o_portal_search_panel',events:{'click .dropdown-item':'_onDropdownItemClick','submit':'_onSubmit',},start:function(){var def=this._super.apply(this,arguments);this._adaptSearchLabel(this.$('.dropdown-item.active'));return def;},_adaptSearchLabel:function(elem){var $label=$(elem).clone();$label.find('span.nolabel').remove();this.$('input[name="search"]').attr('placeholder',$label.text().trim());},_search:function(){var search=new URL(window.location).searchParams;search.set("search_in",this.$('.dropdown-item.active').attr('href')?.replace('#','')||"");search.set("search",this.$('input[name="search"]').val());window.location.search=search.toString();},_onDropdownItemClick:function(ev){ev.preventDefault();var $item=$(ev.currentTarget);$item.closest('.dropdown-menu').find('.dropdown-item').removeClass('active');$item.addClass('active');this._adaptSearchLabel(ev.currentTarget);},_onSubmit:function(ev){ev.preventDefault();this._search();},});return __exports;});; /* /portal/static/src/js/portal_composer.js */ odoo.define('@portal/js/portal_composer',['@web/core/l10n/translation','@web/core/utils/strings','@web/core/utils/render','@web/legacy/js/public/public_widget','@web/core/network/http_service','@odoo/owl','@web/core/network/rpc'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{escape}=require("@web/core/utils/strings");const{renderToElement}=require("@web/core/utils/render");const publicWidget=require("@web/legacy/js/public/public_widget")[Symbol.for("default")];const{post}=require("@web/core/network/http_service");const{Component}=require("@odoo/owl");const{rpc,RPCError}=require("@web/core/network/rpc");var PortalComposer=publicWidget.Widget.extend({template:'portal.Composer',events:{'change .o_portal_chatter_file_input':'_onFileInputChange','click .o_portal_chatter_attachment_btn':'_onAttachmentButtonClick','click .o_portal_chatter_attachment_delete':'async _onAttachmentDeleteClick','click .o_portal_chatter_composer_btn':'async _onSubmitButtonClick',},init:function(parent,options){this._super.apply(this,arguments);this.options=Object.assign({'allow_composer':true,'display_composer':false,'csrf_token':odoo.csrf_token,'token':false,'res_model':false,'res_id':false,'send_button_label':_t("Send"),},options||{});this.attachments=[];this.notification=this.bindService("notification");},start:function(){var self=this;this.$attachmentButton=this.$('.o_portal_chatter_attachment_btn');this.$fileInput=this.$('.o_portal_chatter_file_input');this.$sendButton=this.$('.o_portal_chatter_composer_btn');this.$attachments=this.$('.o_portal_chatter_composer_input .o_portal_chatter_attachments');this.$inputTextarea=this.$('.o_portal_chatter_composer_input textarea[name="message"]');return this._super.apply(this,arguments).then(function(){if(self.options.default_attachment_ids){self.attachments=self.options.default_attachment_ids||[];self.attachments.forEach((attachment)=>{attachment.state='done';});self._updateAttachments();} return Promise.resolve();});},_onAttachmentButtonClick:function(){this.$fileInput.click();},_onAttachmentDeleteClick:function(ev){var self=this;var attachmentId=$(ev.currentTarget).closest('.o_portal_chatter_attachment').data('id');var accessToken=this.attachments.find(attachment=>attachment.id===attachmentId).access_token;ev.preventDefault();ev.stopPropagation();this.$sendButton.prop('disabled',true);return rpc('/portal/attachment/remove',{'attachment_id':attachmentId,'access_token':accessToken,}).then(function(){self.attachments=self.attachments.filter(attachment=>attachment.id!==attachmentId);self._updateAttachments();self.$sendButton.prop('disabled',false);});},_prepareAttachmentData:function(file){return{is_pending:true,thread_id:this.options.res_id,thread_model:this.options.res_model,token:this.options.token,ufile:file,};},_onFileInputChange:function(){var self=this;this.$sendButton.prop('disabled',true);return Promise.all([...this.$fileInput[0].files].map((file)=>{return new Promise(function(resolve,reject){var data=self._prepareAttachmentData(file);if(odoo.csrf_token){data.csrf_token=odoo.csrf_token;} post('/mail/attachment/upload',data).then(function(res){let attachment=res.data["ir.attachment"][0] attachment.state='pending';self.attachments.push(attachment);self._updateAttachments();resolve();}).catch(function(error){if(error instanceof RPCError){self.notification.add(_t("Could not save file %s",escape(file.name)),{type:'warning',sticky:true});resolve();}});});})).then(function(){self.$fileInput[0].value=null;self.$sendButton.prop('disabled',false);});},_prepareMessageData:function(){return Object.assign(this.options||{},{thread_model:this.options.res_model,thread_id:this.options.res_id,post_data:{body:this.$('textarea[name="message"]').val(),attachment_ids:this.attachments.map((a)=>a.id),message_type:"comment",subtype_xmlid:"mail.mt_comment",},attachment_tokens:this.attachments.map((a)=>a.access_token),token:this.options.token,hash:this.options.hash,pid:this.options.pid,});},_onSubmitButtonClick:function(ev){ev.preventDefault();const error=this._onSubmitCheckContent();if(error){this.$inputTextarea.addClass('border-danger');this.$(".o_portal_chatter_composer_error").text(error).removeClass('d-none');return Promise.reject();}else{return this._chatterPostMessage(ev.currentTarget.getAttribute('data-action'));}},_onSubmitCheckContent:function(){if(!this.$inputTextarea.val().trim()&&!this.attachments.length){return _t('Some fields are required. Please make sure to write a message or attach a document');};},_updateAttachments:function(){this.$attachments.empty().append(renderToElement('portal.Chatter.Attachments',{attachments:this.attachments,showDelete:true,}));},_chatterPostMessage:async function(route){const result=await rpc(route,this._prepareMessageData());Component.env.bus.trigger('reload_chatter_content',result);return result;},});__exports[Symbol.for("default")]={PortalComposer:PortalComposer,};return __exports;});; /* /portal/static/src/js/portal_security.js */ odoo.define('@portal/js/portal_security',['@web/core/confirmation_dialog/confirmation_dialog','@web/core/utils/render','@web/legacy/js/public/public_widget','@portal/js/components/input_confirmation_dialog/input_confirmation_dialog','@web/core/l10n/translation','@web/core/user'],function(require){'use strict';let __exports={};const{ConfirmationDialog}=require('@web/core/confirmation_dialog/confirmation_dialog');const{renderToMarkup}=require("@web/core/utils/render");const publicWidget=require('@web/legacy/js/public/public_widget')[Symbol.for("default")];const{InputConfirmationDialog}=require("@portal/js/components/input_confirmation_dialog/input_confirmation_dialog");const{_t}=require("@web/core/l10n/translation");const{user}=require("@web/core/user");publicWidget.registry.NewAPIKeyButton=publicWidget.Widget.extend({selector:'.o_portal_new_api_key',events:{click:'_onClick'},init(){this._super(...arguments);this.orm=this.bindService("orm");this.dialog=this.bindService("dialog");},async _onClick(e){e.preventDefault();await handleCheckIdentity(this.orm.call("res.users","api_key_wizard",[user.userId]),this.orm,this.dialog);const{duration}=await this.bindService("field").loadFields("res.users.apikeys.description",{fieldNames:["duration"],});this.call("dialog","add",InputConfirmationDialog,{title:_t("New API Key"),body:renderToMarkup("portal.keydescription",{duration_selection:duration.selection.filter((option)=>option[0]!=="-1"),}),confirmLabel:_t("Confirm"),confirm:async({inputEl})=>{const formData=Object.fromEntries(new FormData(inputEl.closest("form")));const wizard_id=await this.orm.create("res.users.apikeys.description",[{name:formData['description'],duration:formData['duration']}]);const res=await handleCheckIdentity(this.orm.call("res.users.apikeys.description","make_key",[wizard_id]),this.orm,this.dialog);this.call("dialog","add",ConfirmationDialog,{title:_t("API Key Ready"),body:renderToMarkup("portal.keyshow",{key:res.context.default_key}),confirmLabel:_t("Close"),},{onClose:()=>{window.location=window.location;},})}});}});publicWidget.registry.RemoveAPIKeyButton=publicWidget.Widget.extend({selector:'.o_portal_remove_api_key',events:{click:'_onClick'},init(){this._super(...arguments);this.orm=this.bindService("orm");this.dialog=this.bindService("dialog");},async _onClick(e){e.preventDefault();await handleCheckIdentity(this.orm.call("res.users.apikeys","remove",[parseInt(this.el.id)]),this.orm,this.dialog);window.location=window.location;}});publicWidget.registry.portalSecurity=publicWidget.Widget.extend({selector:'.o_portal_security_body',init:function(){$('.modal.show#portal_deactivate_account_modal').removeClass('d-block').modal('show');$('.modal#portal_deactivate_account_modal').on('hide.bs.modal',(event)=>{const $target=$(event.currentTarget);$target.find('.alert').remove();$target.find('.invalid-feedback').remove();$target.find('.is-invalid').removeClass('is-invalid');});return this._super(...arguments);},});publicWidget.registry.RevokeSessionsButton=publicWidget.Widget.extend({selector:'#portal_revoke_all_sessions_popup',events:{click:'_onClick',},init(){this._super(...arguments);this.orm=this.bindService("orm");this.dialog=this.bindService("dialog")},async _onClick(){await handleCheckIdentity(this.orm.call("res.users","action_revoke_all_devices",[user.userId]),this.orm,this.dialog);window.location=window.location;return true;},});__exports.handleCheckIdentity=handleCheckIdentity;async function handleCheckIdentity(wrapped,ormService,dialogService){return wrapped.then((r)=>{if(!(r.type&&r.type==="ir.actions.act_window"&&r.res_model==="res.users.identitycheck")){return r;} const checkId=r.res_id;return new Promise((resolve)=>{dialogService.add(InputConfirmationDialog,{title:_t("Security Control"),body:renderToMarkup("portal.identitycheck"),confirmLabel:_t("Confirm Password"),confirm:async({inputEl})=>{if(!inputEl.reportValidity()){inputEl.classList.add("is-invalid");return false;} let result;await ormService.write("res.users.identitycheck",[checkId],{password:inputEl.value});try{result=await ormService.call("res.users.identitycheck","run_check",[checkId]);}catch{inputEl.classList.add("is-invalid");inputEl.setCustomValidity(_t("Check failed"));inputEl.reportValidity();return false;} resolve(result);return true;},cancel:()=>{},onInput:({inputEl})=>{inputEl.classList.remove("is-invalid");inputEl.setCustomValidity("");},});});});} return __exports;});; /* /portal/static/src/js/portal_sidebar.js */ odoo.define('@portal/js/portal_sidebar',['@web/core/l10n/translation','@web/legacy/js/public/public_widget','@web/core/l10n/dates'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const publicWidget=require("@web/legacy/js/public/public_widget")[Symbol.for("default")];const{deserializeDateTime}=require("@web/core/l10n/dates");const{DateTime}=luxon;var PortalSidebar=publicWidget.Widget.extend({start:function(){this._setDelayLabel();return this._super.apply(this,arguments);},_setDelayLabel:function(){var $sidebarTimeago=this.$el.find('.o_portal_sidebar_timeago').toArray();$sidebarTimeago.forEach((el)=>{var dateTime=deserializeDateTime($(el).attr('datetime')).startOf('day'),today=DateTime.now().startOf('day'),diff=dateTime.diff(today).as("days"),displayStr;if(diff===0){displayStr=_t('Due today');}else if(diff>0){displayStr=_t('Due in %s days',Math.abs(diff).toFixed());}else{displayStr=_t('%s days overdue',Math.abs(diff).toFixed());} $(el).text(displayStr);});},_printIframeContent:function(href){if(!this.printContent){this.printContent=$('');this.$el.append(this.printContent);this.printContent.on('load',function(){$(this).get(0).contentWindow.print();});}else{this.printContent.get(0).contentWindow.print();}},});__exports[Symbol.for("default")]=PortalSidebar;return __exports;});; /* /portal/static/src/js/components/input_confirmation_dialog/input_confirmation_dialog.js */ odoo.define('@portal/js/components/input_confirmation_dialog/input_confirmation_dialog',['@odoo/owl','@web/core/confirmation_dialog/confirmation_dialog'],function(require){'use strict';let __exports={};const{useEffect}=require("@odoo/owl");const{ConfirmationDialog}=require("@web/core/confirmation_dialog/confirmation_dialog");const InputConfirmationDialog=__exports.InputConfirmationDialog=class InputConfirmationDialog extends ConfirmationDialog{static props={...ConfirmationDialog.props,onInput:{type:Function,optional:true},};static template="portal.InputConfirmationDialog";setup(){super.setup();const onInput=()=>{if(this.props.onInput){this.props.onInput({inputEl:this.inputEl});}};const onKeydown=(ev)=>{if(ev.key&&ev.key.toLowerCase()==="enter"){ev.preventDefault();this._confirm();}};useEffect((inputEl)=>{this.inputEl=inputEl;if(this.inputEl){this.inputEl.focus();this.inputEl.addEventListener("keydown",onKeydown);this.inputEl.addEventListener("input",onInput);return()=>{this.inputEl.removeEventListener("keydown",onKeydown);this.inputEl.removeEventListener("input",onInput);};}},()=>[this.modalRef.el?.querySelector("input")]);} _confirm(){this.execButton(()=>this.props.confirm({inputEl:this.inputEl}));}} return __exports;});; /* /portal/static/src/signature_form/signature_form.js */ odoo.define('@portal/signature_form/signature_form',['@odoo/owl','@web/core/l10n/translation','@web/core/utils/ui','@web/core/network/rpc','@web/core/registry','@web/core/utils/urls','@web/core/signature/name_and_signature'],function(require){'use strict';let __exports={};const{Component,onMounted,useRef,useState}=require("@odoo/owl");const{_t}=require("@web/core/l10n/translation");const{addLoadingEffect}=require('@web/core/utils/ui');const{rpc}=require("@web/core/network/rpc");const{registry}=require("@web/core/registry");const{redirect}=require("@web/core/utils/urls");const{NameAndSignature}=require("@web/core/signature/name_and_signature");class SignatureForm extends Component{static template="portal.SignatureForm" static components={NameAndSignature} static props=["*"];setup(){this.rootRef=useRef("root");this.csrfToken=odoo.csrf_token;this.state=useState({error:false,success:false,});this.signature=useState({name:this.props.defaultName});this.nameAndSignatureProps={signature:this.signature,fontColor:this.props.fontColor||"black",};if(this.props.signatureRatio){this.nameAndSignatureProps.displaySignatureRatio=this.props.signatureRatio;} if(this.props.signatureType){this.nameAndSignatureProps.signatureType=this.props.signatureType;} if(this.props.mode){this.nameAndSignatureProps.mode=this.props.mode;} onMounted(()=>{this.rootRef.el.closest('.modal').addEventListener('shown.bs.modal',()=>{this.signature.resetSignature();this.toggleSignatureFormVisibility();});});} toggleSignatureFormVisibility(){this.rootRef.el.classList.toggle('d-none',document.querySelector('.editor_enable'));} get sendLabel(){return this.props.sendLabel||_t("Accept & Sign");} async onClickSubmit(){const button=document.querySelector('.o_portal_sign_submit') const icon=button.removeChild(button.firstChild) const restoreBtnLoading=addLoadingEffect(button);const name=this.signature.name;const signature=this.signature.getSignatureImage().split(",")[1];const data=await rpc(this.props.callUrl,{name,signature});if(data.force_refresh){restoreBtnLoading();button.prepend(icon) if(data.redirect_url){redirect(data.redirect_url);}else{window.location.reload();} return new Promise(()=>{});} this.state.error=data.error||false;this.state.success=!data.error&&{message:data.message,redirectUrl:data.redirect_url,redirectMessage:data.redirect_message,};}} registry.category("public_components").add("portal.signature_form",SignatureForm);return __exports;});; /* /portal/static/src/chatter/boot/boot_service.js */ odoo.define('@portal/chatter/boot/boot_service',['@web/core/utils/concurrency','@web/core/assets','@web/core/registry','@web/core/utils/functions'],function(require){'use strict';let __exports={};const{Deferred}=require("@web/core/utils/concurrency");const{loadBundle}=require("@web/core/assets");const{registry}=require("@web/core/registry");const{memoize}=require("@web/core/utils/functions");odoo.portalChatterReady=new Deferred();const loader={loadChatter:memoize(()=>loadBundle("portal.assets_chatter")),};const portalChatterBootService=__exports.portalChatterBootService={start(){const chatterEl=document.querySelector(".o_portal_chatter");if(chatterEl){loader.loadChatter();}},};registry.category("services").add("portal.chatter.boot",portalChatterBootService);return __exports;});; /* /google_recaptcha/static/src/js/recaptcha.js */ odoo.define('@google_recaptcha/js/recaptcha',['@web/session','@web/core/assets','@web/core/l10n/translation'],function(require){'use strict';let __exports={};const{session}=require("@web/session");const{loadJS}=require("@web/core/assets");const{_t}=require("@web/core/l10n/translation");const ReCaptcha=__exports.ReCaptcha=class ReCaptcha{constructor(){this._publicKey=session.recaptcha_public_key;} loadLibs(){if(this._publicKey){this._recaptchaReady=loadJS(`https://www.recaptcha.net/recaptcha/api.js?render=${encodeURIComponent(this._publicKey)}`).then(()=>new Promise(resolve=>window.grecaptcha.ready(()=>resolve())));return this._recaptchaReady.then(()=>!!document.querySelector('.grecaptcha-badge'));} return false;} async getToken(action){if(!this._publicKey){return{message:_t("No recaptcha site key set."),};} await this._recaptchaReady;try{return{token:await window.grecaptcha.execute(this._publicKey,{action:action})};}catch{return{error:_t("The recaptcha site key is invalid."),};}}} __exports[Symbol.for("default")]={ReCaptcha:ReCaptcha,};return __exports;});; /* /google_recaptcha/static/src/js/signup.js */ odoo.define('@google_recaptcha/js/signup',['@web/legacy/js/public/public_widget','@google_recaptcha/js/recaptcha'],function(require){'use strict';let __exports={};const publicWidget=require("@web/legacy/js/public/public_widget")[Symbol.for("default")];const{ReCaptcha}=require("@google_recaptcha/js/recaptcha");const CaptchaFunctionality={events:{submit:"_onSubmit",},init(){this._super(...arguments);this._recaptcha=new ReCaptcha();},async willStart(){return this._recaptcha.loadLibs();},_onSubmit(ev){if(this._recaptcha._publicKey&&!this.$el.find("input[name='recaptcha_token_response']").length){ev.preventDefault();this._recaptcha.getToken(this.tokenName).then((tokenCaptcha)=>{this.$el.append(``,);this.$el.submit();});}},};publicWidget.registry.SignupCaptcha=publicWidget.Widget.extend({...CaptchaFunctionality,selector:".oe_signup_form",tokenName:"signup",});publicWidget.registry.ResetPasswordCaptcha=publicWidget.Widget.extend({...CaptchaFunctionality,selector:".oe_reset_password_form",tokenName:"password_reset",});return __exports;});; /* /website/static/src/libs/zoomodoo/zoomodoo.js */ odoo.define('@website/libs/zoomodoo/zoomodoo',[],function(require){'use strict';let __exports={};var dw,dh,rw,rh,lx,ly;var defaults={linkTag:'a',linkAttribute:'data-zoom-image',event:'click',timer:0,preventClicks:true,disabledOnMobile:true,beforeShow:$.noop,beforeHide:$.noop,onShow:$.noop,onHide:$.noop,onMove:$.noop,beforeAttach:$.noop};function ZoomOdoo(target,options){this.$target=$(target);this.opts=$.extend({},defaults,options,this.$target.data());if(this.isOpen===undefined){this._init();}} ZoomOdoo.prototype._init=function(){if(window.outerWidth>467||!this.opts.disabledOnMobile){this.$link=this.$target.find(this.opts.linkTag).length&&this.$target.find(this.opts.linkTag)||this.$target;this.$image=this.$target.find('img').length&&this.$target.find('img')||this.$target;this.$flyout=$('
');var $attach=this.$target;if(this.opts.attach!==undefined&&this.$target.closest(this.opts.attach).length){$attach=this.$target.closest(this.opts.attach);} $attach.parent().on('mousemove.zoomodoo touchmove.zoomodoo',$.proxy(this._onMove,this));$attach.parent().on('mouseleave.zoomodoo touchend.zoomodoo',$.proxy(this._onLeave,this));this.$target.on(this.opts.event+'.zoomodoo touchstart.zoomodoo',$.proxy(this._onEnter,this));if(this.opts.preventClicks){this.$target.on('click.zoomodoo',function(e){e.preventDefault();});}else{var self=this;this.$target.on('click.zoomodoo',function(){self.hide();self.$target.unbind();});}}};ZoomOdoo.prototype.show=function(e,testMouseOver){var w1,h1,w2,h2;var self=this;if(this.opts.beforeShow.call(this)===false)return;if(!this.isReady){return this._loadImage(this.$link.attr(this.opts.linkAttribute),function(){if(self.isMouseOver||!testMouseOver){self.show(e);}});} var $attach=this.$target;if(this.opts.attach!==undefined&&this.$target.closest(this.opts.attach).length){$attach=this.$target.closest(this.opts.attach);} $attach.parent().find('.zoomodoo-flyout').remove();this.$flyout.removeAttr('style');$attach.parent().append(this.$flyout);if(this.opts.attachToTarget){this.opts.beforeAttach.call(this);this.$flyout.css('position','fixed');var flyoutOffset=this.$flyout.offset();if(flyoutOffset.left>0){var flyoutLeft=parseFloat(this.$flyout.css('left').replace('px',''));this.$flyout.css('left',flyoutLeft-flyoutOffset.left+'px');} if(flyoutOffset.top>0){var flyoutTop=parseFloat(this.$flyout.css('top').replace('px',''));this.$flyout.css('top',flyoutTop-flyoutOffset.top+'px');} if(this.$zoom.height()$(document).width()){this.$flyout.css('width',$(document).width()-left+'px');}else if(left===0){this.$flyout.css('width',offset.left+'px');} if((top+this.$flyout.height())>$(document).height()){top=$(document).height()-this.$flyout.height();} this.$flyout.css('transform','translate3d('+left+'px, '+top+'px, 0px)');}else{var rightAvailableSpace=document.body.clientWidth-this.$flyout[0].getBoundingClientRect().left;this.$flyout.css('max-width',rightAvailableSpace);} w1=this.$target[0].offsetWidth;h1=this.$target[0].offsetHeight;w2=this.$flyout.width();h2=this.$flyout.height();dw=this.$zoom.width()-w2;dh=this.$zoom.height()-h2;if(dw<0)dw=0;if(dh<0)dh=0;rw=dw/w1;rh=dh/h1;this.isOpen=true;this.opts.onShow.call(this);if(e){this._move(e);}};ZoomOdoo.prototype._onEnter=function(e){var self=this;var touches=e.originalEvent.touches;e.preventDefault();this.isMouseOver=true;setTimeout(function(){if(self.isMouseOver&&(!touches||touches.length===1)){self.show(e,true);}},this.opts.timer);};ZoomOdoo.prototype._onMove=function(e){if(!this.isOpen)return;e.preventDefault();this._move(e);};ZoomOdoo.prototype._onLeave=function(){this.isMouseOver=false;if(this.isOpen){this.hide();}};ZoomOdoo.prototype._onLoad=function(e){if(!e.currentTarget.width)return;this.isReady=true;this.$flyout.html(this.$zoom);if(e.data.call){e.data();}};ZoomOdoo.prototype._loadImage=function(href,callback){var zoom=new Image();this.$zoom=$(zoom).on('load',callback,$.proxy(this._onLoad,this));zoom.style.position='absolute';zoom.src=href;};ZoomOdoo.prototype._move=function(e){if(e.type.indexOf('touch')===0){var touchlist=e.touches||e.originalEvent.touches;lx=touchlist[0].pageX;ly=touchlist[0].pageY;}else{lx=e.pageX||lx;ly=e.pageY||ly;} var offset=this.$target.offset();var pt=ly-offset.top;var pl=lx-offset.left;var xt=Math.ceil(pt*rh);var xl=Math.ceil(pl*rw);if(!this.opts.attachToTarget&&(xl<0||xt<0||xl>dw||xt>dh||lx>(offset.left+this.$target.outerWidth()))){this.hide();}else{var top=xt*-1;var left=xl*-1;this.$zoom.css({top:top,left:left});this.opts.onMove.call(this,top,left);}};ZoomOdoo.prototype.hide=function(){if(!this.isOpen)return;if(this.opts.beforeHide.call(this)===false)return;this.$flyout.detach();this.isOpen=false;this.opts.onHide.call(this);};$.fn.zoomOdoo=function(options){return this.each(function(){var api=$.data(this,'zoomOdoo');if(!api){$.data(this,'zoomOdoo',new ZoomOdoo(this,options));}else if(api.isOpen===undefined){api._init();}});};return __exports;});; /* /website/static/src/libs/bootstrap/bootstrap.js */ odoo.define('@website/libs/bootstrap/bootstrap',[],function(require){'use strict';let __exports={};const bsGetOffsetFunction=Dropdown.prototype._getOffset;Dropdown.prototype._getOffset=function(){const offset=bsGetOffsetFunction.apply(this,arguments);if(this._element.closest(".o_hoverable_dropdown .navbar")){return[offset[0],0];} return offset;};return __exports;});; /* /website/static/src/js/utils.js */ odoo.define('@website/js/utils',['@web/core/utils/arrays','@web/core/l10n/translation','@web/core/utils/render','@odoo/owl','@web/core/templates','@website/components/autocomplete_with_pages/url_autocomplete'],function(require){'use strict';let __exports={};const{intersection}=require("@web/core/utils/arrays");const{_t}=require("@web/core/l10n/translation");const{renderToElement}=require("@web/core/utils/render");const{App,Component}=require("@odoo/owl");const{getTemplate}=require("@web/core/templates");const{UrlAutoComplete}=require("@website/components/autocomplete_with_pages/url_autocomplete");function loadAnchors(url,body){return new Promise(function(resolve,reject){if(url===window.location.pathname||url[0]==='#'){resolve(body?body:document.body.outerHTML);}else if(url.length&&!url.startsWith("http")){$.get(window.location.origin+url).then(resolve,reject);}else{resolve();}}).then(function(response){const anchors=$(response).find('[id][data-anchor=true], .modal[id][data-display="onClick"]').toArray().map((el)=>{return'#'+el.id;});if(!anchors.includes('#top')){anchors.unshift('#top');} if(!anchors.includes('#bottom')){anchors.push('#bottom');} return anchors;}).catch(error=>{console.debug(error);return[];});} function autocompleteWithPages(input,options={}){const owlApp=new App(UrlAutoComplete,{env:Component.env,dev:Component.env.debug,getTemplate,props:{options,loadAnchors,targetDropdown:input,},translatableAttributes:["data-tooltip"],translateFn:_t,});const container=document.createElement("div");container.classList.add("ui-widget","ui-autocomplete","ui-widget-content","border-0");document.body.appendChild(container);owlApp.mount(container) return()=>{owlApp.destroy();container.remove();}} function onceAllImagesLoaded($element,$excluded){var defs=Array.from($element.find("img").addBack("img")).map((img)=>{if(img.complete||$excluded&&($excluded.is(img)||$excluded.has(img).length)){return;} var def=new Promise(function(resolve,reject){$(img).one('load',function(){resolve();});});return def;});return Promise.all(defs);} function prompt(options,_qweb){if(typeof options==='string'){options={text:options};} if(typeof _qweb==="undefined"){_qweb='website.prompt';} options=Object.assign({window_title:'',field_name:'','default':'',init:function(){},btn_primary_title:_t('Create'),btn_secondary_title:_t('Cancel'),},options||{});var type=intersection(Object.keys(options),['input','textarea','select']);type=type.length?type[0]:'input';options.field_type=type;options.field_name=options.field_name||options[type];var def=new Promise(function(resolve,reject){var dialog=$(renderToElement(_qweb,options)).appendTo('body');options.$dialog=dialog;var field=dialog.find(options.field_type).first();field.val(options['default']);field.fillWith=function(data){if(field.is('select')){var select=field[0];data.forEach(function(item){select.options[select.options.length]=new window.Option(item[1],item[0]);});}else{field.val(data);}};var init=options.init(field,dialog);Promise.resolve(init).then(function(fill){if(fill){field.fillWith(fill);} dialog.modal('show');field.focus();dialog.on('click','.btn-primary',function(){var backdrop=$('.modal-backdrop');resolve({val:field.val(),field:field,dialog:dialog});dialog.modal('hide').remove();backdrop.remove();});});dialog.on('hidden.bs.modal',function(){var backdrop=$('.modal-backdrop');reject();dialog.remove();backdrop.remove();});if(field.is('input[type="text"], select')){field.keypress(function(e){if(e.key==="Enter"){e.preventDefault();dialog.find('.btn-primary').trigger('click');}});}});return def;} function websiteDomain(self){var websiteID;self.trigger_up('context_get',{callback:function(ctx){websiteID=ctx['website_id'];},});return['|',['website_id','=',false],['website_id','=',websiteID]];} function isHTTPSorNakedDomainRedirection(url1,url2){try{url1=new URL(url1).host;url2=new URL(url2).host;}catch{return false;} return url1===url2||url1.replace(/^www\./,'')===url2.replace(/^www\./,'');} function sendRequest(route,params){function _addInput(form,name,value){let param=document.createElement('input');param.setAttribute('type','hidden');param.setAttribute('name',name);param.setAttribute('value',value);form.appendChild(param);} let form=document.createElement('form');form.setAttribute('action',route);form.setAttribute('method',params.method||'POST');if(params.forceTopWindow){form.setAttribute('target','_top');} if(odoo.csrf_token){_addInput(form,'csrf_token',odoo.csrf_token);} for(const key in params){const value=params[key];if(Array.isArray(value)&&value.length){for(const val of value){_addInput(form,key,val);}}else{_addInput(form,key,value);}} document.body.appendChild(form);form.submit();} __exports.svgToPNG=svgToPNG;async function svgToPNG(src){return _exportToPNG(src,"svg+xml");} __exports.webpToPNG=webpToPNG;async function webpToPNG(src){return _exportToPNG(src,"webp");} async function _exportToPNG(src,format){function checkImg(imgEl){return(imgEl.naturalHeight!==0);} function toPNGViaCanvas(imgEl){const canvas=document.createElement('canvas');canvas.width=imgEl.width;canvas.height=imgEl.height;canvas.getContext('2d').drawImage(imgEl,0,0);return canvas.toDataURL('image/png');} if(src instanceof HTMLImageElement){const loadedImgEl=src;if(checkImg(loadedImgEl)){return toPNGViaCanvas(loadedImgEl);} src=loadedImgEl.src;} return new Promise(resolve=>{const imgEl=new Image();imgEl.onload=()=>{if(format!=="svg+xml"||checkImg(imgEl)){resolve(imgEl);return;} imgEl.height=1000;imgEl.style.opacity=0;document.body.appendChild(imgEl);const request=new XMLHttpRequest();request.open('GET',imgEl.src,true);request.onload=()=>{const parser=new DOMParser();const result=parser.parseFromString(request.responseText,'text/xml');const svgEl=result.getElementsByTagName("svg")[0];svgEl.setAttribute('width',imgEl.width);svgEl.setAttribute('height',imgEl.height);imgEl.remove();const svg64=btoa(new XMLSerializer().serializeToString(svgEl));const finalImg=new Image();finalImg.onload=()=>{resolve(finalImg);};finalImg.src=`data:image/svg+xml;base64,${svg64}`;};request.send();};imgEl.src=src;}).then(loadedImgEl=>toPNGViaCanvas(loadedImgEl));} __exports.generateGMapIframe=generateGMapIframe;function generateGMapIframe(){const iframeEl=document.createElement('iframe');iframeEl.classList.add('s_map_embedded','o_not_editable');iframeEl.setAttribute('width','100%');iframeEl.setAttribute('height','100%');iframeEl.setAttribute('frameborder','0');iframeEl.setAttribute('scrolling','no');iframeEl.setAttribute('marginheight','0');iframeEl.setAttribute('marginwidth','0');iframeEl.setAttribute('src','about:blank');iframeEl.setAttribute('aria-label',_t("Map"));return iframeEl;} __exports.generateGMapLink=generateGMapLink;function generateGMapLink(dataset){return'https://maps.google.com/maps?q='+encodeURIComponent(dataset.mapAddress) +'&t='+encodeURIComponent(dataset.mapType) +'&z='+encodeURIComponent(dataset.mapZoom) +'&ie=UTF8&iwloc=&output=embed';} function isMobile(self){let isMobile;self.trigger_up("service_context_get",{callback:(ctx)=>{isMobile=ctx["isMobile"];},});return isMobile;} function getParsedDataFor(formId,parentEl){const dataForEl=parentEl.querySelector(`[data-for='${formId}']`);if(!dataForEl){return;} return JSON.parse(dataForEl.dataset.values.replace(/([,:\[]\s*)True/g,'$1true').replace(/([,:\[]\s*)(False|None)/g,'$1""').replace(/'(\s*[,:\]}])/g,'"$1').replace(/([{\[:,]\s*)'/g,'$1"'));} __exports.cloneContentEls=cloneContentEls;function cloneContentEls(content,keepScripts=false){let copyFragment;if(typeof content==="string"){copyFragment=new Range().createContextualFragment(content);}else{copyFragment=new DocumentFragment();const els=[...content.children].map(el=>el.cloneNode(true));copyFragment.append(...els);} if(!keepScripts){copyFragment.querySelectorAll("script").forEach(scriptEl=>scriptEl.remove());} return copyFragment;} __exports.checkAndNotifySEO=checkAndNotifySEO;function checkAndNotifySEO(seo_data,OptimizeSEODialog,services){if(seo_data){let message;if(!seo_data.website_meta_title){message=_t("Page title not set.");}else if(!seo_data.website_meta_description){message=_t("Page description not set.");} if(message){const closeNotification=services.notification.add(message,{type:"warning",sticky:false,buttons:[{name:_t("Optimize SEO"),onClick:()=>{services.dialog.add(OptimizeSEODialog);closeNotification();},},],});}}} __exports[Symbol.for("default")]={loadAnchors:loadAnchors,autocompleteWithPages:autocompleteWithPages,onceAllImagesLoaded:onceAllImagesLoaded,prompt:prompt,sendRequest:sendRequest,websiteDomain:websiteDomain,isHTTPSorNakedDomainRedirection:isHTTPSorNakedDomainRedirection,svgToPNG:svgToPNG,webpToPNG:webpToPNG,generateGMapIframe:generateGMapIframe,generateGMapLink:generateGMapLink,isMobile:isMobile,getParsedDataFor:getParsedDataFor,cloneContentEls:cloneContentEls,checkAndNotifySEO:checkAndNotifySEO,};return __exports;});; /* /website/static/src/components/autocomplete_with_pages/autocomplete_with_pages.js */ odoo.define('@website/components/autocomplete_with_pages/autocomplete_with_pages',['@web/core/autocomplete/autocomplete','@odoo/owl'],function(require){'use strict';let __exports={};const{AutoComplete}=require("@web/core/autocomplete/autocomplete");const{useEffect}=require("@odoo/owl");const AutoCompleteWithPages=__exports.AutoCompleteWithPages=class AutoCompleteWithPages extends AutoComplete{static props={...AutoComplete.props,targetDropdown:{type:HTMLElement},dropdownClass:{type:String,optional:true},dropdownOptions:{type:Object,optional:true},};static template="website.AutoCompleteWithPages";setup(){super.setup();useEffect((input,inputRef)=>{if(inputRef){inputRef.value=input.value;} const targetBlur=this.onInputBlur.bind(this);const targetClick=this._syncInputClick.bind(this);const targetChange=this.onInputChange.bind(this);const targetInput=this._syncInputValue.bind(this);const targetKeydown=this.onInputKeydown.bind(this);const targetFocus=this.onInputFocus.bind(this);input.addEventListener("blur",targetBlur);input.addEventListener("click",targetClick);input.addEventListener("change",targetChange);input.addEventListener("input",targetInput);input.addEventListener("keydown",targetKeydown);input.addEventListener("focus",targetFocus);return()=>{input.removeEventListener("blur",targetBlur);input.removeEventListener("click",targetClick);input.removeEventListener("change",targetChange);input.removeEventListener("input",targetInput);input.removeEventListener("keydown",targetKeydown);input.removeEventListener("focus",targetFocus);};},()=>[this.targetDropdown,this.inputRef.el]);} get dropdownOptions(){if(this.props.dropdownOptions){return{...super.dropdownOptions,...this.props.dropdownOptions,};} return super.dropdownOptions;} get ulDropdownClass(){let classList=super.ulDropdownClass;if(this.props.dropdownClass){classList+=` ${this.props.dropdownClass}`;} return classList;} get targetDropdown(){return this.props.targetDropdown;} _syncInputClick(ev){ev.stopPropagation();this.onInputClick(ev);} async _syncInputValue(){if(this.inputRef.el){this.inputRef.el.value=this.targetDropdown.value;this.onInput();}} _isCategory(option){return!!option?.separator;} getOption(indices){const[sourceIndex,optionIndex]=indices;return this.sources[sourceIndex]?.options[optionIndex];} onOptionMouseEnter(indices){if(!this._isCategory(this.getOption(indices))){return super.onOptionMouseEnter(...arguments);}} onOptionMouseLeave(indices){if(!this._isCategory(this.getOption(indices))){return super.onOptionMouseLeave(...arguments);}} isActiveSourceOption(indices){if(!this._isCategory(this.getOption(indices))){return super.isActiveSourceOption(...arguments);}} selectOption(option){if(!this._isCategory(option)){const{value}=Object.getPrototypeOf(option);this.targetDropdown.value=value;return super.selectOption(...arguments);}} navigate(direction){super.navigate(direction);if(direction!==0&&this.state.activeSourceOption){let[sourceIndex,optionIndex]=this.state.activeSourceOption;const option=this.sources[sourceIndex]?.options[optionIndex];if(option){if(!!option.separator){this.navigate(direction);} const suggestion=Object.getPrototypeOf(option);if(suggestion&&suggestion.value){this.inputRef.el.value=suggestion.value;}}}} onInputFocus(ev){this.targetDropdown.setSelectionRange(0,this.targetDropdown.value.length);this.props.onFocus(ev);}} return __exports;});; /* /website/static/src/components/autocomplete_with_pages/url_autocomplete.js */ odoo.define('@website/components/autocomplete_with_pages/url_autocomplete',['@odoo/owl','@web/core/network/rpc','@website/components/autocomplete_with_pages/autocomplete_with_pages'],function(require){'use strict';let __exports={};const{Component}=require("@odoo/owl");const{rpc}=require("@web/core/network/rpc");const{AutoCompleteWithPages}=require("@website/components/autocomplete_with_pages/autocomplete_with_pages");const UrlAutoComplete=__exports.UrlAutoComplete=class UrlAutoComplete extends Component{static props={options:{type:Object},loadAnchors:{type:Function},targetDropdown:{type:HTMLElement},};static template="website.UrlAutoComplete";static components={AutoCompleteWithPages};_mapItemToSuggestion(item){return{...item,classList:item.separator?"ui-autocomplete-category":"ui-autocomplete-item",};} get dropdownClass(){const classList=[];for(const key in this.props.options?.classes){classList.push(key,this.props.options.classes[key]);} return classList.join(" ")} get dropdownOptions(){const options={};if(this.props.options?.position){options.position=this.props.options?.position;} return options;} get sources(){return[{optionTemplate:"website.AutoCompleteWithPagesItem",options:async(term)=>{if(term[0]==="#"){const anchors=await this.props.loadAnchors(term,this.props.options&&this.props.options.body);return anchors.map((anchor)=>this._mapItemToSuggestion({label:anchor,value:anchor}));}else if(term.startsWith("http")||term.length===0){return[];} if(this.props.options.isDestroyed?.()){return[];} const res=await rpc("/website/get_suggested_links",{needle:term,limit:15,});let choices=res.matching_pages;res.others.forEach((other)=>{if(other.values.length){choices=choices.concat([{separator:other.title,label:other.title}],other.values);}});return choices.map(this._mapItemToSuggestion);},},];} onSelect(selectedSubjection,{input}){const{value}=Object.getPrototypeOf(selectedSubjection);input.value=value;this.props.targetDropdown.value=value;this.props.options.urlChosen?.();} onInput({inputValue}){this.props.targetDropdown.value=inputValue;}} return __exports;});; /* /website/static/src/js/tours/tour_utils.js */ odoo.define('@website/js/tours/tour_utils',['@web/core/l10n/translation','@web/core/registry','@web/core/browser/cookie','@odoo/owl','@web/core/utils/objects','@web/core/macro'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{registry}=require("@web/core/registry");const{cookie}=require("@web/core/browser/cookie");const{markup}=require("@odoo/owl");const{omit}=require("@web/core/utils/objects");const{waitForStable}=require("@web/core/macro");__exports.addMedia=addMedia;function addMedia(position="right"){return{trigger:`.modal-content footer .btn-primary`,content:markup(_t("Add the selected image.")),tooltipPosition:position,run:"click",};} __exports.assertCssVariable=assertCssVariable;function assertCssVariable(variableName,variableValue,trigger=':iframe body'){return{isActive:["auto"],content:`Check CSS variable ${variableName}=${variableValue}`,trigger:trigger,run(){const styleValue=getComputedStyle(this.anchor).getPropertyValue(variableName);if((styleValue&&styleValue.trim().replace(/["']/g,''))!==variableValue.trim().replace(/["']/g,'')){throw new Error(`Failed precondition: ${variableName}=${styleValue} (should be ${variableValue})`);}},};} __exports.assertPathName=assertPathName;function assertPathName(pathname,trigger){return{content:`Check if we have been redirected to ${pathname}`,trigger:trigger,async run(){await new Promise((resolve)=>{let elapsedTime=0;const intervalTime=100;const interval=setInterval(()=>{if(window.location.pathname.startsWith(pathname)){clearInterval(interval);resolve();} elapsedTime+=intervalTime;if(elapsedTime>=5000){clearInterval(interval);console.error(`The pathname ${pathname} has not been found`);}},intervalTime);});},};} __exports.changeBackground=changeBackground;function changeBackground(snippet,position="bottom"){return[{trigger:".o_we_customize_panel .o_we_bg_success",content:markup(_t("Customize any block through this menu. Try to change the background image of this block.")),tooltipPosition:position,run:"click",},];} __exports.changeBackgroundColor=changeBackgroundColor;function changeBackgroundColor(position="bottom"){return{trigger:".o_we_customize_panel .o_we_color_preview",content:markup(_t("Customize any block through this menu. Try to change the background color of this block.")),tooltipPosition:position,run:"click",};} __exports.selectColorPalette=selectColorPalette;function selectColorPalette(position="left"){return{trigger:".o_we_customize_panel .o_we_so_color_palette we-selection-items, .o_we_customize_panel .o_we_color_preview",content:markup(_t(`Select a Color Palette.`)),tooltipPosition:position,run:'click',};} __exports.changeColumnSize=changeColumnSize;function changeColumnSize(position="right"){return{trigger:`:iframe .oe_overlay.o_draggable.o_we_overlay_sticky.oe_active .o_handle.e`,content:markup(_t("Slide this button to change the column size.")),tooltipPosition:position,run:"click",};} __exports.changeImage=changeImage;function changeImage(snippet,position="bottom"){return[{trigger:"body.editor_enable",},{trigger:snippet.id?`#wrapwrap .${snippet.id} img`:snippet,content:markup(_t("Double click on an image to change it with one of your choice.")),tooltipPosition:position,run:"dblclick",},];} __exports.changeOption=changeOption;function changeOption(optionName,weName='',optionTooltipLabel='',position="bottom",allowPalette=false){const noPalette=allowPalette?'':'.o_we_customize_panel:not(:has(.o_we_so_color_palette.o_we_widget_opened))';const option_block=`${noPalette} we-customizeblock-option[class='snippet-option-${optionName}']`;return{trigger:`${option_block} ${weName}, ${option_block} [title='${weName}']`,content:markup(_t("Click on this option to change the %s of the block.",optionTooltipLabel)),tooltipPosition:position,run:"click",};} __exports.selectNested=selectNested;function selectNested(trigger,optionName,altTrigger=null,optionTooltipLabel='',position="top",allowPalette=false){const noPalette=allowPalette?'':'.o_we_customize_panel:not(:has(.o_we_so_color_palette.o_we_widget_opened))';const option_block=`${noPalette} we-customizeblock-option[class='snippet-option-${optionName}']`;return{trigger:trigger+(altTrigger?`, ${option_block} ${altTrigger}`:""),content:markup(_t("Select a %s.",optionTooltipLabel)),tooltipPosition:position,run:'click',};} __exports.changePaddingSize=changePaddingSize;function changePaddingSize(direction){let paddingDirection="n";let position="top";if(direction==="bottom"){paddingDirection="s";position="bottom";} return{trigger:`:iframe .oe_overlay.o_draggable.o_we_overlay_sticky.oe_active .o_handle.${paddingDirection}`,content:markup(_t("Slide this button to change the %s padding",direction)),tooltipPosition:position,run:"click",};} __exports.checkIfVisibleOnScreen=checkIfVisibleOnScreen;function checkIfVisibleOnScreen(elementSelector){return{content:"Check if the element is visible on screen",trigger:`${elementSelector}`,run(){const boundingRect=this.anchor.getBoundingClientRect();const centerX=boundingRect.left+boundingRect.width/2;const centerY=boundingRect.top+boundingRect.height/2;const iframeDocument=document.querySelector(".o_iframe").contentDocument;const el=iframeDocument.elementFromPoint(centerX,centerY);if(!this.anchor.contains(el)){console.error("The element is not visible on screen");}},};} __exports.clickOnElement=clickOnElement;function clickOnElement(elementName,selector){return{content:`Clicking on the ${elementName}`,trigger:selector,run:'click'};} __exports.clickOnEditAndWaitEditMode=clickOnEditAndWaitEditMode;function clickOnEditAndWaitEditMode(position="bottom"){return[{content:markup(_t("Click Edit to start designing your homepage.")),trigger:"body:not(.editor_has_snippets) .o_menu_systray .o_edit_website_container a",tooltipPosition:position,run:"click",},{content:"Check that we are in edit mode",trigger:".o_website_preview.editor_enable.editor_has_snippets",}];} __exports.clickOnEditAndWaitEditModeInTranslatedPage=clickOnEditAndWaitEditModeInTranslatedPage;function clickOnEditAndWaitEditModeInTranslatedPage(position="bottom"){return[{content:markup(_t("Click Edit dropdown")),trigger:".o_edit_website_container button",tooltipPosition:position,run:"click",},{content:markup(_t("Click Edit to start designing your homepage.")),trigger:".o_edit_website_dropdown_item",tooltipPosition:position,run:"click",},{content:"Check that we are in edit mode",trigger:".o_website_preview.editor_enable.editor_has_snippets",}];} __exports.clickOnSnippet=clickOnSnippet;function clickOnSnippet(snippet,position="bottom"){const trigger=snippet.id?`#wrapwrap .${snippet.id}`:snippet;return[{trigger:"body.editor_has_snippets",noPrepend:true,},{trigger:`:iframe ${trigger}`,content:markup(_t("Click on a snippet to access its options menu.")),tooltipPosition:position,run:"click",},];} __exports.clickOnSave=clickOnSave;function clickOnSave(position="bottom",timeout=50000){return[{trigger:"#oe_snippets:not(:has(.o_we_ongoing_insertion))",},{trigger:"body:not(:has(.o_dialog))",noPrepend:true,},{trigger:"button[data-action=save]:enabled:contains(save)",content:markup(_t("Good job! It's time to Save your work.")),tooltipPosition:position,async run(actions){await waitForStable(document,1000);await actions.click();},timeout,},{trigger:"body:not(.editor_has_dummy_snippets):not(.o_website_navbar_hide):not(.editor_has_snippets):not(:has(.o_notification_bar))",noPrepend:true,timeout,},];} __exports.clickOnText=clickOnText;function clickOnText(snippet,element,position="bottom"){return[{trigger:":iframe body.editor_enable",},{trigger:snippet.id?`:iframe #wrapwrap .${snippet.id} ${element}`:snippet,content:markup(_t("Click on a text to start editing it.")),tooltipPosition:position,run:"click",},];} __exports.insertSnippet=insertSnippet;function insertSnippet(snippet,position="bottom"){const blockEl=snippet.groupName||snippet.name;const insertSnippetSteps=[{trigger:".o_website_preview.editor_enable.editor_has_snippets",noPrepend:true,}];if(snippet.groupName){insertSnippetSteps.push({content:markup(_t("Click on the %s category.",blockEl)),trigger:`#oe_snippets .oe_snippet[name="${blockEl}"].o_we_draggable .oe_snippet_thumbnail:not(.o_we_ongoing_insertion)`,tooltipPosition:position,run:"click",},{content:markup(_t("Click on the %s building block.",snippet.name)),trigger:`:iframe .o_snippet_preview_wrap[data-snippet-id="${snippet.id}"]:not(.d-none)`,noPrepend:true,tooltipPosition:"top",run:"click",},{trigger:`#oe_snippets .oe_snippet[name="${blockEl}"].o_we_draggable .oe_snippet_thumbnail:not(.o_we_ongoing_insertion)`,});}else{insertSnippetSteps.push({content:markup(_t("Drag the %s block and drop it at the bottom of the page.",blockEl)),trigger:`#oe_snippets .oe_snippet[name="${blockEl}"].o_we_draggable .oe_snippet_thumbnail:not(.o_we_ongoing_insertion)`,tooltipPosition:position,run:"drag_and_drop :iframe #wrapwrap > footer",});} return insertSnippetSteps;} __exports.goBackToBlocks=goBackToBlocks;function goBackToBlocks(position="bottom"){return{trigger:'.o_we_add_snippet_btn',content:_t("Click here to go back to block tab."),tooltipPosition:position,run:"click",};} __exports.goToTheme=goToTheme;function goToTheme(position="bottom"){return[{trigger:"#oe_snippets.o_loaded",},{trigger:".o_we_customize_theme_btn",content:_t("Go to the Theme tab"),tooltipPosition:position,run:"click",},];} __exports.selectHeader=selectHeader;function selectHeader(position="bottom"){return{trigger:`:iframe header#top`,content:markup(_t(`Click on this header to configure it.`)),tooltipPosition:position,run:"click",};} __exports.selectSnippetColumn=selectSnippetColumn;function selectSnippetColumn(snippet,index=0,position="bottom"){return{trigger:`:iframe #wrapwrap .${snippet.id} .row div[class*="col-lg-"]:eq(${index})`,content:markup(_t("Click on this column to access its options.")),tooltipPosition:position,run:"click",};} __exports.prepend_trigger=prepend_trigger;function prepend_trigger(steps,prepend_text=''){for(const step of steps){if(!step.noPrepend&&prepend_text){step.trigger=prepend_text+step.trigger;}} return steps;} __exports.getClientActionUrl=getClientActionUrl;function getClientActionUrl(path,edition){let url=`/odoo/action-website.website_preview`;if(path){url+=`?path=${encodeURIComponent(path)}`;} if(edition){url+=`${path ? '&' : '?'}enable_editor=1`;} return url;} __exports.clickOnExtraMenuItem=clickOnExtraMenuItem;function clickOnExtraMenuItem(stepOptions,backend=false){return Object.assign({content:"Click on the extra menu dropdown toggle if it is there and not shown",trigger:`${ backend ? ":iframe" : "" } ul.top_menu`,run(actions){const extraMenuButton=this.anchor.querySelector(".o_extra_menu_items a.nav-link");if(extraMenuButton&&!extraMenuButton.classList.contains("show")){actions.click(extraMenuButton);}},},stepOptions);} __exports.registerWebsitePreviewTour=registerWebsitePreviewTour;function registerWebsitePreviewTour(name,options,steps){if(typeof steps!=="function"){throw new Error(`tour.steps has to be a function that returns TourStep[]`);} registry.category("web_tour.tours").remove(name);return registry.category("web_tour.tours").add(name,{...omit(options,"edition"),url:getClientActionUrl(options.url,!!options.edition),steps:()=>{const tourSteps=[...steps()];if(options.edition){tourSteps.unshift({content:"Wait for the edit mode to be started",trigger:".o_website_preview.editor_enable.editor_has_snippets",timeout:30000,});}else{tourSteps[0].timeout=20000;} return tourSteps.map((step)=>{delete step.noPrepend;return step;});},});} __exports.registerThemeHomepageTour=registerThemeHomepageTour;function registerThemeHomepageTour(name,steps){if(typeof steps!=="function"){throw new Error(`tour.steps has to be a function that returns TourStep[]`);} return registerWebsitePreviewTour("homepage",{url:"/",},()=>[...clickOnEditAndWaitEditMode(),...prepend_trigger(steps().concat(clickOnSave()),".o_website_preview[data-view-xmlid='website.homepage'] "),]);} __exports.registerBackendAndFrontendTour=registerBackendAndFrontendTour;function registerBackendAndFrontendTour(name,options,steps){if(typeof steps!=="function"){throw new Error(`tour.steps has to be a function that returns TourStep[]`);} if(window.location.pathname==='/odoo'){return registerWebsitePreviewTour(name,options,()=>{const newSteps=[];for(const step of steps()){const newStep=Object.assign({},step);newStep.trigger=`:iframe ${step.trigger}`;newSteps.push(newStep);} return newSteps;});} return registry.category("web_tour.tours").add(name,{url:options.url,steps:()=>{return steps();},});} __exports.selectElementInWeSelectWidget=selectElementInWeSelectWidget;function selectElementInWeSelectWidget(widgetName,elementName,searchNeeded=false){const steps=[clickOnElement(`${widgetName} toggler`,`we-select[data-name=${widgetName}] we-toggler`)];if(searchNeeded){steps.push({content:`Inputing ${elementName} in m2o widget search`,trigger:`we-select[data-name=${widgetName}] div.o_we_m2o_search input`,run:`edit ${elementName}`,});} steps.push(clickOnElement(`${elementName} in the ${widgetName} widget`,`we-select[data-name="${widgetName}"] we-button:contains("${elementName}"), `+`we-select[data-name="${widgetName}"] we-button[data-select-label="${elementName}"]`));return steps;} __exports.switchWebsite=switchWebsite;function switchWebsite(websiteId,websiteName){return[{content:`Click on the website switch to switch to website '${websiteName}'`,trigger:'.o_website_switcher_container button',run:"click",},{trigger:`:iframe html:not([data-website-id="${websiteId}"])`,},{content:`Switch to website '${websiteName}'`,trigger:`.o-dropdown--menu .dropdown-item[data-website-id="${websiteId}"]:contains("${websiteName}")`,run:"click",},{content:"Wait for the iframe to be loaded",timeout:20000,trigger:`:iframe html[data-website-id="${websiteId}"]`,}];} __exports.testSwitchWebsite=testSwitchWebsite;function testSwitchWebsite(websiteName){const websiteIdMapping=JSON.parse(cookie.get('websiteIdMapping')||'{}');const websiteId=websiteIdMapping[websiteName];return switchWebsite(websiteId,websiteName)} __exports.toggleMobilePreview=toggleMobilePreview;function toggleMobilePreview(toggleOn){const onOrOff=toggleOn?"on":"off";const mobileOnSelector=".o_is_mobile";const mobileOffSelector=":not(.o_is_mobile)";return[{trigger:`:iframe html${toggleOn ? mobileOffSelector : mobileOnSelector}`,},{content:`Toggle the mobile preview ${onOrOff}`,trigger:".o_we_website_top_actions [data-action='mobile']",run:"click",},{content:`Check that the mobile preview is ${onOrOff}`,trigger:`:iframe html${toggleOn ? mobileOnSelector : mobileOffSelector}`,},];} return __exports;});; /* /website/static/src/js/content/website_root.js */ odoo.define('@website/js/content/website_root',['@web/core/assets','@web/core/l10n/translation','@web/core/user','@web/core/network/rpc','@web/legacy/js/public/public_root','@website/libs/zoomodoo/zoomodoo','@web/core/utils/objects','@odoo/owl'],function(require){'use strict';let __exports={};const{loadJS}=require("@web/core/assets");const{_t}=require("@web/core/l10n/translation");const{user}=require("@web/core/user");const{rpc}=require("@web/core/network/rpc");const publicRootData=require('@web/legacy/js/public/public_root')[Symbol.for("default")];require("@website/libs/zoomodoo/zoomodoo");const{pick}=require("@web/core/utils/objects");const{markup}=require("@odoo/owl");const WebsiteRoot=__exports.WebsiteRoot=publicRootData.PublicRoot.extend({events:Object.assign({},publicRootData.PublicRoot.prototype.events||{},{'click .js_change_lang':'_onLangChangeClick','click .js_publish_management .js_publish_btn':'_onPublishBtnClick','shown.bs.modal':'_onModalShown',}),custom_events:Object.assign({},publicRootData.PublicRoot.prototype.custom_events||{},{'gmap_api_request':'_onGMapAPIRequest','gmap_api_key_request':'_onGMapAPIKeyRequest','ready_to_clean_for_save':'_onWidgetsStopRequest','seo_object_request':'_onSeoObjectRequest','will_remove_snippet':'_onWidgetsStopRequest',}),init(){this.isFullscreen=false;this.notification=this.bindService("notification");this.orm=this.bindService("orm");return this._super(...arguments);},start:function(){this.$('.zoomable img[data-zoom]').zoomOdoo();return this._super.apply(this,arguments);},_getContext:function(context){var html=document.documentElement;return Object.assign({'website_id':html.getAttribute('data-website-id')|0,},this._super.apply(this,arguments));},_getExtraContext:function(context){var html=document.documentElement;return Object.assign({'editable':!!(html.dataset.editable||$('[data-oe-model]').length),'translatable':!!html.dataset.translatable,'edit_translations':!!html.dataset.edit_translations,},this._super.apply(this,arguments));},async _getGMapAPIKey(refetch){if(refetch||!this._gmapAPIKeyProm){this._gmapAPIKeyProm=new Promise(async resolve=>{const data=await rpc('/website/google_maps_api_key');resolve(JSON.parse(data).google_maps_api_key||'');});} return this._gmapAPIKeyProm;},_getPublicWidgetsRegistry:function(options){var registry=this._super.apply(this,arguments);if(options.editableMode){const toPick=Object.keys(registry).filter((key)=>{const PublicWidget=registry[key];return!PublicWidget.prototype.disabledInEditableMode;});return pick(registry,...toPick);} return registry;},async _loadGMapAPI(editableMode,refetch){if(refetch||!this._gmapAPILoading){this._gmapAPILoading=new Promise(async resolve=>{const key=await this._getGMapAPIKey(refetch);window.odoo_gmap_api_post_load=(async function odoo_gmap_api_post_load(){await this._startWidgets($("section.s_google_map"),{editableMode:editableMode});resolve(key);}).bind(this);if(!key){if(!editableMode&&user.isAdmin){const message=_t("Cannot load google map.");const urlTitle=_t("Check your configuration.");this.notification.add(markup(`
${message}
${urlTitle}
`),{type:'warning',sticky:true});} resolve(false);this._gmapAPILoading=false;return;} await loadJS(`https://maps.googleapis.com/maps/api/js?v=3.exp&libraries=places&callback=odoo_gmap_api_post_load&key=${encodeURIComponent(key)}`);});} return this._gmapAPILoading;},_onWidgetsStartRequest:function(ev){ev.data.options=Object.assign({},ev.data.options||{});ev.data.options.editableMode=ev.data.editableMode;this._super.apply(this,arguments);},_onLangChangeClick:function(ev){ev.preventDefault();if(document.body.classList.contains('editor_enable')){return;} var $target=$(ev.currentTarget);var redirect={lang:encodeURIComponent($target.data('url_code')),url:encodeURIComponent($target.attr('href').replace(/[&?]edit_translations[^&?]+/,'')),hash:encodeURIComponent(window.location.hash)};window.location.href=`/website/lang/${redirect.lang}?r=${redirect.url}${redirect.hash}`;},async _onGMapAPIRequest(ev){ev.stopPropagation();const apiKey=await this._loadGMapAPI(ev.data.editableMode,ev.data.refetch);ev.data.onSuccess(apiKey);},async _onGMapAPIKeyRequest(ev){ev.stopPropagation();const apiKey=await this._getGMapAPIKey(ev.data.refetch);ev.data.onSuccess(apiKey);},_onSeoObjectRequest:function(ev){var res=this._unslugHtmlDataObject('seo-object');ev.data.callback(res);},_unslugHtmlDataObject:function(dataAttr){var repr=$('html').data(dataAttr);var match=repr&&repr.match(/(.+)\((\d+),(.*)\)/);if(!match){return null;} return{model:match[1],id:match[2]|0,};},_onPublishBtnClick:function(ev){ev.preventDefault();if(document.body.classList.contains('editor_enable')){return;} const publishEl=ev.currentTarget.closest(".js_publish_management");this.orm.call(publishEl.dataset.object,"website_publish_button",[[parseInt(publishEl.dataset.id,10)]]).then(function(result){publishEl.classList.toggle("css_published",result);publishEl.classList.toggle("css_unpublished",!result);const itemEl=publishEl.closest("[data-publish]");if(itemEl){itemEl.dataset.publish=result?'on':'off';}});},_onModalShown:function(ev){$(ev.target).addClass('modal_shown');},});__exports[Symbol.for("default")]={WebsiteRoot:WebsiteRoot,};return __exports;});; /* /website/static/src/js/content/compatibility.js */ odoo.define('@website/js/content/compatibility',[],function(require){'use strict';let __exports={};var htmlStyle=document.documentElement.style;var isFlexSupported=(('flexWrap'in htmlStyle)||('WebkitFlexWrap'in htmlStyle)||('msFlexWrap'in htmlStyle));if(!isFlexSupported){document.documentElement.setAttribute('data-no-flex','');} __exports[Symbol.for("default")]={isFlexSupported:isFlexSupported,};return __exports;});; /* /website/static/src/js/content/menu.js */ odoo.define('@website/js/content/menu',['@web/legacy/js/public/public_widget','@website/js/content/snippets.animation','@web/core/ui/ui_service','@web/core/utils/scrolling'],function(require){'use strict';let __exports={};const publicWidget=require("@web/legacy/js/public/public_widget")[Symbol.for("default")];const animations=require("@website/js/content/snippets.animation")[Symbol.for("default")];const extraMenuUpdateCallbacks=__exports.extraMenuUpdateCallbacks=[];const{SIZES,utils:uiUtils}=require("@web/core/ui/ui_service");const{compensateScrollbar}=require("@web/core/utils/scrolling");let headerHeight;const BaseAnimatedHeader=animations.Animation.extend({disabledInEditableMode:false,effects:[{startEvents:'scroll',update:'_updateHeaderOnScroll',},{startEvents:'resize',update:'_updateHeaderOnResize',}],init:function(){this._super(...arguments);this.fixedHeader=false;this.scrolledPoint=0;this.hasScrolled=false;this.closeOpenedMenus=false;this.scrollHeightTooShort=false;this.scrollableEl=$().getScrollingElement()[0];},start:function(){this.$main=this.$el.next('main');this.isOverlayHeader=!!this.$el.closest('.o_header_overlay, .o_header_overlay_theme').length;this.hiddenOnScrollEl=this.el.querySelector(".o_header_hide_on_scroll");const disableScroll=function(){if(uiUtils.getSize(){this.el.classList.add('o_transitioning');this._adaptToHeaderChangeLoop(1);});this.$el.on('transitionend.BaseAnimatedHeader',()=>this._adaptToHeaderChangeLoop(-1));return this._super(...arguments);},destroy:function(){this._toggleFixedHeader(false);this.$el.removeClass('o_header_affixed o_header_is_scrolled o_header_no_transition o_transitioning');this.$navbarOffcanvases.off(".BaseAnimatedHeader");this.$navbarCollapses.off('.BaseAnimatedHeader');this.$el.off('.BaseAnimatedHeader');this._super(...arguments);},_adaptFixedHeaderPosition(){compensateScrollbar(this.el,this.fixedHeader,false,'right');},_adaptToHeaderChange:function(){this.options.wysiwyg&&this.options.wysiwyg.odooEditor.observerUnactive();this._updateMainPaddingTop();this.el.classList.toggle('o_top_fixed_element',this._isShown());for(const callback of extraMenuUpdateCallbacks){callback();} this.options.wysiwyg&&this.options.wysiwyg.odooEditor.observerActive();},_adaptToHeaderChangeLoop:function(addCount=0){this._adaptToHeaderChange();this._transitionCount+=addCount;this._transitionCount=Math.max(0,this._transitionCount);if(this._transitionCount>0){window.requestAnimationFrame(()=>this._adaptToHeaderChangeLoop());if(addCount!==0){clearTimeout(this._changeLoopTimer);this._changeLoopTimer=setTimeout(()=>{this._adaptToHeaderChangeLoop(-this._transitionCount);},500);}}else{clearTimeout(this._changeLoopTimer);this.el.classList.remove('o_transitioning');}},_adjustUrlAutoScroll(){if(!this.editableMode){this.scrollableEl.scrollBy(0,-this.el.offsetHeight);}},_computeTopGap(){return 0;},_isShown(){return true;},_toggleFixedHeader:function(useFixed=true){this.fixedHeader=useFixed;this._adaptToHeaderChange();this.el.classList.toggle('o_header_affixed',useFixed);this._adaptFixedHeaderPosition();},_updateMainPaddingTop:function(){headerHeight||=this.el.getBoundingClientRect().height;this.topGap=this._computeTopGap();if(this.isOverlayHeader){return;} this.$main.css('padding-top',this.fixedHeader?headerHeight:'');},_scrollHeightTooShort(){const scrollEl=this.scrollableEl;const remainingScroll=(scrollEl.scrollHeight-scrollEl.clientHeight)-this.scrolledPoint;const clonedHeader=this.el.cloneNode(true);scrollEl.append(clonedHeader);clonedHeader.classList.add('o_header_is_scrolled','o_header_affixed','o_header_no_transition');const endHeaderHeight=clonedHeader.offsetHeight;clonedHeader.remove();const heightDiff=headerHeight-endHeaderHeight;return heightDiff>0?remainingScroll<=heightDiff:false;},_updateHeaderOnScroll:function(scroll){if(!this.hasScrolled){this.hasScrolled=true;if(scroll>0){this.$el.addClass('o_header_no_transition');this._adjustUrlAutoScroll();}}else{this.$el.removeClass('o_header_no_transition');this.closeOpenedMenus=true;} const headerIsScrolled=(scroll>this.scrolledPoint);if(this.headerIsScrolled!==headerIsScrolled){this.scrollHeightTooShort=headerIsScrolled&&this._scrollHeightTooShort();if(!this.scrollHeightTooShort){this.el.classList.toggle('o_header_is_scrolled',headerIsScrolled);this.$el.trigger('odoo-transitionstart');this.headerIsScrolled=headerIsScrolled;}} if(this.closeOpenedMenus){this.el.querySelectorAll(".dropdown-toggle.show").forEach(dropdownToggleEl=>{Dropdown.getOrCreateInstance(dropdownToggleEl).hide();});}},_updateHeaderOnResize:function(){this._adaptFixedHeaderPosition();if(document.body.classList.contains('overflow-hidden')&&uiUtils.getSize()>=SIZES.LG){this.el.querySelectorAll(".offcanvas.show").forEach(offcanvasEl=>{Offcanvas.getOrCreateInstance(offcanvasEl).hide();});this.el.querySelectorAll(".navbar-collapse.show").forEach(collapseEl=>{Collapse.getOrCreateInstance(collapseEl).hide();});}},});publicWidget.registry.StandardAffixedHeader=BaseAnimatedHeader.extend({selector:'header.o_header_standard:not(.o_header_sidebar)',init:function(){this._super(...arguments);this.fixedHeaderShow=false;this.scrolledPoint=300;},start:function(){headerHeight||=this.el.getBoundingClientRect().height;return this._super.apply(this,arguments);},destroy(){this.options.wysiwyg?.odooEditor.observerUnactive("destroyStandardHeader");this.$el.css('transform','');this.el.classList.remove("o_transformed_not_affixed");this.options.wysiwyg?.odooEditor.observerActive("destroyStandardHeader");this._super(...arguments);},_isShown(){return!this.fixedHeader||this.fixedHeaderShow;},_updateHeaderOnScroll:function(scroll){this._super(...arguments);const mainPosScrolled=(scroll>headerHeight+this.topGap);const reachPosScrolled=(scroll>this.scrolledPoint+this.topGap)&&!this.scrollHeightTooShort;const fixedUpdate=(this.fixedHeader!==mainPosScrolled);const showUpdate=(this.fixedHeaderShow!==reachPosScrolled);this.options.wysiwyg?.odooEditor.observerUnactive("updateHeaderOnScroll");if(fixedUpdate||showUpdate){if(fixedUpdate&&(reachPosScrolled||mainPosScrolled)){this.el.classList.add("o_transformed_not_affixed");} this.$el.css('transform',reachPosScrolled?`translate(0, -${this.topGap}px)`:mainPosScrolled?'translate(0, -100%)':'');void this.$el[0].offsetWidth;} this.fixedHeaderShow=reachPosScrolled;this.hiddenOnScrollEl?.classList.toggle("hidden",mainPosScrolled);if(fixedUpdate){this._toggleFixedHeader(mainPosScrolled);this.el.classList.remove("o_transformed_not_affixed");}else if(showUpdate){this._adaptToHeaderChange();} this.options.wysiwyg?.odooEditor.observerActive("updateHeaderOnScroll");},});publicWidget.registry.FixedHeader=BaseAnimatedHeader.extend({selector:'header.o_header_fixed:not(.o_header_sidebar)',start(){const _super=this._super(...arguments);this.dropdownToggleEls=[];if(this.hiddenOnScrollEl){this.dropdownToggleEls=this.hiddenOnScrollEl.querySelectorAll(".dropdown-toggle");for(const dropdownToggleEl of this.dropdownToggleEls){this.__onDropdownShow=this._onDropdownShow.bind(this);dropdownToggleEl.addEventListener("show.bs.dropdown",this.__onDropdownShow);} this.searchbarEl=this.hiddenOnScrollEl.querySelector(":not(.modal-content) > .o_searchbar_form");if(this.searchbarEl){this.__onSearchbarInput=this._onSearchbarInput.bind(this);this.searchbarEl.addEventListener("input",this.__onSearchbarInput);}} return _super;},destroy(){for(const dropdownToggleEl of this.dropdownToggleEls){dropdownToggleEl.removeEventListener("show.bs.dropdown",this.__onDropdownShow);} if(this.searchbarEl){this.searchbarEl.removeEventListener("input",this.__onSearchbarInput);} this._super(...arguments);},_updateHeaderOnScroll:function(scroll){this._super(...arguments);if(scroll>(this.scrolledPoint+this.topGap)){if(!this.$el.hasClass('o_header_affixed')){this.$el.css('transform',`translate(0, -${this.topGap}px)`);void this.$el[0].offsetWidth;this._toggleFixedHeader(true);}}else{this._toggleFixedHeader(false);void this.$el[0].offsetWidth;this.$el.css('transform','');} if(this.hiddenOnScrollEl){let elHeight=0;if(this.fixedHeader&&this.searchbarEl?.matches(".show")){this.searchbarEl.querySelector("input").blur();elHeight=this.hiddenOnScrollEl.offsetHeight;}else{elHeight=this.hiddenOnScrollEl.scrollHeight;} const scrollDelta=window.matchMedia(`(prefers-reduced-motion: reduce)`).matches?scroll:Math.floor(scroll/4);elHeight=Math.max(0,elHeight-scrollDelta);this.hiddenOnScrollEl.classList.toggle("hidden",elHeight===0);if(elHeight===0){this.hiddenOnScrollEl.removeAttribute("style");}else{this.hiddenOnScrollEl.style.overflow=this.fixedHeader?"hidden":"";this.hiddenOnScrollEl.style.height=this.fixedHeader?`${elHeight}px`:"";let elPadding=parseInt(getComputedStyle(this.hiddenOnScrollEl).paddingBlock);if(elHeightthis.position);const atTop=(scroll<=0);if(scrollingDownwards!==this.scrollingDownwards){this.checkPoint=scroll;} this.scrollingDownwards=scrollingDownwards;this.position=scroll;this.atTop=atTop;if(scrollingDownwards){if(!this.hiddenHeader&&scroll-this.checkPoint>(this.scrollOffsetLimit+this.topGap)){this.hiddenHeader=true;this._hideHeader();}}else{if(this.hiddenHeader&&scroll-this.checkPoint<-(this.scrollOffsetLimit+this.topGap)/2){this.hiddenHeader=false;this._showHeader();}} if(atTop&&!this.atTop){this._showHeader();}},});publicWidget.registry.DisappearingHeader=BaseDisappearingHeader.extend({selector:'header.o_header_disappears:not(.o_header_sidebar)',_adjustUrlAutoScroll(){},_hideHeader:function(){this._super(...arguments);this.$el.css('transform','translate(0, -100%)');},_showHeader:function(){this._super(...arguments);this.$el.css('transform',this.atTop?'':`translate(0, -${this.topGap}px)`);},});publicWidget.registry.FadeOutHeader=BaseDisappearingHeader.extend({selector:'header.o_header_fade_out:not(.o_header_sidebar)',_adjustUrlAutoScroll(){},_hideHeader:function(){this._super(...arguments);this.$el.stop(false,true).fadeOut();},_showHeader:function(){this._super(...arguments);this.$el.css('transform',this.atTop?'':`translate(0, -${this.topGap}px)`);this.$el.stop(false,true).fadeIn();},});publicWidget.registry.hoverableDropdown=animations.Animation.extend({selector:'header.o_hoverable_dropdown',disabledInEditableMode:false,effects:[{startEvents:'resize',update:'_dropdownHover',}],events:{'mouseenter .dropdown':'_onMouseEnter','mouseleave .dropdown':'_onMouseLeave',},start:function(){this.$dropdownMenus=this.$el.find('.dropdown-menu');this.$dropdownToggles=this.$el.find('.dropdown-toggle');this._dropdownHover();return this._super.apply(this,arguments);},_dropdownHover:function(){this.$dropdownMenus.attr('data-bs-popper','none');if(uiUtils.getSize()>=SIZES.LG){this.$dropdownMenus.css('margin-top','0');this.$dropdownMenus.css('top','unset');}else{this.$dropdownMenus.css('margin-top','');this.$dropdownMenus.css('top','');}},_updateDropdownVisibility(ev,doShow=true){if(uiUtils.getSize(){const linkEls=Array.from(megaMenuEl.querySelectorAll(`a[href]:not([href="#"])`));matchingLink=linkEls.find((linkEl)=>{try{const url=new URL(linkEl.href);return`${url.origin}${url.pathname}`===currentHrefWithoutHash;}catch{return false;}});if(matchingLink){const megaMenuToggleEl=megaMenuEl.closest(".nav-item").querySelector(".o_mega_menu_toggle");const mobileMegaMenuToggleEl=this.el.querySelectorAll("#top_menu_collapse_mobile .top_menu .o_mega_menu_toggle")[position];megaMenuToggleEl.classList.add("active");mobileMegaMenuToggleEl.classList.add("active");}});},_onMegaMenuClick(ev){const megaMenuToggleEl=ev.currentTarget;if(this.el.classList.contains("o_hoverable_dropdown")&&!megaMenuToggleEl.closest(".o_header_mobile")&&ev.type!=="keyup"){return;} this._moveMegaMenu(megaMenuToggleEl);},_onMegaMenuHover(ev){const megaMenuToggleEl=ev.currentTarget;if(!this.el.classList.contains("o_hoverable_dropdown")||megaMenuToggleEl.closest(".o_header_mobile")){return;} this._moveMegaMenu(megaMenuToggleEl);},_onExtraMenuClick(ev){const megaMenuToggleEls=ev.currentTarget.querySelectorAll(".o_mega_menu_toggle");megaMenuToggleEls.forEach(megaMenuToggleEl=>this._moveMegaMenu(megaMenuToggleEl));},});publicWidget.registry.HeaderGeneral=publicWidget.Widget.extend({selector:'header#top',disabledInEditableMode:false,events:{"show.bs.offcanvas #top_menu_collapse, #top_menu_collapse_mobile":"_onCollapseShow","hidden.bs.offcanvas #top_menu_collapse, #top_menu_collapse_mobile":"_onCollapseHidden",},_onCollapseShow(){this.options.wysiwyg?.odooEditor.observerUnactive("addCollapseClass");this.el.classList.add('o_top_menu_collapse_shown');this.options.wysiwyg?.odooEditor.observerActive("addCollapseClass");},_onCollapseHidden(){this.options.wysiwyg?.odooEditor.observerUnactive("removeCollapseClass");const mobileNavbarEl=this.el.querySelector("#top_menu_collapse_mobile");if(!mobileNavbarEl.matches(".show, .showing")){this.el.classList.remove("o_top_menu_collapse_shown");} this.options.wysiwyg?.odooEditor.observerActive("removeCollapseClass");},});publicWidget.registry.SearchModal=publicWidget.Widget.extend({selector:"#o_search_modal_block #o_search_modal",disabledInEditableMode:false,events:{"show.bs.modal":"_onSearchModalShow","shown.bs.modal":"_onSearchModalShown",},_onSearchModalShow(ev){if(this.editableMode){ev.preventDefault();}},_onSearchModalShown(ev){this.el.querySelector(".search-query").focus();},});__exports[Symbol.for("default")]={extraMenuUpdateCallbacks:extraMenuUpdateCallbacks,};return __exports;});; /* /website/static/src/js/content/snippets.animation.js */ odoo.define('@website/js/content/snippets.animation',['@web/core/l10n/translation','@web/core/assets','@web/core/utils/functions','@web/core/utils/strings','@web/core/utils/timing','@web/legacy/js/core/class','@web/legacy/js/public/public_widget','@website/js/utils','@web/core/utils/render','@web/core/browser/feature_detection','@web/core/ui/ui_service','@website/js/text_processing','@web/core/utils/ui','@website/snippets/observing_cookie_mixin','@web_editor/js/common/scrolling'],function(require){'use strict';let __exports={};const{_t}=require("@web/core/l10n/translation");const{loadJS}=require("@web/core/assets");const{uniqueId}=require("@web/core/utils/functions");const{escape}=require("@web/core/utils/strings");const{debounce,throttleForAnimation}=require("@web/core/utils/timing");const Class=require("@web/legacy/js/core/class")[Symbol.for("default")];const publicWidget=require("@web/legacy/js/public/public_widget")[Symbol.for("default")];const wUtils=require("@website/js/utils")[Symbol.for("default")];const{renderToElement}=require("@web/core/utils/render");const{hasTouch}=require("@web/core/browser/feature_detection");const{SIZES,utils:uiUtils}=require("@web/core/ui/ui_service");const{applyTextHighlight,removeTextHighlight,switchTextHighlight,}=require("@website/js/text_processing");const{touching}=require("@web/core/utils/ui");const{ObservingCookieWidgetMixin}=require("@website/snippets/observing_cookie_mixin");const{scrollTo}=require("@web_editor/js/common/scrolling");window.requestAnimationFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||window.oRequestAnimationFrame;window.cancelAnimationFrame=window.cancelAnimationFrame||window.webkitCancelAnimationFrame||window.mozCancelAnimationFrame||window.msCancelAnimationFrame||window.oCancelAnimationFrame;if(!window.performance||!window.performance.now){window.performance={now:function(){return Date.now();}};} publicWidget.Widget.include({disabledInEditableMode:true,edit_events:null,read_events:null,init:function(parent,options){this._super.apply(this,arguments);this.editableMode=this.options.editableMode||false;var extraEvents=this.editableMode?this.edit_events:this.read_events;if(extraEvents){this.events=Object.assign({},this.events||{},extraEvents);}},});var AnimationEffect=Class.extend(publicWidget.ParentedMixin,{init:function(parent,updateCallback,startEvents,$startTarget,options){publicWidget.ParentedMixin.init.call(this);this.setParent(parent);options=options||{};this._minFrameTime=1000/(options.maxFPS||100);this._updateCallback=updateCallback;this.startEvents=startEvents||'scroll';const modalEl=options.enableInModal?parent.target.closest('.modal'):null;const mainScrollingElement=modalEl?modalEl:$().getScrollingElement()[0];const mainScrollingTarget=$().getScrollingTarget(mainScrollingElement)[0];this.$startTarget=$($startTarget?$startTarget:this.startEvents==='scroll'?mainScrollingTarget:window);if(options.getStateCallback){this._getStateCallback=options.getStateCallback;}else if(this.startEvents==='scroll'&&this.$startTarget[0]===mainScrollingTarget){const $scrollable=this.$startTarget;this._getStateCallback=function(){return $scrollable.scrollTop();};}else if(this.startEvents==='resize'&&this.$startTarget[0]===window){this._getStateCallback=function(){return{width:window.innerWidth,height:window.innerHeight,};};}else{this._getStateCallback=function(){return undefined;};} this.endEvents=options.endEvents||false;this.$endTarget=options.$endTarget?$(options.$endTarget):this.$startTarget;this._updateCallback=this._updateCallback.bind(parent);this._getStateCallback=this._getStateCallback.bind(parent);this._uid=uniqueId("_animationEffect");this.startEvents=_processEvents(this.startEvents,this._uid);if(this.endEvents){this.endEvents=_processEvents(this.endEvents,this._uid);} function _processEvents(events,namespace){return events.split(" ").map((e)=>(e+="."+namespace)).join(" ");}},destroy:function(){publicWidget.ParentedMixin.destroy.call(this);this.stop();},start:function(){this._paused=false;this._rafID=window.requestAnimationFrame((function(t){this._update(t);this._paused=true;}).bind(this));if(this.endEvents){this.$startTarget.on(this.startEvents,(function(e){if(this._paused){setTimeout(()=>this.play.bind(this,e));}}).bind(this));this.$endTarget.on(this.endEvents,(function(){if(!this._paused){setTimeout(()=>this.pause.bind(this));}}).bind(this));}else{this.throttleOnStartEvents=throttleForAnimation(((e)=>{this.play(e);clearTimeout(pauseTimer);pauseTimer=setTimeout((()=>{this.pause();pauseTimer=null;}).bind(this),2000);}).bind(this));var pauseTimer=null;this.$startTarget.on(this.startEvents,this.throttleOnStartEvents);}},stop:function(){this.$startTarget.off(this.startEvents);if(this.endEvents){this.$endTarget.off(this.endEvents);} this.pause();},play:function(e){this._newEvent=e;if(!this._paused){return;} this._paused=false;this._rafID=window.requestAnimationFrame(this._update.bind(this));this._lastUpdateTimestamp=undefined;},pause:function(){if(this._paused){return;} this._paused=true;window.cancelAnimationFrame(this._rafID);this._lastUpdateTimestamp=undefined;},_update:function(timestamp){if(this._paused){return;} this._rafID=window.requestAnimationFrame(this._update.bind(this));var elapsedTime=0;if(this._lastUpdateTimestamp){elapsedTime=timestamp-this._lastUpdateTimestamp;if(elapsedTime{effect.start();});return this._super.apply(this,arguments);},_prepareEffects:function(){this._animationEffects=[];var self=this;this.effects.forEach((desc)=>{self._addEffect(self[desc.update],desc.startEvents,_findTarget(desc.startTarget),{getStateCallback:desc.getState&&self[desc.getState],endEvents:desc.endEvents||undefined,$endTarget:_findTarget(desc.endTarget),maxFPS:self.maxFPS,enableInModal:desc.enableInModal||undefined,});function _findTarget(selector){if(selector){if(selector==='selector'){return self.$el;} return self.$(selector);} return undefined;}});},_addEffect:function(updateCallback,startEvents,$startTarget,options){this._animationEffects.push(new AnimationEffect(this,updateCallback,startEvents,$startTarget,options));},});var registry=publicWidget.registry;const baseSelectorEngineFind=window.SelectorEngine.find;window.SelectorEngine.find=function(...args){try{return baseSelectorEngineFind.call(this,...args);}catch{return[document.createElement('div')];}};registry.slider=publicWidget.Widget.extend({selector:'.carousel',disabledInEditableMode:false,edit_events:{'content_changed':'_onContentChanged',},start:function(){this.$('img').on('load.slider',()=>this._computeHeights());this._computeHeights();$(window).on('resize.slider',debounce(()=>this._computeHeights(),250));const options=this.editableMode?{ride:false,pause:true}:undefined;window.Carousel.getOrCreateInstance(this.el,options);if(this.editableMode&&this.el.matches("section > .carousel")&&!this.options.wysiwyg.options.enableTranslation){this.controlEls=this.el.querySelectorAll(".carousel-control-prev, .carousel-control-next");const indicatorEls=this.el.querySelectorAll(".carousel-indicators > *");this.options.wysiwyg.odooEditor.observerUnactive("disable_controls");this.controlEls.forEach(controlEl=>controlEl.removeAttribute("data-bs-slide"));indicatorEls.forEach(indicatorEl=>indicatorEl.removeAttribute("data-bs-slide-to"));this.options.wysiwyg.odooEditor.observerActive("disable_controls");this.__onControlClick=this._onControlClick.bind(this);[...this.controlEls,...indicatorEls].forEach(controlEl=>{controlEl.addEventListener("mousedown",this.__onControlClick);});} return this._super.apply(this,arguments);},destroy:function(){this._super.apply(this,arguments);window.Carousel.getOrCreateInstance(this.el).dispose();this.options.wysiwyg&&this.options.wysiwyg.odooEditor.observerUnactive("destroy");this.$(".carousel-item").toArray().forEach((el)=>{$(el).css("min-height","");});this.options.wysiwyg&&this.options.wysiwyg.odooEditor.observerActive("destroy");$(window).off('.slider');this.$el.off('.slider');this.$('img').off('.slider');if(this.editableMode&&this.el.matches("section > .carousel")&&!this.options.wysiwyg.options.enableTranslation){const indicatorEls=this.el.querySelectorAll(".carousel-indicators > *");this.options.wysiwyg.odooEditor.observerUnactive("restore_controls");this.controlEls.forEach(controlEl=>{const direction=controlEl.classList.contains("carousel-control-prev")?"prev":"next";controlEl.setAttribute("data-bs-slide",direction);});indicatorEls.forEach((indicatorEl,i)=>indicatorEl.setAttribute("data-bs-slide-to",i));this.options.wysiwyg.odooEditor.observerActive("restore_controls");[...this.controlEls,...indicatorEls].forEach(controlEl=>{controlEl.removeEventListener("mousedown",this.__onControlClick);});}},_computeHeights:function(){var maxHeight=0;var $items=this.$('.carousel-item');this.options.wysiwyg&&this.options.wysiwyg.odooEditor.observerUnactive("_computeHeights");$items.css('min-height','');$items.toArray().forEach((el)=>{var $item=$(el);var isActive=$item.hasClass('active');$item.addClass('active');var height=$item.outerHeight();if(height>maxHeight){maxHeight=height;} $item.toggleClass('active',isActive);});$items.css('min-height',maxHeight);this.options.wysiwyg&&this.options.wysiwyg.odooEditor.observerActive("_computeHeights");},_onContentChanged:function(ev){this._computeHeights();},_onControlClick(){this.el.querySelector(".carousel-item.active").click();},});const CAROUSEL_SLIDING_CLASS="o_carousel_sliding";async function waitForCarouselToFinishSliding(carouselEl){if(!carouselEl.classList.contains(CAROUSEL_SLIDING_CLASS)){return;} return new Promise(resolve=>{carouselEl.addEventListener("slid.bs.carousel",()=>resolve(),{once:true});});} publicWidget.registry.CarouselBootstrapUpgradeFix=publicWidget.Widget.extend({selector:["[data-snippet='s_image_gallery'] .carousel","[data-snippet='s_carousel'] .carousel","[data-snippet='s_quotes_carousel'] .carousel","[data-snippet='s_quotes_carousel_minimal'] .carousel","[data-snippet='s_carousel_intro'] .carousel","#o-carousel-product.carousel",].join(", "),disabledInEditableMode:false,events:{"slide.bs.carousel":"_onSlideCarousel","slid.bs.carousel":"_onSlidCarousel",},OLD_AUTO_SLIDING_SNIPPETS:["s_image_gallery"],async start(){await this._super(...arguments);const hasInterval=![undefined,"false","0"].includes(this.el.dataset.bsInterval);if(!hasInterval&&this.el.dataset.bsRide){delete this.el.dataset.bsRide;await this._destroyCarouselInstance();const options=this.editableMode?{ride:false,pause:true}:undefined;window.Carousel.getOrCreateInstance(this.el,options);}else if(hasInterval&&!this.el.dataset.bsRide){const snippetName=this.el.closest("[data-snippet]")?.dataset.snippet;this.el.dataset.bsRide=this.OLD_AUTO_SLIDING_SNIPPETS.includes(snippetName)?"carousel":"true";await this._destroyCarouselInstance();const options=this.editableMode?{ride:false,pause:true}:undefined;window.Carousel.getOrCreateInstance(this.el,options);}},destroy(){this._super(...arguments);this.el.classList.remove(CAROUSEL_SLIDING_CLASS);},async _destroyCarouselInstance(){await waitForCarouselToFinishSliding(this.el);window.Carousel.getInstance(this.el)?.dispose();},_onSlideCarousel(ev){ev.currentTarget.classList.add(CAROUSEL_SLIDING_CLASS);},_onSlidCarousel(ev){ev.currentTarget.classList.remove(CAROUSEL_SLIDING_CLASS);},});registry.Parallax=Animation.extend({selector:'.parallax',disabledInEditableMode:false,effects:[{startEvents:'scroll',update:'_onWindowScroll',enableInModal:true,}],start:function(){this._rebuild();$(window).on('resize.animation_parallax',debounce(this._rebuild.bind(this),500));this.modalEl=this.$target[0].closest('.modal');if(this.modalEl){$(this.modalEl).on('shown.bs.modal.animation_parallax',()=>{this._rebuild();this.modalEl.dispatchEvent(new Event('scroll'));});} return this._super.apply(this,arguments);},destroy:function(){this._super.apply(this,arguments);this._updateBgCss({transform:'',top:'',bottom:'',});$(window).off('.animation_parallax');if(this.modalEl){$(this.modalEl).off('.animation_parallax');}},_rebuild:function(){this.$bg=this.$('> .s_parallax_bg');this.speed=parseFloat(this.$el.attr('data-scroll-background-ratio')||0);var noParallaxSpeed=(this.speed===0||this.speed===1);if(noParallaxSpeed){return;} this.viewport=document.body.clientHeight-$('#wrapwrap').position().top;this.visibleArea=[this.$el.offset().top];this.visibleArea.push(this.visibleArea[0]+this.$el.innerHeight()+this.viewport);this.ratio=this.speed*(this.viewport/10);const absoluteRatio=Math.abs(this.ratio);this._updateBgCss({top:-absoluteRatio,bottom:-absoluteRatio,});},_updateBgCss(cssValues){if(!this.$bg){return;} if(this.options.wysiwyg){this.options.wysiwyg.odooEditor.observerUnactive('_updateBgCss');} this.$bg.css(cssValues);if(this.options.wysiwyg){this.options.wysiwyg.odooEditor.observerActive('_updateBgCss');}},_onWindowScroll:function(scrollOffset){if(this.speed===0||this.speed===1){return;} var vpEndOffset=scrollOffset+this.viewport;if(vpEndOffset>=this.visibleArea[0]&&vpEndOffset<=this.visibleArea[1]){this._updateBgCss({'transform':'translateY('+_getNormalizedPosition.call(this,vpEndOffset)+'px)'});} function _getNormalizedPosition(pos){var r=(pos-this.visibleArea[1])/(this.visibleArea[0]-this.visibleArea[1]);return Math.round(this.ratio*(2*r-1));}},});const MobileYoutubeAutoplayMixin={_setupAutoplay:function(src){let promise=Promise.resolve();this.isYoutubeVideo=src.indexOf('youtube')>=0;this.isMobileEnv=uiUtils.getSize()<=SIZES.LG&&hasTouch();if(this.isYoutubeVideo&&this.isMobileEnv&&!window.YT&&!this.el.dataset.needCookiesApproval){const oldOnYoutubeIframeAPIReady=window.onYouTubeIframeAPIReady;promise=new Promise(resolve=>{window.onYouTubeIframeAPIReady=()=>{if(oldOnYoutubeIframeAPIReady){oldOnYoutubeIframeAPIReady();} return resolve();};});loadJS('https://www.youtube.com/iframe_api');} return promise;},_triggerAutoplay:function(iframeEl){if(this.isMobileEnv&&this.isYoutubeVideo&&!this.el.dataset.needCookiesApproval){new window.YT.Player(iframeEl,{events:{onReady:ev=>ev.target.playVideo(),}});}},};registry.mediaVideo=publicWidget.Widget.extend(MobileYoutubeAutoplayMixin,ObservingCookieWidgetMixin,{selector:'.media_iframe_video',start:function(){const proms=[this._super.apply(this,arguments)];let iframeEl=this.el.querySelector(':scope > iframe');if(!iframeEl){iframeEl=this._generateIframe();} if(this.el.dataset.needCookiesApproval){const sizeContainerEl=this.el.querySelector(":scope > .media_iframe_video_size");sizeContainerEl.classList.add("d-none");this._showSizeContainerEl=()=>{sizeContainerEl.classList.remove("d-none");};document.addEventListener("optionalCookiesAccepted",this._showSizeContainerEl,{once:true});} if(!iframeEl||!iframeEl.getAttribute('src')){return Promise.all(proms);} proms.push(this._setupAutoplay(iframeEl.getAttribute('src')));return Promise.all(proms).then(()=>{this._triggerAutoplay(iframeEl);});},destroy(){if(this._showSizeContainerEl){document.removeEventListener("optionalCookiesAccepted",this._showSizeContainerEl);this._showSizeContainerEl();} return this._super(...arguments);},_generateIframe:function(){this.$el.empty();this.$el.append('
 
'+'
 
');var src=escape(this.$el.data('oe-expression')||this.$el.data('src'));var m=src.match(/^(?:https?:)?\/\/([^/?#]+)/);if(!m){return;} var domain=m[1].replace(/^www\./,'');const supportedDomains=["youtu.be","youtube.com","youtube-nocookie.com","instagram.com","player.vimeo.com","vimeo.com","dailymotion.com","player.youku.com","youku.com",];if(!supportedDomains.includes(domain)){return;} const iframeEl=$(' `); registerTemplate("knowledge.ArticleIndexList", `/knowledge/static/src/editor/embedded_components/core/article_index/article_index_list.xml`, ` `); registerTemplate("knowledge.ArticleIndexNestedList", `/knowledge/static/src/editor/embedded_components/core/article_index/article_index_list.xml`, `
`); registerTemplate("knowledge.ReadonlyEmbeddedArticleIndex", `/knowledge/static/src/editor/embedded_components/core/article_index/readonly_article_index.xml`, `

No article to display

`); registerTemplate("knowledge.EmbeddedClipboard", `/knowledge/static/src/editor/embedded_components/core/clipboard/embedded_clipboard.xml`, `
Clipboard
`); registerTemplate("website_knowledge.ViewPlaceholder", `/website_knowledge/static/src/frontend/editor/embedded_components/view/view_placeholder.xml`, `
`); registerTemplate("knowledge.PublicEmbeddedViewLink", `/website_knowledge/static/src/frontend/editor/embedded_components/view_link/public_embedded_view_link.xml`, ` `); registerTemplate("website_knowledge.knowledgePublic", `/website_knowledge/static/src/frontend/knowledge_public_view/knowledge_public_view.xml`, `
Untitled

Article not found


The article you are trying the read has either been removed or you do not have access to it.

`); registerTemplate("website_knowledge.knowledgePublicSidebar", `/website_knowledge/static/src/frontend/knowledge_public_view/knowledge_public_view.xml`, `
`); registerTemplate("website_knowledge.knowledgePublicFormResizer", `/website_knowledge/static/src/frontend/knowledge_public_view/knowledge_public_view.xml`, `
`); registerTemplate("website_knowledge.sidebarLoader", `/website_knowledge/static/src/frontend/knowledge_public_view/knowledge_public_view.xml`, `
`); registerTemplate("website_links.RecentLink", `/website_links/static/src/xml/recent_link.xml`, `

clicks

`); registerTemplate("website_links.WebsiteLinksTagsWrapper", `/website_links/static/src/xml/website_links_tags_wrapper.xml`, ` Create option "" `); registerTemplate("website_mass_mailing.edition.wrapper", `/website_mass_mailing/static/src/xml/website_mass_mailing.xml`, `