From a29d0f3ffbbef5a0703cc76dda12360cdcff4ca3 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Mon, 27 Nov 2023 16:41:36 -0500 Subject: [PATCH 01/53] feat(translator): rework the translator and translation systems to standardize translatables with TranslatableInterface.php and add a new TranslatableValue.php enabling dissociating translation from the core translator --- .../Charcoal/Property/AbstractProperty.php | 5 +- .../Charcoal/Property/StructureProperty.php | 136 +++++++++------ .../Translator/TranslatableInterface.php | 13 ++ .../Charcoal/Translator/TranslatableValue.php | 159 ++++++++++++++++++ .../src/Charcoal/Translator/Translation.php | 37 +++- .../src/Charcoal/Translator/Translator.php | 4 +- 6 files changed, 294 insertions(+), 60 deletions(-) create mode 100644 packages/translator/src/Charcoal/Translator/TranslatableInterface.php create mode 100644 packages/translator/src/Charcoal/Translator/TranslatableValue.php diff --git a/packages/property/src/Charcoal/Property/AbstractProperty.php b/packages/property/src/Charcoal/Property/AbstractProperty.php index 4b5b97ae9..d23f767b0 100644 --- a/packages/property/src/Charcoal/Property/AbstractProperty.php +++ b/packages/property/src/Charcoal/Property/AbstractProperty.php @@ -22,6 +22,7 @@ use Charcoal\Validator\ValidatableTrait; use Charcoal\Validator\ValidatorInterface; // From 'charcoal-translator' +use Charcoal\Translator\TranslatableInterface; use Charcoal\Translator\Translation; use Charcoal\Translator\TranslatorAwareTrait; // From 'charcoal-property' @@ -522,9 +523,9 @@ public function getL10n() /** * @param mixed $val A L10N variable. - * @return Translation The translation value. + * @return TranslatableInterface|null The translation value. */ - public function parseValAsL10n($val) + public function parseValAsL10n($val): ?TranslatableInterface { return $this->translator()->translation($val); } diff --git a/packages/property/src/Charcoal/Property/StructureProperty.php b/packages/property/src/Charcoal/Property/StructureProperty.php index f379875bd..4e3ed2c69 100644 --- a/packages/property/src/Charcoal/Property/StructureProperty.php +++ b/packages/property/src/Charcoal/Property/StructureProperty.php @@ -6,6 +6,8 @@ use InvalidArgumentException; use UnexpectedValueException; // From 'charcoal-translator' +use Charcoal\Translator\TranslatableInterface; +use Charcoal\Translator\TranslatableValue; use Charcoal\Translator\Translation; // From 'charcoal-property' use Charcoal\Property\AbstractProperty; @@ -29,7 +31,7 @@ class StructureProperty extends AbstractProperty * * @var string */ - private $sqlType; + private string $sqlType = 'TEXT'; /** * Retrieve the property's type identifier. @@ -42,35 +44,36 @@ public function type() } /** - * Ensure l10n can not be TRUE for structure property. - * - * @param boolean $flag The l10n, or "translatable" flag. - * @throws InvalidArgumentException If the L10N argument is TRUE (must be FALSE). - * @see AbstractProperty::setL10n() - * @return self + * @param mixed $val The value to convert for display. + * @param array $options Optional display options. + * @return string */ - public function setL10n($flag) + public function displayVal($val, array $options = []) { - $flag = !!$flag; + if ($val === null || $val === '') { + return ''; + } - if ($flag === true) { - throw new InvalidArgumentException( - 'The structure property can not be translatable.' - ); + /** Parse multilingual values */ + if ($this['l10n']) { + $propertyValue = $this->l10nVal($val, $options); + if ($propertyValue === null) { + return ''; + } + } elseif ($val instanceof TranslatableValue) { + $propertyValue = $val->trans($this->translator()); + } elseif ($val instanceof Translation) { + $propertyValue = (string)$val; + } else { + $propertyValue = $val; } - return $this; - } + if (!is_scalar($propertyValue)) { + $flags = ($options['json'] ?? JSON_PRETTY_PRINT); + return json_encode($propertyValue, $flags); + } - /** - * L10N is always FALSE for structure property. - * - * @see AbstractProperty::getL10n() - * @return boolean - */ - public function getL10n() - { - return false; + return (string)$propertyValue; } /** @@ -78,7 +81,7 @@ public function getL10n() * @param array $options Optional input options. * @return string */ - public function inputVal($val, array $options = []) + public function inputVal($val, array $options = []): string { unset($options); if ($val === null) { @@ -98,6 +101,59 @@ public function inputVal($val, array $options = []) return json_encode($propertyValue, JSON_PRETTY_PRINT); } + /** + * Get the property's value in a format suitable for storage. + * + * @param mixed $val Optional. The value to convert to storage value. + * @return mixed + */ + public function storageVal($val) + { + if ($val === null || $val === '') { + // Do not serialize NULL values + return null; + } + + + if ($val instanceof TranslatableValue) { + $val = $val->trans($this->translator()); + } + + if ($val instanceof Translation) { + $val = (string)$val; + } + + if (!is_scalar($val)) { + return json_encode($val, JSON_UNESCAPED_UNICODE); + } + + return $val; + } + + /** + * Attempt to get the multilingual value in the requested language. + * + * @param mixed $val The multilingual value to lookup. + * @param mixed $lang The language to return the value in. + * @return string|null + */ + protected function l10nVal($val, $lang = null): ?string + { + if (!is_string($lang)) { + if (is_array($lang) && isset($lang['lang'])) { + $lang = $lang['lang']; + } else { + $lang = $this->translator()->getLocale(); + } + } + + if ($val instanceof TranslatableValue) { + return $val->trans($this->translator(), $lang); + } + + return ($val[$lang] ?? null); + } + /** * Retrieve the structure as a plain array. * @@ -146,27 +202,15 @@ public function parseOne($val) } /** - * Get the property's value in a format suitable for storage. + * Creates a custom data value object with a similar API to the + * {@see \Charcoal\Translator\Translation Translation class}. * - * @param mixed $val Optional. The value to convert to storage value. - * @return mixed + * @param mixed $val A L10N variable. + * @return TranslatableInterface|null The translation value. */ - public function storageVal($val) + public function parseValAsL10n($val): ?TranslatableInterface { - if ($val === null || $val === '') { - // Do not serialize NULL values - return null; - } - - if ($val instanceof Translation) { - $val = (string)$val; - } - - if (!is_scalar($val)) { - return json_encode($val, JSON_UNESCAPED_UNICODE); - } - - return $val; + return new TranslatableValue($val); } /** @@ -223,12 +267,8 @@ public function setSqlType($sqlType) * @see StorableProperyTrait::sqlType() * @return string */ - public function sqlType() + public function sqlType(): string { - if ($this->sqlType === null) { - $this->sqlType = 'TEXT'; - } - return $this->sqlType; } diff --git a/packages/translator/src/Charcoal/Translator/TranslatableInterface.php b/packages/translator/src/Charcoal/Translator/TranslatableInterface.php new file mode 100644 index 000000000..cc4e7d5d5 --- /dev/null +++ b/packages/translator/src/Charcoal/Translator/TranslatableInterface.php @@ -0,0 +1,13 @@ + + */ + private array $translations; + + /** @var array */ + private array $parameters; + + /** @var string|null */ + private ?string $domain; + + /** + * @param array|Translation|self $translations Values keyed by locale. + * @param array $parameters An array of parameters for the message. + * @param string|null $domain The domain for the message or NULL to use the default. + */ + public function __construct($translations, array $parameters = [], string $domain = null) + { + $this->translations = $this->sanitizeTranslations($translations); + $this->parameters = $parameters; + $this->domain = $domain; + } + + /** + * @param array|Translation|self $value Values keyed by locale. + * @return array + * @throws InvalidArgumentException If the value is invalid. + */ + protected function sanitizeTranslations($value): array + { + if ($value instanceof self) { + return $value->toArray(); + } + + if ($value instanceof Translation) { + return $value->data(); + } + + if (\is_array($value)) { + $translations = []; + + foreach ($value as $locale => $translation) { + if (!\is_string($locale)) { + throw new InvalidArgumentException(\sprintf( + 'Expected multilingual value locale to be a string, received %s', + \gettype($locale) + )); + } + + $translations[$locale] = $translation; + } + + return $translations; + } + + throw new InvalidArgumentException(\sprintf( + 'Expected at least one localized value, received %s', + (\is_object($value) ? \get_class($value) : \gettype($value)) + )); + } + + /** + * @return array + */ + public function toArray(): array + { + return $this->translations; + } + + /** + * @return string + */ + public function __toString(): string + { + return $this->toJson(); + } + + /** + * @param integer $options From {@see \json_encode()} flags. + * @return string + */ + public function toJson(int $options = 0): string + { + return \json_encode($this->jsonSerialize(), $options); + } + + /** + * @return array + */ + public function jsonSerialize(): array + { + return $this->toArray(); + } + + /** + * Transform each translation value. + * + * This method is to maintain compatibility with {@see Translation}. + * + * @param (callable(mixed, string): mixed) $callback Function to apply to each value. + * @return self + */ + public function each(callable $callback): self + { + foreach ($this->translations as $locale => $translation) { + $this->translations[$locale] = \call_user_func($callback, $translation, $locale); + } + return $this; + } + + /** + * Transform each translation value. + * + * This method is to maintain compatibility with {@see Translation}. + * + * @param (callable(mixed): mixed) $callback Function to apply to each value. + * @return self + */ + public function sanitize(callable $callback): self + { + foreach ($this->translations as $locale => $translation) { + $this->translations[$locale] = \call_user_func($callback, $translation); + } + return $this; + } + + /** + * @param Translator $translator The translator. + * @param string|null $locale The locale. + * @return string + */ + public function trans(Translator $translator, ?string $locale = null): string + { + return $translator->translate($this->translations, $this->parameters, $this->domain, $locale); + } +} diff --git a/packages/translator/src/Charcoal/Translator/Translation.php b/packages/translator/src/Charcoal/Translator/Translation.php index ca51e5e66..af9ada335 100644 --- a/packages/translator/src/Charcoal/Translator/Translation.php +++ b/packages/translator/src/Charcoal/Translator/Translation.php @@ -15,6 +15,7 @@ * Available locales is provided with a locales manager. */ class Translation implements + TranslatableInterface, ArrayAccess, JsonSerializable { @@ -28,18 +29,28 @@ class Translation implements private $val = []; /** - * @var LocalesManager + * @var Translator */ - private $manager; + private $translator; + + /** @var array */ + private array $parameters; + + /** @var string|null */ + private ?string $domain; /** - * @param Translation|array|string $val The translation values. - * @param LocalesManager $manager A LocalesManager instance. + * @param Translation|array|string $val The translation values. + * @param Translator $translator Translator. + * @param array $parameters An array of parameters for the message. + * @param string|null $domain The domain for the message or NULL to use the default. */ - public function __construct($val, LocalesManager $manager) + public function __construct($val, Translator $translator, array $parameters = [], string $domain = null) { - $this->manager = $manager; + $this->translator = $translator; $this->setVal($val); + $this->parameters = $parameters; + $this->domain = $domain; } /** @@ -49,7 +60,7 @@ public function __construct($val, LocalesManager $manager) */ public function __toString() { - $lang = $this->manager->currentLocale(); + $lang = $this->translator->getLocale(); if (isset($this->val[$lang])) { return $this->val[$lang]; } else { @@ -227,7 +238,7 @@ private function setVal($val) $this->val[$lang] = (string)$l10n; } } elseif (is_string($val)) { - $lang = $this->manager->currentLocale(); + $lang = $this->translator->getLocale(); $this->val[$lang] = $val; } else { @@ -238,4 +249,14 @@ private function setVal($val) return $this; } + + /** + * @param Translator $translator The translator. + * @param string|null $locale The locale. + * @return string + */ + public function trans(Translator $translator, ?string $locale = null): string + { + return $translator->translate($this->val, $this->parameters, $this->domain, $locale); + } } diff --git a/packages/translator/src/Charcoal/Translator/Translator.php b/packages/translator/src/Charcoal/Translator/Translator.php index 20a86ba54..40be3483d 100644 --- a/packages/translator/src/Charcoal/Translator/Translator.php +++ b/packages/translator/src/Charcoal/Translator/Translator.php @@ -131,7 +131,7 @@ public function translation($val, array $parameters = [], $domain = null) return null; } - $translation = new Translation($val, $this->manager()); + $translation = new Translation($val, $this); $localized = (string)$translation; foreach ($this->availableLocales() as $lang) { if (!isset($translation[$lang]) || $translation[$lang] === $val) { @@ -208,7 +208,7 @@ public function translationChoice($val, $number, array $parameters = [], $domain '%count%' => $number, ], $parameters); - $translation = new Translation($val, $this->manager()); + $translation = new Translation($val, $this); $localized = (string)$translation; foreach ($this->availableLocales() as $lang) { if (!isset($translation[$lang]) || $translation[$lang] === $val) { From 672343302f6511bbe8687832e14409a48da6dd87 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Wed, 29 Nov 2023 14:28:11 -0500 Subject: [PATCH 02/53] fix(translation): revert construct to use manager and trans method no longer relay to `translator->translate()` --- .../src/Charcoal/Translator/Translation.php | 37 +++++++------------ .../src/Charcoal/Translator/Translator.php | 4 +- 2 files changed, 15 insertions(+), 26 deletions(-) diff --git a/packages/translator/src/Charcoal/Translator/Translation.php b/packages/translator/src/Charcoal/Translator/Translation.php index af9ada335..4dd441804 100644 --- a/packages/translator/src/Charcoal/Translator/Translation.php +++ b/packages/translator/src/Charcoal/Translator/Translation.php @@ -8,6 +8,7 @@ use JsonSerializable; // From 'charcoal-translator' use Charcoal\Translator\LocalesManager; +use Symfony\Component\Translation\TranslatorInterface; /** * A translation object holds a localized message in all available locales. @@ -29,30 +30,19 @@ class Translation implements private $val = []; /** - * @var Translator + * @var LocalesManager */ - private $translator; - - /** @var array */ - private array $parameters; - - /** @var string|null */ - private ?string $domain; + private $manager; /** - * @param Translation|array|string $val The translation values. - * @param Translator $translator Translator. - * @param array $parameters An array of parameters for the message. - * @param string|null $domain The domain for the message or NULL to use the default. + * @param Translation|array|string $val The translation values. + * @param LocalesManager $manager A LocalesManager instance. */ - public function __construct($val, Translator $translator, array $parameters = [], string $domain = null) + public function __construct($val, LocalesManager $manager) { - $this->translator = $translator; + $this->manager = $manager; $this->setVal($val); - $this->parameters = $parameters; - $this->domain = $domain; } - /** * Output the current language's value, when cast to string. * @@ -60,7 +50,7 @@ public function __construct($val, Translator $translator, array $parameters = [] */ public function __toString() { - $lang = $this->translator->getLocale(); + $lang = $this->manager->currentLocale(); if (isset($this->val[$lang])) { return $this->val[$lang]; } else { @@ -238,7 +228,7 @@ private function setVal($val) $this->val[$lang] = (string)$l10n; } } elseif (is_string($val)) { - $lang = $this->translator->getLocale(); + $lang = $this->manager->currentLocale(); $this->val[$lang] = $val; } else { @@ -251,12 +241,11 @@ private function setVal($val) } /** - * @param Translator $translator The translator. - * @param string|null $locale The locale. - * @return string + * @param TranslatorInterface $translator The translator to use. + * @return mixed */ - public function trans(Translator $translator, ?string $locale = null): string + public function trans(TranslatorInterface $translator) { - return $translator->translate($this->val, $this->parameters, $this->domain, $locale); + return ($this->val[$translator->getLocale()] ?? null); } } diff --git a/packages/translator/src/Charcoal/Translator/Translator.php b/packages/translator/src/Charcoal/Translator/Translator.php index 40be3483d..20a86ba54 100644 --- a/packages/translator/src/Charcoal/Translator/Translator.php +++ b/packages/translator/src/Charcoal/Translator/Translator.php @@ -131,7 +131,7 @@ public function translation($val, array $parameters = [], $domain = null) return null; } - $translation = new Translation($val, $this); + $translation = new Translation($val, $this->manager()); $localized = (string)$translation; foreach ($this->availableLocales() as $lang) { if (!isset($translation[$lang]) || $translation[$lang] === $val) { @@ -208,7 +208,7 @@ public function translationChoice($val, $number, array $parameters = [], $domain '%count%' => $number, ], $parameters); - $translation = new Translation($val, $this); + $translation = new Translation($val, $this->manager()); $localized = (string)$translation; foreach ($this->availableLocales() as $lang) { if (!isset($translation[$lang]) || $translation[$lang] === $val) { From a728e0788e8b83d3e5a54ae8e2320e294fafa76e Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Wed, 29 Nov 2023 14:30:29 -0500 Subject: [PATCH 03/53] fix(translatable): update the `TranslatableInterface` to change the `trans` method signature and update `TranslatableValue` with said method and deprecate `each` and `sanitize` for future version of charcoal --- .../Translator/TranslatableInterface.php | 9 ++-- .../Charcoal/Translator/TranslatableValue.php | 50 ++++++++++++------- 2 files changed, 38 insertions(+), 21 deletions(-) diff --git a/packages/translator/src/Charcoal/Translator/TranslatableInterface.php b/packages/translator/src/Charcoal/Translator/TranslatableInterface.php index cc4e7d5d5..5108121e6 100644 --- a/packages/translator/src/Charcoal/Translator/TranslatableInterface.php +++ b/packages/translator/src/Charcoal/Translator/TranslatableInterface.php @@ -2,12 +2,13 @@ namespace Charcoal\Translator; +use Symfony\Component\Translation\TranslatorInterface; + interface TranslatableInterface { /** - * @param Translator $translator The translator. - * @param string|null $locale The locale. - * @return string + * @param TranslatorInterface $translator The $translator to use. + * @return mixed */ - public function trans(Translator $translator, ?string $locale = null): string; + public function trans(TranslatorInterface $translator); } diff --git a/packages/translator/src/Charcoal/Translator/TranslatableValue.php b/packages/translator/src/Charcoal/Translator/TranslatableValue.php index 71076957d..e02696483 100644 --- a/packages/translator/src/Charcoal/Translator/TranslatableValue.php +++ b/packages/translator/src/Charcoal/Translator/TranslatableValue.php @@ -4,6 +4,7 @@ use InvalidArgumentException; use JsonSerializable; +use Stringable; use Symfony\Component\Translation\TranslatorInterface; /** @@ -19,29 +20,19 @@ class TranslatableValue implements TranslatableInterface, JsonSerializable, - \Stringable + Stringable { /** * @var array */ private array $translations; - /** @var array */ - private array $parameters; - - /** @var string|null */ - private ?string $domain; - /** * @param array|Translation|self $translations Values keyed by locale. - * @param array $parameters An array of parameters for the message. - * @param string|null $domain The domain for the message or NULL to use the default. */ - public function __construct($translations, array $parameters = [], string $domain = null) + final public function __construct($translations) { $this->translations = $this->sanitizeTranslations($translations); - $this->parameters = $parameters; - $this->domain = $domain; } /** @@ -115,6 +106,19 @@ public function jsonSerialize(): array return $this->toArray(); } + /** + * @param callable $callback The callback function. + * @return static + */ + public function map(callable $callback): self + { + $keys = array_keys($this->translations); + + $translations = array_map($callback, $this->translations, $keys); + + return new static(array_combine($keys, $translations)); + } + /** * Transform each translation value. * @@ -122,6 +126,8 @@ public function jsonSerialize(): array * * @param (callable(mixed, string): mixed) $callback Function to apply to each value. * @return self + * + * @deprecated Will be removed in future version in favor of keeping this class Immutable. */ public function each(callable $callback): self { @@ -138,6 +144,8 @@ public function each(callable $callback): self * * @param (callable(mixed): mixed) $callback Function to apply to each value. * @return self + * + * @deprecated Will be removed in future version in favor of keeping this class Immutable. */ public function sanitize(callable $callback): self { @@ -148,12 +156,20 @@ public function sanitize(callable $callback): self } /** - * @param Translator $translator The translator. - * @param string|null $locale The locale. - * @return string + * @param string $locale The requested locale. + * @return mixed + */ + public function toLocale(string $locale) + { + return ($this->translations[$locale] ?? null); + } + + /** + * @param TranslatorInterface $translator The translator to use. + * @return mixed */ - public function trans(Translator $translator, ?string $locale = null): string + public function trans(TranslatorInterface $translator) { - return $translator->translate($this->translations, $this->parameters, $this->domain, $locale); + return $this->toLocale($translator->getLocale()); } } From ca6761247cc32fc7dcb5274d818e4b9ec8a8e289 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Tue, 5 Dec 2023 13:34:46 -0500 Subject: [PATCH 04/53] feat(structure): add TranslatableValue.php awareness to AbstractProperty.php - remove inputVal from StructureProperty.php --- .../Charcoal/Property/AbstractProperty.php | 11 +++++++- .../Charcoal/Property/StructureProperty.php | 26 ------------------- 2 files changed, 10 insertions(+), 27 deletions(-) diff --git a/packages/property/src/Charcoal/Property/AbstractProperty.php b/packages/property/src/Charcoal/Property/AbstractProperty.php index d23f767b0..5ac7be17d 100644 --- a/packages/property/src/Charcoal/Property/AbstractProperty.php +++ b/packages/property/src/Charcoal/Property/AbstractProperty.php @@ -23,6 +23,7 @@ use Charcoal\Validator\ValidatorInterface; // From 'charcoal-translator' use Charcoal\Translator\TranslatableInterface; +use Charcoal\Translator\TranslatableValue; use Charcoal\Translator\Translation; use Charcoal\Translator\TranslatorAwareTrait; // From 'charcoal-property' @@ -415,6 +416,8 @@ public function inputVal($val, array $options = []) if ($propertyValue === null) { return ''; } + } elseif ($val instanceof TranslatableValue) { + $val = $val->trans($this->translator()); } elseif ($val instanceof Translation) { $propertyValue = (string)$val; } else { @@ -429,7 +432,13 @@ public function inputVal($val, array $options = []) } if (!is_scalar($propertyValue)) { - $propertyValue = json_encode($propertyValue, JSON_PRETTY_PRINT); + if (isset($options['json'])) { + $flags = $options['json']; + } elseif ($options['pretty'] ?? false) { + $flags = JSON_PRETTY_PRINT; + } + $propertyValue = json_encode($propertyValue, $flags); + return $propertyValue; } return (string)$propertyValue; diff --git a/packages/property/src/Charcoal/Property/StructureProperty.php b/packages/property/src/Charcoal/Property/StructureProperty.php index 4e3ed2c69..aecc10ba6 100644 --- a/packages/property/src/Charcoal/Property/StructureProperty.php +++ b/packages/property/src/Charcoal/Property/StructureProperty.php @@ -76,31 +76,6 @@ public function displayVal($val, array $options = []) return (string)$propertyValue; } - /** - * @param mixed $val Optional. The value to to convert for input. - * @param array $options Optional input options. - * @return string - */ - public function inputVal($val, array $options = []): string - { - unset($options); - if ($val === null) { - return ''; - } - - if (is_string($val)) { - return $val; - } - - if ($val instanceof Translation) { - $propertyValue = (string)$val; - } else { - $propertyValue = $val; - } - - return json_encode($propertyValue, JSON_PRETTY_PRINT); - } - /** * Get the property's value in a format suitable for storage. * @@ -114,7 +89,6 @@ public function storageVal($val) return null; } - if ($val instanceof TranslatableValue) { $val = $val->trans($this->translator()); } From 4c40ea092a21d68b4d5acc7b5cb6f87e700d72df Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Tue, 5 Dec 2023 13:36:00 -0500 Subject: [PATCH 05/53] fix(translatable): make TranslatableValue.php ArrayAccess compliant --- .../Charcoal/Translator/TranslatableValue.php | 96 ++++++++++++++++++- 1 file changed, 93 insertions(+), 3 deletions(-) diff --git a/packages/translator/src/Charcoal/Translator/TranslatableValue.php b/packages/translator/src/Charcoal/Translator/TranslatableValue.php index e02696483..bec2ee9a9 100644 --- a/packages/translator/src/Charcoal/Translator/TranslatableValue.php +++ b/packages/translator/src/Charcoal/Translator/TranslatableValue.php @@ -2,6 +2,8 @@ namespace Charcoal\Translator; +use ArrayAccess; +use DomainException; use InvalidArgumentException; use JsonSerializable; use Stringable; @@ -19,6 +21,7 @@ */ class TranslatableValue implements TranslatableInterface, + ArrayAccess, JsonSerializable, Stringable { @@ -155,6 +158,15 @@ public function sanitize(callable $callback): self return $this; } + /** + * @param TranslatorInterface $translator The translator to use. + * @return mixed + */ + public function trans(TranslatorInterface $translator) + { + return $this->toLocale($translator->getLocale()); + } + /** * @param string $locale The requested locale. * @return mixed @@ -165,11 +177,89 @@ public function toLocale(string $locale) } /** - * @param TranslatorInterface $translator The translator to use. + * @param string $offset The requested offset to test. + * @return boolean + * @throws InvalidArgumentException If array key isn't a string. + * @see ArrayAccess::offsetExists() + */ + public function offsetExists($offset): bool + { + if (!is_string($offset)) { + throw new InvalidArgumentException(sprintf( + 'Invalid language; must be a string, received %s', + (is_object($offset) ? get_class($offset) : gettype($offset)) + )); + } + + return isset($this->translations[$offset]); + } + + /** + * @param string $offset The requested offset. * @return mixed + * @throws InvalidArgumentException If array key isn't a string. + * @throws DomainException If the array key is not found. + * @see ArrayAccess::offsetGet() */ - public function trans(TranslatorInterface $translator) + public function offsetGet($offset) { - return $this->toLocale($translator->getLocale()); + if (!is_string($offset)) { + throw new InvalidArgumentException(sprintf( + 'Invalid language; must be a string, received %s', + (is_object($offset) ? get_class($offset) : gettype($offset)) + )); + } + + if (!isset($this->translations[$offset])) { + throw new DomainException(sprintf( + 'Translation for "%s" is not defined.', + $offset + )); + } + + return $this->translations[$offset]; + } + + /** + * @param strin`g $offset The lang offset to set. + * @param mixed $value The value to store. + * @return void + * @throws InvalidArgumentException If array key isn't a string. + * @see ArrayAccess::offsetSet() + */ + public function offsetSet($offset, $value) + { + if (!is_string($offset)) { + throw new InvalidArgumentException(sprintf( + 'Invalid language; must be a string, received %s', + (is_object($offset) ? get_class($offset) : gettype($offset)) + )); + } + + if (!is_string($value)) { + throw new InvalidArgumentException(sprintf( + 'Translation must be a string, received %s', + (is_object($value) ? get_class($value) : gettype($value)) + )); + } + + $this->translations[$offset] = $value; + } + + /** + * @param string $offset The language offset to unset. + * @return void + * @throws InvalidArgumentException If array key isn't a string. + */ + public function offsetUnset($offset) + { + if (!is_string($offset)) { + throw new InvalidArgumentException(sprintf( + 'Invalid language; must be a string, received %s', + (is_object($offset) ? get_class($offset) : gettype($offset)) + )); + } + + unset($this->translations[$offset]); } } From a4a36c2022861c49dccf340fd542a85c1c17ae3c Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Tue, 5 Dec 2023 13:36:45 -0500 Subject: [PATCH 06/53] build(assets): add es6 support to admin assets build --- packages/admin/.eslintrc.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/admin/.eslintrc.json b/packages/admin/.eslintrc.json index dd315a086..61a54b237 100644 --- a/packages/admin/.eslintrc.json +++ b/packages/admin/.eslintrc.json @@ -1,8 +1,12 @@ { "root": true, + "parserOptions": { + "ecmaVersion": "latest" + }, "env": { "amd": true, - "browser": true + "browser": true, + "es6": true }, "globals": { "$": true, From 8d3ce52828b9526b88172a1a2ca088d92936b759 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Tue, 5 Dec 2023 13:39:53 -0500 Subject: [PATCH 07/53] feat(input): add getInputValOptions to allow input classes to define their own set of options. --- .../Admin/Property/AbstractPropertyInput.php | 18 ++++++++++++++++-- .../Admin/Property/Input/JsonEditorInput.php | 17 +++++------------ .../Admin/Property/Input/TextareaInput.php | 11 +++++++++++ 3 files changed, 32 insertions(+), 14 deletions(-) diff --git a/packages/admin/src/Charcoal/Admin/Property/AbstractPropertyInput.php b/packages/admin/src/Charcoal/Admin/Property/AbstractPropertyInput.php index afcd5e48f..a9e9d5193 100644 --- a/packages/admin/src/Charcoal/Admin/Property/AbstractPropertyInput.php +++ b/packages/admin/src/Charcoal/Admin/Property/AbstractPropertyInput.php @@ -376,6 +376,17 @@ public function escapeVal($val, array $options = []) return $callback($val, ...$args); } + /** + * Overridable. + * Makes it easier to pass InputVal options from children input types. + * + * @return array + **/ + public function getInputValOptions(): array + { + return []; + } + /** * @uses AbstractProperty::inputVal() Must handle string sanitization of value. * @throws UnexpectedValueException If the value is invalid. @@ -384,9 +395,12 @@ public function escapeVal($val, array $options = []) public function inputVal() { $prop = $this->p(); - $val = $prop->inputVal($this->propertyVal(), [ + $val = $prop->inputVal($this->propertyVal(), array_replace( + [ 'lang' => $this->lang(), - ]); + ], + $this->getInputValOptions() + )); if ($val === null) { return ''; diff --git a/packages/admin/src/Charcoal/Admin/Property/Input/JsonEditorInput.php b/packages/admin/src/Charcoal/Admin/Property/Input/JsonEditorInput.php index c9fe4faf8..2a7067cbe 100644 --- a/packages/admin/src/Charcoal/Admin/Property/Input/JsonEditorInput.php +++ b/packages/admin/src/Charcoal/Admin/Property/Input/JsonEditorInput.php @@ -104,19 +104,12 @@ public function defaultEditorOptions() } /** - * Retrieve the property's value as a json encoded string. - * - * @return string + * @return array */ - public function jsonVal() + public function getInputValOptions() : array { - $json = $this->propertyVal(); - if (!is_string($json)) { - $json = json_encode($json); - } - if (!$json || $json == 'null') { - $json = ''; - } - return $json; + return [ + 'pretty' => false, + ]; } } diff --git a/packages/admin/src/Charcoal/Admin/Property/Input/TextareaInput.php b/packages/admin/src/Charcoal/Admin/Property/Input/TextareaInput.php index 76f4a27e5..d06978569 100644 --- a/packages/admin/src/Charcoal/Admin/Property/Input/TextareaInput.php +++ b/packages/admin/src/Charcoal/Admin/Property/Input/TextareaInput.php @@ -4,6 +4,7 @@ use InvalidArgumentException; use Charcoal\Admin\Property\AbstractPropertyInput; +use UnexpectedValueException; /** * Multi-Line Text Input Property @@ -118,6 +119,16 @@ public function setMaxLength($maxLength) return $this; } + /** + * @return array + */ + public function getInputValOptions() : array + { + return [ + 'pretty' => true, + ]; + } + /** * @return integer */ From b2cda4af3c60a34f42e0053e37bc639b94ef40f8 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Tue, 5 Dec 2023 13:40:58 -0500 Subject: [PATCH 08/53] feat(tabulator): add tabulator front-end lib and templates --- packages/admin/build/grunt/config/concat.js | 2 ++ packages/admin/package.json | 1 + .../admin/property/input/tabulator.mustache | 8 +++++++ .../property/input/tabulator/control.mustache | 3 +++ .../property/input/tabulator/footer.mustache | 22 +++++++++++++++++++ .../property/input/tabulator/js.mustache | 9 ++++++++ 6 files changed, 45 insertions(+) create mode 100644 packages/admin/templates/charcoal/admin/property/input/tabulator.mustache create mode 100644 packages/admin/templates/charcoal/admin/property/input/tabulator/control.mustache create mode 100644 packages/admin/templates/charcoal/admin/property/input/tabulator/footer.mustache create mode 100644 packages/admin/templates/charcoal/admin/property/input/tabulator/js.mustache diff --git a/packages/admin/build/grunt/config/concat.js b/packages/admin/build/grunt/config/concat.js index 8ac748789..4ecec567e 100644 --- a/packages/admin/build/grunt/config/concat.js +++ b/packages/admin/build/grunt/config/concat.js @@ -62,6 +62,8 @@ module.exports = { '<%= paths.npm %>/selectize/dist/js/standalone/selectize.min.js', // Selectize '<%= paths.npm %>/clipboard/dist/clipboard.min.js', + // Tabulator + '<%= paths.npm %>/tabulator-tables/dist/js/tabulator.js', // jQuery Timeago '<%= paths.npm %>/timeago/jquery.timeago.js', ], diff --git a/packages/admin/package.json b/packages/admin/package.json index 0e5e3e0ae..407237b10 100644 --- a/packages/admin/package.json +++ b/packages/admin/package.json @@ -26,6 +26,7 @@ "multiselect-two-sides": "^2.5.7", "recorderjs": "git+https://github.com/mattdiamond/Recorderjs.git", "selectize": "~0.12.6", + "tabulator-tables": "^5.5.2", "tempusdominus-bootstrap-4": "^5.39.2", "timeago": "^1.6.5", "tinymce": "^5.10.9", diff --git a/packages/admin/templates/charcoal/admin/property/input/tabulator.mustache b/packages/admin/templates/charcoal/admin/property/input/tabulator.mustache new file mode 100644 index 000000000..9ad16ad08 --- /dev/null +++ b/packages/admin/templates/charcoal/admin/property/input/tabulator.mustache @@ -0,0 +1,8 @@ +{{!-- + Tabulator Property Input + ======================== + + `charcoal/admin/property/input/tabulator` +--}} +{{> charcoal/admin/property/input/tabulator/control }} +{{> charcoal/admin/property/input/tabulator/js }} diff --git a/packages/admin/templates/charcoal/admin/property/input/tabulator/control.mustache b/packages/admin/templates/charcoal/admin/property/input/tabulator/control.mustache new file mode 100644 index 000000000..5f010acb5 --- /dev/null +++ b/packages/admin/templates/charcoal/admin/property/input/tabulator/control.mustache @@ -0,0 +1,3 @@ +
{{!-- TABULATOR WIDGET --}}
+{{> charcoal/admin/property/input/tabulator/footer }} + diff --git a/packages/admin/templates/charcoal/admin/property/input/tabulator/footer.mustache b/packages/admin/templates/charcoal/admin/property/input/tabulator/footer.mustache new file mode 100644 index 000000000..6d40c6b91 --- /dev/null +++ b/packages/admin/templates/charcoal/admin/property/input/tabulator/footer.mustache @@ -0,0 +1,22 @@ +{{# controlDataForJs }} + +{{/ controlDataForJs }} diff --git a/packages/admin/templates/charcoal/admin/property/input/tabulator/js.mustache b/packages/admin/templates/charcoal/admin/property/input/tabulator/js.mustache new file mode 100644 index 000000000..50a532c5c --- /dev/null +++ b/packages/admin/templates/charcoal/admin/property/input/tabulator/js.mustache @@ -0,0 +1,9 @@ +{{# addJs }} + +{{/ addJs }} From 013573b4b1789cd3c78f901694463e8439897eee Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Tue, 5 Dec 2023 13:42:40 -0500 Subject: [PATCH 09/53] fix(json-editor): use inputVal instead of jsonVal for json-editor.mustache since it's no longer needed following changes to TranslatableValue and AbstractProperty/Input --- .../admin/property/input/json-editor.mustache | 15 +++------------ 1 file changed, 3 insertions(+), 12 deletions(-) diff --git a/packages/admin/templates/charcoal/admin/property/input/json-editor.mustache b/packages/admin/templates/charcoal/admin/property/input/json-editor.mustache index b6fcd5ba6..3d1771364 100644 --- a/packages/admin/templates/charcoal/admin/property/input/json-editor.mustache +++ b/packages/admin/templates/charcoal/admin/property/input/json-editor.mustache @@ -12,14 +12,6 @@ {{/ addJsRequirement }} -{{=<% %>=}} - <%# jsonVal %> - - <%/ jsonVal %> -<%={{ }}=%> - {{# addJs }} {{/ addJs }} \ No newline at end of file From 8815b63a3642bc2a9705824505f43f52efcf6cd5 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Tue, 5 Dec 2023 13:43:14 -0500 Subject: [PATCH 10/53] build(assets): import tabulator base css --- .../assets/src/styles/charcoal/admin/_imports-vendors.scss | 3 +++ 1 file changed, 3 insertions(+) diff --git a/packages/admin/assets/src/styles/charcoal/admin/_imports-vendors.scss b/packages/admin/assets/src/styles/charcoal/admin/_imports-vendors.scss index dc380e93b..6eb499b0c 100644 --- a/packages/admin/assets/src/styles/charcoal/admin/_imports-vendors.scss +++ b/packages/admin/assets/src/styles/charcoal/admin/_imports-vendors.scss @@ -46,6 +46,9 @@ // jQuery MiniColors @import "../../../../../node_modules/@claviska/jquery-minicolors/jquery.minicolors"; +// Tabulator +@import "../../../../../node_modules/tabulator-tables/dist/css/tabulator"; + // Dependency overrides // ========================================================================== From 0626c6116a42da7bfd96025c6f5320b6252d0279 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Tue, 5 Dec 2023 13:43:45 -0500 Subject: [PATCH 11/53] feat(tabulator): implement tabulator.js as Charcoal js module --- .../admin/property/input/tabulator.js | 738 ++++++++++++++++++ 1 file changed, 738 insertions(+) create mode 100644 packages/admin/assets/src/scripts/charcoal/admin/property/input/tabulator.js diff --git a/packages/admin/assets/src/scripts/charcoal/admin/property/input/tabulator.js b/packages/admin/assets/src/scripts/charcoal/admin/property/input/tabulator.js new file mode 100644 index 000000000..d2433c098 --- /dev/null +++ b/packages/admin/assets/src/scripts/charcoal/admin/property/input/tabulator.js @@ -0,0 +1,738 @@ +/* global formWidgetL10n commonL10n tabulatorWidgetL10n Tabulator */ + +(function (Charcoal, $, document, Tabulator) { + + /** + * Tabulator Input Property + * + * charcoal/admin/property/input/tabulator + * + * Require: + * - tabulator + * + * @param {Object} opts - Options for input property. + */ + Charcoal.Admin.Property_Input_Tabulator = function (opts) { + Charcoal.Admin.Property.call(this, opts); + + this.input_type = 'charcoal/admin/property/input/tabulator'; + + this.input_id = null; + + this.property_label = null; + this.tabulator_selector = null; + this.tabulator_input = null; + this.tabulator_options = null; + this.tabulator_instance = null; + this.tabulator_events = []; + + this.set_properties(opts).create_tabulator(); + this.set_events(); + }; + Charcoal.Admin.Property_Input_Tabulator.prototype = Object.create(Charcoal.Admin.Property.prototype); + Charcoal.Admin.Property_Input_Tabulator.prototype.constructor = Charcoal.Admin.Property_Input_Tabulator; + Charcoal.Admin.Property_Input_Tabulator.prototype.parent = Charcoal.Admin.Property.prototype; + + Charcoal.Admin.Property_Input_Tabulator.prototype.set_properties = function (opts) { + this.input_id = opts.id || this.input_id; + + if (typeof opts.data === 'function') { + opts.data = opts.data.apply(this); + } + + this.input_options = opts.data.input_options || this.input_options; + + this.tabulator_selector = opts.data.tabulator_selector || this.tabulator_selector; + this.tabulator_input = opts.data.tabulator_input || this.tabulator_input; + this.tabulator_options = opts.data.tabulator_options || this.tabulator_options; + this.tabulator_events = opts.data.tabulator_events || this.tabulator_events; + + if (this.tabulator_events && !Array.isArray(this.tabulator_events)) { + const tabulator_events_map = this.tabulator_events; + this.tabulator_events = []; + + for (const event in tabulator_events_map) { + const listeners = Array.isArray(tabulator_events_map[event]) + ? tabulator_events_map[event] + : [ tabulator_events_map[event] ]; + + for (const listener of listeners) { + if (typeof listener === 'function') { + this.tabulator_events.push([ event, listener ]); + } else { + console.warn('[Charcoal.Property.Tabulator]', 'Bad event listener:', event, listener); + } + } + } + } + + if (this.tabulator_selector) { + if (!this.tabulator_input) { + this.tabulator_input = document.querySelector(this.tabulator_selector); + } + } + + if (!this.tabulator_input) { + console.error('Tabulator input element or selector not defined'); + return; + } + + if (!this.property_label && this.tabulator_input.id) { + this.property_label = + document.querySelector('[for="' + this.tabulator_input.id.replace(/_[a-z]{2}$/, '') + '"]') + .textContent ?? this.tabulator_input.name; + } + + var default_tabulator_options = { + rowFormatter: (row) => { + var data = row.getData(); + + if (typeof data.active !== 'undefined') { + const rowElem = row.getElement(); + + if (data.active !== true) { + rowElem.style.backgroundColor = '#FFEFEF'; + } else { + rowElem.style.backgroundColor = null; + } + } + }, + footerElement: `${this.tabulator_selector}-tabulator-footer`, + }; + + if (typeof opts.pre_tabulator_options === 'function') { + opts.pre_tabulator_options.apply(this); + } + + this.tabulator_options = Object.assign({}, default_tabulator_options, this.tabulator_options); + + if (typeof opts.post_tabulator_options === 'function') { + opts.post_tabulator_options.apply(this); + } + + this.parse_tabulator_options(); + + return this; + }; + + Charcoal.Admin.Property_Input_Tabulator.prototype.parse_tabulator_options = function () { + /** + * Adds support to reuse custom 'newRowData' definition + * for Tabulator's new row on tab option. + */ + if (this.tabulator_options?.tabEndNewRow === 'newRowData') { + this.tabulator_options.tabEndNewRow = (this.input_options.newRowData || true); + } + + /** + * Adds support for merging predefined columns and + * automatic column generation, and automatic column templating. + */ + if (this.tabulator_options?.autoColumns) { + if ( + !this.tabulator_options?.autoColumnsDefinitions && + ( + this.tabulator_options?.columns || + this.input_options?.defaultColumnTemplate || + this.input_options?.autoColumnTemplates + ) + ) { + this.tabulator_options.autoColumnsDefinitions = (definitions) => { + if (Array.isArray(this.tabulator_options?.columns)) { + /** + * Replace any automatic column definition with + * a predefined column equivalent. + */ + definitions = definitions.filter( + ({ field: autoField }) => !this.tabulator_options.columns.some( + ({ field: colField }) => autoField === colField + ) + ); + + /** + * Merge predefined columns with automatic column definitions. + */ + definitions = this.tabulator_options.columns.concat(definitions); + } + + const defaultTemplate = this.input_options?.defaultColumnTemplate || {}; + const distinctTemplates = this.input_options?.autoColumnTemplates; + + if (!defaultTemplate && !distinctTemplates) { + return definitions; + } + + const calcAutoColumnStartIndex = (typeof this.input_options?.autoColumnStartIndex === 'number'); + + return definitions.map((column) => { + const field = column.field; + + if (typeof field === 'undefined') { + return column; + } + + if (distinctTemplates) { + for (const key in distinctTemplates) { + let query; + + try { + query = parseAutoColumnTemplatesKeyQuery(key); + } catch (err) { + console.error('[Charcoal.Property.Tabulator]', 'Bad autoColumnTemplates key:', key, err); + break; + } + + const template = distinctTemplates[key]; + + if (query instanceof RegExp) { + if (query.test(field)) { + column = Object.assign({}, column, defaultTemplate, template); + + column.title = field.replace(query, template.title); + column.field = field.replace(query, template.field); + + if (calcAutoColumnStartIndex && column.autoColumnStartIndex) { + this.input_options.autoColumnStartIndex = parseInt(field.replace(query, column.autoColumnStartIndex)); + // console.log('- Initial Column:', this.input_options.autoColumnStartIndex); + } + + // Custom option is deleted to avoid invalid column definition warning. + delete column.autoColumnStartIndex; + } + } else { + if (query === field) { + column = Object.assign({}, column, defaultTemplate, template); + + column.title = template.title; + column.field = template.field; + } + } + } + } else if (defaultTemplate) { + column = Object.assign({}, column, defaultTemplate); + } + + column = this.parse_tabulator_column_definition(column); + + return column; + }); + }; + } + } else if (this.tabulator_options?.columns) { + if (this.input_options?.defaultColumnTemplate) { + const defaultTemplate = this.input_options.defaultColumnTemplate; + + this.tabulator_options.columns = this.tabulator_options.columns.map((column) => { + column = Object.assign({}, defaultTemplate, column); + column = this.parse_tabulator_column_definition(column); + + return column; + }); + } else { + this.tabulator_options.columns = this.tabulator_options.columns.map( + (column) => this.parse_tabulator_column_definition(column) + ); + } + } + + if (Array.isArray(this.tabulator_options?.groupContextMenu)) { + this.tabulator_options.groupContextMenu = this.tabulator_options.groupContextMenu.map((item) => this.parse_tabulator_column_menu_item(item)); + } + + if (Array.isArray(this.tabulator_options?.rowContextMenu)) { + this.tabulator_options.rowContextMenu = this.tabulator_options.rowContextMenu.map((item) => this.parse_tabulator_row_menu_item(item)); + } + }; + + Charcoal.Admin.Property_Input_Tabulator.prototype.parse_tabulator_column_definition = function (column) { + if (Array.isArray(column?.clickMenu)) { + column.clickMenu = column.clickMenu.map((item) => this.parse_tabulator_cell_menu_item(item)); + } + + if (Array.isArray(column?.contextMenu)) { + column.contextMenu = column.contextMenu.map((item) => this.parse_tabulator_cell_menu_item(item)); + } + + if (Array.isArray(column?.headerContextMenu)) { + column.headerContextMenu = column.headerContextMenu.map((item) => this.parse_tabulator_column_menu_item(item)); + } + + if (Array.isArray(column?.headerMenu)) { + column.headerMenu = column.headerMenu.map((item) => this.parse_tabulator_column_menu_item(item)); + } + + if (typeof column?.cellClick === 'string') { + column.cellClick = this.parse_tabulator_cell_click_action(column.cellClick); + } + + if (typeof column?.formatterIcon === 'string') { + const formatterIcon = column.formatterIcon; + delete column.formatterIcon; + + column.formatter = () => { + return ``; + }; + } + + return column; + }; + + Charcoal.Admin.Property_Input_Tabulator.prototype.parse_tabulator_cell_click_action = function (action) { + switch (action) { + case 'addRow': + return (event, cell) => { + this.add_row(cell.getRow()); + this.update_input_data(); + }; + + case 'removeRow': + return (event, cell) => { + this.tabulator_instance.deleteRow(cell.getRow()); + this.update_input_data(); + }; + + case 'toggleCell': + return (event, cell) => { + // event.preventDefault(); + cell.setValue(!cell.getValue()); + // cell.cancelEdit(); + }; + } + + return null; + }; + + Charcoal.Admin.Property_Input_Tabulator.prototype.parse_tabulator_cell_menu_item = function (item) { + if (typeof item?.action === 'string') { + if (typeof cellMenuItemActions[item.action] === 'function') { + item.action = cellMenuItemActions[item.action].bind(this); + } + } + + return item; + }; + + Charcoal.Admin.Property_Input_Tabulator.prototype.parse_tabulator_column_menu_item = function (item) { + if (typeof item?.action === 'string') { + if (typeof columnMenuItemActions[item.action] === 'function') { + item.action = columnMenuItemActions[item.action].bind(this); + } + } + + return item; + }; + + Charcoal.Admin.Property_Input_Tabulator.prototype.parse_tabulator_row_menu_item = function (item) { + if (typeof item?.action === 'string') { + if (typeof rowMenuItemActions[item.action] === 'function') { + item.action = rowMenuItemActions[item.action].bind(this); + } + } + + return item; + }; + + Charcoal.Admin.Property_Input_Tabulator.prototype.set_events = function () { + $(`.js-${this.input_id}-add-col`).on('click.charcoal.tabulator', () => { + this.add_col(); + this.update_input_data(); + }); + + $(`.js-${this.input_id}-add-row`).on('click.charcoal.tabulator', () => { + this.add_row(); + this.update_input_data(); + }); + + $(`.js-${this.input_id}-history-undo`).on('click.charcoal.tabulator', () => { + this.tabulator_instance.undo(); + this.update_input_data(); + }); + + $(`.js-${this.input_id}-history-redo`).on('click.charcoal.tabulator', () => { + this.tabulator_instance.redo(); + this.update_input_data(); + }); + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.new_col_data = function () { + let column = this.input_options.newColumnData; + + const defaultTemplate = this.input_options?.defaultColumnTemplate || {}; + + if (typeof column === 'string') { + // let query; + + // try { + // query = parseAutoColumnTemplatesKeyQuery(column); + // } catch (err) { + // console.error('[Charcoal.Property.Tabulator]', 'Bad autoColumnTemplates key:', column, err); + // return {}; + // } + + if (this.input_options?.autoColumnTemplates[column]) { + const template = this.input_options.autoColumnTemplates[column]; + + column = Object.assign({}, defaultTemplate, template); + + if (typeof this.input_options?.autoColumnStartIndex === 'number') { + const index = ++(this.input_options.autoColumnStartIndex); + + // console.log('+ New Column:', index); + + column.title = column.title.replace('$1', index); + column.field = column.field.replace('$1', index); + + // Custom option is deleted to avoid invalid column definition warning. + delete column.autoColumnStartIndex; + } + } + } else { + column = Object.assign({}, defaultTemplate, column); + } + + column = this.parse_tabulator_column_definition(column); + + if (Array.isArray(column)) { + return [ ...column ]; + } + + return Object.assign({}, column); + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.new_row_data = function () { + let row = this.input_options?.newRowData || {}; + + if (Array.isArray(row)) { + return [ ...row ]; + } + + return Object.assign({}, row); + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.add_col = function (index = null) { + const addColumn = this.tabulator_instance.addColumn(this.new_col_data(), (void 0), index); + + if (this.input_options?.columnsManipulateData) { + addColumn.then((column) => { + const field = column.getField(); + + this.tabulator_instance.getRows().forEach((row) => { + const data = row.getData(); + + if (typeof data[field] === 'undefined') { + data[field] = this.input_options?.newRowData?.[field] ?? ''; + + row.update(data); + } + }); + }); + } + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.add_row = function (index = null) { + this.tabulator_instance.setHeight() + this.tabulator_instance.addRow(this.new_row_data(), (void 0), index); + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.delete_column = function (column) { + if (typeof column === 'string') { + column = this.tabulator_instance.getColumn(column); + + if (!column) { + console.error('[Charcoal.Property.Tabulator]', 'Column does not exist:', column); + return; + } + } + + const field = column.getField(); + + const deleteColumn = column.delete(); + + if (this.input_options?.columnsManipulateData) { + deleteColumn.then(() => { + this.tabulator_instance.getRows().forEach((row) => { + const data = row.getData(); + + if (typeof data[field] !== 'undefined') { + delete data[field]; + + row.update(data); + } + }); + }); + } + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.update_input_data = function () { + try { + const data = this.get_table_data(); + const json = JSON.stringify(data); + + this.tabulator_input.value = json; + } catch (err) { + console.warn('[Charcoal.Property.Tabulator]', 'Could not update input value:', err); + + Charcoal.Admin.feedback([ { + level: 'error', + message: commonL10n.errorTemplate.replaceMap({ + '[[ errorMessage ]]': this.property_label, + '[[ errorThrown ]]': tabulatorWidgetL10n.data.badOutput + }) + } ]).dispatch(); + } + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.get_input_data = function () { + try { + const json = this.tabulator_input.value.trim(); + if (!json) { + return []; + } + + const data = JSON.parse(json); + console.log(data); + return data; + } catch (err) { + console.warn('[Charcoal.Property.Tabulator]', 'Could not retrieve input value:', err); + + Charcoal.Admin.feedback([ { + level: 'error', + message: commonL10n.errorTemplate.replaceMap({ + '[[ errorMessage ]]': this.property_label, + '[[ errorThrown ]]': tabulatorWidgetL10n.data.badInput + }) + } ]).dispatch(); + } + + return []; + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.get_table_data = function () { + /** + * Adds support for customizing the table data to be stored on the + * property input by using one of Tabulator's row range lookups. + */ + return this.tabulator_instance.getData(this.input_options?.storableRowRange); + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.validate_table = function () { + return this.tabulator_instance?.validate(); + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.create_tabulator = function () { + // var lang = Charcoal.Admin.lang(); + + this.tabulator_instance = new Tabulator( + `${this.tabulator_selector}-tabulator`, + { + data: this.get_input_data(), + ...this.tabulator_options + } + ); + + const update_input_data = () => this.update_input_data(); + + this.tabulator_instance.on('columnMoved', update_input_data); + this.tabulator_instance.on('dataChanged', update_input_data); + this.tabulator_instance.on('rowMoved', update_input_data); + + for (const [ event, listener ] of this.tabulator_events) { + this.tabulator_instance.on(event, listener); + } + + /** + * Adds support for data validation on specified callbacks. + */ + if (Array.isArray(this.input_options?.validateOn)) { + const validate_table = () => { + try { + this.validate_table(); + } catch (err) { + console.warn('[Charcoal.Property.Tabulator]', 'Could not validate table on callback:', err); + } + }; + + this.input_options.validateOn.forEach((callback) => { + if (typeof callback !== 'string') { + console.error('[Charcoal.Property.Tabulator]', 'Invalid validateOn callback:', callback); + } + + this.tabulator_instance.on(callback, validate_table); + }); + } + + return this; + }; + + /** + * Determines if the component is a candidate for validation. + * + * @param {Component} [scope] - The parent component that calls for validation. + * @return {boolean} + */ + Charcoal.Admin.Property_Input_Tabulator.prototype.will_validate = function (scope) { + return (scope && $.contains(scope.element()[0], this.element()[0])); + }; + + /** + * Validates the property input. + * + * @return {boolean} + */ + Charcoal.Admin.Property_Input_Tabulator.prototype.validate = function () { + const validity = this.tabulator_instance.validate(); + + if (validity === true) { + return true; + } + + const propLabel = document.querySelector('label[for="' + this.input_id.replace(/_[a-z]{2}$/, '') + '"]').textContent; + + validity.forEach((cellComponent) => { + const rowComponent = cellComponent.getRow(); + const rowIndex = (rowComponent.getIndex() ?? (rowComponent.getPosition(true) + 1)); + + const fieldLabel = `${propLabel || this.tabulator_input.name} #${rowIndex}`; + const constraints = cellComponent._getSelf().modules.validate.invalid ?? []; + + constraints.forEach((constraint) => { + let message = ( + constraint.parameters?.validationMessage ?? + resolveTabulatorValidatorMessage(constraint) ?? + formWidgetL10n.validation.badInput + ); + + Charcoal.Admin.feedback([ { + level: 'error', + message: commonL10n.errorTemplate.replaceMap({ + '[[ errorMessage ]]': fieldLabel, + '[[ errorThrown ]]': message + }) + } ]); + }); + }); + + return false; + }; + + const cellMenuItemActions = { + deleteColumn: function (event, cell) { + this.delete_column(cell.getColumn()); + this.update_input_data(); + }, + deleteRow: function (event, cell) { + cell.getRow().delete(); + this.update_input_data(); + }, + insertColumn: function (event, cell) { + this.add_col(cell.getColumn()); + this.update_input_data(); + }, + insertRow: function (event, cell) { + this.add_row(cell.getRow()); + this.update_input_data(); + }, + }; + + const columnMenuItemActions = { + deleteColumn: function (event, column) { + this.delete_column(column); + this.update_input_data(); + }, + insertColumn: function (event, column) { + this.add_col(column); + this.update_input_data(); + }, + }; + + const rowMenuItemActions = { + deleteRow: function (event, row) { + row.delete(); + this.update_input_data(); + }, + insertRow: function (event, row) { + this.add_row(row); + this.update_input_data(); + }, + }; + + const parseAutoColumnTemplatesKeyQuery = (key) => { + const isRE = key.match(/^\/(.*)\/([a-z]*)$/); + if (isRE) { + return new RegExp(isRE[1], isRE[2].indexOf('i') === -1 ? '' : 'i'); + } + + return key; + }; + + /** + * Resolves the localized validation message for one of Tabulator's + * built-in validators. + * + * @see https://github.com/olifolkerd/tabulator/blob/5.2.3/src/js/modules/Validate/defaults/validators.js + * + * @param {object} constraint - The constraint object. + * @param {string} constraint.type - The constraint type. + * @param {*} constraint.parameters - The constraint parameters. + * @return {?string} + */ + const resolveTabulatorValidatorMessage = (constraint) => { + switch (constraint.type) { + case 'integer': + case 'float': + case 'numeric': { + return formWidgetL10n.validation.typeMismatchNumber; + } + + case 'string': { + return formWidgetL10n.validation.typeMismatch; + } + + case 'max': { + return formWidgetL10n.validation.rangeOverflow.replace('{{ max }}', constraint.parameters); + } + + case 'min': { + return formWidgetL10n.validation.rangeUnderflow.replace('{{ min }}', constraint.parameters); + } + + case 'starts': { + // starts with value + return formWidgetL10n.validation.patternMismatchWithStart.replace('{{ format }}', constraint.parameters); + } + + case 'ends': { + // ends with value + return formWidgetL10n.validation.patternMismatchWithEnd.replace('{{ format }}', constraint.parameters); + } + + case 'maxLength': { + return formWidgetL10n.validation.tooLong.replace('{{ max }}', constraint.parameters); + } + + case 'minLength': { + return formWidgetL10n.validation.tooShort.replace('{{ min }}', constraint.parameters); + } + + case 'in': { + // in provided value list + return formWidgetL10n.validation.valueMissingSelect; + } + + case 'regex': { + return formWidgetL10n.validation.patternMismatch; + } + + case 'unique': { + return formWidgetL10n.validation.notUnique; + } + + case 'required': { + return formWidgetL10n.validation.valueMissing; + } + } + + return null; + }; + +}(Charcoal, jQuery, document, Tabulator)); From 6461bd3fba0f7fe090c66960796402e39fa690c9 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Tue, 5 Dec 2023 13:44:17 -0500 Subject: [PATCH 12/53] chore(admin): Update NPM manifest and lockfile Changed: - Update Node from v14 to v16. - Update NPM from v8 to v9. - Update Node Sass from v7 to v9. - Update lockfile. --- packages/admin/.nvmrc | 2 +- packages/admin/package-lock.json | 1064 +++++++++++++++++++----------- packages/admin/package.json | 6 +- 3 files changed, 674 insertions(+), 398 deletions(-) diff --git a/packages/admin/.nvmrc b/packages/admin/.nvmrc index 898c8715b..b6a7d89c6 100644 --- a/packages/admin/.nvmrc +++ b/packages/admin/.nvmrc @@ -1 +1 @@ -14.17 +16 diff --git a/packages/admin/package-lock.json b/packages/admin/package-lock.json index 874526cff..3cd8e9fb0 100644 --- a/packages/admin/package-lock.json +++ b/packages/admin/package-lock.json @@ -25,6 +25,7 @@ "multiselect-two-sides": "^2.5.7", "recorderjs": "git+https://github.com/mattdiamond/Recorderjs.git", "selectize": "~0.12.6", + "tabulator-tables": "^5.5.2", "tempusdominus-bootstrap-4": "^5.39.2", "timeago": "^1.6.5", "tinymce": "^5.10.9", @@ -46,14 +47,14 @@ "grunt-sass": "^3.1.0", "grunt-svg-sprite": "^1.5.0", "load-grunt-config": "^4.0.1", - "node-sass": "^7.0.1", + "node-sass": "^9.0.0", "postcss": "^8.4.14", "postcss-banner": "^4.0.1", "tempusdominus-core": "^5.19.3" }, "engines": { - "node": "^14.17", - "npm": "^8" + "node": ">=16", + "npm": ">=9" } }, "node_modules/@babel/code-frame": { @@ -193,9 +194,9 @@ } }, "node_modules/@gar/promisify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.2.tgz", - "integrity": "sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "dev": true }, "node_modules/@humanwhocodes/config-array": { @@ -299,41 +300,6 @@ "node": ">=10" } }, - "node_modules/@npmcli/move-file/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@npmcli/move-file/node_modules/rimraf/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/@shopify/draggable": { "version": "1.0.0-beta.8", "resolved": "https://registry.npmjs.org/@shopify/draggable/-/draggable-1.0.0-beta.8.tgz", @@ -470,15 +436,6 @@ "node": ">= 0.6" } }, - "node_modules/accepts/node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, "node_modules/ace-builds": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.7.1.tgz", @@ -518,13 +475,11 @@ } }, "node_modules/agentkeepalive": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.0.tgz", - "integrity": "sha512-0PhAp58jZNw13UJv7NVdTGb0ZcghHUb3DrZ046JiiJY/BOaTTpbwdHq2VObPCBV8M2GPh7sgrJ3AQ8Ey468LJw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", "dev": true, "dependencies": { - "debug": "^4.1.0", - "depd": "^1.1.2", "humanize-ms": "^1.2.1" }, "engines": { @@ -1256,21 +1211,6 @@ "node": ">=10" } }, - "node_modules/cacache/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/call-bind": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", @@ -2766,26 +2706,6 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "dev": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/gaze": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", @@ -3736,41 +3656,6 @@ "url": "https://github.com/sponsors/mysticatea" } }, - "node_modules/grunt-eslint/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/grunt-eslint/node_modules/rimraf/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/grunt-eslint/node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -4142,21 +4027,6 @@ "node": ">=10" } }, - "node_modules/grunt/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/gzip-size": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz", @@ -4554,10 +4424,29 @@ "resolved": "https://registry.npmjs.org/inline-worker/-/inline-worker-0.1.0.tgz", "integrity": "sha1-spDDNutUpyHtPSL3KiuarN9oDoQ=" }, - "node_modules/ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dev": true, + "dependencies": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "engines": { + "node": ">= 12" + } + }, + "node_modules/ip-address/node_modules/jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true + }, + "node_modules/ip-address/node_modules/sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", "dev": true }, "node_modules/is-absolute": { @@ -5988,9 +5877,9 @@ } }, "node_modules/nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", + "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", "dev": true }, "node_modules/nanoid": { @@ -6018,9 +5907,9 @@ "dev": true }, "node_modules/negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true, "engines": { "node": ">= 0.6" @@ -6120,21 +6009,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16" } }, - "node_modules/node-gyp/node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/node-gyp/node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -6172,9 +6046,9 @@ "dev": true }, "node_modules/node-sass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-7.0.3.tgz", - "integrity": "sha512-8MIlsY/4dXUkJDYht9pIWBhMil3uHmE8b/AdJPjmFn1nBx9X9BASzfzmsCy0uCCb8eqI3SYYzVPDswWqSx7gjw==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-9.0.0.tgz", + "integrity": "sha512-yltEuuLrfH6M7Pq2gAj5B6Zm7m+gdZoG66wTqG6mIZV/zijq3M2OO2HswtT6oBspPyFhHDcaxWpsBm0fRNDHPg==", "dev": true, "hasInstallScript": true, "dependencies": { @@ -6185,20 +6059,55 @@ "get-stdin": "^4.0.1", "glob": "^7.0.3", "lodash": "^4.17.15", + "make-fetch-happen": "^10.0.4", "meow": "^9.0.0", - "nan": "^2.13.2", + "nan": "^2.17.0", "node-gyp": "^8.4.1", - "npmlog": "^5.0.0", - "request": "^2.88.0", "sass-graph": "^4.0.1", "stdout-stream": "^1.4.0", - "true-case-path": "^1.0.2" + "true-case-path": "^2.2.1" }, "bin": { "node-sass": "bin/node-sass" }, "engines": { - "node": ">=12" + "node": ">=16" + } + }, + "node_modules/node-sass/node_modules/@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "dev": true, + "dependencies": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-sass/node_modules/@npmcli/move-file": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "dev": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-sass/node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true, + "engines": { + "node": ">= 10" } }, "node_modules/node-sass/node_modules/ansi-styles": { @@ -6216,6 +6125,75 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "node_modules/node-sass/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/node-sass/node_modules/cacache": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "dev": true, + "dependencies": { + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-sass/node_modules/cacache/node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/node-sass/node_modules/cacache/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-sass/node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -6293,6 +6271,85 @@ "node": ">=8" } }, + "node_modules/node-sass/node_modules/http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/node-sass/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true, + "engines": { + "node": ">=12" + } + }, + "node_modules/node-sass/node_modules/make-fetch-happen": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, + "dependencies": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-sass/node_modules/minipass-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, + "dependencies": { + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + }, + "optionalDependencies": { + "encoding": "^0.1.13" + } + }, + "node_modules/node-sass/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-sass/node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -6302,6 +6359,33 @@ "node": ">=8" } }, + "node_modules/node-sass/node_modules/semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/node-sass/node_modules/semver/node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/node-sass/node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -6323,6 +6407,32 @@ "node": ">=8" } }, + "node_modules/node-sass/node_modules/socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, + "dependencies": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/node-sass/node_modules/ssri": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "dev": true, + "dependencies": { + "minipass": "^3.1.1" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/node-sass/node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -6335,6 +6445,30 @@ "node": ">=8" } }, + "node_modules/node-sass/node_modules/unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dev": true, + "dependencies": { + "unique-slug": "^3.0.0" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/node-sass/node_modules/unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dev": true, + "dependencies": { + "imurmurhash": "^0.1.4" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, "node_modules/node-sass/node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -6380,18 +6514,6 @@ "node": ">=0.10.0" } }, - "node_modules/npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "dev": true, - "dependencies": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, "node_modules/nth-check": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", @@ -7299,6 +7421,53 @@ "node": ">= 4" } }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/rimraf/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, "node_modules/rx": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", @@ -7780,16 +7949,16 @@ } }, "node_modules/socks": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz", - "integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.1.tgz", + "integrity": "sha512-B6w7tkwNid7ToxjZ08rQMT8M9BJAf8DKx8Ft4NivzH0zBUfd6jldGcisJn/RLgxcX3FPNDdNQCUEMMT79b+oCQ==", "dev": true, "dependencies": { - "ip": "^1.1.5", - "smart-buffer": "^4.1.0" + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" }, "engines": { - "node": ">= 10.13.0", + "node": ">= 10.0.0", "npm": ">= 3.0.0" } }, @@ -8334,6 +8503,11 @@ "node": ">=0.10.0" } }, + "node_modules/tabulator-tables": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/tabulator-tables/-/tabulator-tables-5.6.1.tgz", + "integrity": "sha512-DsmaZqEmlQS/NL5ZJbVtoaeYjJgofEFp+2er7+uwKerGwd/E2rZbeQgux4+Ab1dxNJcbptiX7oUiTwogOnUdgQ==" + }, "node_modules/tar": { "version": "6.1.11", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", @@ -8569,45 +8743,22 @@ "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/triple-beam": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", - "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==", - "dev": true - }, - "node_modules/true-case-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", - "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", - "dev": true, - "dependencies": { - "glob": "^7.1.2" - } - }, - "node_modules/true-case-path/node_modules/glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "engines": { + "node": ">=8" } }, + "node_modules/triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==", + "dev": true + }, + "node_modules/true-case-path": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-2.2.1.tgz", + "integrity": "sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q==", + "dev": true + }, "node_modules/tslib": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.0.tgz", @@ -9298,9 +9449,9 @@ } }, "@gar/promisify": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.2.tgz", - "integrity": "sha512-82cpyJyKRoQoRi+14ibCeGPu0CwypgtBAdBhq1WfvagpCZNKqwXbKwXllYSMG91DhmG4jt9gN8eP6lGOtozuaw==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "dev": true }, "@humanwhocodes/config-array": { @@ -9375,31 +9526,6 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } } } }, @@ -9520,12 +9646,6 @@ "requires": { "mime-db": "1.52.0" } - }, - "negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "dev": true } } }, @@ -9557,13 +9677,11 @@ } }, "agentkeepalive": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.2.0.tgz", - "integrity": "sha512-0PhAp58jZNw13UJv7NVdTGb0ZcghHUb3DrZ046JiiJY/BOaTTpbwdHq2VObPCBV8M2GPh7sgrJ3AQ8Ey468LJw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", "dev": true, "requires": { - "debug": "^4.1.0", - "depd": "^1.1.2", "humanize-ms": "^1.2.1" } }, @@ -10118,15 +10236,6 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } } } }, @@ -11312,23 +11421,6 @@ "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", "dev": true }, - "gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "dev": true, - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.2", - "console-control-strings": "^1.0.0", - "has-unicode": "^2.0.1", - "object-assign": "^4.1.1", - "signal-exit": "^3.0.0", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.2" - } - }, "gaze": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/gaze/-/gaze-1.1.3.tgz", @@ -11590,15 +11682,6 @@ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true - }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } } } }, @@ -12124,31 +12207,6 @@ "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==", "dev": true }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - }, - "dependencies": { - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } - }, "semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -12653,11 +12711,29 @@ "resolved": "https://registry.npmjs.org/inline-worker/-/inline-worker-0.1.0.tgz", "integrity": "sha1-spDDNutUpyHtPSL3KiuarN9oDoQ=" }, - "ip": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz", - "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo=", - "dev": true + "ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "dev": true, + "requires": { + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" + }, + "dependencies": { + "jsbn": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", + "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", + "dev": true + }, + "sprintf-js": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", + "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "dev": true + } + } }, "is-absolute": { "version": "1.0.0", @@ -13774,9 +13850,9 @@ "dev": true }, "nan": { - "version": "2.14.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.14.0.tgz", - "integrity": "sha512-INOFj37C7k3AfaNTtX8RhsTw7qRy7eLET14cROi9+5HAVbbHuIWUHEauBv5qT4Av2tWasiTY1Jw6puUNqRJXQg==", + "version": "2.18.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.18.0.tgz", + "integrity": "sha512-W7tfG7vMOGtD30sHoZSSc/JVYiyDPEyQVso/Zz+/uQd0B0L46gtC+pHha5FFMRpil6fm/AoEcRWyOVi4+E/f8w==", "dev": true }, "nanoid": { @@ -13792,9 +13868,9 @@ "dev": true }, "negotiator": { - "version": "0.6.2", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", - "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "dev": true }, "node-gyp": { @@ -13867,15 +13943,6 @@ "set-blocking": "^2.0.0" } }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, "semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -13903,9 +13970,9 @@ "dev": true }, "node-sass": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-7.0.3.tgz", - "integrity": "sha512-8MIlsY/4dXUkJDYht9pIWBhMil3uHmE8b/AdJPjmFn1nBx9X9BASzfzmsCy0uCCb8eqI3SYYzVPDswWqSx7gjw==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/node-sass/-/node-sass-9.0.0.tgz", + "integrity": "sha512-yltEuuLrfH6M7Pq2gAj5B6Zm7m+gdZoG66wTqG6mIZV/zijq3M2OO2HswtT6oBspPyFhHDcaxWpsBm0fRNDHPg==", "dev": true, "requires": { "async-foreach": "^0.1.3", @@ -13915,16 +13982,41 @@ "get-stdin": "^4.0.1", "glob": "^7.0.3", "lodash": "^4.17.15", + "make-fetch-happen": "^10.0.4", "meow": "^9.0.0", - "nan": "^2.13.2", + "nan": "^2.17.0", "node-gyp": "^8.4.1", - "npmlog": "^5.0.0", - "request": "^2.88.0", "sass-graph": "^4.0.1", "stdout-stream": "^1.4.0", - "true-case-path": "^1.0.2" + "true-case-path": "^2.2.1" }, "dependencies": { + "@npmcli/fs": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-2.1.2.tgz", + "integrity": "sha512-yOJKRvohFOaLqipNtwYB9WugyZKhC/DZC4VYPmpaCzDBrA8YpK3qHZ8/HGscMnE4GqbkLNuVcCnxkeQEdGt6LQ==", + "dev": true, + "requires": { + "@gar/promisify": "^1.1.3", + "semver": "^7.3.5" + } + }, + "@npmcli/move-file": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-2.0.1.tgz", + "integrity": "sha512-mJd2Z5TjYWq/ttPLLGqArdtnC74J6bOzg4rMDnN+p1xTacZ2yPRCk2y0oSWQtygLR9YVQXgOcONrwtnk3JupxQ==", + "dev": true, + "requires": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, + "@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "dev": true + }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", @@ -13934,6 +14026,65 @@ "color-convert": "^2.0.1" } }, + "brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "cacache": { + "version": "16.1.3", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-16.1.3.tgz", + "integrity": "sha512-/+Emcj9DAXxX4cwlLmRI9c166RuL3w30zp4R7Joiv2cQTtTtA+jeuCAjH3ZlGnYS3tKENSrKhAzVVP9GVyzeYQ==", + "dev": true, + "requires": { + "@npmcli/fs": "^2.1.0", + "@npmcli/move-file": "^2.0.0", + "chownr": "^2.0.0", + "fs-minipass": "^2.1.0", + "glob": "^8.0.1", + "infer-owner": "^1.0.4", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "mkdirp": "^1.0.4", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^9.0.0", + "tar": "^6.1.11", + "unique-filename": "^2.0.0" + }, + "dependencies": { + "glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + } + }, + "minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.1" + } + } + } + }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -13990,12 +14141,91 @@ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true }, + "http-proxy-agent": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", + "dev": true, + "requires": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + } + }, + "lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "dev": true + }, + "make-fetch-happen": { + "version": "10.2.1", + "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-10.2.1.tgz", + "integrity": "sha512-NgOPbRiaQM10DYXvN3/hhGVI2M5MtITFryzBGxHM5p4wnFxsVCbxkrBrDsk+EZ5OB4jEOT7AjDxtdF+KVEFT7w==", + "dev": true, + "requires": { + "agentkeepalive": "^4.2.1", + "cacache": "^16.1.0", + "http-cache-semantics": "^4.1.0", + "http-proxy-agent": "^5.0.0", + "https-proxy-agent": "^5.0.0", + "is-lambda": "^1.0.1", + "lru-cache": "^7.7.1", + "minipass": "^3.1.6", + "minipass-collect": "^1.0.2", + "minipass-fetch": "^2.0.3", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.4", + "negotiator": "^0.6.3", + "promise-retry": "^2.0.1", + "socks-proxy-agent": "^7.0.0", + "ssri": "^9.0.0" + } + }, + "minipass-fetch": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-2.1.2.tgz", + "integrity": "sha512-LT49Zi2/WMROHYoqGgdlQIZh8mLPZmOrN2NdJjMXxYe4nkN6FUyuPuOAOedNJDrx0IRGg9+4guZewtp8hE6TxA==", + "dev": true, + "requires": { + "encoding": "^0.1.13", + "minipass": "^3.1.6", + "minipass-sized": "^1.0.3", + "minizlib": "^2.1.2" + } + }, + "mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true + }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true }, + "semver": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", + "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + }, + "dependencies": { + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + } + } + }, "shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", @@ -14011,6 +14241,26 @@ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true }, + "socks-proxy-agent": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-7.0.0.tgz", + "integrity": "sha512-Fgl0YPZ902wEsAyiQ+idGd1A7rSFx/ayC1CQVMw5P+EQx2V0SgpGtf6OKFhVjPflPUl9YMmEOnmfjCdMUsygww==", + "dev": true, + "requires": { + "agent-base": "^6.0.2", + "debug": "^4.3.3", + "socks": "^2.6.2" + } + }, + "ssri": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/ssri/-/ssri-9.0.1.tgz", + "integrity": "sha512-o57Wcn66jMQvfHG1FlYbWeZWW/dHZhJXjpIcTfXldXEk5nz5lStPo3mK0OJQfGR3RbZUlbISexbljkJzuEj/8Q==", + "dev": true, + "requires": { + "minipass": "^3.1.1" + } + }, "supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", @@ -14020,6 +14270,24 @@ "has-flag": "^4.0.0" } }, + "unique-filename": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-2.0.1.tgz", + "integrity": "sha512-ODWHtkkdx3IAR+veKxFV+VBkUMcN+FaqzUUd7IZzt+0zhDZFPFxhlqwPF3YQvMHx1TD0tdgYl+kuPnJ8E6ql7A==", + "dev": true, + "requires": { + "unique-slug": "^3.0.0" + } + }, + "unique-slug": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-3.0.0.tgz", + "integrity": "sha512-8EyMynh679x/0gqE9fT9oilG+qEt+ibFyqjuVTsZn1+CMxH+XLlpvr2UZx4nVcCwTpx81nICr2JQFkM+HPLq4w==", + "dev": true, + "requires": { + "imurmurhash": "^0.1.4" + } + }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -14052,18 +14320,6 @@ "integrity": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI=", "dev": true }, - "npmlog": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz", - "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==", - "dev": true, - "requires": { - "are-we-there-yet": "^2.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^3.0.0", - "set-blocking": "^2.0.0" - } - }, "nth-check": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz", @@ -14771,6 +15027,40 @@ "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=", "dev": true }, + "rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "dev": true, + "requires": { + "glob": "^7.1.3" + }, + "dependencies": { + "glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + } + } + }, "rx": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/rx/-/rx-4.1.0.tgz", @@ -15171,13 +15461,13 @@ } }, "socks": { - "version": "2.6.1", - "resolved": "https://registry.npmjs.org/socks/-/socks-2.6.1.tgz", - "integrity": "sha512-kLQ9N5ucj8uIcxrDwjm0Jsqk06xdpBjGNQtpXy4Q8/QY2k+fY7nZH8CARy+hkbG+SGAovmzzuauCpBlb8FrnBA==", + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.1.tgz", + "integrity": "sha512-B6w7tkwNid7ToxjZ08rQMT8M9BJAf8DKx8Ft4NivzH0zBUfd6jldGcisJn/RLgxcX3FPNDdNQCUEMMT79b+oCQ==", "dev": true, "requires": { - "ip": "^1.1.5", - "smart-buffer": "^4.1.0" + "ip-address": "^9.0.5", + "smart-buffer": "^4.2.0" } }, "socks-proxy-agent": { @@ -15602,6 +15892,11 @@ "integrity": "sha1-g0D8RwLDEi310iKI+IKD9RPT/dQ=", "dev": true }, + "tabulator-tables": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/tabulator-tables/-/tabulator-tables-5.6.1.tgz", + "integrity": "sha512-DsmaZqEmlQS/NL5ZJbVtoaeYjJgofEFp+2er7+uwKerGwd/E2rZbeQgux4+Ab1dxNJcbptiX7oUiTwogOnUdgQ==" + }, "tar": { "version": "6.1.11", "resolved": "https://registry.npmjs.org/tar/-/tar-6.1.11.tgz", @@ -15802,29 +16097,10 @@ "dev": true }, "true-case-path": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-1.0.3.tgz", - "integrity": "sha512-m6s2OdQe5wgpFMC+pAJ+q9djG82O2jcHPOI6RNg1yy9rCYR+WD6Nbpl32fDpfC56nirdRy+opFa/Vk7HYhqaew==", - "dev": true, - "requires": { - "glob": "^7.1.2" - }, - "dependencies": { - "glob": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz", - "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==", - "dev": true, - "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - } - } - } + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/true-case-path/-/true-case-path-2.2.1.tgz", + "integrity": "sha512-0z3j8R7MCjy10kc/g+qg7Ln3alJTodw9aDuVWZa3uiWqfuBMKeAeP2ocWcxoyM3D73yz3Jt/Pu4qPr4wHSdB/Q==", + "dev": true }, "tslib": { "version": "2.3.0", diff --git a/packages/admin/package.json b/packages/admin/package.json index 407237b10..2351b62ca 100644 --- a/packages/admin/package.json +++ b/packages/admin/package.json @@ -5,8 +5,8 @@ "version": "1.0.0", "author": "Locomotive ", "engines": { - "node": "^14.17", - "npm": "^8" + "node": ">=16", + "npm": ">=9" }, "dependencies": { "@claviska/jquery-minicolors": "^2.3.6", @@ -48,7 +48,7 @@ "grunt-sass": "^3.1.0", "grunt-svg-sprite": "^1.5.0", "load-grunt-config": "^4.0.1", - "node-sass": "^7.0.1", + "node-sass": "^9.0.0", "postcss": "^8.4.14", "postcss-banner": "^4.0.1", "tempusdominus-core": "^5.19.3" From e9b94e85bf5bf2d05eb6bf20241014121859a39b Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Tue, 5 Dec 2023 13:45:53 -0500 Subject: [PATCH 13/53] build(admin): Build assets --- .../assets/dist/scripts/charcoal.admin.js | 739 + .../assets/dist/scripts/charcoal.admin.min.js | 2 +- .../dist/scripts/charcoal.admin.vendors.js | 28006 ++++++++++++++++ .../scripts/charcoal.admin.vendors.min.js | 9 +- .../dist/styles/charcoal.admin.vendors.css | 2 +- 5 files changed, 28755 insertions(+), 3 deletions(-) diff --git a/packages/admin/assets/dist/scripts/charcoal.admin.js b/packages/admin/assets/dist/scripts/charcoal.admin.js index dbdba9a7e..7628ff4d4 100644 --- a/packages/admin/assets/dist/scripts/charcoal.admin.js +++ b/packages/admin/assets/dist/scripts/charcoal.admin.js @@ -12185,6 +12185,745 @@ Charcoal.Admin.Property_Input_Selectize_Tags.prototype.init_clipboard = function }); }; +/* global formWidgetL10n commonL10n tabulatorWidgetL10n Tabulator */ + +(function (Charcoal, $, document, Tabulator) { + + /** + * Tabulator Input Property + * + * charcoal/admin/property/input/tabulator + * + * Require: + * - tabulator + * + * @param {Object} opts - Options for input property. + */ + Charcoal.Admin.Property_Input_Tabulator = function (opts) { + Charcoal.Admin.Property.call(this, opts); + + this.input_type = 'charcoal/admin/property/input/tabulator'; + + this.input_id = null; + + this.property_label = null; + this.tabulator_selector = null; + this.tabulator_input = null; + this.tabulator_options = null; + this.tabulator_instance = null; + this.tabulator_events = []; + + this.set_properties(opts).create_tabulator(); + this.set_events(); + }; + Charcoal.Admin.Property_Input_Tabulator.prototype = Object.create(Charcoal.Admin.Property.prototype); + Charcoal.Admin.Property_Input_Tabulator.prototype.constructor = Charcoal.Admin.Property_Input_Tabulator; + Charcoal.Admin.Property_Input_Tabulator.prototype.parent = Charcoal.Admin.Property.prototype; + + Charcoal.Admin.Property_Input_Tabulator.prototype.set_properties = function (opts) { + this.input_id = opts.id || this.input_id; + + if (typeof opts.data === 'function') { + opts.data = opts.data.apply(this); + } + + this.input_options = opts.data.input_options || this.input_options; + + this.tabulator_selector = opts.data.tabulator_selector || this.tabulator_selector; + this.tabulator_input = opts.data.tabulator_input || this.tabulator_input; + this.tabulator_options = opts.data.tabulator_options || this.tabulator_options; + this.tabulator_events = opts.data.tabulator_events || this.tabulator_events; + + if (this.tabulator_events && !Array.isArray(this.tabulator_events)) { + const tabulator_events_map = this.tabulator_events; + this.tabulator_events = []; + + for (const event in tabulator_events_map) { + const listeners = Array.isArray(tabulator_events_map[event]) + ? tabulator_events_map[event] + : [ tabulator_events_map[event] ]; + + for (const listener of listeners) { + if (typeof listener === 'function') { + this.tabulator_events.push([ event, listener ]); + } else { + console.warn('[Charcoal.Property.Tabulator]', 'Bad event listener:', event, listener); + } + } + } + } + + if (this.tabulator_selector) { + if (!this.tabulator_input) { + this.tabulator_input = document.querySelector(this.tabulator_selector); + } + } + + if (!this.tabulator_input) { + console.error('Tabulator input element or selector not defined'); + return; + } + + if (!this.property_label && this.tabulator_input.id) { + this.property_label = + document.querySelector('[for="' + this.tabulator_input.id.replace(/_[a-z]{2}$/, '') + '"]') + .textContent ?? this.tabulator_input.name; + } + + var default_tabulator_options = { + rowFormatter: (row) => { + var data = row.getData(); + + if (typeof data.active !== 'undefined') { + const rowElem = row.getElement(); + + if (data.active !== true) { + rowElem.style.backgroundColor = '#FFEFEF'; + } else { + rowElem.style.backgroundColor = null; + } + } + }, + footerElement: `${this.tabulator_selector}-tabulator-footer`, + }; + + if (typeof opts.pre_tabulator_options === 'function') { + opts.pre_tabulator_options.apply(this); + } + + this.tabulator_options = Object.assign({}, default_tabulator_options, this.tabulator_options); + + if (typeof opts.post_tabulator_options === 'function') { + opts.post_tabulator_options.apply(this); + } + + this.parse_tabulator_options(); + + return this; + }; + + Charcoal.Admin.Property_Input_Tabulator.prototype.parse_tabulator_options = function () { + /** + * Adds support to reuse custom 'newRowData' definition + * for Tabulator's new row on tab option. + */ + if (this.tabulator_options?.tabEndNewRow === 'newRowData') { + this.tabulator_options.tabEndNewRow = (this.input_options.newRowData || true); + } + + /** + * Adds support for merging predefined columns and + * automatic column generation, and automatic column templating. + */ + if (this.tabulator_options?.autoColumns) { + if ( + !this.tabulator_options?.autoColumnsDefinitions && + ( + this.tabulator_options?.columns || + this.input_options?.defaultColumnTemplate || + this.input_options?.autoColumnTemplates + ) + ) { + this.tabulator_options.autoColumnsDefinitions = (definitions) => { + if (Array.isArray(this.tabulator_options?.columns)) { + /** + * Replace any automatic column definition with + * a predefined column equivalent. + */ + definitions = definitions.filter( + ({ field: autoField }) => !this.tabulator_options.columns.some( + ({ field: colField }) => autoField === colField + ) + ); + + /** + * Merge predefined columns with automatic column definitions. + */ + definitions = this.tabulator_options.columns.concat(definitions); + } + + const defaultTemplate = this.input_options?.defaultColumnTemplate || {}; + const distinctTemplates = this.input_options?.autoColumnTemplates; + + if (!defaultTemplate && !distinctTemplates) { + return definitions; + } + + const calcAutoColumnStartIndex = (typeof this.input_options?.autoColumnStartIndex === 'number'); + + return definitions.map((column) => { + const field = column.field; + + if (typeof field === 'undefined') { + return column; + } + + if (distinctTemplates) { + for (const key in distinctTemplates) { + let query; + + try { + query = parseAutoColumnTemplatesKeyQuery(key); + } catch (err) { + console.error('[Charcoal.Property.Tabulator]', 'Bad autoColumnTemplates key:', key, err); + break; + } + + const template = distinctTemplates[key]; + + if (query instanceof RegExp) { + if (query.test(field)) { + column = Object.assign({}, column, defaultTemplate, template); + + column.title = field.replace(query, template.title); + column.field = field.replace(query, template.field); + + if (calcAutoColumnStartIndex && column.autoColumnStartIndex) { + this.input_options.autoColumnStartIndex = parseInt(field.replace(query, column.autoColumnStartIndex)); + // console.log('- Initial Column:', this.input_options.autoColumnStartIndex); + } + + // Custom option is deleted to avoid invalid column definition warning. + delete column.autoColumnStartIndex; + } + } else { + if (query === field) { + column = Object.assign({}, column, defaultTemplate, template); + + column.title = template.title; + column.field = template.field; + } + } + } + } else if (defaultTemplate) { + column = Object.assign({}, column, defaultTemplate); + } + + column = this.parse_tabulator_column_definition(column); + + return column; + }); + }; + } + } else if (this.tabulator_options?.columns) { + if (this.input_options?.defaultColumnTemplate) { + const defaultTemplate = this.input_options.defaultColumnTemplate; + + this.tabulator_options.columns = this.tabulator_options.columns.map((column) => { + column = Object.assign({}, defaultTemplate, column); + column = this.parse_tabulator_column_definition(column); + + return column; + }); + } else { + this.tabulator_options.columns = this.tabulator_options.columns.map( + (column) => this.parse_tabulator_column_definition(column) + ); + } + } + + if (Array.isArray(this.tabulator_options?.groupContextMenu)) { + this.tabulator_options.groupContextMenu = this.tabulator_options.groupContextMenu.map((item) => this.parse_tabulator_column_menu_item(item)); + } + + if (Array.isArray(this.tabulator_options?.rowContextMenu)) { + this.tabulator_options.rowContextMenu = this.tabulator_options.rowContextMenu.map((item) => this.parse_tabulator_row_menu_item(item)); + } + }; + + Charcoal.Admin.Property_Input_Tabulator.prototype.parse_tabulator_column_definition = function (column) { + if (Array.isArray(column?.clickMenu)) { + column.clickMenu = column.clickMenu.map((item) => this.parse_tabulator_cell_menu_item(item)); + } + + if (Array.isArray(column?.contextMenu)) { + column.contextMenu = column.contextMenu.map((item) => this.parse_tabulator_cell_menu_item(item)); + } + + if (Array.isArray(column?.headerContextMenu)) { + column.headerContextMenu = column.headerContextMenu.map((item) => this.parse_tabulator_column_menu_item(item)); + } + + if (Array.isArray(column?.headerMenu)) { + column.headerMenu = column.headerMenu.map((item) => this.parse_tabulator_column_menu_item(item)); + } + + if (typeof column?.cellClick === 'string') { + column.cellClick = this.parse_tabulator_cell_click_action(column.cellClick); + } + + if (typeof column?.formatterIcon === 'string') { + const formatterIcon = column.formatterIcon; + delete column.formatterIcon; + + column.formatter = () => { + return ``; + }; + } + + return column; + }; + + Charcoal.Admin.Property_Input_Tabulator.prototype.parse_tabulator_cell_click_action = function (action) { + switch (action) { + case 'addRow': + return (event, cell) => { + this.add_row(cell.getRow()); + this.update_input_data(); + }; + + case 'removeRow': + return (event, cell) => { + this.tabulator_instance.deleteRow(cell.getRow()); + this.update_input_data(); + }; + + case 'toggleCell': + return (event, cell) => { + // event.preventDefault(); + cell.setValue(!cell.getValue()); + // cell.cancelEdit(); + }; + } + + return null; + }; + + Charcoal.Admin.Property_Input_Tabulator.prototype.parse_tabulator_cell_menu_item = function (item) { + if (typeof item?.action === 'string') { + if (typeof cellMenuItemActions[item.action] === 'function') { + item.action = cellMenuItemActions[item.action].bind(this); + } + } + + return item; + }; + + Charcoal.Admin.Property_Input_Tabulator.prototype.parse_tabulator_column_menu_item = function (item) { + if (typeof item?.action === 'string') { + if (typeof columnMenuItemActions[item.action] === 'function') { + item.action = columnMenuItemActions[item.action].bind(this); + } + } + + return item; + }; + + Charcoal.Admin.Property_Input_Tabulator.prototype.parse_tabulator_row_menu_item = function (item) { + if (typeof item?.action === 'string') { + if (typeof rowMenuItemActions[item.action] === 'function') { + item.action = rowMenuItemActions[item.action].bind(this); + } + } + + return item; + }; + + Charcoal.Admin.Property_Input_Tabulator.prototype.set_events = function () { + $(`.js-${this.input_id}-add-col`).on('click.charcoal.tabulator', () => { + this.add_col(); + this.update_input_data(); + }); + + $(`.js-${this.input_id}-add-row`).on('click.charcoal.tabulator', () => { + this.add_row(); + this.update_input_data(); + }); + + $(`.js-${this.input_id}-history-undo`).on('click.charcoal.tabulator', () => { + this.tabulator_instance.undo(); + this.update_input_data(); + }); + + $(`.js-${this.input_id}-history-redo`).on('click.charcoal.tabulator', () => { + this.tabulator_instance.redo(); + this.update_input_data(); + }); + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.new_col_data = function () { + let column = this.input_options.newColumnData; + + const defaultTemplate = this.input_options?.defaultColumnTemplate || {}; + + if (typeof column === 'string') { + // let query; + + // try { + // query = parseAutoColumnTemplatesKeyQuery(column); + // } catch (err) { + // console.error('[Charcoal.Property.Tabulator]', 'Bad autoColumnTemplates key:', column, err); + // return {}; + // } + + if (this.input_options?.autoColumnTemplates[column]) { + const template = this.input_options.autoColumnTemplates[column]; + + column = Object.assign({}, defaultTemplate, template); + + if (typeof this.input_options?.autoColumnStartIndex === 'number') { + const index = ++(this.input_options.autoColumnStartIndex); + + // console.log('+ New Column:', index); + + column.title = column.title.replace('$1', index); + column.field = column.field.replace('$1', index); + + // Custom option is deleted to avoid invalid column definition warning. + delete column.autoColumnStartIndex; + } + } + } else { + column = Object.assign({}, defaultTemplate, column); + } + + column = this.parse_tabulator_column_definition(column); + + if (Array.isArray(column)) { + return [ ...column ]; + } + + return Object.assign({}, column); + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.new_row_data = function () { + let row = this.input_options?.newRowData || {}; + + if (Array.isArray(row)) { + return [ ...row ]; + } + + return Object.assign({}, row); + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.add_col = function (index = null) { + const addColumn = this.tabulator_instance.addColumn(this.new_col_data(), (void 0), index); + + if (this.input_options?.columnsManipulateData) { + addColumn.then((column) => { + const field = column.getField(); + + this.tabulator_instance.getRows().forEach((row) => { + const data = row.getData(); + + if (typeof data[field] === 'undefined') { + data[field] = this.input_options?.newRowData?.[field] ?? ''; + + row.update(data); + } + }); + }); + } + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.add_row = function (index = null) { + this.tabulator_instance.setHeight() + this.tabulator_instance.addRow(this.new_row_data(), (void 0), index); + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.delete_column = function (column) { + if (typeof column === 'string') { + column = this.tabulator_instance.getColumn(column); + + if (!column) { + console.error('[Charcoal.Property.Tabulator]', 'Column does not exist:', column); + return; + } + } + + const field = column.getField(); + + const deleteColumn = column.delete(); + + if (this.input_options?.columnsManipulateData) { + deleteColumn.then(() => { + this.tabulator_instance.getRows().forEach((row) => { + const data = row.getData(); + + if (typeof data[field] !== 'undefined') { + delete data[field]; + + row.update(data); + } + }); + }); + } + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.update_input_data = function () { + try { + const data = this.get_table_data(); + const json = JSON.stringify(data); + + this.tabulator_input.value = json; + } catch (err) { + console.warn('[Charcoal.Property.Tabulator]', 'Could not update input value:', err); + + Charcoal.Admin.feedback([ { + level: 'error', + message: commonL10n.errorTemplate.replaceMap({ + '[[ errorMessage ]]': this.property_label, + '[[ errorThrown ]]': tabulatorWidgetL10n.data.badOutput + }) + } ]).dispatch(); + } + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.get_input_data = function () { + try { + const json = this.tabulator_input.value.trim(); + if (!json) { + return []; + } + + const data = JSON.parse(json); + console.log(data); + return data; + } catch (err) { + console.warn('[Charcoal.Property.Tabulator]', 'Could not retrieve input value:', err); + + Charcoal.Admin.feedback([ { + level: 'error', + message: commonL10n.errorTemplate.replaceMap({ + '[[ errorMessage ]]': this.property_label, + '[[ errorThrown ]]': tabulatorWidgetL10n.data.badInput + }) + } ]).dispatch(); + } + + return []; + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.get_table_data = function () { + /** + * Adds support for customizing the table data to be stored on the + * property input by using one of Tabulator's row range lookups. + */ + return this.tabulator_instance.getData(this.input_options?.storableRowRange); + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.validate_table = function () { + return this.tabulator_instance?.validate(); + } + + Charcoal.Admin.Property_Input_Tabulator.prototype.create_tabulator = function () { + // var lang = Charcoal.Admin.lang(); + + this.tabulator_instance = new Tabulator( + `${this.tabulator_selector}-tabulator`, + { + data: this.get_input_data(), + ...this.tabulator_options + } + ); + + const update_input_data = () => this.update_input_data(); + + this.tabulator_instance.on('columnMoved', update_input_data); + this.tabulator_instance.on('dataChanged', update_input_data); + this.tabulator_instance.on('rowMoved', update_input_data); + + for (const [ event, listener ] of this.tabulator_events) { + this.tabulator_instance.on(event, listener); + } + + /** + * Adds support for data validation on specified callbacks. + */ + if (Array.isArray(this.input_options?.validateOn)) { + const validate_table = () => { + try { + this.validate_table(); + } catch (err) { + console.warn('[Charcoal.Property.Tabulator]', 'Could not validate table on callback:', err); + } + }; + + this.input_options.validateOn.forEach((callback) => { + if (typeof callback !== 'string') { + console.error('[Charcoal.Property.Tabulator]', 'Invalid validateOn callback:', callback); + } + + this.tabulator_instance.on(callback, validate_table); + }); + } + + return this; + }; + + /** + * Determines if the component is a candidate for validation. + * + * @param {Component} [scope] - The parent component that calls for validation. + * @return {boolean} + */ + Charcoal.Admin.Property_Input_Tabulator.prototype.will_validate = function (scope) { + return (scope && $.contains(scope.element()[0], this.element()[0])); + }; + + /** + * Validates the property input. + * + * @return {boolean} + */ + Charcoal.Admin.Property_Input_Tabulator.prototype.validate = function () { + const validity = this.tabulator_instance.validate(); + + if (validity === true) { + return true; + } + + const propLabel = document.querySelector('label[for="' + this.input_id.replace(/_[a-z]{2}$/, '') + '"]').textContent; + + validity.forEach((cellComponent) => { + const rowComponent = cellComponent.getRow(); + const rowIndex = (rowComponent.getIndex() ?? (rowComponent.getPosition(true) + 1)); + + const fieldLabel = `${propLabel || this.tabulator_input.name} #${rowIndex}`; + const constraints = cellComponent._getSelf().modules.validate.invalid ?? []; + + constraints.forEach((constraint) => { + let message = ( + constraint.parameters?.validationMessage ?? + resolveTabulatorValidatorMessage(constraint) ?? + formWidgetL10n.validation.badInput + ); + + Charcoal.Admin.feedback([ { + level: 'error', + message: commonL10n.errorTemplate.replaceMap({ + '[[ errorMessage ]]': fieldLabel, + '[[ errorThrown ]]': message + }) + } ]); + }); + }); + + return false; + }; + + const cellMenuItemActions = { + deleteColumn: function (event, cell) { + this.delete_column(cell.getColumn()); + this.update_input_data(); + }, + deleteRow: function (event, cell) { + cell.getRow().delete(); + this.update_input_data(); + }, + insertColumn: function (event, cell) { + this.add_col(cell.getColumn()); + this.update_input_data(); + }, + insertRow: function (event, cell) { + this.add_row(cell.getRow()); + this.update_input_data(); + }, + }; + + const columnMenuItemActions = { + deleteColumn: function (event, column) { + this.delete_column(column); + this.update_input_data(); + }, + insertColumn: function (event, column) { + this.add_col(column); + this.update_input_data(); + }, + }; + + const rowMenuItemActions = { + deleteRow: function (event, row) { + row.delete(); + this.update_input_data(); + }, + insertRow: function (event, row) { + this.add_row(row); + this.update_input_data(); + }, + }; + + const parseAutoColumnTemplatesKeyQuery = (key) => { + const isRE = key.match(/^\/(.*)\/([a-z]*)$/); + if (isRE) { + return new RegExp(isRE[1], isRE[2].indexOf('i') === -1 ? '' : 'i'); + } + + return key; + }; + + /** + * Resolves the localized validation message for one of Tabulator's + * built-in validators. + * + * @see https://github.com/olifolkerd/tabulator/blob/5.2.3/src/js/modules/Validate/defaults/validators.js + * + * @param {object} constraint - The constraint object. + * @param {string} constraint.type - The constraint type. + * @param {*} constraint.parameters - The constraint parameters. + * @return {?string} + */ + const resolveTabulatorValidatorMessage = (constraint) => { + switch (constraint.type) { + case 'integer': + case 'float': + case 'numeric': { + return formWidgetL10n.validation.typeMismatchNumber; + } + + case 'string': { + return formWidgetL10n.validation.typeMismatch; + } + + case 'max': { + return formWidgetL10n.validation.rangeOverflow.replace('{{ max }}', constraint.parameters); + } + + case 'min': { + return formWidgetL10n.validation.rangeUnderflow.replace('{{ min }}', constraint.parameters); + } + + case 'starts': { + // starts with value + return formWidgetL10n.validation.patternMismatchWithStart.replace('{{ format }}', constraint.parameters); + } + + case 'ends': { + // ends with value + return formWidgetL10n.validation.patternMismatchWithEnd.replace('{{ format }}', constraint.parameters); + } + + case 'maxLength': { + return formWidgetL10n.validation.tooLong.replace('{{ max }}', constraint.parameters); + } + + case 'minLength': { + return formWidgetL10n.validation.tooShort.replace('{{ min }}', constraint.parameters); + } + + case 'in': { + // in provided value list + return formWidgetL10n.validation.valueMissingSelect; + } + + case 'regex': { + return formWidgetL10n.validation.patternMismatch; + } + + case 'unique': { + return formWidgetL10n.validation.notUnique; + } + + case 'required': { + return formWidgetL10n.validation.valueMissing; + } + } + + return null; + }; + +}(Charcoal, jQuery, document, Tabulator)); + /** * Basic text input that also manages multiple (split) values * charcoal/admin/property/input/text diff --git a/packages/admin/assets/dist/scripts/charcoal.admin.min.js b/packages/admin/assets/dist/scripts/charcoal.admin.min.js index e0d1a4ebe..7bdaa3f3a 100644 --- a/packages/admin/assets/dist/scripts/charcoal.admin.min.js +++ b/packages/admin/assets/dist/scripts/charcoal.admin.min.js @@ -1,2 +1,2 @@ /*! @charcoal/admin */ -$.fn.enable=function(){return this.each(function(){$(this).removeAttr("disabled").prop("disabled",!1)}),this},$.fn.disable=function(){return this.each(function(){$(this).attr("disabled",!0).prop("disabled",!0)}),this},$.fn.exists=function(){return 0>>0,o=arguments[1],r=0;r'+o[t].join('

')+"

",level:t,type:e.type,buttons:i},s=this.getDisplay(),l=null;switch(s){case"dialog":case"toast":l=s;break;default:l=e.display}"toast"===l?(a.dismissible=0===i.length,new d(a)):BootstrapDialog.show(a)}this.empty()}return this},o.prototype.empty=function(){t(),this.display=null,this.actions=[],this.storage=[]},function(t,e){if(i.feedback(),this.validLevel(t))return this.setLevel(t),this.validMessage(e)&&this.setMessage(e),this;throw new TypeError("Feedback level required. Must be one of: "+r.join(", "))}),d=(l.createFromObject=function(t){var e=t.level||null,t=t.message||null;return e||t?new l(e,t):null},l.prototype={toString:function(){return this.message()},level:function(){return this._level||null},setLevel:function(t){var e=c.type(t);if("string"!==e)throw new TypeError("Feedback level must be a string, received "+e);return o.prototype.assertValidLevel(t),t in a&&(t=a[t]),this._level=t,this},validLevel:function(t){return o.prototype.isValidLevel(t)},message:function(){return this._message||null},setMessage:function(t){var e=c.type(t);if("string"!==e)throw new TypeError("Feedback message must be a string, received "+e);return this._message=t,this},validMessage:function(t){return o.prototype.validMessage(t)}},function(t){var e=c.type(t);if("object"!==e)throw new TypeError("Notification config must be an associative array, received "+e);return this.validMessage(t.message)&&this.setMessage(t.message),this.config=c.extend({},{id:BootstrapDialog.newGuid(),delay:s.delay},t),this.$elem=c(''),this.$elem.prop("id",this.config.id),this.$elem.addClass("alert-"+this.config.type.replace("type-","")),this.config.dismissible&&(this.$elem.addClass("alert-dismissible"),(e=c('')).append(''),this.$elem.append(e)),this.config.message&&((t=c('
')).html("").append(this.config.message),this.$elem.append(t)),this.$elem.appendTo(".c-notifications").addClass("show"),this.$elem.on("closed.bs.alert",{notification:this},function(t){t=t.data.notification;t.$elem.off(".charcoal.feedback"),t.closeTimer&&window.clearTimeout(t.closeTimer)}),"number"==typeof this.config.delay&&0{text}';return t.onshown=function(r){var t=Charcoal.Admin.admin_url()+"widget/load";r.xhr=$.ajax({method:"POST",url:t,data:e,dataType:"json"}),r.xhr.then(function(t,e,i){return t&&t.success?$.Deferred().resolve(t,e,i):t.feedbacks?$.Deferred().reject(i,e,t.feedbacks):$.Deferred().reject(i,e,widgetL10n.loadingFailed)}).done(function(t){r.setMessage(t.widget_html),"function"==typeof i&&i(t,r),$('[data-toggle="tooltip"]',r.getModalBody()).tooltip()}).fail(function(t,e,i){r.setType(BootstrapDialog.TYPE_DANGER),r.setMessage(widgetL10n.loadingFailed);var o="";"string"===$.type(i)&&t.responseJSON&&t.responseJSON.feedbacks&&(i=t.responseJSON.feedbacks),$.isArray(i)?$.each(i,function(t,e){e.message&&("error"===e.level&&(e.level="danger"),o+=c.replaceMap({"{type}":e.level,"{text}":e.message}))}):"string"===$.type(i)&&(o=c.replaceMap({"{type}":"danger","{text}":i})),o&&r.setMessage(o),$('[data-toggle="tooltip"]',r.getModalBody()).tooltip()}),Charcoal.Admin.manager().render()},t.message=function(t){var e=$(c.replaceMap({"{type}":"warning","{text}":widgetL10n.loading}));return a||t.getModalHeader().addClass("d-none"),s||t.getModalFooter().addClass("d-none"),t.getModalBody().on("click.charcoal.bs.dialog",'[data-dismiss="dialog"]',{dialog:t},function(t){t.data.dialog.close()}),e},new BootstrapDialog.show(t)},Charcoal.Admin.Widget.prototype.confirm=function(t,e,i){var o={type:BootstrapDialog.TYPE_DANGER,callback:function(t){t?"function"==typeof e&&e():"function"==typeof i&&i()}},o=$.extend(o,t);return BootstrapDialog.confirm(o)},{});Charcoal.Admin.Widget_Attachment=function(t){this.EVENT_NAMESPACE=Charcoal.Admin.Widget_Attachment.EVENT_NAMESPACE,Charcoal.Admin.Widget.call(this,t),this.busy=!1,this.dirty=!1,this.glyphs={embed:"glyphicon-blackboard",video:"glyphicon-film",image:"glyphicon-picture",file:"glyphicon-file",link:"glyphicon-link",text:"glyphicon-font",gallery:"glyphicon-duplicate",container:"glyphicon-list",accordion:"glyphicon-list"};var e=this;return $(document).on("beforelanguageswitch"+Charcoal.Admin.Widget_Form.EVENT_NAMESPACE,function(t){if(e.is_busy())return t.preventDefault(),void e.enqueue_is_busy_feedback().dispatch();e.perform_save()}).on("languageswitch"+Charcoal.Admin.Widget_Form.EVENT_NAMESPACE,function(){e.change_locale().try_reload()}),this},Charcoal.Admin.Widget_Attachment.EVENT_NAMESPACE=".charcoal.attachments",Charcoal.Admin.Widget_Attachment.prototype=Object.create(Charcoal.Admin.Widget.prototype),Charcoal.Admin.Widget_Attachment.prototype.constructor=Charcoal.Admin.Widget_Attachment,Charcoal.Admin.Widget_Attachment.prototype.parent=Charcoal.Admin.Widget.prototype,Charcoal.Admin.Widget_Attachment.prototype.init=function(){var t,e=this.element().find(".js-attachment-sortable > .js-grid-container");return e.length&&(this.element().on("hidden.bs.collapse",'[data-toggle="collapse"]',function(){e.sortable("refreshPositions")}),t=this,e.sortable({handle:'[draggable="true"]',placeholder:"card c-attachments_row -placeholder",start:function(t,e){e.item.children(".card-header").find('[data-toggle="collapse"]').hasClass("collapsed")||e.item.children(".collapse").collapse("hide")},update:function(){t.set_dirty_state(!0)}}).disableSelection()),this.listeners(),this},Charcoal.Admin.Widget_Attachment.prototype.is_busy=function(){return this.busy||this.is_reloading()},Charcoal.Admin.Widget_Attachment.prototype.set_busy_state=function(t){return this.busy=t,this},Charcoal.Admin.Widget_Attachment.prototype.is_dirty=function(){return this.dirty},Charcoal.Admin.Widget_Attachment.prototype.set_dirty_state=function(t){return this.dirty=t,this},Charcoal.Admin.Widget_Attachment.prototype.change_locale=function(t){var e=this.opts();return e.widget_options.lang=t||Charcoal.Admin.lang(),this.set_opts(e),this},Charcoal.Admin.Widget_Attachment.prototype.listeners=function(){var p=this,e=this.element().find(".c-attachments_container > .js-grid-container");this.element().off(this.EVENT_NAMESPACE).on("click"+this.EVENT_NAMESPACE,".js-attachments-collapse",function(){var t=e.children(".js-attachment");e.hasClass("js-attachment-preview-only")&&t.find(".card-header.sr-only").removeClass("sr-only").addClass("sr-only-off"),t.find(".collapse.show").collapse("hide")}).on("click"+this.EVENT_NAMESPACE,".js-attachments-expand",function(){var t=e.children(".js-attachment");e.hasClass("js-attachment-preview-only")&&t.find(".card-header.sr-only-off").removeClass("sr-only-off").addClass("sr-only"),t.find(".collapse:not(.show)").collapse("show")}).on("click"+this.EVENT_NAMESPACE,".js-add-attachment",function(t){t.preventDefault();var t=$(this),e=t.data("type");if(!e)return!1;var i=t.data("id");i?(p.add({id:i,type:e}),p.join(function(){p.reload()})):(i={title:t.data("title")||attachmentWidgetL10n.editObject,formIdent:t.data("form-ident"),skipForm:t.data("skip-form")},p.create_attachment(e,0,null,i,function(t){t.success&&(t.obj.id=t.obj_id,p.add(t.obj),p.join(function(){p.reload()}))}))}).on("click"+this.EVENT_NAMESPACE,".js-attachment-actions a",function(t){var e=$(this);if(e.data("action"))switch(t.preventDefault(),e.data("action")){case"edit":var i=e.data("type"),o=e.data("id");if(!i||!o)break;var r={title:e.data("title")||attachmentWidgetL10n.editObject,formIdent:e.data("form-ident")};p.create_attachment(i,o,null,r,function(t){t.success&&p.reload()});break;case"delete":if(!e.data("id"))break;p.confirm({title:attachmentWidgetL10n.confirmRemoval,message:commonL10n.confirmAction,btnOKLabel:commonL10n.removeObject,callback:function(t){t&&p.remove_join(e.data("id"),function(){p.reload()})}});break;case"add-object":var i=e.data("title"),o=e.data("attachment"),n=e.data("type"),a=e.data("id"),s=e.data("group"),l=e.data("form-ident"),c=e.data("skip-form"),d={id:a,type:n,group:s},r={title:i,formIdent:l,skipForm:c};p.create_attachment(o,0,d,r,function(t){t.success&&p.add_object_to_container({id:t.obj_id,type:t.obj.type},d)})}})},Charcoal.Admin.Widget_Attachment.prototype.select_attachment=function(t){if(!t.data("id")||!t.data("type"))return this},Charcoal.Admin.Widget_Attachment.prototype.create_attachment=function(t,e,i,o,r){return o&&o.skipForm?this.create_quick_attachment(t,e,i,o,r):this.create_dialog_attachment(t,e,i,o,r)},Charcoal.Admin.Widget_Attachment.prototype.create_quick_attachment=function(t,i,e,o,r){return i=i||0,e=e||this.get_parent_container(),this.xhr=$.ajax({type:"POST",url:"object/save",data:{obj_type:t,obj_id:i,pivot:e}}),Charcoal.Admin.resolveSimpleJsonXhr(this.xhr,function(t){t.feedbacks.length&&Charcoal.Admin.feedback(t.feedbacks),"function"==typeof r&&r(t)},function(t){var e;t.feedbacks.length?Charcoal.Admin.feedback(t.feedbacks):(t=i?formWidgetL10n.updateFailed:formWidgetL10n.createFailed,e=commonL10n.errorOccurred,Charcoal.Admin.feedback([{level:"error",message:commonL10n.errorTemplate.replaceMap({"[[ errorMessage ]]":t,"[[ errorThrown ]]":e})}]))},function(){Charcoal.Admin.feedback().dispatch(),Charcoal.Admin.manager().render()})},Charcoal.Admin.Widget_Attachment.prototype.create_dialog_attachment=function(t,i,e,o,r){i=i||0,o=o||{},e=e||this.get_parent_container();t={size:BootstrapDialog.SIZE_WIDE,cssClass:"-quick-form",widget_type:"charcoal/admin/widget/quick-form",with_data:!0,widget_options:{obj_type:t,obj_id:i,form_ident:o.formIdent||null,form_data:{pivot:e}}},e=$.extend({},t,o,{});return this.dialog(e,function(t,e){return!!t.success&&(!!t.widget_id&&(Charcoal.Admin.manager().add_widget({id:t.widget_id,type:"charcoal/admin/widget/quick-form",data:t.widget_data,obj_id:i,save_callback:function(t){"function"==typeof r&&r(t),this instanceof Charcoal.Admin.Component&&this.id()&&Charcoal.Admin.manager().destroy_component("widgets",this.id()),e.close()}}),void Charcoal.Admin.manager().render()))})},Charcoal.Admin.Widget_Attachment.prototype.get_parent_container=function(){var t=this.opts();return{obj_type:t.data.obj_type,obj_id:t.data.obj_id,group:t.data.group}},Charcoal.Admin.Widget_Attachment.prototype.add_object_to_container=function(t,e,i){if(this.is_busy())return null;this.set_busy_state(!0);var o=this,r={obj_type:e.type,obj_id:e.id,attachments:[{attachment_id:t.id,attachment_type:t.type,position:0}],group:i||e.group||""},t=(null!=globalXHR[r.group]&&globalXHR[r.group].abort&&globalXHR[r.group].abort(),$.post("add-join",r));return globalXHR[r.group]=Charcoal.Admin.resolveSimpleJsonXhr(t,function(){o.reload()},function(t){t.feedbacks.length?Charcoal.Admin.feedback(t.feedbacks):Charcoal.Admin.feedback([{level:"error",message:commonL10n.errorTemplate.replaceMap({"[[ errorMessage ]]":formWidgetL10n.saveFailed,"[[ errorThrown ]]":commonL10n.errorOccurred})}])},function(){delete globalXHR[r.group],o.set_busy_state(!1),Charcoal.Admin.feedback().dispatch()})},Charcoal.Admin.Widget_Attachment.prototype.add=function(t){if(!t)return!1;this.set_dirty_state(!0);var e=this.element().find(".js-attachment-template").clone();return e.find(".js-attachment").data("id",t.id).data("type",t.type),this.element().find(".c-attachments_container > .js-grid-container").append(e),this},Charcoal.Admin.Widget_Attachment.prototype.enqueue_is_busy_feedback=function(){var t=this.widget_options(),t=t&&t.title||attachmentWidgetL10n.widgetName;return Charcoal.Admin.feedback([{level:"warning",display:"toast",message:commonL10n.errorTemplate.replaceMap({"[[ errorMessage ]]":t,"[[ errorThrown ]]":widgetL10n.isBusy})}])},Charcoal.Admin.Widget_Attachment.prototype.validate=function(t){return!this.is_busy()||(t.attempts&&t.max_attempts&&t.attempts .js-sortable-item")).map(function(t){return t.classList.contains("draggable-mirror")||t.classList.contains("draggable--original")?"":t.getAttribute("data-id")}).filter(function(t){return""!==t}),$.ajax({method:"POST",url:Charcoal.Admin.admin_url()+"object/reorder",data:{obj_type:e.obj_type,obj_orders:t,starting_order:1},dataType:"json"}).done(function(t){console.debug(t),t.feedbacks&&Charcoal.Admin.feedback(t.feedbacks).dispatch()}))})),$(".js-jump-page-form",e.table_selector).on("submit",function(t){t.preventDefault();t=$(this),t=parseInt(t.find("input").val());t&&(e.pagination.page=t,e.reload(null,!0))}),$(".js-page-switch",e.table_selector).on("click",function(t){t.preventDefault();t=$(this).data("page-num");console.log(t),e.pagination.page=t,e.reload(null,!0)})},Charcoal.Admin.Widget_Card_Collection.prototype.widget_options=function(){return{obj_type:this.obj_type,template:this.template,collection_ident:this.collection_ident,card_template:this.card_template,num_columns:this.num_columns,collection_config:{properties:this.properties,properties_options:this.properties_options,search_query:this.get_search_query(),filters:this.get_filters(),orders:this.get_orders(),pagination:this.pagination,list_actions:this.list_actions,object_actions:this.object_actions}}},Charcoal.Admin.Widget_Form=function(t){this.EVENT_NAMESPACE=Charcoal.Admin.Widget_Form.EVENT_NAMESPACE,Charcoal.Admin.Widget.call(this,t),this.widget_id=null,this.obj_type=null,this.obj_id=null,this.save_action=t.save_action||"object/save",this.update_action=t.update_action||"object/update",this.extra_form_data=t.extra_form_data||{},this.form_selector=null,this.form_working=!1,this.attempts=0,this.max_attempts=5,this.submitted_via=null,this.is_new_object=!1,this.xhr=null,this.useDefaultAction=!1,this.confirmed=!1;t=$("[data-lang]:not(.d-none)").data("lang");t&&Charcoal.Admin.setLang(t),this._on_popstate_tab=this._on_popstate_tab.bind(this),this._on_shown_tab=this._on_shown_tab.bind(this)},Charcoal.Admin.Widget_Form.EVENT_NAMESPACE=".charcoal.form",Charcoal.Admin.Widget_Form.prototype=Object.create(Charcoal.Admin.Widget.prototype),Charcoal.Admin.Widget_Form.prototype.constructor=Charcoal.Admin.Widget_Form,Charcoal.Admin.Widget_Form.prototype.parent=Charcoal.Admin.Widget.prototype,Charcoal.Admin.Widget_Form.prototype.init=function(){this.set_properties(this.opts()),this.update_tab_ident(),this.bind_events(),this.parse_group_conditions()},Charcoal.Admin.Widget_Form.prototype.set_properties=function(t){return this.widget_id=t.id||this.widget_id,this.obj_type=t.data.obj_type||this.obj_type,this.obj_id=Charcoal.Admin.parseNumber(t.data.obj_id||this.obj_id),this.form_selector=t.data.form_selector||this.form_selector,this.isTab=t.data.tab,this.group_conditions=t.data.group_conditions,this.$form=$(this.form_selector),this.allow_reload=t.data.allow_reload,this.force_page_reload=t.data.force_page_reload,this.useDefaultAction=t.data.use_default_action,this},Charcoal.Admin.Widget_Form.prototype.widget_options=function(){var t=this.parent.widget_options.call(this);return $.extend({},t,this.opts("data"))},Charcoal.Admin.Widget_Form.prototype.bind_events=function(){var e=this,i=this.$form,t=(i.on("submit"+this.EVENT_NAMESPACE,function(t){t.preventDefault(),e.request_submit()}).find(":submit").on("click"+this.EVENT_NAMESPACE,function(){e.submitted_via=this}),$(".js-sidebar-widget",this.form_selector));t.on("click"+this.EVENT_NAMESPACE,".js-obj-delete",function(t){t.preventDefault(),e.delete_object(this)}),t.on("click"+this.EVENT_NAMESPACE,".js-reset-form",function(t){t.preventDefault(),i[0].reset()}),t.on("click"+this.EVENT_NAMESPACE,".js-obj-revision",function(t){t.preventDefault(),e.view_revision(this)}),t.on("click"+this.EVENT_NAMESPACE,".js-obj-list",function(t){t.preventDefault(),e.back_to_list(this)}),t.on("click"+this.EVENT_NAMESPACE,".js-lang-switch button",function(t){t.preventDefault();t=$(this).attr("data-lang-switch");e.switch_language(t)}),window.addEventListener("popstate",this._on_popstate_tab),this.isTab&&i.on("shown.bs.tab",".js-group-tabs",this._on_shown_tab)},Charcoal.Admin.Widget_Form.prototype._on_popstate_tab=function(){this.update_tab_ident()},Charcoal.Admin.Widget_Form.prototype._on_shown_tab=function(t){var t=$(t.target),e=[],i=Charcoal.Admin.queryParams();if(void 0===i.tab_ident||t.data("tab-ident")!==i.tab_ident){for(var o in i.tab_ident=t.data("tab-ident"),i)e.push(o+"="+i[o]);history.pushState("","",window.location.pathname+"?"+e.join("&"))}},Charcoal.Admin.Widget_Form.prototype.parse_group_conditions=function(){var o=this,r=this.$form;$.each(this.group_conditions,function(i,t){var e=o.validate_group_conditions(i);e||o.toggle_conditional_group(i,e,!1),$.each(t,function(t,e){r.on("change"+this.EVENT_NAMESPACE,"#"+e.input_id,{condition_target:i},function(t){var e=o.validate_group_conditions(t.data.condition_target);o.toggle_conditional_group(t.data.condition_target,e)})})})},Charcoal.Admin.Widget_Form.prototype.validate_group_conditions=function(t){var t=this.group_conditions[t],r=this,n=this.$form,a=!0;return $.each(t,function(t,e){var i=n.find("#"+e.input_id),o=r.get_input_value(i);switch(JSON.stringify(e.operator)){case'"!=="':case'"!="':case'"!"':case'"not"':if(o===e.value)return void(a=!1);break;default:case'"==="':case'"=="':case'"="':case'"is"':if(o!==e.value)return void(a=!1)}}),a},Charcoal.Admin.Widget_Form.prototype.toggle_conditional_group=function(t,e,i){function o(){r.each(function(){$(this).attr("disabled",!e)})}var t=this.$form.find("#"+t),r=t.find("select, input, textarea");i=void 0===i||i;e?i?t.slideDown({easing:"easeInOutQuad",start:o}):t.show(0,o):i?t.slideUp({easing:"easeInOutQuad",complete:o}):t.hide(0,o)},Charcoal.Admin.Widget_Form.prototype.get_input_value=function(t){if("disabled"===t.attr("disabled"))return null;var e;switch(t.attr("type")){case"select":e=t.find(":selected").val();break;case"checkbox":e=t.is(":checked");break;default:e=t.val()}return e},Charcoal.Admin.Widget_Form.prototype.update_tab_ident=function(){var t=Charcoal.Admin.queryParams();"tab_ident"in t&&$('.js-group-tabs[data-tab-ident="'+t.tab_ident+'"]').tab("show")},Charcoal.Admin.Widget_Form.prototype.get_form_data=function(){var t=this.$form.length?new FormData(this.$form[0]):new FormData;if(this.submitted_via&&this.submitted_via.name&&t.append(this.submitted_via.name,this.submitted_via.value||!0),this.confirmed&&t.append("confirmed",!0),this.extra_form_data)for(var e in this.extra_form_data)this.extra_form_data.hasOwnProperty(e)&&t.append(e,this.extra_form_data[e]);return t},Charcoal.Admin.Widget_Form.prototype.request_submit=function(){var t;return this.attempts++,this.form_working?(t=this.attempts>=this.max_attempts?commonL10n.errorTemplate.replaceMap({"[[ errorMessage ]]":formWidgetL10n.isBlocked,"[[ errorThrown ]]":commonL10n.tryAgainLater}):commonL10n.errorTemplate.replaceMap({"[[ errorMessage ]]":formWidgetL10n.isProcessing,"[[ errorThrown ]]":commonL10n.pleaseWait}),void Charcoal.Admin.feedback([{level:"warning",display:"toast",message:t}])):(this.form_working=!0,this.is_new_object=!this.obj_id,!0!==Charcoal.Admin.manager().prepare_submit(this)?(t=$.Event("failed"+this.EVENT_NAMESPACE,{subtype:"validation",component:this}),this.$form.trigger(t),void this.request_complete()):(this.disable_form(),void this.submit_form()))},Charcoal.Admin.Widget_Form.prototype.submit_form=function(){this.xhr=$.ajax({type:"POST",url:this.request_url(),data:this.get_form_data(),dataType:"json",processData:!1,contentType:!1}),this.xhr.then($.proxy(this.request_done,this)).done($.proxy(this.request_success,this)).fail($.proxy(this.request_failed,this)).always($.proxy(this.request_complete,this))},Charcoal.Admin.Widget_Form.prototype.request_done=function(t,e,i){return t&&t.success?$.Deferred().resolve(t,e,i):t.feedbacks?$.Deferred().reject(i,e,t.feedbacks):$.Deferred().reject(i,e,commonL10n.errorOccurred)},Charcoal.Admin.Widget_Form.prototype.request_success=function(t){this.attempts=0;var e=$.Event("success"+this.EVENT_NAMESPACE,{subtype:"submission",component:this,response:t});this.$form.trigger(e),e.isDefaultPrevented()||(this.confirmed=!1,t.feedbacks&&Charcoal.Admin.feedback(t.feedbacks),t.need_confirmation?this.add_actions_for_confirmation(t.confirmation_label):t.next_url?this.add_action_for_next_url(t.next_url,t.next_url_label):!this.useDefaultAction&&this.is_new_object?(this.suppress_feedback(!0),t.next_url?Charcoal.Admin.redirect_to_url(t.next_url):(e=new URLSearchParams(window.location.search),window.location.href=Charcoal.Admin.admin_url()+"object/edit?"+(e.has("main_menu")?"main_menu="+e.get("main_menu")+"&":"")+(e.has("secondary_menu")?"secondary_menu="+e.get("secondary_menu")+"&":"")+"obj_type="+this.obj_type+"&obj_id="+t.obj_id)):this.force_page_reload?window.location.reload():this.allow_reload&&(e=Charcoal.Admin.manager().get_widgets(),$.each(e,function(t,e){e.reload()}.bind(this))))},Charcoal.Admin.Widget_Form.prototype.request_failed=function(t,e,i){var o=$.Event("failed"+this.EVENT_NAMESPACE,{subtype:"submission",component:this,response:t.responseJSON||{}});this.$form.trigger(o),o.isDefaultPrevented()||(t.responseJSON&&t.responseJSON.feedbacks?Charcoal.Admin.feedback(t.responseJSON.feedbacks):(o=this.is_new_object?formWidgetL10n.createFailed:formWidgetL10n.updateFailed,t=i||commonL10n.errorOccurred,Charcoal.Admin.feedback([{level:"error",message:commonL10n.errorTemplate.replaceMap({"[[ errorMessage ]]":o,"[[ errorThrown ]]":t})}])))},Charcoal.Admin.Widget_Form.prototype.request_complete=function(){var t=$.Event("complete"+this.EVENT_NAMESPACE,{subtype:"submission",component:this});this.$form.trigger(t),t.isDefaultPrevented()||(this.suppress_feedback()||(this.attempts>=this.max_attempts&&Charcoal.Admin.feedback([{level:"error",message:commonL10n.errorTemplate.replaceMap({"[[ errorMessage ]]":formWidgetL10n.isBlocked,"[[ errorThrown ]]":commonL10n.tryAgainLater})}]),Charcoal.Admin.feedback().dispatch(),this.enable_form()),this.submitted_via=null,this.suppress_feedback(!1),this.form_working=this.is_new_object=!1)},Charcoal.Admin.Widget_Form.prototype.add_action_for_next_url=function(t,e){Charcoal.Admin.feedback().add_action({label:e||commonL10n.continue,callback:function(){Charcoal.Admin.redirect_to_url(t)}})},Charcoal.Admin.Widget_Form.prototype.add_actions_for_confirmation=function(t){Charcoal.Admin.feedback().add_action({label:commonL10n.cancel,cssClass:"btn-danger",callback:function(t){t.close()}}).add_action({label:t||commonL10n.continue,callback:function(t){t.close(),this.confirmed=!0,this.request_submit()}.bind(this)})},Charcoal.Admin.Widget_Form.prototype.disable_form=function(){var t=this.$form;return t.length&&(t.prop("disabled",!0),(t=t.find('[type="submit"]')).length&&t.prop("disabled",!0)),this.submitted_via&&this.disable_button($(this.submitted_via)),this},Charcoal.Admin.Widget_Form.prototype.enable_form=function(){var t=this.$form;return t.length&&(t.prop("disabled",!1),(t=t.find('[type="submit"]')).length&&t.prop("disabled",!1)),this.submitted_via&&this.enable_button($(this.submitted_via)),this},Charcoal.Admin.Widget_Form.prototype.disable_button=function(t){return t.prop("disabled",!0).children(".fa").removeClass("d-none").next(".btn-label").addClass("sr-only"),this},Charcoal.Admin.Widget_Form.prototype.enable_button=function(t){return t.prop("disabled",!1).children(".fa").addClass("d-none").next(".btn-label").removeClass("sr-only"),this},Charcoal.Admin.Widget_Form.prototype.request_url=function(){return this.useDefaultAction?this.$form.attr("action"):this.is_new_object?Charcoal.Admin.admin_url()+this.save_action:Charcoal.Admin.admin_url()+this.update_action},Charcoal.Admin.Widget_Form.prototype.view_revision=function(){var e=this.obj_type,i=this.obj_id,t={size:BootstrapDialog.SIZE_WIDE,title:formWidgetL10n.revisions,widget_type:"charcoal/admin/widget/object-revisions",widget_options:{obj_type:e,obj_id:i}},t=$.extend({},t);this.dialog(t,function(t){if(t.success){if(!t.widget_id)return!1;Charcoal.Admin.manager().add_widget({id:t.widget_id,type:"charcoal/admin/widget/object-revisions",obj_type:e,obj_id:i}),Charcoal.Admin.manager().render()}})},Charcoal.Admin.Widget_Form.prototype.back_to_list=function(){var t=new URLSearchParams(window.location.search);window.location.href="object/collection?"+(t.has("main_menu")?"main_menu="+t.get("main_menu")+"&":"")+(t.has("secondary_menu")?"secondary_menu="+t.get("secondary_menu")+"&":"")+"obj_type="+this.obj_type},Charcoal.Admin.Widget_Form.prototype.delete_object=function(){var i=this,t=new URLSearchParams(window.location.search),o=Charcoal.Admin.admin_url()+"object/collection?"+(t.has("main_menu")?"main_menu="+t.get("main_menu")+"&":"")+(t.has("secondary_menu")?"secondary_menu="+t.get("secondary_menu")+"&":"")+"obj_type="+this.obj_type;if(!i.obj_type||!i.obj_id)return t={level:"warning",message:commonL10n.errorTemplate.replaceMap({"[[ errorMessage ]]":formWidgetL10n.deleteFailed,"[[ errorThrown ]]":commonL10n.invalidObject})},void Charcoal.Admin.feedback([t]).dispatch();BootstrapDialog.confirm({title:formWidgetL10n.confirmDeletion,type:BootstrapDialog.TYPE_DANGER,message:$("

"+commonL10n.confirmAction+'

'+commonL10n.cantUndo+"

"),btnOKLabel:commonL10n.delete,callback:function(t){var e;t&&(t=Charcoal.Admin.admin_url()+"object/delete",e={obj_type:i.obj_type,obj_id:i.obj_id},t=$.ajax({method:"POST",url:t,data:e,dataType:"json"}),Charcoal.Admin.resolveSimpleJsonXhr(t,function(){window.location.href=o},function(t){t.feedbacks.length?Charcoal.Admin.feedback(t.feedbacks):Charcoal.Admin.feedback([{level:"error",message:formWidgetL10n.deleteFailed}])},function(){i.suppress_feedback()||Charcoal.Admin.feedback().dispatch()}))}})},Charcoal.Admin.Widget_Form.prototype.reload=function(i){return this.destroy(),Charcoal.Admin.Widget.prototype.reload.call(this,function(t,e){"function"==typeof i&&i.call(t,e),Charcoal.Admin.manager().render()},!0),this},Charcoal.Admin.Widget_Form.prototype.switch_language=function(t){var e,i=Charcoal.Admin.lang();i!==t&&(e=$.Event("beforelanguageswitch"+this.EVENT_NAMESPACE,{language:t,originalLanguage:i,relatedTarget:this.$form[0],relatedComponent:this}),$(document).triggerHandler(e),e.isDefaultPrevented()||(Charcoal.Admin.setLang(t),$("[data-lang][data-lang!="+t+"]").addClass("d-none"),$("[data-lang][data-lang="+t+"]").removeClass("d-none"),$("[data-lang-switch][data-lang-switch!="+t+"]").removeClass("btn-primary").addClass("btn-outline-primary"),$("[data-lang-switch][data-lang-switch="+t+"]").removeClass("btn-outline-primary").addClass("btn-primary"),$(document).triggerHandler({type:"switch_language.charcoal"}),e=$.Event("languageswitch"+this.EVENT_NAMESPACE,{language:t,originalLanguage:i,relatedTarget:this.$form[0],relatedComponent:this}),$(document).triggerHandler(e)))},Charcoal.Admin.Widget_Form.prototype.destroy=function(){$(this.form_selector).off(this.EVENT_NAMESPACE),$(".js-sidebar-widget",this.form_selector).off(this.EVENT_NAMESPACE),window.removeEventListener("popstate",this._on_popstate_tab),this.isTab&&$(this.form_selector).off("shown.bs.tab",".js-group-tabs",this._shown_tab_handler)},function(e,t,i){"use strict";function o(t){this.EVENT_NAMESPACE=o.EVENT_NAMESPACE,Charcoal.Admin.Widget.call(this,t),this.graph_options=t.graph_options||t.data.graph_options||{}}o.EVENT_NAMESPACE=".charcoal.widget.graph",((o.prototype=Object.create(Charcoal.Admin.Widget.prototype)).contructor=o).prototype.parent=Charcoal.Admin.Widget.prototype,o.prototype.init=function(){var t;echarts?(t=echarts.init(this.element()[0]),(this.chart=t).setOption(this.graph_options),e(i).on("resize"+this.EVENT_NAMESPACE,function(){t.resize()})):console.error("Could not initialize graph widget:","eCharts is missing")},o.prototype.destroy=function(){this.chart&&this.chart.dispose(),e(i).off("resize"+this.EVENT_NAMESPACE)},t.Widget_Graph=o}(jQuery,Charcoal.Admin,window),Charcoal.Admin.Widget_Map=function(t){return Charcoal.Admin.Widget.call(this,t),this._controller=void 0,this},Charcoal.Admin.Widget_Map.prototype=Object.create(Charcoal.Admin.Widget.prototype),Charcoal.Admin.Widget_Map.prototype.constructor=Charcoal.Admin.Widget_Map,Charcoal.Admin.Widget_Map.prototype.parent=Charcoal.Admin.Widget.prototype,Charcoal.Admin.Widget_Map.prototype.init=function(){var t=this;return"undefined"==typeof google?(window._tmp_google_onload_function=function(){t.activate_map()},$.getScript("https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&language=fr&callback=_tmp_google_onload_function",function(){})):t.activate_map(),this},Charcoal.Admin.Widget_Map.prototype.activate_map=function(){var t={default_styles:{strokeColor:"#000000",strokeOpacity:.8,strokeWeight:3,fillColor:"#ffffff",fillOpacity:.35,hover:{strokeColor:"#000000",strokeOpacity:1,strokeWeight:2,fillColor:"#ffffff",fillOpacity:.5},focused:{fillOpacity:.8}},use_clusterer:!1,map:{center:{x:this.opts("coords")[0],y:this.opts("coords")[1]},zoom:14,mapType:"roadmap",coordsType:"inpage",map_mode:"default"},places:{first:{type:"marker",coords:this.coords()}}};this._controller=new window.BB.gmap.controller(this.element().find(".js-map-maker-map").get(0),t),this.controller().set_styles([{featureType:"poi",elementType:"all",stylers:[{visibility:"off"}]}]),this.controller().remove_focus(),this.controller().init()},Charcoal.Admin.Widget_Map.prototype.controller=function(){return this._controller},Charcoal.Admin.Widget_Map.prototype.coords=function(){return this.opts("coords")},Charcoal.Admin.Widget_Object_Revisions=function(t){return Charcoal.Admin.Widget.call(this,t),this.extra_form_data=t.extra_form_data||{},this.xhr=null,this.obj_id=Charcoal.Admin.parseNumber(t.obj_id)||0,this.obj_type=t.obj_type,this},Charcoal.Admin.Widget_Object_Revisions.prototype=Object.create(Charcoal.Admin.Widget.prototype),Charcoal.Admin.Widget_Object_Revisions.prototype.constructor=Charcoal.Admin.Widget_Object_Revisions,Charcoal.Admin.Widget_Object_Revisions.prototype.parent=Charcoal.Admin.Widget.prototype,Charcoal.Admin.Widget_Object_Revisions.prototype.init=function(){this.bind_events()},Charcoal.Admin.Widget_Object_Revisions.prototype.bind_events=function(){var e=this;$("#"+this.id()).on("click.object.revisions",".js-obj-revert",this.revert.bind(this)),$("#"+this.id()).on("click.charcoal.bs.dialog",'[data-dismiss="dialog"]',function(t){$.isFunction(e.cancel_callback)&&e.cancel_callback(t)})},Charcoal.Admin.Widget_Object_Revisions.prototype.revert=function(t){t.preventDefault();var e=Charcoal.Admin.admin_url()+"object/revert-revision",i={obj_type:this.obj_type,obj_id:this.obj_id,rev_num:$(t.currentTarget).attr("data-rev-num")};BootstrapDialog.show({title:objectRevisionsWidgetL10n.title,message:objectRevisionsWidgetL10n.message,buttons:[{id:"ok-btn",label:objectRevisionsWidgetL10n.restore,action:function(t){t.close(),$.ajax({url:e,type:"POST",data:i,dataType:"json",success:function(t){t.success?window.location.reload():(Charcoal.Admin.feedback().push([{level:"error",message:objectRevisionsWidgetL10n.restoreError}]),Charcoal.Admin.feedback().dispatch())},error:function(){Charcoal.Admin.feedback().push([{level:"error",message:objectRevisionsWidgetL10n.restoreError}]),Charcoal.Admin.feedback().dispatch()}})}}]})},Charcoal.Admin.Widget_Object_Revisions.prototype.disable_form=Charcoal.Admin.Widget_Form.prototype.disable_form,Charcoal.Admin.Widget_Object_Revisions.prototype.enable_form=Charcoal.Admin.Widget_Form.prototype.enable_form,Charcoal.Admin.Widget_Object_Revisions.prototype.request_url=Charcoal.Admin.Widget_Form.prototype.request_url,Charcoal.Admin.Widget_Object_Revisions.prototype.request_done=Charcoal.Admin.Widget_Form.prototype.request_done,Charcoal.Admin.Widget_Object_Revisions.prototype.request_failed=Charcoal.Admin.Widget_Form.prototype.request_failed,Charcoal.Admin.Widget_Object_Revisions.prototype.request_complete=Charcoal.Admin.Widget_Form.prototype.request_complete,Charcoal.Admin.Widget_Object_Revisions.prototype.request_success=function(t,e,i){i.feedbacks&&!this.suppress_feedback()&&Charcoal.Admin.feedback(i.feedbacks),i.next_url&&Charcoal.Admin.feedback().add_action({label:commonL10n.continue,callback:function(){window.location.href=Charcoal.Admin.admin_url()+i.next_url}})},Charcoal.Admin.Widget_Quick_Form=function(t){this.EVENT_NAMESPACE=Charcoal.Admin.Widget_Quick_Form.EVENT_NAMESPACE,Charcoal.Admin.Widget.call(this,t),this.save_callback=t.save_callback||"",this.cancel_callback=t.cancel_callback||"",this.form_selector=t.data.form_selector,this.save_action=t.save_action||"object/save",this.update_action=t.update_action||"object/update",this.extra_form_data=t.extra_form_data||{},this.group_conditions=t.data.group_conditions,this.group_display_mode=t.data.group_display_mode||"",this.show_language_switch=t.data.show_language_switch||!1,this.form_working=!1,this.is_new_object=!1,this.xhr=null,this.obj_id=Charcoal.Admin.parseNumber(t.obj_id)||0},Charcoal.Admin.Widget_Quick_Form.EVENT_NAMESPACE=".charcoal.quickform",Charcoal.Admin.Widget_Quick_Form.prototype=Object.create(Charcoal.Admin.Widget_Form.prototype),Charcoal.Admin.Widget_Quick_Form.prototype.constructor=Charcoal.Admin.Widget_Quick_Form,Charcoal.Admin.Widget_Quick_Form.prototype.parent=Charcoal.Admin.Widget.prototype,Charcoal.Admin.Widget_Quick_Form.prototype.init=function(){this.set_properties(this.opts()),this.bind_events(),this.parse_group_conditions(),this.show_language_switch&&$('.nav-link.nav-lang[data-tab-ident="'+Charcoal.Admin.lang()+'"]').trigger("click")},Charcoal.Admin.Widget_Quick_Form.prototype.set_properties=function(){this.$form=$(this.form_selector)},Charcoal.Admin.Widget_Quick_Form.prototype.bind_events=function(){var e=this,t=this.$form;t.on("submit"+this.EVENT_NAMESPACE,function(t){t.preventDefault(),e.request_submit()}).on("click"+this.EVENT_NAMESPACE,'[data-dismiss="dialog"]',function(t){$.isFunction(e.cancel_callback)&&e.cancel_callback(t)}),this.show_language_switch&&t.on("click.nav-link.nav-lang","a.nav-link.nav-lang",function(t){t.preventDefault(),e.trigger_lang_tab($(this).attr("data-tab-ident"))})},Charcoal.Admin.Widget_Quick_Form.prototype.request_success=function(t){var e=$.Event("success"+this.EVENT_NAMESPACE,{subtype:"submission",component:this,response:t});this.$form.trigger(e),e.isDefaultPrevented()||(this.confirmed=!1,t.feedbacks&&!this.suppress_feedback()&&Charcoal.Admin.feedback(t.feedbacks),t.need_confirmation?this.add_actions_for_confirmation(t.confirmation_label):t.next_url?this.add_action_for_next_url(t.next_url,t.next_url_label):(this.enable_form(),this.form_working=!1,"function"==typeof this.save_callback&&this.save_callback(t)))},Charcoal.Admin.Widget_Quick_Form.prototype.trigger_lang_tab=function(e){$(".modal .form-field").each(function(){var t=$(this).attr("data-lang");t&&(e!==t?this.style.setProperty("display","none","important"):this.style.setProperty("display","block","important"))})},Charcoal.Admin.Widget_Relation=function(t){return Charcoal.Admin.Widget.call(this,t),this.dirty=!1,this},Charcoal.Admin.Widget_Relation.prototype=Object.create(Charcoal.Admin.Widget.prototype),Charcoal.Admin.Widget_Relation.prototype.constructor=Charcoal.Admin.Widget_Relation,Charcoal.Admin.Widget_Relation.prototype.parent=Charcoal.Admin.Widget.prototype,Charcoal.Admin.Widget_Relation.prototype.init=function(){var t=this.element().find(".js-relation-sortable .js-grid-container");return this.element().on("hidden.bs.collapse",'[data-toggle="collapse"]',function(){t.sortable("refreshPositions")}),t.sortable({handle:'[draggable="true"]',placeholder:"panel c-attachment_placeholder",start:function(t,e){e.item.children(".panel-heading").find('[data-toggle="collapse"]').hasClass("collapsed")||e.item.children(".panel-collapse").collapse("hide")}}).disableSelection(),this.listeners(),this},Charcoal.Admin.Widget_Relation.prototype.is_dirty=function(){return this.dirty},Charcoal.Admin.Widget_Relation.prototype.set_dirty_state=function(t){return this.dirty=t,this},Charcoal.Admin.Widget_Relation.prototype.listeners=function(){var r=this;this.element().off("click").on("click.charcoal.relation",".js-add-relation",function(t){t.preventDefault();t=$(this).data("type");if(!t)return!1;var e=$(this).data("id");e?(r.add({id:e,type:t}),r.create_relation(function(){r.reload()})):(e=$(this).data("title")||relationWidgetL10n.editObject,r.create_relation_dialog({title:e,widget_options:{form_data:{target_object_type:t,target_object_id:null}}},function(t){t.success&&(t.obj.id=t.obj_id,r.add(t.obj),r.create_relation(function(){r.reload()}))}))}).on("click.charcoal.relation",".js-relation-actions a",function(t){var e=$(this);if(e.data("action"))switch(t.preventDefault(),e.data("action")){case"edit":var i=e.data("type"),o=e.data("id");if(!i||!o)break;o=e.data("title")||relationWidgetL10n.editObject;r.create_relation_dialog({title:o,widget_options:{form_data:{target_object_type:i,target_object_id:null}}},function(t){t.success&&r.reload()});break;case"unlink":if(!e.data("id"))break;r.confirm({title:relationWidgetL10n.confirmRemoval,message:commonL10n.confirmAction,btnOKLabel:commonL10n.removeObject,callback:function(t){t&&r.remove_relation(e.data("id"),function(){r.reload()})}})}})},Charcoal.Admin.Widget_Relation.prototype.create_relation_dialog=function(t,e){t=t||{};var i=this.opts().data,i={size:BootstrapDialog.SIZE_WIDE,cssClass:"-quick-form",widget_type:"charcoal/admin/widget/quick-form",widget_options:{obj_type:"charcoal/relation/pivot",obj_id:0,form_data:{group:i.group,source_object_type:i.obj_type,source_object_id:i.obj_id,target_object_type:"",target_object_id:0}}},o=$.extend(!0,{},i,t,{}),r=this.dialog(o,function(t){if(t.success){if(!t.widget_id)return!1;Charcoal.Admin.manager().add_widget({id:t.widget_id,type:"charcoal/admin/widget/quick-form",data:{obj_type:o.widget_options.type},obj_id:o.widget_options.id,save_callback:function(t){e(t),this instanceof Charcoal.Admin.Component&&this.id()&&Charcoal.Admin.manager().destroy_component("widgets",this.id()),r.close()}}),Charcoal.Admin.manager().render()}})},Charcoal.Admin.Widget_Relation.prototype.add=function(t){if(!t)return!1;this.set_dirty_state(!0);var e=this.element().find(".js-relation-template").clone();return e.find(".js-relation").attr({"data-id":t.target_object_id,"data-type":t.target_object_type}),this.element().find(".js-relation-sortable").find(".js-grid-container").append(e),this},Charcoal.Admin.Widget_Relation.prototype.will_save=function(t){return t&&$.contains(t.element()[0],this.element()[0])},Charcoal.Admin.Widget_Relation.prototype.save=function(){return!this.is_dirty()&&(this.create_relation(),!0)},Charcoal.Admin.Widget_Relation.prototype.create_relation=function(t){var e=this,i=e.opts(),o={obj_type:i.data.obj_type,obj_id:i.data.obj_id,group:i.data.group,pivots:[]};this.element().find(".js-relation-container").find(".js-relation").each(function(t){var e=$(this),i=e.attr("data-id"),e=e.attr("data-type");o.pivots.push({target_object_id:i,target_object_type:e,position:t})}),$.post("relation/link",o,function(){"function"==typeof t&&t(),e.set_dirty_state(!1)},"json")},Charcoal.Admin.Widget_Relation.prototype.remove_relation=function(t,e){if(!t)return!1;var i=this;$.post("relation/unlink",{pivot_id:t},function(){"function"==typeof e&&e(),i.set_dirty_state(!1)},"json")},Charcoal.Admin.Widget_Relation.prototype.widget_options=function(){return this.opts("widget_options")},Charcoal.Admin.Widget_Search=function(t){return this.EVENT_NAMESPACE=Charcoal.Admin.Widget_Search.EVENT_NAMESPACE,Charcoal.Admin.Widget.call(this,t),this._elem=void 0,!!t&&(void 0!==t.id&&(this.set_element($("#"+t.id)),"object"==typeof t.data&&(this.data=t.data,this.$input=null,this._search_filters=!1,this._search_query=!1,this)))},Charcoal.Admin.Widget_Search.EVENT_NAMESPACE=".charcoal.widget.search",Charcoal.Admin.Widget_Search.prototype=Object.create(Charcoal.Admin.Widget.prototype),Charcoal.Admin.Widget_Search.prototype.constructor=Charcoal.Admin.Widget_Search,Charcoal.Admin.Widget_Search.prototype.parent=Charcoal.Admin.Widget.prototype,Charcoal.Admin.Widget_Search.prototype.widget_options=function(){return this.data},Charcoal.Admin.Widget_Search.prototype.set_remote_widget=function(){},Charcoal.Admin.Widget_Search.prototype.init=function(){var e=this,t=this.element();this.$input=t.find('[name="query"]'),t.on("submit"+this.EVENT_NAMESPACE,function(t){t.preventDefault(),e.submit()}),t.on("reset"+this.EVENT_NAMESPACE,function(t){t.preventDefault(),e.clear()})},Charcoal.Admin.Widget_Search.prototype.submit=function(){return this.set_search_query(this.$input.val()),Charcoal.Admin.manager().get_widgets().forEach(this.dispatch.bind(this)),this.set_search_query(null),this},Charcoal.Admin.Widget_Search.prototype.clear=function(){return this._search_search=!1,this._search_filters=!1,this.$input.val(""),this.submit(),this},Charcoal.Admin.Widget_Search.prototype.parse_search_query=function(t){return"string"!=typeof t||0===(t=t.trim()).length?null:t},Charcoal.Admin.Widget_Search.prototype.parse_search_filters=function(t){var e,o,r=[];return(t=this.parse_search_query(t))&&(t=t.split(/\s/),e=this.data.properties||[],$.each(t,function(t,i){o=[],i=i.replace(/'/g,"\\'"),$.each(e,function(t,e){o.push({property:e,operator:"LIKE",value:"%"+i+"%"})}),r.push({conjunction:"OR",filters:o})})),r.length?r:null},Charcoal.Admin.Widget_Search.prototype.set_search_query=function(t){this._search_search=this.parse_search_query(t),this._search_filters=!1},Charcoal.Admin.Widget_Search.prototype.search_query=function(){return!1===this._search_search?null:this._search_search},Charcoal.Admin.Widget_Search.prototype.search_filters=function(){return!1===this._search_filters&&(this._search_filters=this.parse_search_filters(this._search_search)),this._search_filters},Charcoal.Admin.Widget_Search.prototype.dispatch=function(t){if(t&&t!==this){var e="function"==typeof t.set_search_query,i="function"==typeof t.set_filter;if(!e&&!i)return this;e&&(e=this.search_query(),t.set_search_query(e)),i&&(e=this.search_filters(),t.set_filter("search",e)),void 0!==t.pagination&&(t.pagination.page=1),t.reload(null,!0)}},Charcoal.Admin.Widget_Search.prototype.destroy=function(){this.element().off(this.EVENT_NAMESPACE)},Charcoal.Admin.Widget_Table=function(t){Charcoal.Admin.Widget.call(this,t),this.obj_type=null,this.widget_id=null,this.table_selector=null,this.pagination={page:1,num_per_page:50},this.list_actions={},this.object_actions={},this.template=this.properties=this.properties_options=void 0,this.sortable=!1,this.sortable_handler=null},Charcoal.Admin.Widget_Table.prototype=Object.create(Charcoal.Admin.Widget.prototype),Charcoal.Admin.Widget_Table.prototype.constructor=Charcoal.Admin.Widget_Table,Charcoal.Admin.Widget_Table.prototype.parent=Charcoal.Admin.Widget.prototype,Object.assign(Charcoal.Admin.Widget_Table.prototype,Charcoal.Admin.Mixin_Model_Search),Object.assign(Charcoal.Admin.Widget_Table.prototype,Charcoal.Admin.Mixin_Model_Filters),Object.assign(Charcoal.Admin.Widget_Table.prototype,Charcoal.Admin.Mixin_Model_Orders),Charcoal.Admin.Widget_Table.prototype.init=function(){this.set_properties().bind_events()},Charcoal.Admin.Widget_Table.prototype.set_properties=function(){var t=this.opts();return this.obj_type=t.data.obj_type||this.obj_type,this.widget_id=t.id||this.widget_id,this.table_selector="#"+this.widget_id,this.sortable=t.data.sortable||this.sortable,this.template=t.data.template||this.template,this.collection_ident=t.data.collection_ident||"default","properties"in t.data&&Array.isArray(t.data.properties)&&(this.properties=t.data.properties),"properties_options"in t.data&&$.isPlainObject(t.data.properties_options)&&(this.properties_options=t.data.properties_options),"filters"in t.data&&this.set_filters(t.data.filters),"orders"in t.data&&this.set_orders(t.data.orders),"pagination"in t.data&&$.isPlainObject(t.data.pagination)&&(this.pagination=t.data.pagination),"list_actions"in t.data&&(Array.isArray(t.data.list_actions)?this.list_actions=Object.assign({},t.data.list_actions):$.isPlainObject(t.data.list_actions)&&(this.list_actions=t.data.list_actions)),"object_actions"in t.data&&(Array.isArray(t.data.object_actions)?this.object_actions=Object.assign({},t.data.object_actions):$.isPlainObject(t.data.object_actions)&&(this.object_actions=t.data.object_actions)),this},Charcoal.Admin.Widget_Table.prototype.bind_events=function(){null!==this.sortable_handler&&this.sortable_handler.destroy();var e=this,t=$("tbody.js-sortable",e.table_selector);0 td"),i=t.source.querySelectorAll(":scope > td");e.forEach(function(t,e){i[e].style.width=t.offsetWidth+"px"})}).on("sortable:stop",function(t){t.oldIndex!==t.newIndex&&(t=Array.from(t.newContainer.querySelectorAll(":scope > tr")).map(function(t){return t.classList.contains("draggable-mirror")||t.classList.contains("draggable--original")?"":t.getAttribute("data-id")}).filter(function(t){return""!==t}),$.ajax({method:"POST",url:Charcoal.Admin.admin_url()+"object/reorder",data:{obj_type:e.obj_type,obj_orders:t,starting_order:1},dataType:"json"}).done(function(t){console.debug(t),t.feedbacks&&Charcoal.Admin.feedback(t.feedbacks).dispatch()}))})),$(".js-jump-page-form",e.table_selector).on("submit",function(t){t.preventDefault();t=$(this),t=parseInt(t.find("input").val());t&&(e.pagination.page=t,e.reload(null,!0))}),$(".js-page-switch",e.table_selector).on("click",function(t){t.preventDefault();t=$(this).data("page-num");e.pagination.page=t,e.reload(null,!0)})},Charcoal.Admin.Widget_Table.prototype.widget_options=function(){return{obj_type:this.obj_type,template:this.template,sortable:this.sortable,collection_ident:this.collection_ident,collection_config:{properties:this.properties,properties_options:this.properties_options,search_query:this.get_search_query(),filters:this.get_filters(),orders:this.get_orders(),pagination:this.pagination,list_actions:this.list_actions,object_actions:this.object_actions}}},Charcoal.Admin.Property=function(t){return Charcoal.Admin.Component.call(this,t),this._ident,this._val,this._input_type,t&&("string"==typeof t.ident&&this.set_ident(t.ident),void 0!==t.val&&this.set_val(t.val),void 0!==t.input_type&&this.set_input_type(t.input_type)),this},Charcoal.Admin.Property.prototype=Object.create(Charcoal.Admin.Component.prototype),Charcoal.Admin.Property.prototype.constructor=Charcoal.Admin.Property,Charcoal.Admin.Property.prototype.parent=Charcoal.Admin.Component.prototype,Charcoal.Admin.Property.prototype.element=function(){if(!this._element){if(!this.id())return null;this.set_element("#"+this.id())}return this._element},Charcoal.Admin.Property.prototype.set_ident=function(t){return this._ident=t,this},Charcoal.Admin.Property.prototype.ident=function(){return this._ident},Charcoal.Admin.Property.prototype.set_input_type=function(t){return this._input_type=t,this},Charcoal.Admin.Property.prototype.input_type=function(){return this._input_type},Charcoal.Admin.Property.prototype.set_val=function(t){return this._val=t,this},Charcoal.Admin.Property.prototype.val=function(){return this._val},Charcoal.Admin.Property.prototype.error=function(t){window.console.error(t)},Charcoal.Admin.Property_Input_File=function(t){this.EVENT_NAMESPACE=Charcoal.Admin.Property_Input_File.EVENT_NAMESPACE,this.input_type="charcoal/admin/property/input/file",Charcoal.Admin.Property.call(this,t),this.data=t.data,this.dialog=null,this.set_input_id(t.id).init()},Charcoal.Admin.Property_Input_File.EVENT_NAMESPACE=".charcoal.property.file",Charcoal.Admin.Property_Input_File.prototype=Object.create(Charcoal.Admin.Property.prototype),Charcoal.Admin.Property_Input_File.prototype.constructor=Charcoal.Admin.Property_Input_File,Charcoal.Admin.Property_Input_File.prototype.parent=Charcoal.Admin.Property.prototype,Charcoal.Admin.Property_Input_File.prototype.init=function(){this.input_id&&(this.$input=$("#"+this.input_id),this.$file=$("#"+this.data.file_input_id).or('input[type="file"]',this.$input),this.$hidden=$("#"+this.data.hidden_input_id).or('input[type="hidden"]',this.$input),this.$previewFile=this.$input.find(".js-preview-file"),this.$previewText=this.$input.find(".js-preview-text"),window.elFinderCallback||(window.elFinderCallback={}),this.set_listeners())},Charcoal.Admin.Property_Input_File.prototype.set_listeners=function(){void 0!==this.$input&&(this.$input.on("click"+this.EVENT_NAMESPACE,".js-remove-file",this.remove_file.bind(this)).on("click"+this.EVENT_NAMESPACE,".js-elfinder",this.load_elfinder.bind(this)),this.$file.on("change"+this.EVENT_NAMESPACE,this.change_file.bind(this)),window.elFinderCallback[this.input_id]=this.elfinder_callback.bind(this))},Charcoal.Admin.Property_Input_File.prototype.remove_file=function(t){t.preventDefault(),this.$hidden.val(""),this.$file.val(""),this.$previewFile.empty(),this.$previewText.empty(),this.$input.find(".hide-if-no-file").addClass("d-none"),this.$input.find(".show-if-no-file").removeClass("d-none")},Charcoal.Admin.Property_Input_File.prototype.change_file=function(t){this.$input.find(".hide-if-no-file").addClass("d-none"),this.$input.find(".show-if-no-file").removeClass("d-none"),this.$previewFile.empty(),this.$previewText.empty(),t.target&&t.target.files&&t.target.files[0]&&(t=t.target.files[0],console.log("[Property_Input_File.change_file]",t),this.$input.find(".hide-if-no-file").removeClass("d-none"),this.$input.find(".show-if-no-file").addClass("d-none"),this.$previewText.html(t.name))},Charcoal.Admin.Property_Input_File.prototype.load_elfinder=function(t){t.preventDefault(),this.dialog=BootstrapDialog.show({title:this.data.dialog_title||"",size:BootstrapDialog.SIZE_WIDE,cssClass:"-elfinder",message:$('')})},Charcoal.Admin.Property_Input_File.prototype.elfinder_callback=function(t){var e;this.dialog&&this.dialog.close(),this.$input.find(".hide-if-no-file").addClass("d-none"),this.$input.find(".show-if-no-file").removeClass("d-none"),this.$previewFile.empty(),this.$previewText.empty(),t&&t.url&&(e=decodeURI(t.url).replace(Charcoal.Admin.base_url(),""),console.log("[Property_Input_File.elfinder_callback]",t),this.$hidden.val(e),this.$input.find(".hide-if-no-file").removeClass("d-none"),this.$input.find(".show-if-no-file").addClass("d-none"),this.$previewText.html(t.name))},Charcoal.Admin.Property_Input_File.prototype.set_input_id=function(t){return this.input_id=t,this},Charcoal.Admin.Property_Input_File.prototype.set_input_name=function(t){return this.input_name=t,this},Charcoal.Admin.Property_Input_File.prototype.set_input_val=function(t){return this.input_val=t,this},Charcoal.Admin.Property_Input_File.prototype.destroy=function(){this.$input.off(this.EVENT_NAMESPACE),this.$file.off(this.EVENT_NAMESPACE)},function(s,n,y){"use strict";var l="[Property_Input_Audio_Recorder]",e=".charcoal.property.audio.recorder",a={CLICK:"click"+e},i=0,r=1,c=2,o=3,d=4,p=5,h=6,u=7,_=8,m=9,f=10,g=11,b=12,A=".js-recording-record",C=".js-recording-playback",v=".js-recording-stop",w=".js-recording-reset",F=".js-recording-visualizer",O=".js-recording-time-elapsed",L=".js-recording-time-duration",E="round",P="#EBEDF0",j="#DEE2E6",k=5,N=2,t=null,$=null;function T(t){this.EVENT_NAMESPACE=e,this.PROPERTY_IDLE=i,this.PROPERTY_READY=r,this.PROPERTY_LIVE=c,this.MODE_IDLE=o,this.MODE_PLAYBACK=d,this.MODE_CAPTURE=p,this.MEDIA_IDLE=h,this.MEDIA_LOCKED=u,this.MEDIA_BUSY=_,this.MEDIA_PAUSED=m,this.VISUAL_NONE=f,this.VISUAL_WAVEFORM=g,this.VISUAL_FREQUENCY=b,n.Property.call(this,t),this.data=t.data,this.data.id=t.id,this.readyState=i,this.mediaMode=o,this.mediaState=h,this.mediaVisual=f,this.status=null,this.mediaPromise=null,this.mediaStream=null,this.audioRecorder=null,this.audioContext=null,this.analyserNode=null,this.canvasElement=null,this.canvasContext=null,this.isFirefox=-1