From: Louis Jeckel Date: Fri, 10 Apr 2020 17:08:04 +0000 (+0200) Subject: algolia instantsearch X-Git-Url: http://git.cubedesigners.com/?a=commitdiff_plain;h=6b620d785989d034682f1c833a0dd6468071ed24;p=psq.git algolia instantsearch --- diff --git a/.idea/lettre-pharma.iml b/.idea/lettre-pharma.iml index e6ec509..c87e110 100644 --- a/.idea/lettre-pharma.iml +++ b/.idea/lettre-pharma.iml @@ -5,10 +5,15 @@ + + + + + @@ -24,9 +29,12 @@ + + + diff --git a/.idea/php.xml b/.idea/php.xml index ba95671..c9e7565 100644 --- a/.idea/php.xml +++ b/.idea/php.xml @@ -166,6 +166,11 @@ + + + + + diff --git a/app/FileCollection.php b/app/FileCollection.php index f71b839..4ba9425 100644 --- a/app/FileCollection.php +++ b/app/FileCollection.php @@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Model; * Class FileCollection * @package App * @property string $slug; + * @property string $name; */ class FileCollection extends Model { @@ -25,7 +26,7 @@ class FileCollection extends Model */ public function __toString(): string { - return $this->slug; + return $this->name; } } diff --git a/app/Http/Controllers/FileController.php b/app/Http/Controllers/FileController.php new file mode 100644 index 0000000..4c889e1 --- /dev/null +++ b/app/Http/Controllers/FileController.php @@ -0,0 +1,32 @@ +coverUrl); + } + + public function search() + { + return view('layouts.vue', [ + 'extends' => 'layouts.app', + 'component' => 'file-instant-search' + ]); + } + + +} + + diff --git a/app/Http/Controllers/FlowpaperController.php b/app/Http/Controllers/FlowpaperController.php index 044f655..edf2065 100644 --- a/app/Http/Controllers/FlowpaperController.php +++ b/app/Http/Controllers/FlowpaperController.php @@ -13,25 +13,29 @@ use Illuminate\View\View; class FlowpaperController extends Controller { /** + * @param PdfFile $file * @return View + * @throws \Illuminate\Auth\Access\AuthorizationException */ - public function view($slug): View + public function view(PdfFile $file): View { - $pdfFile = PdfFile::where('slug', $slug)->firstOrFail(); - return $pdfFile->view(); + $this->authorize('view', $file); + return $file->view(); } /** * Obfuscates PDF file and outputs them as base64 bin file. - * @param $slug + * @param PdfFile $file * @return Response + * @throws \Illuminate\Auth\Access\AuthorizationException * @throws FileNotFoundException * @noinspection PhpUnused */ - public function outputFile($slug): Response + public function outputFile(PdfFile $file): Response { - $pdfFile = PdfFile::where('slug', $slug)->firstOrFail(); - return response(base64_encode($pdfFile->getPdf())) + $this->authorize('view', $file); + + return response(base64_encode($file->getPdf())) ->header('Content-Type', 'application/octet-stream'); } } diff --git a/app/Jobs/ProcessEmailBatch.php b/app/Jobs/ProcessEmailBatch.php index 49b2fc9..d5caeb3 100644 --- a/app/Jobs/ProcessEmailBatch.php +++ b/app/Jobs/ProcessEmailBatch.php @@ -74,6 +74,7 @@ class ProcessEmailBatch implements ShouldQueue $view = view('emails.batch', [ 'subject' => $this->batch->subject, 'content' => $this->batch->content['body'], + 'link' => $this->batch->file->getUrl(), ])->render(); $params = [ diff --git a/app/Nova/Organization.php b/app/Nova/Organization.php index 12df869..bc8a67c 100644 --- a/app/Nova/Organization.php +++ b/app/Nova/Organization.php @@ -22,7 +22,7 @@ class Organization extends Resource * * @var string */ - public static $title = 'id'; + public static $title = 'name'; /** * The columns that should be searched. diff --git a/app/Nova/User.php b/app/Nova/User.php index b5b9b17..3167c32 100644 --- a/app/Nova/User.php +++ b/app/Nova/User.php @@ -3,6 +3,7 @@ namespace App\Nova; use Illuminate\Http\Request; +use Laravel\Nova\Fields\BelongsTo; use Laravel\Nova\Fields\ID; use Laravel\Nova\Fields\Text; use Laravel\Nova\Http\Requests\NovaRequest; @@ -42,8 +43,9 @@ class User extends Resource { return [ ID::make()->sortable(), - Text::make('Name'), + Text::make('Nom', 'name'), Text::make('Email'), + BelongsTo::make('Organisation', 'organization', Organization::class), ]; } diff --git a/app/PdfFile.php b/app/PdfFile.php index 83c7da3..7525500 100644 --- a/app/PdfFile.php +++ b/app/PdfFile.php @@ -1,39 +1,61 @@ - 'bool' + ]; /** * @param Request $request * @return array + * @throws PdfToImage\Exceptions\PdfDoesNotExist + * @throws \Exception */ public static function createFromRequest(Request $request): array { @@ -55,12 +77,14 @@ class PdfFile extends Model 'file_name' => $path->getBasename(), 'ref' => $ref, 'collection_id' => $collection_id, - 'slug' => Str::slug("${collection}_${ref}"), + 'slug' => Str::slug("{$collection->slug}_{$ref}"), ]); $file->setTags($tags); $file->makeJson(); + $file->makeCover(); + $file->makeSearchable(); return [ 'pdfFile' => $file, @@ -133,23 +157,22 @@ class PdfFile extends Model /** * @return string - * returns relative json path + * Returns absolute PDF file path */ - public function getJsonPathAttribute(): string + public function getAbsolutePdfPathAttribute(): string { - return "flowpaper/$this->file_name.json"; + return Storage::disk('local')->path($this->pdfPath); } /** * @return string - * Returns absolute PDF file path + * returns relative json path */ - public function getAbsolutePdfPathAttribute(): string + public function getJsonPathAttribute(): string { - return Storage::disk('local')->path($this->pdfPath); + return "flowpaper/$this->file_name.json"; } - /** * @return string * Returns absolute Json file path @@ -161,12 +184,40 @@ class PdfFile extends Model /** * @return string + * Returns json public url */ public function getJsonUrlAttribute(): string { return asset("storage/$this->jsonPath"); } + /** + * @return string + * returns cover path + */ + public function getCoverPathAttribute(): string + { + return "covers/$this->file_name.jpg"; + } + + /** + * @return string + * returns absolute cover path + */ + public function getAbsoluteCoverPathAttribute(): string + { + return Storage::disk('public')->path($this->coverPath); + } + + /** + * @return string + */ + public function getCoverUrlAttribute(): string + { + return asset("storage/$this->coverPath"); + } + + /** * @return string * @throws \Illuminate\Contracts\Filesystem\FileNotFoundException @@ -176,9 +227,12 @@ class PdfFile extends Model return Storage::disk('local')->get($this->pdfPath); } + /** + * @return string + */ public function getUrl() { - return route('flowpaper.view', ['slug' => $this->slug]); + return route('flowpaper.view', ['file' => $this->slug]); } /** @@ -189,6 +243,63 @@ class PdfFile extends Model Pdf2Json::convert($this->absolutePdfPath, $this->absoluteJsonPath); } + /** + * @throws PdfToImage\Exceptions\PdfDoesNotExist + * Generates a jpg cover + */ + public function makeCover(): void + { + Storage::disk('public')->makeDirectory('covers'); + $pdf = new PdfToImage\Pdf($this->absolutePdfPath); + $pdf->setResolution(72) + ->setCompressionQuality(60) + ->saveImage($this->absoluteCoverPath); + } + + /** + * @return void + * @throws \Exception + */ + public function makeSearchable() + { + $client = resolve(TikaClient::class); + $html = $client + ->setEncoding('UTF-8') + ->getHTML($this->absolutePdfPath); + + $html = preg_replace('/\-\n/', '', $html); + + $result = []; + + $this->searchableTexts()->delete(); + + $page_i = 0; + + foreach(HtmlDomParser::str_get_html($html)->find('div.page') as $page){ + $page_i++; + foreach ($page->find('p') as $paragraph){ + $text = html_entity_decode($paragraph->plaintext); + if(empty($text)) + continue; + $text = preg_replace('/^([A-Z]) /', '$1', $text); + + $result[] = [ + 'content' => trim($text), + 'page' => $page_i, + ]; + } + } + + $this->searchableTexts()->createMany($result); + } + + + + + /** + * @return \Illuminate\View\View + * Returns Flowpaper viewer + */ public function view() { @@ -197,7 +308,7 @@ class PdfFile extends Model } return view('flowpaper.view', [ - 'pdfPath' => route('flowpaper.bin', ['slug' => $this->slug]), + 'pdfPath' => route('flowpaper.bin', ['file' => $this->slug]), 'jsonPath' => $this->jsonUrl, 'title' => 'La Lettre Pharma', ]); @@ -229,6 +340,20 @@ class PdfFile extends Model return $tags; } + + + + + /** Scopes */ + + /** + * @param Builder $builder + */ + public function scopeFree(Builder $builder): void + { + $builder->where('is_free', true); + } + } diff --git a/app/PhpVars.php b/app/PhpVars.php new file mode 100644 index 0000000..b86798d --- /dev/null +++ b/app/PhpVars.php @@ -0,0 +1,27 @@ + env('ALGOLIA_APP_ID'), + 'algolia_search_key' => env('ALGOLIA_SEARCH_KEY'), + 'algolia_prefix' => env('SCOUT_PREFIX'), + ]; + } + + public static function output() + { + $json = json_encode(self::data()); + + return 'const php_vars = '.$json; + + } + +} diff --git a/app/Policies/PdfFilePolicy.php b/app/Policies/PdfFilePolicy.php new file mode 100644 index 0000000..0135909 --- /dev/null +++ b/app/Policies/PdfFilePolicy.php @@ -0,0 +1,105 @@ +is_free || ($user ? $user->isSubscribed() : false)) { + return true; + } + + throw new AuthenticationException( + 'Unauthenticated.', + ['web'], + route('login', ['redirect_to' => request()->getUri()]) + ); + + } + + /** + * Determine whether the user can create models. + * + * @param \App\User $user + * @return mixed + */ + public function create(User $user) + { + // + } + + /** + * Determine whether the user can update the model. + * + * @param \App\User $user + * @param \App\PdfFile $pdfFile + * @return mixed + */ + public function update(User $user, PdfFile $pdfFile) + { + // + } + + /** + * Determine whether the user can delete the model. + * + * @param \App\User $user + * @param \App\PdfFile $pdfFile + * @return mixed + */ + public function delete(User $user, PdfFile $pdfFile) + { + // + } + + /** + * Determine whether the user can restore the model. + * + * @param \App\User $user + * @param \App\PdfFile $pdfFile + * @return mixed + */ + public function restore(User $user, PdfFile $pdfFile) + { + // + } + + /** + * Determine whether the user can permanently delete the model. + * + * @param \App\User $user + * @param \App\PdfFile $pdfFile + * @return mixed + */ + public function forceDelete(User $user, PdfFile $pdfFile) + { + // + } +} diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 0189194..906216f 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -4,6 +4,7 @@ namespace App\Providers; use Illuminate\Support\ServiceProvider; use Mailgun\Mailgun; +use Vaites\ApacheTika\Client; class AppServiceProvider extends ServiceProvider { @@ -17,6 +18,16 @@ class AppServiceProvider extends ServiceProvider $this->app->singleton(Mailgun::class, function($app) { return Mailgun::create(env('MAILGUN_API_KEY'), 'https://api.eu.mailgun.net'); }); + + $this->app->singleton(Client::class, function($app) { + return Client::prepare( + env('TIKA_HOST', 'localhost'), + env('TIKA_PORT', 9998) + ); + }); + + + } /** diff --git a/app/SearchableText.php b/app/SearchableText.php index 7496321..dc956f6 100644 --- a/app/SearchableText.php +++ b/app/SearchableText.php @@ -3,8 +3,33 @@ namespace App; use Illuminate\Database\Eloquent\Model; +use Laravel\Scout\Searchable; +/** + * Class SearchableText + * @package App + * @property int $file_id + * @property string $content + * @property int $page + */ class SearchableText extends Model { + use Searchable; use BelongsToPdfFile; + + protected $guarded = []; + + public function toSearchableArray() + { + return [ + 'file' => [ + 'slug' => $this->file->slug, + 'tags' => $this->file->tags()->pluck('content')->toArray(), + 'collection' => (string) $this->file->collection, + 'ref' => $this->file->ref + ], + 'content' => $this->content, + 'page' => $this->page, + ]; + } } diff --git a/app/User.php b/app/User.php index ef977a7..a0083cc 100644 --- a/app/User.php +++ b/app/User.php @@ -8,6 +8,14 @@ use Illuminate\Database\Eloquent\Relations\BelongsTo; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; +/** + * Class User + * @package App + * @property $first_name + * @property $last_name + * @property-read $name + * @property Organization $organization + */ class User extends Authenticatable { use Notifiable; @@ -18,7 +26,7 @@ class User extends Authenticatable * @var array */ protected $fillable = [ - 'name', 'email', 'password', + 'first_name', 'last_name', 'email', 'password', ]; /** @@ -49,6 +57,18 @@ class User extends Authenticatable return $this->belongsTo(Organization::class); } + /** + * @return bool + */ + public function isSubscribed(): bool + { + if($o = $this->organization){ + return $o->isSubscribed(); + } + + return false; + } + /** * @param Builder $builder */ @@ -60,6 +80,19 @@ class User extends Authenticatable } + /** + * @return string|null + */ + public function getNameAttribute(): ?string + { + if($this->first_name === null && $this->last_name === null) { + return null; + } + + return "{$this->first_name} {$this->last_name}"; + } + + } diff --git a/composer.json b/composer.json index 473a32c..d9480c4 100644 --- a/composer.json +++ b/composer.json @@ -10,18 +10,23 @@ "require": { "php": "^7.2.5", "ext-json": "*", + "algolia/algoliasearch-client-php": "^2.6", "area17/twill": "^2.0", "fideloper/proxy": "^4.2", "fruitcake/laravel-cors": "^1.0", "guzzlehttp/guzzle": "^6.3", "kriswallsmith/buzz": "^1.1", + "kub-at/php-simple-html-dom-parser": "^1.9", "laravel/framework": "^7.0", "laravel/horizon": "^4.2", "laravel/nova": "~3.0", + "laravel/scout": "^8.0", "laravel/tinker": "^2.0", "mailgun/mailgun-php": "^3.0", "nyholm/psr7": "^1.2", "pusher/pusher-php-server": "~4.0", + "spatie/pdf-to-image": "^2.0", + "spatie/pdf-to-text": "^1.3", "vaites/php-apache-tika": "^0.9.1" }, "require-dev": { diff --git a/composer.lock b/composer.lock index 8602201..6107f3b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,78 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1912851787b3e088f71853cde3abc8b6", + "content-hash": "d2f6d9ec8418941a47a410ee6a3b33f8", "packages": [ + { + "name": "algolia/algoliasearch-client-php", + "version": "2.6.0", + "source": { + "type": "git", + "url": "https://github.com/algolia/algoliasearch-client-php.git", + "reference": "cf00bbc55e0701691abbd92101c963e34ec4a496" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/algolia/algoliasearch-client-php/zipball/cf00bbc55e0701691abbd92101c963e34ec4a496", + "reference": "cf00bbc55e0701691abbd92101c963e34ec4a496", + "shasum": "" + }, + "require": { + "ext-curl": "*", + "ext-json": "*", + "ext-mbstring": "*", + "php": "^5.3 || ^7.0", + "psr/http-message": "^1.0", + "psr/log": "^1.0", + "psr/simple-cache": "^1.0" + }, + "require-dev": { + "friendsofphp/php-cs-fixer": "^2.0", + "fzaninotto/faker": "^1.8", + "phpunit/phpunit": "^4.8", + "symfony/yaml": "^2.0 || ^4.0" + }, + "suggest": { + "guzzlehttp/guzzle": "If you prefer to use Guzzle HTTP client instead of the Http Client implementation provided by the package" + }, + "bin": [ + "bin/algolia-doctor" + ], + "type": "library", + "extra": { + "branch-alias": { + "dev-2.0": "2.0.x-dev" + } + }, + "autoload": { + "psr-4": { + "Algolia\\AlgoliaSearch\\": "src/" + }, + "files": [ + "src/Http/Psr7/functions.php", + "src/functions.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Algolia Team", + "email": "contact@algolia.com" + } + ], + "description": "Algolia Search API Client for PHP", + "keywords": [ + "algolia", + "api", + "client", + "php", + "search" + ], + "time": "2020-03-09T09:11:44+00:00" + }, { "name": "area17/twill", "version": "2.0.1", @@ -1933,6 +2003,52 @@ ], "time": "2020-03-07T13:42:51+00:00" }, + { + "name": "kub-at/php-simple-html-dom-parser", + "version": "1.9.1", + "source": { + "type": "git", + "url": "https://github.com/Kub-AT/php-simple-html-dom-parser.git", + "reference": "ff22f98bfd9235115c128059076f3eb740d66913" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Kub-AT/php-simple-html-dom-parser/zipball/ff22f98bfd9235115c128059076f3eb740d66913", + "reference": "ff22f98bfd9235115c128059076f3eb740d66913", + "shasum": "" + }, + "require": { + "php": ">=5.3.2" + }, + "type": "library", + "autoload": { + "psr-0": { + "KubAT\\PhpSimple\\HtmlDomParser": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "S.C. Chen", + "email": "me578022@gmail.com" + }, + { + "name": "Jakub Stawowy", + "email": "Kub-AT@users.noreply.github.com" + } + ], + "description": "PHP Simple HTML DOM Parser with namespace and PHP 7.3 compatible", + "homepage": "http://simplehtmldom.sourceforge.net/", + "keywords": [ + "Simple", + "dom", + "html" + ], + "time": "2019-10-25T12:34:43+00:00" + }, { "name": "laravel/framework", "version": "v7.4.0", @@ -2231,6 +2347,71 @@ ], "time": "2020-04-03T16:18:38+00:00" }, + { + "name": "laravel/scout", + "version": "v8.0.0", + "source": { + "type": "git", + "url": "https://github.com/laravel/scout.git", + "reference": "1c4b66c36c2d6fdf94a8b79e2fbb9f4b378a6e26" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/scout/zipball/1c4b66c36c2d6fdf94a8b79e2fbb9f4b378a6e26", + "reference": "1c4b66c36c2d6fdf94a8b79e2fbb9f4b378a6e26", + "shasum": "" + }, + "require": { + "illuminate/bus": "^6.0|^7.0", + "illuminate/contracts": "^6.0|^7.0", + "illuminate/database": "^6.0|^7.0", + "illuminate/pagination": "^6.0|^7.0", + "illuminate/queue": "^6.0|^7.0", + "illuminate/support": "^6.0|^7.0", + "php": "^7.2" + }, + "require-dev": { + "algolia/algoliasearch-client-php": "^2.2", + "mockery/mockery": "^1.0", + "phpunit/phpunit": "^8.0" + }, + "suggest": { + "algolia/algoliasearch-client-php": "Required to use the Algolia engine (^2.2)." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "8.x-dev" + }, + "laravel": { + "providers": [ + "Laravel\\Scout\\ScoutServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Laravel\\Scout\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel Scout provides a driver based solution to searching your Eloquent models.", + "keywords": [ + "algolia", + "laravel", + "search" + ], + "time": "2020-03-03T13:33:44+00:00" + }, { "name": "laravel/socialite", "version": "v4.3.2", @@ -5356,6 +5537,103 @@ ], "time": "2020-02-18T15:10:38+00:00" }, + { + "name": "spatie/pdf-to-image", + "version": "2.0.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/pdf-to-image.git", + "reference": "67136abe0db0540b4f29bb461389917ffa1b7e37" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/pdf-to-image/zipball/67136abe0db0540b4f29bb461389917ffa1b7e37", + "reference": "67136abe0db0540b4f29bb461389917ffa1b7e37", + "shasum": "" + }, + "require": { + "ext-imagick": "*", + "php": "^7.2" + }, + "require-dev": { + "phpunit/phpunit": "^8.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\PdfToImage\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Convert a pdf to an image", + "homepage": "https://github.com/spatie/pdf-to-image", + "keywords": [ + "convert", + "image", + "pdf", + "pdf-to-image", + "spatie" + ], + "time": "2020-01-08T00:13:23+00:00" + }, + { + "name": "spatie/pdf-to-text", + "version": "1.3.0", + "source": { + "type": "git", + "url": "https://github.com/spatie/pdf-to-text.git", + "reference": "9c11b44c6469f6e1d9b097e30f0f1d44aa65a8e8" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/spatie/pdf-to-text/zipball/9c11b44c6469f6e1d9b097e30f0f1d44aa65a8e8", + "reference": "9c11b44c6469f6e1d9b097e30f0f1d44aa65a8e8", + "shasum": "" + }, + "require": { + "php": "^7.3", + "symfony/process": "^4.0|^5.0" + }, + "require-dev": { + "phpunit/phpunit": "^8.0|^9.0" + }, + "type": "library", + "autoload": { + "psr-4": { + "Spatie\\PdfToText\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Freek Van der Herten", + "email": "freek@spatie.be", + "homepage": "https://spatie.be", + "role": "Developer" + } + ], + "description": "Extract text from a pdf", + "homepage": "https://github.com/spatie/pdf-to-text", + "keywords": [ + "pdf-to-text", + "spatie" + ], + "time": "2020-03-11T17:11:25+00:00" + }, { "name": "swiftmailer/swiftmailer", "version": "v6.2.3", diff --git a/config/scout.php b/config/scout.php new file mode 100644 index 0000000..6e47577 --- /dev/null +++ b/config/scout.php @@ -0,0 +1,91 @@ + env('SCOUT_DRIVER', 'algolia'), + + /* + |-------------------------------------------------------------------------- + | Index Prefix + |-------------------------------------------------------------------------- + | + | Here you may specify a prefix that will be applied to all search index + | names used by Scout. This prefix may be useful if you have multiple + | "tenants" or applications sharing the same search infrastructure. + | + */ + + 'prefix' => env('SCOUT_PREFIX', ''), + + /* + |-------------------------------------------------------------------------- + | Queue Data Syncing + |-------------------------------------------------------------------------- + | + | This option allows you to control if the operations that sync your data + | with your search engines are queued. When this is set to "true" then + | all automatic data syncing will get queued for better performance. + | + */ + + 'queue' => env('SCOUT_QUEUE', false), + + /* + |-------------------------------------------------------------------------- + | Chunk Sizes + |-------------------------------------------------------------------------- + | + | These options allow you to control the maximum chunk size when you are + | mass importing data into the search engine. This allows you to fine + | tune each of these chunk sizes based on the power of the servers. + | + */ + + 'chunk' => [ + 'searchable' => 500, + 'unsearchable' => 500, + ], + + /* + |-------------------------------------------------------------------------- + | Soft Deletes + |-------------------------------------------------------------------------- + | + | This option allows to control whether to keep soft deleted records in + | the search indexes. Maintaining soft deleted records can be useful + | if your application still needs to search for the records later. + | + */ + + 'soft_delete' => false, + + /* + |-------------------------------------------------------------------------- + | Algolia Configuration + |-------------------------------------------------------------------------- + | + | Here you may configure your Algolia settings. Algolia is a cloud hosted + | search engine which works great with Scout out of the box. Just plug + | in your application ID and admin API key to get started searching. + | + */ + + 'algolia' => [ + 'id' => env('ALGOLIA_APP_ID', '2DN9N2PQBK'), + 'secret' => env('ALGOLIA_SECRET', '8a1916ad1188b1b570cb85a43e5be2fa'), + ], + +]; diff --git a/database/migrations/2020_04_07_140454_add_columns_to_email_batches.php b/database/migrations/2020_04_07_140454_add_columns_to_email_batches.php index 41aeabe..5b57e20 100644 --- a/database/migrations/2020_04_07_140454_add_columns_to_email_batches.php +++ b/database/migrations/2020_04_07_140454_add_columns_to_email_batches.php @@ -16,7 +16,7 @@ class AddColumnsToEmailBatches extends Migration Schema::create('mailgun_events', function (Blueprint $table) { $table->id(); $table->string('event'); - $table->unsignedInteger('email_batch_id'); + $table->unsignedBigInteger('email_batch_id'); $table->string('recipient'); $table->timestamps(); }); diff --git a/database/migrations/2020_04_09_123936_add_page_column_to_searchable_texts.php b/database/migrations/2020_04_09_123936_add_page_column_to_searchable_texts.php new file mode 100644 index 0000000..0e1d294 --- /dev/null +++ b/database/migrations/2020_04_09_123936_add_page_column_to_searchable_texts.php @@ -0,0 +1,32 @@ +integer('page')->nullable(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('searchable_texts', function (Blueprint $table) { + $table->dropColumn('page'); + }); + } +} diff --git a/database/migrations/2020_04_10_093007_update_fileds_users_table.php b/database/migrations/2020_04_10_093007_update_fileds_users_table.php new file mode 100644 index 0000000..39e4dab --- /dev/null +++ b/database/migrations/2020_04_10_093007_update_fileds_users_table.php @@ -0,0 +1,50 @@ +dropColumn('name'); + $table->string('first_name')->nullable(); + $table->string('last_name')->nullable(); + $table->string('position')->nullable(); + $table->string('phone')->nullable(); + $table->string('address_line_1')->nullable(); + $table->string('city_name')->nullable(); + $table->string('zip_code')->nullable(); + $table->string('country')->nullable(); + }); + + + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function(Blueprint $table) { + $table->string('name'); + $table->dropColumn('first_name'); + $table->dropColumn('last_name'); + $table->dropColumn('position'); + $table->dropColumn('phone'); + $table->dropColumn('address_line_1'); + $table->dropColumn('city_name'); + $table->dropColumn('zip_code'); + $table->dropColumn('country'); + }); + } +} diff --git a/database/migrations/2020_04_10_094131_create_constraints.php b/database/migrations/2020_04_10_094131_create_constraints.php new file mode 100644 index 0000000..fe4c5e7 --- /dev/null +++ b/database/migrations/2020_04_10_094131_create_constraints.php @@ -0,0 +1,50 @@ +foreign('file_id')->references('id')->on('pdf_files')->cascadeOnDelete(); + }); + Schema::table('mailgun_events', function(Blueprint $table) { + $table->foreign('email_batch_id')->references('id')->on('email_batches')->cascadeOnDelete(); + }); + Schema::table('files_tags_pivot', function(Blueprint $table) { + $table->foreign('file_tag_id')->references('id')->on('file_tags')->cascadeOnDelete(); + $table->foreign('pdf_file_id')->references('id')->on('pdf_files')->cascadeOnDelete(); + }); + Schema::table('pdf_files', function(Blueprint $table) { + $table->foreign('collection_id')->references('id')->on('collections'); + }); + Schema::table('searchable_texts', function(Blueprint $table) { + $table->foreign('file_id')->references('id')->on('pdf_files')->cascadeOnDelete(); + }); + Schema::table('tracked_links', function(Blueprint $table) { + $table->foreign('file_id')->references('id')->on('pdf_files')->onDelete('SET NULL'); + $table->unique('slug'); + }); + Schema::table('users', function(Blueprint $table) { + $table->foreign('organization_id')->references('id')->on('organizations'); + }); + + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + } +} diff --git a/database/migrations/2020_04_10_111345_add_free_col_to_pdf_files.php b/database/migrations/2020_04_10_111345_add_free_col_to_pdf_files.php new file mode 100644 index 0000000..c17b316 --- /dev/null +++ b/database/migrations/2020_04_10_111345_add_free_col_to_pdf_files.php @@ -0,0 +1,32 @@ +boolean('is_free')->default(false); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('pdf_files', function (Blueprint $table) { + $table->dropColumn('is_free'); + }); + } +} diff --git a/package-lock.json b/package-lock.json index 3c0f2de..9735095 100644 --- a/package-lock.json +++ b/package-lock.json @@ -2,6 +2,121 @@ "requires": true, "lockfileVersion": 1, "dependencies": { + "@algolia/cache-browser-local-storage": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.1.0.tgz", + "integrity": "sha512-r8BOgqZXVt+JPgP19PQNzZ+lYP+MP6eZKNQqfRYofFEx+K9oyfdtGCqmoWJsBUi3nNOzhbOcg2jfP2GJzJBZ5g==", + "requires": { + "@algolia/cache-common": "4.1.0" + } + }, + "@algolia/cache-common": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.1.0.tgz", + "integrity": "sha512-ZvvK40bs1BWLErchleZL4ctHT2uH56uLMnpZPCuIk+H2PKddeiIQc/z2JDu2BHr68u513XIAAoQ+C+LgKNugmw==" + }, + "@algolia/cache-in-memory": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.1.0.tgz", + "integrity": "sha512-2382OXYFDeoPLA5vP9KP58ad15ows24ML5/io/T1N0xsZ0eVXDkT52qgaJw/esUfEkWScZ2R8kpesUa+qEP+kw==", + "requires": { + "@algolia/cache-common": "4.1.0" + } + }, + "@algolia/client-account": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.1.0.tgz", + "integrity": "sha512-GFINlsxAHM/GEeDBjoTx8+J1ra9SINQCuXi2C9QSLFClPKug2lzApm8niJJGXckhyZ2aDLb7drJ1qJ8bTspApw==", + "requires": { + "@algolia/client-common": "4.1.0", + "@algolia/client-search": "4.1.0", + "@algolia/transporter": "4.1.0" + } + }, + "@algolia/client-analytics": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.1.0.tgz", + "integrity": "sha512-JMyZ9vXGbTJWiO66fWEu9uJ7GSYfouUyaq8W/6esADPtBbelf+Nc0NRlicOwHHJGwiJvWdvELafxrhkR1+KR8A==", + "requires": { + "@algolia/client-common": "4.1.0", + "@algolia/client-search": "4.1.0", + "@algolia/requester-common": "4.1.0", + "@algolia/transporter": "4.1.0" + } + }, + "@algolia/client-common": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.1.0.tgz", + "integrity": "sha512-fjSMKeG54vAyQAhf+uz039/birTiLun8nDuCNx4CUbzGl97M0g96Q8jpsiZa0cjSNgh0VakMzn2GnHbS55W9/Q==", + "requires": { + "@algolia/requester-common": "4.1.0", + "@algolia/transporter": "4.1.0" + } + }, + "@algolia/client-recommendation": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@algolia/client-recommendation/-/client-recommendation-4.1.0.tgz", + "integrity": "sha512-UEN/QgQwVtVH++yAs2uTuyZZQQ1p5Xs/7/FKT4Kh9/8NAyqDD49zuyq/giw8PRNhWc3C/9jiO7X4RKE8QrVWGw==", + "requires": { + "@algolia/client-common": "4.1.0", + "@algolia/requester-common": "4.1.0", + "@algolia/transporter": "4.1.0" + } + }, + "@algolia/client-search": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.1.0.tgz", + "integrity": "sha512-bpCYMEXUdyiopEBSHHwnrRhNEwOLstIeb0Djz+/pVuTXEr3Xg3JUoAZ8xFsCVldcXaZQpbi1/T0y3ky6xUVzfw==", + "requires": { + "@algolia/client-common": "4.1.0", + "@algolia/requester-common": "4.1.0", + "@algolia/transporter": "4.1.0" + } + }, + "@algolia/logger-common": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.1.0.tgz", + "integrity": "sha512-QrE4Srf1LB7ekLzl68bFqlTrv7Wk7+GpsaGfB4xFZ9Pfv89My9p7qTVqdLlA44hEFY3fZ9csJp1/PFVucgNB4w==" + }, + "@algolia/logger-console": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.1.0.tgz", + "integrity": "sha512-sKELkiKIrj/tPRAdhOPNI0UxhK2uiIUXnGs/3ztAif6QX7vyE3lY19sj5pIVJctRvl8LW2UlzpBFGlcCDkho9Q==", + "requires": { + "@algolia/logger-common": "4.1.0" + } + }, + "@algolia/requester-browser-xhr": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.1.0.tgz", + "integrity": "sha512-bLMfIAkOLs1/vGA09yxU0N5+bE0fSSvEH2ySqVssfWLMP+KRAvby2Goxm8BgI9xLkOvLbhazfQ4Ov2448VvA1g==", + "requires": { + "@algolia/requester-common": "4.1.0" + } + }, + "@algolia/requester-common": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.1.0.tgz", + "integrity": "sha512-Cy0ciOv5uIm6wF+uLc9DHhxgPJtYQuy1f//hwJcW5mlPX/prPgxWwLXzWyyA+Ca7uU3q+0Y3cIFvEWM5pDxMEg==" + }, + "@algolia/requester-node-http": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.1.0.tgz", + "integrity": "sha512-tXp6Pjx9dFgM5ccW6YfEN6v2Zqq8uGwhS1pyq03/aRYRBK60LptjG5jo++vrOytrQDOnIjcZtQzBQch2GjCVmw==", + "requires": { + "@algolia/requester-common": "4.1.0" + } + }, + "@algolia/transporter": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.1.0.tgz", + "integrity": "sha512-Z7PjHazSC+KFLDuCFOjvRNgLfh7XOE4tXi0a9O3gBRup4Sk3VQCfTw4ygCF3rRx6uYbq192efLu0nL1E9azxLA==", + "requires": { + "@algolia/cache-common": "4.1.0", + "@algolia/logger-common": "4.1.0", + "@algolia/requester-common": "4.1.0" + } + }, "@babel/code-frame": { "version": "7.8.3", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.8.3.tgz", @@ -1245,6 +1360,11 @@ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, "accepts": { "version": "1.3.7", "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", @@ -1339,6 +1459,44 @@ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz", "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==" }, + "algoliasearch": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.1.0.tgz", + "integrity": "sha512-0lzjvqQZkJYPuv7LyQauMIMCFFzJWfUf3m9KuHjmFubwbnTDa87KCMXKouMJ0kWXXt6nTLNt0+2YRREOWx2PHw==", + "requires": { + "@algolia/cache-browser-local-storage": "4.1.0", + "@algolia/cache-common": "4.1.0", + "@algolia/cache-in-memory": "4.1.0", + "@algolia/client-account": "4.1.0", + "@algolia/client-analytics": "4.1.0", + "@algolia/client-common": "4.1.0", + "@algolia/client-recommendation": "4.1.0", + "@algolia/client-search": "4.1.0", + "@algolia/logger-common": "4.1.0", + "@algolia/logger-console": "4.1.0", + "@algolia/requester-browser-xhr": "4.1.0", + "@algolia/requester-common": "4.1.0", + "@algolia/requester-node-http": "4.1.0", + "@algolia/transporter": "4.1.0" + } + }, + "algoliasearch-helper": { + "version": "2.28.1", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-2.28.1.tgz", + "integrity": "sha512-4yg3anWdILD6ZJ/GxWmtu4HgxauSemhSqbe9Cx6SFdPzaMHrccew4IDomMeQlz9RHJwRgi5sEeX//jx2H/PaWg==", + "requires": { + "events": "^1.1.1", + "lodash": "^4.17.5", + "qs": "^6.5.1" + }, + "dependencies": { + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + } + } + }, "alphanum-sort": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz", @@ -2192,6 +2350,11 @@ } } }, + "classnames": { + "version": "2.2.6", + "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz", + "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q==" + }, "clean-css": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz", @@ -2651,46 +2814,30 @@ } }, "css-loader": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-1.0.1.tgz", - "integrity": "sha512-+ZHAZm/yqvJ2kDtPne3uX0C+Vr3Zn5jFn2N4HywtS5ujwvsVkyg0VArEXpl3BgczDA8anieki1FIzhchX4yrDw==", + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.5.1.tgz", + "integrity": "sha512-0G4CbcZzQ9D1Q6ndOfjFuMDo8uLYMu5vc9Abs5ztyHcKvmil6GJrMiNjzzi3tQvUF+mVRuDg7bE6Oc0Prolgig==", "dev": true, "requires": { - "babel-code-frame": "^6.26.0", - "css-selector-tokenizer": "^0.7.0", - "icss-utils": "^2.1.0", - "loader-utils": "^1.0.2", - "lodash": "^4.17.11", - "postcss": "^6.0.23", - "postcss-modules-extract-imports": "^1.2.0", - "postcss-modules-local-by-default": "^1.2.0", - "postcss-modules-scope": "^1.1.0", - "postcss-modules-values": "^1.3.0", - "postcss-value-parser": "^3.3.0", - "source-list-map": "^2.0.0" + "camelcase": "^5.3.1", + "cssesc": "^3.0.0", + "icss-utils": "^4.1.1", + "loader-utils": "^1.2.3", + "normalize-path": "^3.0.0", + "postcss": "^7.0.27", + "postcss-modules-extract-imports": "^2.0.0", + "postcss-modules-local-by-default": "^3.0.2", + "postcss-modules-scope": "^2.2.0", + "postcss-modules-values": "^3.0.0", + "postcss-value-parser": "^4.0.3", + "schema-utils": "^2.6.5", + "semver": "^6.3.0" }, "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "postcss-value-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", - "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", - "dev": true - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", "dev": true } } @@ -2936,7 +3083,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -4562,8 +4708,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "gensync": { "version": "1.0.0-beta.1", @@ -4771,8 +4916,7 @@ "has-symbols": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" }, "has-value": { "version": "1.0.0", @@ -4855,6 +4999,22 @@ "minimalistic-crypto-utils": "^1.0.1" } }, + "hogan.js": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/hogan.js/-/hogan.js-3.0.2.tgz", + "integrity": "sha1-TNnhq9QpQUbnZ55B14mHMrAse/0=", + "requires": { + "mkdirp": "0.3.0", + "nopt": "1.0.10" + }, + "dependencies": { + "mkdirp": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.3.0.tgz", + "integrity": "sha1-G79asbqCevI1dRQ0kEJkVfSB/h4=" + } + } + }, "homedir-polyfill": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", @@ -5011,31 +5171,12 @@ "dev": true }, "icss-utils": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", - "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz", + "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==", "dev": true, "requires": { - "postcss": "^6.0.1" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } + "postcss": "^7.0.14" } }, "ieee754": { @@ -5098,6 +5239,14 @@ "loader-utils": "^1.1.0" } }, + "immutability-helper": { + "version": "2.9.1", + "resolved": "https://registry.npmjs.org/immutability-helper/-/immutability-helper-2.9.1.tgz", + "integrity": "sha512-r/RmRG8xO06s/k+PIaif2r5rGc3j4Yhc01jSBfwPCXDLYZwp/yxralI37Df1mwmuzcCsen/E/ITKcTEvc1PQmQ==", + "requires": { + "invariant": "^2.2.0" + } + }, "import-cwd": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz", @@ -5182,6 +5331,34 @@ "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==", "dev": true }, + "instantsearch.css": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/instantsearch.css/-/instantsearch.css-7.4.2.tgz", + "integrity": "sha512-CaOdFWCpHOWGAkJRpwC4+8ROU3Upp3xrUuc0Mg92UucJ84MWMJWkVZDDyRwubgJe4HXQM2rV6b+bJaDeeZGunw==" + }, + "instantsearch.js": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/instantsearch.js/-/instantsearch.js-3.7.0.tgz", + "integrity": "sha512-Hkj72CP/Du7uR6R8N2IXo/JHiGU9Z/DwDbQcvRaLKWGd3fc4WjQpl1QPB2OUsoM0Ym0Zv1xjyYTmuU1VvGdySw==", + "requires": { + "algoliasearch-helper": "^2.26.0", + "classnames": "^2.2.5", + "events": "^1.1.0", + "hogan.js": "^3.0.2", + "preact": "^8.3.0", + "preact-compat": "^3.18.0", + "preact-rheostat": "^2.1.1", + "prop-types": "^15.5.10", + "qs": "^6.5.1" + }, + "dependencies": { + "events": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz", + "integrity": "sha1-nr23Y1rQmccNzEwqH1AEKI6L2SQ=" + } + } + }, "internal-ip": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz", @@ -5202,7 +5379,6 @@ "version": "2.2.4", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", - "dev": true, "requires": { "loose-envify": "^1.0.0" } @@ -5549,8 +5725,7 @@ "js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" }, "js-yaml": { "version": "3.13.1", @@ -5672,6 +5847,120 @@ "webpack-merge": "^4.1.0", "webpack-notifier": "^1.5.1", "yargs": "^12.0.5" + }, + "dependencies": { + "css-loader": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-1.0.1.tgz", + "integrity": "sha512-+ZHAZm/yqvJ2kDtPne3uX0C+Vr3Zn5jFn2N4HywtS5ujwvsVkyg0VArEXpl3BgczDA8anieki1FIzhchX4yrDw==", + "dev": true, + "requires": { + "babel-code-frame": "^6.26.0", + "css-selector-tokenizer": "^0.7.0", + "icss-utils": "^2.1.0", + "loader-utils": "^1.0.2", + "lodash": "^4.17.11", + "postcss": "^6.0.23", + "postcss-modules-extract-imports": "^1.2.0", + "postcss-modules-local-by-default": "^1.2.0", + "postcss-modules-scope": "^1.1.0", + "postcss-modules-values": "^1.3.0", + "postcss-value-parser": "^3.3.0", + "source-list-map": "^2.0.0" + } + }, + "icss-utils": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-2.1.0.tgz", + "integrity": "sha1-g/Cg7DeL8yRheLbCrZE28TWxyWI=", + "dev": true, + "requires": { + "postcss": "^6.0.1" + } + }, + "postcss": { + "version": "6.0.23", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", + "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", + "dev": true, + "requires": { + "chalk": "^2.4.1", + "source-map": "^0.6.1", + "supports-color": "^5.4.0" + } + }, + "postcss-modules-extract-imports": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz", + "integrity": "sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==", + "dev": true, + "requires": { + "postcss": "^6.0.1" + } + }, + "postcss-modules-local-by-default": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", + "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", + "dev": true, + "requires": { + "css-selector-tokenizer": "^0.7.0", + "postcss": "^6.0.1" + } + }, + "postcss-modules-scope": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", + "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", + "dev": true, + "requires": { + "css-selector-tokenizer": "^0.7.0", + "postcss": "^6.0.1" + } + }, + "postcss-modules-values": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", + "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", + "dev": true, + "requires": { + "icss-replace-symbols": "^1.1.0", + "postcss": "^6.0.1" + } + }, + "postcss-value-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz", + "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==", + "dev": true + }, + "schema-utils": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", + "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", + "dev": true, + "requires": { + "ajv": "^6.1.0", + "ajv-errors": "^1.0.0", + "ajv-keywords": "^3.1.0" + } + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "style-loader": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", + "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", + "dev": true, + "requires": { + "loader-utils": "^1.1.0", + "schema-utils": "^1.0.0" + } + } } }, "last-call-webpack-plugin": { @@ -5857,7 +6146,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "dev": true, "requires": { "js-tokens": "^3.0.0 || ^4.0.0" } @@ -6341,6 +6629,14 @@ "integrity": "sha512-wp8zyQVwef2hpZ/dJH7SfSrIPD6YoJz6BDQDpGEkcA0s3LpAQoxBIYmfIq6QAhC1DhwsyCgTaTTcONwX8qzCuQ==", "dev": true }, + "nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha1-bd0hvSoxQXuScn3Vhfim83YI6+4=", + "requires": { + "abbrev": "1" + } + }, "normalize-path": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", @@ -10557,8 +10853,7 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", - "dev": true + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" }, "object-copy": { "version": "0.1.0", @@ -10606,8 +10901,7 @@ "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, "object-path": { "version": "0.9.2", @@ -10628,7 +10922,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, "requires": { "define-properties": "^1.1.2", "function-bind": "^1.1.1", @@ -11385,118 +11678,44 @@ } }, "postcss-modules-extract-imports": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-1.2.1.tgz", - "integrity": "sha512-6jt9XZwUhwmRUhb/CkyJY020PYaPJsCyt3UjbaWo6XEbH/94Hmv6MP7fG2C5NDU/BcHzyGYxNtHvM+LTf9HrYw==", + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz", + "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==", "dev": true, "requires": { - "postcss": "^6.0.1" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } + "postcss": "^7.0.5" } }, "postcss-modules-local-by-default": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-1.2.0.tgz", - "integrity": "sha1-99gMOYxaOT+nlkRmvRlQCn1hwGk=", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.2.tgz", + "integrity": "sha512-jM/V8eqM4oJ/22j0gx4jrp63GSvDH6v86OqyTHHUvk4/k1vceipZsaymiZ5PvocqZOl5SFHiFJqjs3la0wnfIQ==", "dev": true, "requires": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } + "icss-utils": "^4.1.1", + "postcss": "^7.0.16", + "postcss-selector-parser": "^6.0.2", + "postcss-value-parser": "^4.0.0" } }, "postcss-modules-scope": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-1.1.0.tgz", - "integrity": "sha1-1upkmUx5+XtipytCb75gVqGUu5A=", + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz", + "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==", "dev": true, "requires": { - "css-selector-tokenizer": "^0.7.0", - "postcss": "^6.0.1" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } + "postcss": "^7.0.6", + "postcss-selector-parser": "^6.0.0" } }, "postcss-modules-values": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-1.3.0.tgz", - "integrity": "sha1-7P+p1+GSUYOJ9CrQ6D9yrsRW6iA=", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz", + "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==", "dev": true, "requires": { - "icss-replace-symbols": "^1.1.0", - "postcss": "^6.0.1" - }, - "dependencies": { - "postcss": { - "version": "6.0.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz", - "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==", - "dev": true, - "requires": { - "chalk": "^2.4.1", - "source-map": "^0.6.1", - "supports-color": "^5.4.0" - } - }, - "source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true - } + "icss-utils": "^4.0.0", + "postcss": "^7.0.6" } }, "postcss-normalize-charset": { @@ -11761,12 +11980,64 @@ "integrity": "sha512-N7h4pG+Nnu5BEIzyeaaIYWs0LI5XC40OrRh5L60z0QjFsqGWcHcbkBvpe1WYpcIS9yQ8sOi/vIPt1ejQCrMVrg==", "dev": true }, + "preact": { + "version": "8.5.3", + "resolved": "https://registry.npmjs.org/preact/-/preact-8.5.3.tgz", + "integrity": "sha512-O3kKP+1YdgqHOFsZF2a9JVdtqD+RPzCQc3rP+Ualf7V6rmRDchZ9MJbiGTT7LuyqFKZqlHSOyO/oMFmI2lVTsw==" + }, + "preact-compat": { + "version": "3.19.0", + "resolved": "https://registry.npmjs.org/preact-compat/-/preact-compat-3.19.0.tgz", + "integrity": "sha512-f83A4hIhH8Uzhb9GbIcGk8SM19ffWlwP9mDaYwQdRnMdekZwcCA7eIAbeV4EMQaV9C0Yuy8iKgBAtyTKPZQt/Q==", + "requires": { + "immutability-helper": "^2.7.1", + "preact-context": "^1.1.3", + "preact-render-to-string": "^3.8.2", + "preact-transition-group": "^1.1.1", + "prop-types": "^15.6.2", + "standalone-react-addons-pure-render-mixin": "^0.1.1" + } + }, + "preact-context": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/preact-context/-/preact-context-1.1.4.tgz", + "integrity": "sha512-gcCjPJ65R0MiW9hDu8W/3WAmyTElIvwLyEO6oLQiM6/TbLKLxCpBCWV8GJjx52TTEyUr60HLDcmoCXZlslelzQ==" + }, + "preact-render-to-string": { + "version": "3.8.2", + "resolved": "https://registry.npmjs.org/preact-render-to-string/-/preact-render-to-string-3.8.2.tgz", + "integrity": "sha512-przuZPajiurStGgxMoJP0EJeC4xj5CgHv+M7GfF3YxAdhGgEWAkhOSE0xympAFN20uMayntBZpttIZqqLl77fw==", + "requires": { + "pretty-format": "^3.5.1" + } + }, + "preact-rheostat": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/preact-rheostat/-/preact-rheostat-2.1.1.tgz", + "integrity": "sha512-d03JgkpbjknALYl+zfNiJQ60sFd4A0YjnLCe/DB+rqKQck7jXpsW9RqSN0R50/lV8fEezhVCjq2WMPDDOKmwaA==", + "requires": { + "object.assign": "^4.0.4", + "preact": "^8.2.5", + "preact-compat": "^3.17.0", + "prop-types": "^15.5.10" + } + }, + "preact-transition-group": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/preact-transition-group/-/preact-transition-group-1.1.1.tgz", + "integrity": "sha1-8KSTJ+pRXs406ivoZMSn0p5dbhA=" + }, "prettier": { "version": "1.19.1", "resolved": "https://registry.npmjs.org/prettier/-/prettier-1.19.1.tgz", "integrity": "sha512-s7PoyDv/II1ObgQunCbB9PdLmUcBZcnWOcxDh7O0N/UwDEsHyqkW+Qh28jW+mVuCdx7gLB0BotYI1Y6uI9iyew==", "dev": true }, + "pretty-format": { + "version": "3.8.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-3.8.0.tgz", + "integrity": "sha1-v77VbV6ad2ZF9LH/eqGjrE+jw4U=" + }, "private": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", @@ -11791,6 +12062,16 @@ "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM=", "dev": true }, + "prop-types": { + "version": "15.7.2", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz", + "integrity": "sha512-8QQikdH7//R2vurIJSutZ1smHYTcLpRWEOlHnzcWHmBYrOGUysKwSsrC89BCiFj3CbrfJ/nXFdJepOVrY1GCHQ==", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.8.1" + } + }, "proxy-addr": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", @@ -11879,8 +12160,7 @@ "qs": { "version": "6.7.0", "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", - "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==", - "dev": true + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" }, "querystring": { "version": "0.2.0", @@ -11945,6 +12225,11 @@ } } }, + "react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==" + }, "readable-stream": { "version": "2.3.7", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", @@ -12962,6 +13247,11 @@ "integrity": "sha512-0PlYhdKh6AfFxRyK/v+6/k+/mMfyiEBbTM5L94D0ZytQnJ166wuwoTYLHFWGbs2dpA8Rgq763KGWmN1EQEYHRQ==", "dev": true }, + "standalone-react-addons-pure-render-mixin": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/standalone-react-addons-pure-render-mixin/-/standalone-react-addons-pure-render-mixin-0.1.1.tgz", + "integrity": "sha1-PHQJ9MecQN6axyxhbPZ5qZTzdVE=" + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", @@ -13122,26 +13412,13 @@ "dev": true }, "style-loader": { - "version": "0.23.1", - "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-0.23.1.tgz", - "integrity": "sha512-XK+uv9kWwhZMZ1y7mysB+zoihsEj4wneFWAS5qoiLwzW0WzSqMrrsIy+a3zkQJq0ipFtBpX5W3MqyRIBF/WFGg==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-1.1.3.tgz", + "integrity": "sha512-rlkH7X/22yuwFYK357fMN/BxYOorfnfq0eD7+vqlemSK4wEcejFF1dg4zxP0euBW8NrYx2WZzZ8PPFevr7D+Kw==", "dev": true, "requires": { - "loader-utils": "^1.1.0", - "schema-utils": "^1.0.0" - }, - "dependencies": { - "schema-utils": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz", - "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==", - "dev": true, - "requires": { - "ajv": "^6.1.0", - "ajv-errors": "^1.0.0", - "ajv-keywords": "^3.1.0" - } - } + "loader-utils": "^1.2.3", + "schema-utils": "^2.6.4" } }, "stylehacks": { @@ -13782,6 +14059,15 @@ "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==", "dev": true }, + "vue-instantsearch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/vue-instantsearch/-/vue-instantsearch-2.7.0.tgz", + "integrity": "sha512-K9UtJLF3nJfSUfE21V9BmKfhMTlPPB3yxqttC9exDrI6pKk+xcdmh0y4hkqljtAkjCsOYLHGP1r6iqoGN1U1Ww==", + "requires": { + "algoliasearch-helper": "^2.28.1", + "instantsearch.js": "^3.6.0" + } + }, "vue-loader": { "version": "15.9.1", "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.1.tgz", diff --git a/package.json b/package.json index 466e29b..5305e9e 100644 --- a/package.json +++ b/package.json @@ -21,6 +21,7 @@ "axios": "^0.19.2", "bootstrap": "^4.0.0", "cross-env": "^7.0", + "css-loader": "^3.5.1", "deepmerge": "^4.2.2", "fibers": "^4.0.2", "jquery": "^3.2", @@ -30,6 +31,7 @@ "resolve-url-loader": "^2.3.1", "sass": "^1.20.1", "sass-loader": "^8.0.0", + "style-loader": "^1.1.3", "vue": "^2.5.17", "vue-template-compiler": "^2.6.10" }, @@ -37,9 +39,12 @@ "@ckeditor/ckeditor5-build-classic": "^18.0.0", "@ckeditor/ckeditor5-vue": "^1.0.1", "@fortawesome/fontawesome-free": "^5.13.0", + "algoliasearch": "^4.1.0", + "instantsearch.css": "^7.4.2", "laravel-echo": "^1.7.0", "pusher-js": "^5.1.1", "selectize": "^0.12.6", + "vue-instantsearch": "^2.7.0", "vue-simple-progress": "^1.1.1", "vue-stepper": "^1.4.2", "vue-upload-component": "^2.8.20", diff --git a/public/css/app.css b/public/css/app.css index d7100e0..559cf39 100644 --- a/public/css/app.css +++ b/public/css/app.css @@ -502,7 +502,7 @@ mark, } .blockquote-footer::before { - content: "\2014\A0"; + content: "— "; } .img-fluid { diff --git a/public/js/app.js b/public/js/app.js index 18e63ef..043e4ff 100644 --- a/public/js/app.js +++ b/public/js/app.js @@ -125,26 +125,27 @@ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { +var api = __webpack_require__(/*! ../../../style-loader/dist/runtime/injectStylesIntoStyleTag.js */ "./node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js"); + var content = __webpack_require__(/*! !../../../css-loader/dist/cjs.js??ref--6-1!../../../postcss-loader/src??ref--6-2!./all.min.css */ "./node_modules/css-loader/dist/cjs.js?!./node_modules/postcss-loader/src/index.js?!./node_modules/@fortawesome/fontawesome-free/css/all.min.css"); -var content = __webpack_require__(/*! !../../../css-loader??ref--6-1!../../../postcss-loader/src??ref--6-2!./all.min.css */ "./node_modules/css-loader/index.js?!./node_modules/postcss-loader/src/index.js?!./node_modules/@fortawesome/fontawesome-free/css/all.min.css"); + content = content.__esModule ? content.default : content; -if(typeof content === 'string') content = [[module.i, content, '']]; - -var transform; -var insertInto; + if (typeof content === 'string') { + content = [[module.i, content, '']]; + } +var options = {}; +options.insert = "head"; +options.singleton = false; -var options = {"hmr":true} +var update = api(content, options); -options.transform = transform -options.insertInto = undefined; +var exported = content.locals ? content.locals : {}; -var update = __webpack_require__(/*! ../../../style-loader/lib/addStyles.js */ "./node_modules/style-loader/lib/addStyles.js")(content, options); -if(content.locals) module.exports = content.locals; -if(false) {} +module.exports = exported; /***/ }), @@ -313,278 +314,152 @@ module.exports = "/fonts/vendor/@fortawesome/fontawesome-free/webfa-solid-900.wo /***/ }), -/***/ "./node_modules/axios/index.js": -/*!*************************************!*\ - !*** ./node_modules/axios/index.js ***! - \*************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -module.exports = __webpack_require__(/*! ./lib/axios */ "./node_modules/axios/lib/axios.js"); - -/***/ }), - -/***/ "./node_modules/axios/lib/adapters/xhr.js": -/*!************************************************!*\ - !*** ./node_modules/axios/lib/adapters/xhr.js ***! - \************************************************/ +/***/ "./node_modules/algoliasearch-helper/index.js": +/*!****************************************************!*\ + !*** ./node_modules/algoliasearch-helper/index.js ***! + \****************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js"); -var settle = __webpack_require__(/*! ./../core/settle */ "./node_modules/axios/lib/core/settle.js"); -var buildURL = __webpack_require__(/*! ./../helpers/buildURL */ "./node_modules/axios/lib/helpers/buildURL.js"); -var buildFullPath = __webpack_require__(/*! ../core/buildFullPath */ "./node_modules/axios/lib/core/buildFullPath.js"); -var parseHeaders = __webpack_require__(/*! ./../helpers/parseHeaders */ "./node_modules/axios/lib/helpers/parseHeaders.js"); -var isURLSameOrigin = __webpack_require__(/*! ./../helpers/isURLSameOrigin */ "./node_modules/axios/lib/helpers/isURLSameOrigin.js"); -var createError = __webpack_require__(/*! ../core/createError */ "./node_modules/axios/lib/core/createError.js"); - -module.exports = function xhrAdapter(config) { - return new Promise(function dispatchXhrRequest(resolve, reject) { - var requestData = config.data; - var requestHeaders = config.headers; - - if (utils.isFormData(requestData)) { - delete requestHeaders['Content-Type']; // Let the browser set it - } - - var request = new XMLHttpRequest(); - - // HTTP basic authentication - if (config.auth) { - var username = config.auth.username || ''; - var password = config.auth.password || ''; - requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password); - } - - var fullPath = buildFullPath(config.baseURL, config.url); - request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true); - - // Set the request timeout in MS - request.timeout = config.timeout; - - // Listen for ready state - request.onreadystatechange = function handleLoad() { - if (!request || request.readyState !== 4) { - return; - } - - // The request errored out and we didn't get a response, this will be - // handled by onerror instead - // With one exception: request that using file: protocol, most browsers - // will return status as 0 even though it's a successful request - if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) { - return; - } - - // Prepare the response - var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null; - var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response; - var response = { - data: responseData, - status: request.status, - statusText: request.statusText, - headers: responseHeaders, - config: config, - request: request - }; - - settle(resolve, reject, response); - - // Clean up request - request = null; - }; - - // Handle browser request cancellation (as opposed to a manual cancellation) - request.onabort = function handleAbort() { - if (!request) { - return; - } - - reject(createError('Request aborted', config, 'ECONNABORTED', request)); - - // Clean up request - request = null; - }; - - // Handle low level network errors - request.onerror = function handleError() { - // Real errors are hidden from us by the browser - // onerror should only fire if it's a network error - reject(createError('Network Error', config, null, request)); - - // Clean up request - request = null; - }; - - // Handle timeout - request.ontimeout = function handleTimeout() { - var timeoutErrorMessage = 'timeout of ' + config.timeout + 'ms exceeded'; - if (config.timeoutErrorMessage) { - timeoutErrorMessage = config.timeoutErrorMessage; - } - reject(createError(timeoutErrorMessage, config, 'ECONNABORTED', - request)); - - // Clean up request - request = null; - }; - - // Add xsrf header - // This is only done if running in a standard browser environment. - // Specifically not if we're in a web worker, or react-native. - if (utils.isStandardBrowserEnv()) { - var cookies = __webpack_require__(/*! ./../helpers/cookies */ "./node_modules/axios/lib/helpers/cookies.js"); - - // Add xsrf header - var xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) && config.xsrfCookieName ? - cookies.read(config.xsrfCookieName) : - undefined; - - if (xsrfValue) { - requestHeaders[config.xsrfHeaderName] = xsrfValue; - } - } - - // Add headers to the request - if ('setRequestHeader' in request) { - utils.forEach(requestHeaders, function setRequestHeader(val, key) { - if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') { - // Remove Content-Type if data is undefined - delete requestHeaders[key]; - } else { - // Otherwise add header to the request - request.setRequestHeader(key, val); - } - }); - } +var AlgoliaSearchHelper = __webpack_require__(/*! ./src/algoliasearch.helper */ "./node_modules/algoliasearch-helper/src/algoliasearch.helper.js"); - // Add withCredentials to request if needed - if (!utils.isUndefined(config.withCredentials)) { - request.withCredentials = !!config.withCredentials; - } +var SearchParameters = __webpack_require__(/*! ./src/SearchParameters */ "./node_modules/algoliasearch-helper/src/SearchParameters/index.js"); +var SearchResults = __webpack_require__(/*! ./src/SearchResults */ "./node_modules/algoliasearch-helper/src/SearchResults/index.js"); - // Add responseType to request if needed - if (config.responseType) { - try { - request.responseType = config.responseType; - } catch (e) { - // Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2. - // But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function. - if (config.responseType !== 'json') { - throw e; - } - } - } +/** + * The algoliasearchHelper module is the function that will let its + * contains everything needed to use the Algoliasearch + * Helper. It is a also a function that instanciate the helper. + * To use the helper, you also need the Algolia JS client v3. + * @example + * //using the UMD build + * var client = algoliasearch('latency', '6be0576ff61c053d5f9a3225e2a90f76'); + * var helper = algoliasearchHelper(client, 'bestbuy', { + * facets: ['shipping'], + * disjunctiveFacets: ['category'] + * }); + * helper.on('result', function(result) { + * console.log(result); + * }); + * helper + * .toggleFacetRefinement('category', 'Movies & TV Shows') + * .toggleFacetRefinement('shipping', 'Free shipping') + * .search(); + * @example + * // The helper is an event emitter using the node API + * helper.on('result', updateTheResults); + * helper.once('result', updateTheResults); + * helper.removeListener('result', updateTheResults); + * helper.removeAllListeners('result'); + * @module algoliasearchHelper + * @param {AlgoliaSearch} client an AlgoliaSearch client + * @param {string} index the name of the index to query + * @param {SearchParameters|object} opts an object defining the initial config of the search. It doesn't have to be a {SearchParameters}, just an object containing the properties you need from it. + * @return {AlgoliaSearchHelper} + */ +function algoliasearchHelper(client, index, opts) { + return new AlgoliaSearchHelper(client, index, opts); +} - // Handle progress if needed - if (typeof config.onDownloadProgress === 'function') { - request.addEventListener('progress', config.onDownloadProgress); - } +/** + * The version currently used + * @member module:algoliasearchHelper.version + * @type {number} + */ +algoliasearchHelper.version = __webpack_require__(/*! ./src/version.js */ "./node_modules/algoliasearch-helper/src/version.js"); - // Not all browsers support upload events - if (typeof config.onUploadProgress === 'function' && request.upload) { - request.upload.addEventListener('progress', config.onUploadProgress); - } +/** + * Constructor for the Helper. + * @member module:algoliasearchHelper.AlgoliaSearchHelper + * @type {AlgoliaSearchHelper} + */ +algoliasearchHelper.AlgoliaSearchHelper = AlgoliaSearchHelper; - if (config.cancelToken) { - // Handle cancellation - config.cancelToken.promise.then(function onCanceled(cancel) { - if (!request) { - return; - } +/** + * Constructor for the object containing all the parameters of the search. + * @member module:algoliasearchHelper.SearchParameters + * @type {SearchParameters} + */ +algoliasearchHelper.SearchParameters = SearchParameters; - request.abort(); - reject(cancel); - // Clean up request - request = null; - }); - } +/** + * Constructor for the object containing the results of the search. + * @member module:algoliasearchHelper.SearchResults + * @type {SearchResults} + */ +algoliasearchHelper.SearchResults = SearchResults; - if (requestData === undefined) { - requestData = null; - } +/** + * URL tools to generate query string and parse them from/into + * SearchParameters + * @member module:algoliasearchHelper.url + * @type {object} {@link url} + * + */ +algoliasearchHelper.url = __webpack_require__(/*! ./src/url */ "./node_modules/algoliasearch-helper/src/url.js"); - // Send the request - request.send(requestData); - }); -}; +module.exports = algoliasearchHelper; /***/ }), -/***/ "./node_modules/axios/lib/axios.js": -/*!*****************************************!*\ - !*** ./node_modules/axios/lib/axios.js ***! - \*****************************************/ +/***/ "./node_modules/algoliasearch-helper/src/DerivedHelper/index.js": +/*!**********************************************************************!*\ + !*** ./node_modules/algoliasearch-helper/src/DerivedHelper/index.js ***! + \**********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(/*! ./utils */ "./node_modules/axios/lib/utils.js"); -var bind = __webpack_require__(/*! ./helpers/bind */ "./node_modules/axios/lib/helpers/bind.js"); -var Axios = __webpack_require__(/*! ./core/Axios */ "./node_modules/axios/lib/core/Axios.js"); -var mergeConfig = __webpack_require__(/*! ./core/mergeConfig */ "./node_modules/axios/lib/core/mergeConfig.js"); -var defaults = __webpack_require__(/*! ./defaults */ "./node_modules/axios/lib/defaults.js"); +var events = __webpack_require__(/*! events */ "./node_modules/events/events.js"); +var inherits = __webpack_require__(/*! ../functions/inherits */ "./node_modules/algoliasearch-helper/src/functions/inherits.js"); /** - * Create an instance of Axios - * - * @param {Object} defaultConfig The default config for the instance - * @return {Axios} A new instance of Axios + * A DerivedHelper is a way to create sub requests to + * Algolia from a main helper. + * @class + * @classdesc The DerivedHelper provides an event based interface for search callbacks: + * - search: when a search is triggered using the `search()` method. + * - result: when the response is retrieved from Algolia and is processed. + * This event contains a {@link SearchResults} object and the + * {@link SearchParameters} corresponding to this answer. */ -function createInstance(defaultConfig) { - var context = new Axios(defaultConfig); - var instance = bind(Axios.prototype.request, context); - - // Copy axios.prototype to instance - utils.extend(instance, Axios.prototype, context); - - // Copy context to instance - utils.extend(instance, context); - - return instance; +function DerivedHelper(mainHelper, fn) { + this.main = mainHelper; + this.fn = fn; + this.lastResults = null; } -// Create the default instance to be exported -var axios = createInstance(defaults); - -// Expose Axios class to allow class inheritance -axios.Axios = Axios; +inherits(DerivedHelper, events.EventEmitter); -// Factory for creating new instances -axios.create = function create(instanceConfig) { - return createInstance(mergeConfig(axios.defaults, instanceConfig)); +/** + * Detach this helper from the main helper + * @return {undefined} + * @throws Error if the derived helper is already detached + */ +DerivedHelper.prototype.detach = function() { + this.removeAllListeners(); + this.main.detachDerivedHelper(this); }; -// Expose Cancel & CancelToken -axios.Cancel = __webpack_require__(/*! ./cancel/Cancel */ "./node_modules/axios/lib/cancel/Cancel.js"); -axios.CancelToken = __webpack_require__(/*! ./cancel/CancelToken */ "./node_modules/axios/lib/cancel/CancelToken.js"); -axios.isCancel = __webpack_require__(/*! ./cancel/isCancel */ "./node_modules/axios/lib/cancel/isCancel.js"); - -// Expose all/spread -axios.all = function all(promises) { - return Promise.all(promises); +DerivedHelper.prototype.getModifiedState = function(parameters) { + return this.fn(parameters); }; -axios.spread = __webpack_require__(/*! ./helpers/spread */ "./node_modules/axios/lib/helpers/spread.js"); - -module.exports = axios; -// Allow use of default import syntax in TypeScript -module.exports.default = axios; +module.exports = DerivedHelper; /***/ }), -/***/ "./node_modules/axios/lib/cancel/Cancel.js": -/*!*************************************************!*\ - !*** ./node_modules/axios/lib/cancel/Cancel.js ***! - \*************************************************/ +/***/ "./node_modules/algoliasearch-helper/src/SearchParameters/RefinementList.js": +/*!**********************************************************************************!*\ + !*** ./node_modules/algoliasearch-helper/src/SearchParameters/RefinementList.js ***! + \**********************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { @@ -592,5998 +467,8512 @@ module.exports.default = axios; /** - * A `Cancel` is an object that is thrown when an operation is canceled. + * Functions to manipulate refinement lists * - * @class - * @param {string=} message The message. + * The RefinementList is not formally defined through a prototype but is based + * on a specific structure. + * + * @module SearchParameters.refinementList + * + * @typedef {string[]} SearchParameters.refinementList.Refinements + * @typedef {Object.} SearchParameters.refinementList.RefinementList */ -function Cancel(message) { - this.message = message; -} - -Cancel.prototype.toString = function toString() { - return 'Cancel' + (this.message ? ': ' + this.message : ''); -}; -Cancel.prototype.__CANCEL__ = true; +var isUndefined = __webpack_require__(/*! lodash/isUndefined */ "./node_modules/lodash/isUndefined.js"); +var isString = __webpack_require__(/*! lodash/isString */ "./node_modules/lodash/isString.js"); +var isFunction = __webpack_require__(/*! lodash/isFunction */ "./node_modules/lodash/isFunction.js"); +var isEmpty = __webpack_require__(/*! lodash/isEmpty */ "./node_modules/lodash/isEmpty.js"); +var defaults = __webpack_require__(/*! lodash/defaults */ "./node_modules/lodash/defaults.js"); -module.exports = Cancel; +var reduce = __webpack_require__(/*! lodash/reduce */ "./node_modules/lodash/reduce.js"); +var filter = __webpack_require__(/*! lodash/filter */ "./node_modules/lodash/filter.js"); +var omit = __webpack_require__(/*! lodash/omit */ "./node_modules/lodash/omit.js"); +var lib = { + /** + * Adds a refinement to a RefinementList + * @param {RefinementList} refinementList the initial list + * @param {string} attribute the attribute to refine + * @param {string} value the value of the refinement, if the value is not a string it will be converted + * @return {RefinementList} a new and updated refinement list + */ + addRefinement: function addRefinement(refinementList, attribute, value) { + if (lib.isRefined(refinementList, attribute, value)) { + return refinementList; + } -/***/ }), + var valueAsString = '' + value; -/***/ "./node_modules/axios/lib/cancel/CancelToken.js": -/*!******************************************************!*\ - !*** ./node_modules/axios/lib/cancel/CancelToken.js ***! - \******************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { + var facetRefinement = !refinementList[attribute] ? + [valueAsString] : + refinementList[attribute].concat(valueAsString); -"use strict"; + var mod = {}; + mod[attribute] = facetRefinement; -var Cancel = __webpack_require__(/*! ./Cancel */ "./node_modules/axios/lib/cancel/Cancel.js"); + return defaults({}, mod, refinementList); + }, + /** + * Removes refinement(s) for an attribute: + * - if the value is specified removes the refinement for the value on the attribute + * - if no value is specified removes all the refinements for this attribute + * @param {RefinementList} refinementList the initial list + * @param {string} attribute the attribute to refine + * @param {string} [value] the value of the refinement + * @return {RefinementList} a new and updated refinement lst + */ + removeRefinement: function removeRefinement(refinementList, attribute, value) { + if (isUndefined(value)) { + return lib.clearRefinement(refinementList, attribute); + } -/** - * A `CancelToken` is an object that can be used to request cancellation of an operation. - * - * @class - * @param {Function} executor The executor function. - */ -function CancelToken(executor) { - if (typeof executor !== 'function') { - throw new TypeError('executor must be a function.'); - } + var valueAsString = '' + value; - var resolvePromise; - this.promise = new Promise(function promiseExecutor(resolve) { - resolvePromise = resolve; - }); + return lib.clearRefinement(refinementList, function(v, f) { + return attribute === f && valueAsString === v; + }); + }, + /** + * Toggles the refinement value for an attribute. + * @param {RefinementList} refinementList the initial list + * @param {string} attribute the attribute to refine + * @param {string} value the value of the refinement + * @return {RefinementList} a new and updated list + */ + toggleRefinement: function toggleRefinement(refinementList, attribute, value) { + if (isUndefined(value)) throw new Error('toggleRefinement should be used with a value'); - var token = this; - executor(function cancel(message) { - if (token.reason) { - // Cancellation has already been requested - return; + if (lib.isRefined(refinementList, attribute, value)) { + return lib.removeRefinement(refinementList, attribute, value); } - token.reason = new Cancel(message); - resolvePromise(token.reason); - }); -} - -/** - * Throws a `Cancel` if cancellation has been requested. - */ -CancelToken.prototype.throwIfRequested = function throwIfRequested() { - if (this.reason) { - throw this.reason; - } -}; - -/** - * Returns an object that contains a new `CancelToken` and a function that, when called, - * cancels the `CancelToken`. - */ -CancelToken.source = function source() { - var cancel; - var token = new CancelToken(function executor(c) { - cancel = c; - }); - return { - token: token, - cancel: cancel - }; -}; + return lib.addRefinement(refinementList, attribute, value); + }, + /** + * Clear all or parts of a RefinementList. Depending on the arguments, three + * kinds of behavior can happen: + * - if no attribute is provided: clears the whole list + * - if an attribute is provided as a string: clears the list for the specific attribute + * - if an attribute is provided as a function: discards the elements for which the function returns true + * @param {RefinementList} refinementList the initial list + * @param {string} [attribute] the attribute or function to discard + * @param {string} [refinementType] optional parameter to give more context to the attribute function + * @return {RefinementList} a new and updated refinement list + */ + clearRefinement: function clearRefinement(refinementList, attribute, refinementType) { + if (isUndefined(attribute)) { + if (isEmpty(refinementList)) return refinementList; + return {}; + } else if (isString(attribute)) { + if (isEmpty(refinementList[attribute])) return refinementList; + return omit(refinementList, attribute); + } else if (isFunction(attribute)) { + var hasChanged = false; + + var newRefinementList = reduce(refinementList, function(memo, values, key) { + var facetList = filter(values, function(value) { + return !attribute(value, key, refinementType); + }); -module.exports = CancelToken; + if (!isEmpty(facetList)) { + if (facetList.length !== values.length) hasChanged = true; + memo[key] = facetList; + } + else hasChanged = true; + return memo; + }, {}); -/***/ }), + if (hasChanged) return newRefinementList; + return refinementList; + } + }, + /** + * Test if the refinement value is used for the attribute. If no refinement value + * is provided, test if the refinementList contains any refinement for the + * given attribute. + * @param {RefinementList} refinementList the list of refinement + * @param {string} attribute name of the attribute + * @param {string} [refinementValue] value of the filter/refinement + * @return {boolean} + */ + isRefined: function isRefined(refinementList, attribute, refinementValue) { + var indexOf = __webpack_require__(/*! lodash/indexOf */ "./node_modules/lodash/indexOf.js"); -/***/ "./node_modules/axios/lib/cancel/isCancel.js": -/*!***************************************************!*\ - !*** ./node_modules/axios/lib/cancel/isCancel.js ***! - \***************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { + var containsRefinements = !!refinementList[attribute] && + refinementList[attribute].length > 0; -"use strict"; + if (isUndefined(refinementValue) || !containsRefinements) { + return containsRefinements; + } + var refinementValueAsString = '' + refinementValue; -module.exports = function isCancel(value) { - return !!(value && value.__CANCEL__); + return indexOf(refinementList[attribute], refinementValueAsString) !== -1; + } }; +module.exports = lib; + /***/ }), -/***/ "./node_modules/axios/lib/core/Axios.js": -/*!**********************************************!*\ - !*** ./node_modules/axios/lib/core/Axios.js ***! - \**********************************************/ +/***/ "./node_modules/algoliasearch-helper/src/SearchParameters/filterState.js": +/*!*******************************************************************************!*\ + !*** ./node_modules/algoliasearch-helper/src/SearchParameters/filterState.js ***! + \*******************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js"); -var buildURL = __webpack_require__(/*! ../helpers/buildURL */ "./node_modules/axios/lib/helpers/buildURL.js"); -var InterceptorManager = __webpack_require__(/*! ./InterceptorManager */ "./node_modules/axios/lib/core/InterceptorManager.js"); -var dispatchRequest = __webpack_require__(/*! ./dispatchRequest */ "./node_modules/axios/lib/core/dispatchRequest.js"); -var mergeConfig = __webpack_require__(/*! ./mergeConfig */ "./node_modules/axios/lib/core/mergeConfig.js"); - -/** - * Create a new instance of Axios - * - * @param {Object} instanceConfig The default config for the instance - */ -function Axios(instanceConfig) { - this.defaults = instanceConfig; - this.interceptors = { - request: new InterceptorManager(), - response: new InterceptorManager() - }; -} - -/** - * Dispatch a request - * - * @param {Object} config The config specific for this request (merged with this.defaults) - */ -Axios.prototype.request = function request(config) { - /*eslint no-param-reassign:0*/ - // Allow for axios('example/url'[, config]) a la fetch API - if (typeof config === 'string') { - config = arguments[1] || {}; - config.url = arguments[0]; - } else { - config = config || {}; - } - - config = mergeConfig(this.defaults, config); +var forEach = __webpack_require__(/*! lodash/forEach */ "./node_modules/lodash/forEach.js"); +var filter = __webpack_require__(/*! lodash/filter */ "./node_modules/lodash/filter.js"); +var map = __webpack_require__(/*! lodash/map */ "./node_modules/lodash/map.js"); +var isEmpty = __webpack_require__(/*! lodash/isEmpty */ "./node_modules/lodash/isEmpty.js"); +var indexOf = __webpack_require__(/*! lodash/indexOf */ "./node_modules/lodash/indexOf.js"); - // Set config.method - if (config.method) { - config.method = config.method.toLowerCase(); - } else if (this.defaults.method) { - config.method = this.defaults.method.toLowerCase(); - } else { - config.method = 'get'; - } +function filterState(state, filters) { + var partialState = {}; + var attributeFilters = filter(filters, function(f) { return f.indexOf('attribute:') !== -1; }); + var attributes = map(attributeFilters, function(aF) { return aF.split(':')[1]; }); - // Hook up interceptors middleware - var chain = [dispatchRequest, undefined]; - var promise = Promise.resolve(config); + if (indexOf(attributes, '*') === -1) { + forEach(attributes, function(attr) { + if (state.isConjunctiveFacet(attr) && state.isFacetRefined(attr)) { + if (!partialState.facetsRefinements) partialState.facetsRefinements = {}; + partialState.facetsRefinements[attr] = state.facetsRefinements[attr]; + } - this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { - chain.unshift(interceptor.fulfilled, interceptor.rejected); - }); + if (state.isDisjunctiveFacet(attr) && state.isDisjunctiveFacetRefined(attr)) { + if (!partialState.disjunctiveFacetsRefinements) partialState.disjunctiveFacetsRefinements = {}; + partialState.disjunctiveFacetsRefinements[attr] = state.disjunctiveFacetsRefinements[attr]; + } - this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) { - chain.push(interceptor.fulfilled, interceptor.rejected); - }); + if (state.isHierarchicalFacet(attr) && state.isHierarchicalFacetRefined(attr)) { + if (!partialState.hierarchicalFacetsRefinements) partialState.hierarchicalFacetsRefinements = {}; + partialState.hierarchicalFacetsRefinements[attr] = state.hierarchicalFacetsRefinements[attr]; + } - while (chain.length) { - promise = promise.then(chain.shift(), chain.shift()); + var numericRefinements = state.getNumericRefinements(attr); + if (!isEmpty(numericRefinements)) { + if (!partialState.numericRefinements) partialState.numericRefinements = {}; + partialState.numericRefinements[attr] = state.numericRefinements[attr]; + } + }); + } else { + if (!isEmpty(state.numericRefinements)) { + partialState.numericRefinements = state.numericRefinements; + } + if (!isEmpty(state.facetsRefinements)) partialState.facetsRefinements = state.facetsRefinements; + if (!isEmpty(state.disjunctiveFacetsRefinements)) { + partialState.disjunctiveFacetsRefinements = state.disjunctiveFacetsRefinements; + } + if (!isEmpty(state.hierarchicalFacetsRefinements)) { + partialState.hierarchicalFacetsRefinements = state.hierarchicalFacetsRefinements; + } } - return promise; -}; - -Axios.prototype.getUri = function getUri(config) { - config = mergeConfig(this.defaults, config); - return buildURL(config.url, config.params, config.paramsSerializer).replace(/^\?/, ''); -}; + var searchParameters = filter( + filters, + function(f) { + return f.indexOf('attribute:') === -1; + } + ); -// Provide aliases for supported request methods -utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) { - /*eslint func-names:0*/ - Axios.prototype[method] = function(url, config) { - return this.request(utils.merge(config || {}, { - method: method, - url: url - })); - }; -}); + forEach( + searchParameters, + function(parameterKey) { + partialState[parameterKey] = state[parameterKey]; + } + ); -utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { - /*eslint func-names:0*/ - Axios.prototype[method] = function(url, data, config) { - return this.request(utils.merge(config || {}, { - method: method, - url: url, - data: data - })); - }; -}); + return partialState; +} -module.exports = Axios; +module.exports = filterState; /***/ }), -/***/ "./node_modules/axios/lib/core/InterceptorManager.js": -/*!***********************************************************!*\ - !*** ./node_modules/axios/lib/core/InterceptorManager.js ***! - \***********************************************************/ +/***/ "./node_modules/algoliasearch-helper/src/SearchParameters/index.js": +/*!*************************************************************************!*\ + !*** ./node_modules/algoliasearch-helper/src/SearchParameters/index.js ***! + \*************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js"); +var keys = __webpack_require__(/*! lodash/keys */ "./node_modules/lodash/keys.js"); +var intersection = __webpack_require__(/*! lodash/intersection */ "./node_modules/lodash/intersection.js"); +var forOwn = __webpack_require__(/*! lodash/forOwn */ "./node_modules/lodash/forOwn.js"); +var forEach = __webpack_require__(/*! lodash/forEach */ "./node_modules/lodash/forEach.js"); +var filter = __webpack_require__(/*! lodash/filter */ "./node_modules/lodash/filter.js"); +var map = __webpack_require__(/*! lodash/map */ "./node_modules/lodash/map.js"); +var reduce = __webpack_require__(/*! lodash/reduce */ "./node_modules/lodash/reduce.js"); +var omit = __webpack_require__(/*! lodash/omit */ "./node_modules/lodash/omit.js"); +var indexOf = __webpack_require__(/*! lodash/indexOf */ "./node_modules/lodash/indexOf.js"); +var isNaN = __webpack_require__(/*! lodash/isNaN */ "./node_modules/lodash/isNaN.js"); +var isEmpty = __webpack_require__(/*! lodash/isEmpty */ "./node_modules/lodash/isEmpty.js"); +var isEqual = __webpack_require__(/*! lodash/isEqual */ "./node_modules/lodash/isEqual.js"); +var isUndefined = __webpack_require__(/*! lodash/isUndefined */ "./node_modules/lodash/isUndefined.js"); +var isString = __webpack_require__(/*! lodash/isString */ "./node_modules/lodash/isString.js"); +var isFunction = __webpack_require__(/*! lodash/isFunction */ "./node_modules/lodash/isFunction.js"); +var find = __webpack_require__(/*! lodash/find */ "./node_modules/lodash/find.js"); +var trim = __webpack_require__(/*! lodash/trim */ "./node_modules/lodash/trim.js"); -function InterceptorManager() { - this.handlers = []; -} +var defaults = __webpack_require__(/*! lodash/defaults */ "./node_modules/lodash/defaults.js"); +var merge = __webpack_require__(/*! lodash/merge */ "./node_modules/lodash/merge.js"); + +var valToNumber = __webpack_require__(/*! ../functions/valToNumber */ "./node_modules/algoliasearch-helper/src/functions/valToNumber.js"); + +var filterState = __webpack_require__(/*! ./filterState */ "./node_modules/algoliasearch-helper/src/SearchParameters/filterState.js"); + +var RefinementList = __webpack_require__(/*! ./RefinementList */ "./node_modules/algoliasearch-helper/src/SearchParameters/RefinementList.js"); /** - * Add a new interceptor to the stack - * - * @param {Function} fulfilled The function to handle `then` for a `Promise` - * @param {Function} rejected The function to handle `reject` for a `Promise` - * - * @return {Number} An ID used to remove interceptor later + * like _.find but using _.isEqual to be able to use it + * to find arrays. + * @private + * @param {any[]} array array to search into + * @param {any} searchedValue the value we're looking for + * @return {any} the searched value or undefined */ -InterceptorManager.prototype.use = function use(fulfilled, rejected) { - this.handlers.push({ - fulfilled: fulfilled, - rejected: rejected +function findArray(array, searchedValue) { + return find(array, function(currentValue) { + return isEqual(currentValue, searchedValue); }); - return this.handlers.length - 1; -}; +} /** - * Remove an interceptor from the stack - * - * @param {Number} id The ID that was returned by `use` + * The facet list is the structure used to store the list of values used to + * filter a single attribute. + * @typedef {string[]} SearchParameters.FacetList */ -InterceptorManager.prototype.eject = function eject(id) { - if (this.handlers[id]) { - this.handlers[id] = null; - } -}; /** - * Iterate over all the registered interceptors - * - * This method is particularly useful for skipping over any - * interceptors that may have become `null` calling `eject`. - * - * @param {Function} fn The function to call for each interceptor + * Structure to store numeric filters with the operator as the key. The supported operators + * are `=`, `>`, `<`, `>=`, `<=` and `!=`. + * @typedef {Object.>} SearchParameters.OperatorList */ -InterceptorManager.prototype.forEach = function forEach(fn) { - utils.forEach(this.handlers, function forEachHandler(h) { - if (h !== null) { - fn(h); - } - }); -}; - -module.exports = InterceptorManager; - - -/***/ }), - -/***/ "./node_modules/axios/lib/core/buildFullPath.js": -/*!******************************************************!*\ - !*** ./node_modules/axios/lib/core/buildFullPath.js ***! - \******************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { - -"use strict"; - - -var isAbsoluteURL = __webpack_require__(/*! ../helpers/isAbsoluteURL */ "./node_modules/axios/lib/helpers/isAbsoluteURL.js"); -var combineURLs = __webpack_require__(/*! ../helpers/combineURLs */ "./node_modules/axios/lib/helpers/combineURLs.js"); /** - * Creates a new URL by combining the baseURL with the requestedURL, - * only when the requestedURL is not already an absolute URL. - * If the requestURL is absolute, this function returns the requestedURL untouched. - * - * @param {string} baseURL The base URL - * @param {string} requestedURL Absolute or relative URL to combine - * @returns {string} The combined full path + * SearchParameters is the data structure that contains all the information + * usable for making a search to Algolia API. It doesn't do the search itself, + * nor does it contains logic about the parameters. + * It is an immutable object, therefore it has been created in a way that each + * changes does not change the object itself but returns a copy with the + * modification. + * This object should probably not be instantiated outside of the helper. It will + * be provided when needed. This object is documented for reference as you'll + * get it from events generated by the {@link AlgoliaSearchHelper}. + * If need be, instantiate the Helper from the factory function {@link SearchParameters.make} + * @constructor + * @classdesc contains all the parameters of a search + * @param {object|SearchParameters} newParameters existing parameters or partial object + * for the properties of a new SearchParameters + * @see SearchParameters.make + * @example SearchParameters of the first query in + * the instant search demo +{ + "query": "", + "disjunctiveFacets": [ + "customerReviewCount", + "category", + "salePrice_range", + "manufacturer" + ], + "maxValuesPerFacet": 30, + "page": 0, + "hitsPerPage": 10, + "facets": [ + "type", + "shipping" + ] +} */ -module.exports = function buildFullPath(baseURL, requestedURL) { - if (baseURL && !isAbsoluteURL(requestedURL)) { - return combineURLs(baseURL, requestedURL); - } - return requestedURL; -}; +function SearchParameters(newParameters) { + var params = newParameters ? SearchParameters._parseNumbers(newParameters) : {}; + /** + * Targeted index. This parameter is mandatory. + * @member {string} + */ + this.index = params.index || ''; -/***/ }), + // Query + /** + * Query string of the instant search. The empty string is a valid query. + * @member {string} + * @see https://www.algolia.com/doc/rest#param-query + */ + this.query = params.query || ''; -/***/ "./node_modules/axios/lib/core/createError.js": -/*!****************************************************!*\ - !*** ./node_modules/axios/lib/core/createError.js ***! - \****************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { + // Facets + /** + * This attribute contains the list of all the conjunctive facets + * used. This list will be added to requested facets in the + * [facets attribute](https://www.algolia.com/doc/rest-api/search#param-facets) sent to algolia. + * @member {string[]} + */ + this.facets = params.facets || []; + /** + * This attribute contains the list of all the disjunctive facets + * used. This list will be added to requested facets in the + * [facets attribute](https://www.algolia.com/doc/rest-api/search#param-facets) sent to algolia. + * @member {string[]} + */ + this.disjunctiveFacets = params.disjunctiveFacets || []; + /** + * This attribute contains the list of all the hierarchical facets + * used. This list will be added to requested facets in the + * [facets attribute](https://www.algolia.com/doc/rest-api/search#param-facets) sent to algolia. + * Hierarchical facets are a sub type of disjunctive facets that + * let you filter faceted attributes hierarchically. + * @member {string[]|object[]} + */ + this.hierarchicalFacets = params.hierarchicalFacets || []; -"use strict"; + // Refinements + /** + * This attribute contains all the filters that need to be + * applied on the conjunctive facets. Each facet must be properly + * defined in the `facets` attribute. + * + * The key is the name of the facet, and the `FacetList` contains all + * filters selected for the associated facet name. + * + * When querying algolia, the values stored in this attribute will + * be translated into the `facetFilters` attribute. + * @member {Object.} + */ + this.facetsRefinements = params.facetsRefinements || {}; + /** + * This attribute contains all the filters that need to be + * excluded from the conjunctive facets. Each facet must be properly + * defined in the `facets` attribute. + * + * The key is the name of the facet, and the `FacetList` contains all + * filters excluded for the associated facet name. + * + * When querying algolia, the values stored in this attribute will + * be translated into the `facetFilters` attribute. + * @member {Object.} + */ + this.facetsExcludes = params.facetsExcludes || {}; + /** + * This attribute contains all the filters that need to be + * applied on the disjunctive facets. Each facet must be properly + * defined in the `disjunctiveFacets` attribute. + * + * The key is the name of the facet, and the `FacetList` contains all + * filters selected for the associated facet name. + * + * When querying algolia, the values stored in this attribute will + * be translated into the `facetFilters` attribute. + * @member {Object.} + */ + this.disjunctiveFacetsRefinements = params.disjunctiveFacetsRefinements || {}; + /** + * This attribute contains all the filters that need to be + * applied on the numeric attributes. + * + * The key is the name of the attribute, and the value is the + * filters to apply to this attribute. + * + * When querying algolia, the values stored in this attribute will + * be translated into the `numericFilters` attribute. + * @member {Object.} + */ + this.numericRefinements = params.numericRefinements || {}; + /** + * This attribute contains all the tags used to refine the query. + * + * When querying algolia, the values stored in this attribute will + * be translated into the `tagFilters` attribute. + * @member {string[]} + */ + this.tagRefinements = params.tagRefinements || []; + /** + * This attribute contains all the filters that need to be + * applied on the hierarchical facets. Each facet must be properly + * defined in the `hierarchicalFacets` attribute. + * + * The key is the name of the facet, and the `FacetList` contains all + * filters selected for the associated facet name. The FacetList values + * are structured as a string that contain the values for each level + * separated by the configured separator. + * + * When querying algolia, the values stored in this attribute will + * be translated into the `facetFilters` attribute. + * @member {Object.} + */ + this.hierarchicalFacetsRefinements = params.hierarchicalFacetsRefinements || {}; + /** + * Contains the numeric filters in the raw format of the Algolia API. Setting + * this parameter is not compatible with the usage of numeric filters methods. + * @see https://www.algolia.com/doc/javascript#numericFilters + * @member {string} + */ + this.numericFilters = params.numericFilters; -var enhanceError = __webpack_require__(/*! ./enhanceError */ "./node_modules/axios/lib/core/enhanceError.js"); + /** + * Contains the tag filters in the raw format of the Algolia API. Setting this + * parameter is not compatible with the of the add/remove/toggle methods of the + * tag api. + * @see https://www.algolia.com/doc/rest#param-tagFilters + * @member {string} + */ + this.tagFilters = params.tagFilters; -/** - * Create an Error with the specified message, config, error code, request and response. - * - * @param {string} message The error message. - * @param {Object} config The config. - * @param {string} [code] The error code (for example, 'ECONNABORTED'). - * @param {Object} [request] The request. - * @param {Object} [response] The response. - * @returns {Error} The created error. - */ -module.exports = function createError(message, config, code, request, response) { - var error = new Error(message); - return enhanceError(error, config, code, request, response); -}; + /** + * Contains the optional tag filters in the raw format of the Algolia API. + * @see https://www.algolia.com/doc/rest#param-tagFilters + * @member {string} + */ + this.optionalTagFilters = params.optionalTagFilters; + /** + * Contains the optional facet filters in the raw format of the Algolia API. + * @see https://www.algolia.com/doc/rest#param-tagFilters + * @member {string} + */ + this.optionalFacetFilters = params.optionalFacetFilters; -/***/ }), -/***/ "./node_modules/axios/lib/core/dispatchRequest.js": -/*!********************************************************!*\ - !*** ./node_modules/axios/lib/core/dispatchRequest.js ***! - \********************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { + // Misc. parameters + /** + * Number of hits to be returned by the search API + * @member {number} + * @see https://www.algolia.com/doc/rest#param-hitsPerPage + */ + this.hitsPerPage = params.hitsPerPage; + /** + * Number of values for each faceted attribute + * @member {number} + * @see https://www.algolia.com/doc/rest#param-maxValuesPerFacet + */ + this.maxValuesPerFacet = params.maxValuesPerFacet; + /** + * The current page number + * @member {number} + * @see https://www.algolia.com/doc/rest#param-page + */ + this.page = params.page || 0; + /** + * How the query should be treated by the search engine. + * Possible values: prefixAll, prefixLast, prefixNone + * @see https://www.algolia.com/doc/rest#param-queryType + * @member {string} + */ + this.queryType = params.queryType; + /** + * How the typo tolerance behave in the search engine. + * Possible values: true, false, min, strict + * @see https://www.algolia.com/doc/rest#param-typoTolerance + * @member {string} + */ + this.typoTolerance = params.typoTolerance; -"use strict"; + /** + * Number of characters to wait before doing one character replacement. + * @see https://www.algolia.com/doc/rest#param-minWordSizefor1Typo + * @member {number} + */ + this.minWordSizefor1Typo = params.minWordSizefor1Typo; + /** + * Number of characters to wait before doing a second character replacement. + * @see https://www.algolia.com/doc/rest#param-minWordSizefor2Typos + * @member {number} + */ + this.minWordSizefor2Typos = params.minWordSizefor2Typos; + /** + * Configure the precision of the proximity ranking criterion + * @see https://www.algolia.com/doc/rest#param-minProximity + */ + this.minProximity = params.minProximity; + /** + * Should the engine allow typos on numerics. + * @see https://www.algolia.com/doc/rest#param-allowTyposOnNumericTokens + * @member {boolean} + */ + this.allowTyposOnNumericTokens = params.allowTyposOnNumericTokens; + /** + * Should the plurals be ignored + * @see https://www.algolia.com/doc/rest#param-ignorePlurals + * @member {boolean} + */ + this.ignorePlurals = params.ignorePlurals; + /** + * Restrict which attribute is searched. + * @see https://www.algolia.com/doc/rest#param-restrictSearchableAttributes + * @member {string} + */ + this.restrictSearchableAttributes = params.restrictSearchableAttributes; + /** + * Enable the advanced syntax. + * @see https://www.algolia.com/doc/rest#param-advancedSyntax + * @member {boolean} + */ + this.advancedSyntax = params.advancedSyntax; + /** + * Enable the analytics + * @see https://www.algolia.com/doc/rest#param-analytics + * @member {boolean} + */ + this.analytics = params.analytics; + /** + * Tag of the query in the analytics. + * @see https://www.algolia.com/doc/rest#param-analyticsTags + * @member {string} + */ + this.analyticsTags = params.analyticsTags; + /** + * Enable the synonyms + * @see https://www.algolia.com/doc/rest#param-synonyms + * @member {boolean} + */ + this.synonyms = params.synonyms; + /** + * Should the engine replace the synonyms in the highlighted results. + * @see https://www.algolia.com/doc/rest#param-replaceSynonymsInHighlight + * @member {boolean} + */ + this.replaceSynonymsInHighlight = params.replaceSynonymsInHighlight; + /** + * Add some optional words to those defined in the dashboard + * @see https://www.algolia.com/doc/rest#param-optionalWords + * @member {string} + */ + this.optionalWords = params.optionalWords; + /** + * Possible values are "lastWords" "firstWords" "allOptional" "none" (default) + * @see https://www.algolia.com/doc/rest#param-removeWordsIfNoResults + * @member {string} + */ + this.removeWordsIfNoResults = params.removeWordsIfNoResults; + /** + * List of attributes to retrieve + * @see https://www.algolia.com/doc/rest#param-attributesToRetrieve + * @member {string} + */ + this.attributesToRetrieve = params.attributesToRetrieve; + /** + * List of attributes to highlight + * @see https://www.algolia.com/doc/rest#param-attributesToHighlight + * @member {string} + */ + this.attributesToHighlight = params.attributesToHighlight; + /** + * Code to be embedded on the left part of the highlighted results + * @see https://www.algolia.com/doc/rest#param-highlightPreTag + * @member {string} + */ + this.highlightPreTag = params.highlightPreTag; + /** + * Code to be embedded on the right part of the highlighted results + * @see https://www.algolia.com/doc/rest#param-highlightPostTag + * @member {string} + */ + this.highlightPostTag = params.highlightPostTag; + /** + * List of attributes to snippet + * @see https://www.algolia.com/doc/rest#param-attributesToSnippet + * @member {string} + */ + this.attributesToSnippet = params.attributesToSnippet; + /** + * Enable the ranking informations in the response, set to 1 to activate + * @see https://www.algolia.com/doc/rest#param-getRankingInfo + * @member {number} + */ + this.getRankingInfo = params.getRankingInfo; + /** + * Remove duplicates based on the index setting attributeForDistinct + * @see https://www.algolia.com/doc/rest#param-distinct + * @member {boolean|number} + */ + this.distinct = params.distinct; + /** + * Center of the geo search. + * @see https://www.algolia.com/doc/rest#param-aroundLatLng + * @member {string} + */ + this.aroundLatLng = params.aroundLatLng; + /** + * Center of the search, retrieve from the user IP. + * @see https://www.algolia.com/doc/rest#param-aroundLatLngViaIP + * @member {boolean} + */ + this.aroundLatLngViaIP = params.aroundLatLngViaIP; + /** + * Radius of the geo search. + * @see https://www.algolia.com/doc/rest#param-aroundRadius + * @member {number} + */ + this.aroundRadius = params.aroundRadius; + /** + * Precision of the geo search. + * @see https://www.algolia.com/doc/rest#param-aroundPrecision + * @member {number} + */ + this.minimumAroundRadius = params.minimumAroundRadius; + /** + * Precision of the geo search. + * @see https://www.algolia.com/doc/rest#param-minimumAroundRadius + * @member {number} + */ + this.aroundPrecision = params.aroundPrecision; + /** + * Geo search inside a box. + * @see https://www.algolia.com/doc/rest#param-insideBoundingBox + * @member {string} + */ + this.insideBoundingBox = params.insideBoundingBox; + /** + * Geo search inside a polygon. + * @see https://www.algolia.com/doc/rest#param-insidePolygon + * @member {string} + */ + this.insidePolygon = params.insidePolygon; + /** + * Allows to specify an ellipsis character for the snippet when we truncate the text + * (added before and after if truncated). + * The default value is an empty string and we recommend to set it to "…" + * @see https://www.algolia.com/doc/rest#param-insidePolygon + * @member {string} + */ + this.snippetEllipsisText = params.snippetEllipsisText; + /** + * Allows to specify some attributes name on which exact won't be applied. + * Attributes are separated with a comma (for example "name,address" ), you can also use a + * JSON string array encoding (for example encodeURIComponent('["name","address"]') ). + * By default the list is empty. + * @see https://www.algolia.com/doc/rest#param-disableExactOnAttributes + * @member {string|string[]} + */ + this.disableExactOnAttributes = params.disableExactOnAttributes; + /** + * Applies 'exact' on single word queries if the word contains at least 3 characters + * and is not a stop word. + * Can take two values: true or false. + * By default, its set to false. + * @see https://www.algolia.com/doc/rest#param-enableExactOnSingleWordQuery + * @member {boolean} + */ + this.enableExactOnSingleWordQuery = params.enableExactOnSingleWordQuery; + // Undocumented parameters, still needed otherwise we fail + this.offset = params.offset; + this.length = params.length; -var utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js"); -var transformData = __webpack_require__(/*! ./transformData */ "./node_modules/axios/lib/core/transformData.js"); -var isCancel = __webpack_require__(/*! ../cancel/isCancel */ "./node_modules/axios/lib/cancel/isCancel.js"); -var defaults = __webpack_require__(/*! ../defaults */ "./node_modules/axios/lib/defaults.js"); + var self = this; + forOwn(params, function checkForUnknownParameter(paramValue, paramName) { + if (SearchParameters.PARAMETERS.indexOf(paramName) === -1) { + self[paramName] = paramValue; + } + }); +} /** - * Throws a `Cancel` if cancellation has been requested. + * List all the properties in SearchParameters and therefore all the known Algolia properties + * This doesn't contain any beta/hidden features. + * @private */ -function throwIfCancellationRequested(config) { - if (config.cancelToken) { - config.cancelToken.throwIfRequested(); - } -} +SearchParameters.PARAMETERS = keys(new SearchParameters()); /** - * Dispatch a request to the server using the configured adapter. - * - * @param {object} config The config that is to be used for the request - * @returns {Promise} The Promise to be fulfilled + * @private + * @param {object} partialState full or part of a state + * @return {object} a new object with the number keys as number */ -module.exports = function dispatchRequest(config) { - throwIfCancellationRequested(config); - - // Ensure headers exist - config.headers = config.headers || {}; +SearchParameters._parseNumbers = function(partialState) { + // Do not reparse numbers in SearchParameters, they ought to be parsed already + if (partialState instanceof SearchParameters) return partialState; + + var numbers = {}; + + var numberKeys = [ + 'aroundPrecision', + 'aroundRadius', + 'getRankingInfo', + 'minWordSizefor2Typos', + 'minWordSizefor1Typo', + 'page', + 'maxValuesPerFacet', + 'distinct', + 'minimumAroundRadius', + 'hitsPerPage', + 'minProximity' + ]; - // Transform request data - config.data = transformData( - config.data, - config.headers, - config.transformRequest - ); + forEach(numberKeys, function(k) { + var value = partialState[k]; + if (isString(value)) { + var parsedValue = parseFloat(value); + numbers[k] = isNaN(parsedValue) ? value : parsedValue; + } + }); - // Flatten headers - config.headers = utils.merge( - config.headers.common || {}, - config.headers[config.method] || {}, - config.headers - ); + // there's two formats of insideBoundingBox, we need to parse + // the one which is an array of float geo rectangles + if (Array.isArray(partialState.insideBoundingBox)) { + numbers.insideBoundingBox = partialState.insideBoundingBox.map(function(geoRect) { + return geoRect.map(function(value) { + return parseFloat(value); + }); + }); + } - utils.forEach( - ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'], - function cleanHeaderConfig(method) { - delete config.headers[method]; - } - ); + if (partialState.numericRefinements) { + var numericRefinements = {}; + forEach(partialState.numericRefinements, function(operators, attribute) { + numericRefinements[attribute] = {}; + forEach(operators, function(values, operator) { + var parsedValues = map(values, function(v) { + if (Array.isArray(v)) { + return map(v, function(vPrime) { + if (isString(vPrime)) { + return parseFloat(vPrime); + } + return vPrime; + }); + } else if (isString(v)) { + return parseFloat(v); + } + return v; + }); + numericRefinements[attribute][operator] = parsedValues; + }); + }); + numbers.numericRefinements = numericRefinements; + } - var adapter = config.adapter || defaults.adapter; + return merge({}, partialState, numbers); +}; - return adapter(config).then(function onAdapterResolution(response) { - throwIfCancellationRequested(config); +/** + * Factory for SearchParameters + * @param {object|SearchParameters} newParameters existing parameters or partial + * object for the properties of a new SearchParameters + * @return {SearchParameters} frozen instance of SearchParameters + */ +SearchParameters.make = function makeSearchParameters(newParameters) { + var instance = new SearchParameters(newParameters); - // Transform response data - response.data = transformData( - response.data, - response.headers, - config.transformResponse - ); + forEach(newParameters.hierarchicalFacets, function(facet) { + if (facet.rootPath) { + var currentRefinement = instance.getHierarchicalRefinement(facet.name); - return response; - }, function onAdapterRejection(reason) { - if (!isCancel(reason)) { - throwIfCancellationRequested(config); + if (currentRefinement.length > 0 && currentRefinement[0].indexOf(facet.rootPath) !== 0) { + instance = instance.clearRefinements(facet.name); + } - // Transform response data - if (reason && reason.response) { - reason.response.data = transformData( - reason.response.data, - reason.response.headers, - config.transformResponse - ); + // get it again in case it has been cleared + currentRefinement = instance.getHierarchicalRefinement(facet.name); + if (currentRefinement.length === 0) { + instance = instance.toggleHierarchicalFacetRefinement(facet.name, facet.rootPath); } } - - return Promise.reject(reason); }); -}; + return instance; +}; -/***/ }), +/** + * Validates the new parameters based on the previous state + * @param {SearchParameters} currentState the current state + * @param {object|SearchParameters} parameters the new parameters to set + * @return {Error|null} Error if the modification is invalid, null otherwise + */ +SearchParameters.validate = function(currentState, parameters) { + var params = parameters || {}; -/***/ "./node_modules/axios/lib/core/enhanceError.js": -/*!*****************************************************!*\ - !*** ./node_modules/axios/lib/core/enhanceError.js ***! - \*****************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { + if (currentState.tagFilters && params.tagRefinements && params.tagRefinements.length > 0) { + return new Error( + '[Tags] Cannot switch from the managed tag API to the advanced API. It is probably ' + + 'an error, if it is really what you want, you should first clear the tags with clearTags method.'); + } -"use strict"; + if (currentState.tagRefinements.length > 0 && params.tagFilters) { + return new Error( + '[Tags] Cannot switch from the advanced tag API to the managed API. It is probably ' + + 'an error, if it is not, you should first clear the tags with clearTags method.'); + } + if (currentState.numericFilters && params.numericRefinements && !isEmpty(params.numericRefinements)) { + return new Error( + "[Numeric filters] Can't switch from the advanced to the managed API. It" + + ' is probably an error, if this is really what you want, you have to first' + + ' clear the numeric filters.'); + } -/** - * Update an Error with the specified config, error code, and response. - * - * @param {Error} error The error to update. - * @param {Object} config The config. - * @param {string} [code] The error code (for example, 'ECONNABORTED'). - * @param {Object} [request] The request. - * @param {Object} [response] The response. - * @returns {Error} The error. - */ -module.exports = function enhanceError(error, config, code, request, response) { - error.config = config; - if (code) { - error.code = code; + if (!isEmpty(currentState.numericRefinements) && params.numericFilters) { + return new Error( + "[Numeric filters] Can't switch from the managed API to the advanced. It" + + ' is probably an error, if this is really what you want, you have to first' + + ' clear the numeric filters.'); } - error.request = request; - error.response = response; - error.isAxiosError = true; + return null; +}; - error.toJSON = function() { - return { - // Standard - message: this.message, - name: this.name, - // Microsoft - description: this.description, - number: this.number, - // Mozilla - fileName: this.fileName, - lineNumber: this.lineNumber, - columnNumber: this.columnNumber, - stack: this.stack, - // Axios - config: this.config, - code: this.code +SearchParameters.prototype = { + constructor: SearchParameters, + + /** + * Remove all refinements (disjunctive + conjunctive + excludes + numeric filters) + * @method + * @param {undefined|string|SearchParameters.clearCallback} [attribute] optional string or function + * - If not given, means to clear all the filters. + * - If `string`, means to clear all refinements for the `attribute` named filter. + * - If `function`, means to clear all the refinements that return truthy values. + * @return {SearchParameters} + */ + clearRefinements: function clearRefinements(attribute) { + var clear = RefinementList.clearRefinement; + var patch = { + numericRefinements: this._clearNumericRefinements(attribute), + facetsRefinements: clear(this.facetsRefinements, attribute, 'conjunctiveFacet'), + facetsExcludes: clear(this.facetsExcludes, attribute, 'exclude'), + disjunctiveFacetsRefinements: clear(this.disjunctiveFacetsRefinements, attribute, 'disjunctiveFacet'), + hierarchicalFacetsRefinements: clear(this.hierarchicalFacetsRefinements, attribute, 'hierarchicalFacet') }; - }; - return error; -}; + if (patch.numericRefinements === this.numericRefinements && + patch.facetsRefinements === this.facetsRefinements && + patch.facetsExcludes === this.facetsExcludes && + patch.disjunctiveFacetsRefinements === this.disjunctiveFacetsRefinements && + patch.hierarchicalFacetsRefinements === this.hierarchicalFacetsRefinements) { + return this; + } + return this.setQueryParameters(patch); + }, + /** + * Remove all the refined tags from the SearchParameters + * @method + * @return {SearchParameters} + */ + clearTags: function clearTags() { + if (this.tagFilters === undefined && this.tagRefinements.length === 0) return this; + return this.setQueryParameters({ + tagFilters: undefined, + tagRefinements: [] + }); + }, + /** + * Set the index. + * @method + * @param {string} index the index name + * @return {SearchParameters} + */ + setIndex: function setIndex(index) { + if (index === this.index) return this; -/***/ }), + return this.setQueryParameters({ + index: index + }); + }, + /** + * Query setter + * @method + * @param {string} newQuery value for the new query + * @return {SearchParameters} + */ + setQuery: function setQuery(newQuery) { + if (newQuery === this.query) return this; -/***/ "./node_modules/axios/lib/core/mergeConfig.js": -/*!****************************************************!*\ - !*** ./node_modules/axios/lib/core/mergeConfig.js ***! - \****************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { + return this.setQueryParameters({ + query: newQuery + }); + }, + /** + * Page setter + * @method + * @param {number} newPage new page number + * @return {SearchParameters} + */ + setPage: function setPage(newPage) { + if (newPage === this.page) return this; -"use strict"; + return this.setQueryParameters({ + page: newPage + }); + }, + /** + * Facets setter + * The facets are the simple facets, used for conjunctive (and) faceting. + * @method + * @param {string[]} facets all the attributes of the algolia records used for conjunctive faceting + * @return {SearchParameters} + */ + setFacets: function setFacets(facets) { + return this.setQueryParameters({ + facets: facets + }); + }, + /** + * Disjunctive facets setter + * Change the list of disjunctive (or) facets the helper chan handle. + * @method + * @param {string[]} facets all the attributes of the algolia records used for disjunctive faceting + * @return {SearchParameters} + */ + setDisjunctiveFacets: function setDisjunctiveFacets(facets) { + return this.setQueryParameters({ + disjunctiveFacets: facets + }); + }, + /** + * HitsPerPage setter + * Hits per page represents the number of hits retrieved for this query + * @method + * @param {number} n number of hits retrieved per page of results + * @return {SearchParameters} + */ + setHitsPerPage: function setHitsPerPage(n) { + if (this.hitsPerPage === n) return this; + return this.setQueryParameters({ + hitsPerPage: n + }); + }, + /** + * typoTolerance setter + * Set the value of typoTolerance + * @method + * @param {string} typoTolerance new value of typoTolerance ("true", "false", "min" or "strict") + * @return {SearchParameters} + */ + setTypoTolerance: function setTypoTolerance(typoTolerance) { + if (this.typoTolerance === typoTolerance) return this; -var utils = __webpack_require__(/*! ../utils */ "./node_modules/axios/lib/utils.js"); + return this.setQueryParameters({ + typoTolerance: typoTolerance + }); + }, + /** + * Add a numeric filter for a given attribute + * When value is an array, they are combined with OR + * When value is a single value, it will combined with AND + * @method + * @param {string} attribute attribute to set the filter on + * @param {string} operator operator of the filter (possible values: =, >, >=, <, <=, !=) + * @param {number | number[]} value value of the filter + * @return {SearchParameters} + * @example + * // for price = 50 or 40 + * searchparameter.addNumericRefinement('price', '=', [50, 40]); + * @example + * // for size = 38 and 40 + * searchparameter.addNumericRefinement('size', '=', 38); + * searchparameter.addNumericRefinement('size', '=', 40); + */ + addNumericRefinement: function(attribute, operator, v) { + var value = valToNumber(v); -/** - * Config-specific merge-function which creates a new config-object - * by merging two configuration objects together. - * - * @param {Object} config1 - * @param {Object} config2 - * @returns {Object} New object resulting from merging config2 to config1 - */ -module.exports = function mergeConfig(config1, config2) { - // eslint-disable-next-line no-param-reassign - config2 = config2 || {}; - var config = {}; + if (this.isNumericRefined(attribute, operator, value)) return this; - var valueFromConfig2Keys = ['url', 'method', 'params', 'data']; - var mergeDeepPropertiesKeys = ['headers', 'auth', 'proxy']; - var defaultToConfig2Keys = [ - 'baseURL', 'url', 'transformRequest', 'transformResponse', 'paramsSerializer', - 'timeout', 'withCredentials', 'adapter', 'responseType', 'xsrfCookieName', - 'xsrfHeaderName', 'onUploadProgress', 'onDownloadProgress', - 'maxContentLength', 'validateStatus', 'maxRedirects', 'httpAgent', - 'httpsAgent', 'cancelToken', 'socketPath' - ]; + var mod = merge({}, this.numericRefinements); - utils.forEach(valueFromConfig2Keys, function valueFromConfig2(prop) { - if (typeof config2[prop] !== 'undefined') { - config[prop] = config2[prop]; - } - }); + mod[attribute] = merge({}, mod[attribute]); - utils.forEach(mergeDeepPropertiesKeys, function mergeDeepProperties(prop) { - if (utils.isObject(config2[prop])) { - config[prop] = utils.deepMerge(config1[prop], config2[prop]); - } else if (typeof config2[prop] !== 'undefined') { - config[prop] = config2[prop]; - } else if (utils.isObject(config1[prop])) { - config[prop] = utils.deepMerge(config1[prop]); - } else if (typeof config1[prop] !== 'undefined') { - config[prop] = config1[prop]; + if (mod[attribute][operator]) { + // Array copy + mod[attribute][operator] = mod[attribute][operator].slice(); + // Add the element. Concat can't be used here because value can be an array. + mod[attribute][operator].push(value); + } else { + mod[attribute][operator] = [value]; } - }); - utils.forEach(defaultToConfig2Keys, function defaultToConfig2(prop) { - if (typeof config2[prop] !== 'undefined') { - config[prop] = config2[prop]; - } else if (typeof config1[prop] !== 'undefined') { - config[prop] = config1[prop]; + return this.setQueryParameters({ + numericRefinements: mod + }); + }, + /** + * Get the list of conjunctive refinements for a single facet + * @param {string} facetName name of the attribute used for faceting + * @return {string[]} list of refinements + */ + getConjunctiveRefinements: function(facetName) { + if (!this.isConjunctiveFacet(facetName)) { + throw new Error(facetName + ' is not defined in the facets attribute of the helper configuration'); } - }); + return this.facetsRefinements[facetName] || []; + }, + /** + * Get the list of disjunctive refinements for a single facet + * @param {string} facetName name of the attribute used for faceting + * @return {string[]} list of refinements + */ + getDisjunctiveRefinements: function(facetName) { + if (!this.isDisjunctiveFacet(facetName)) { + throw new Error( + facetName + ' is not defined in the disjunctiveFacets attribute of the helper configuration' + ); + } + return this.disjunctiveFacetsRefinements[facetName] || []; + }, + /** + * Get the list of hierarchical refinements for a single facet + * @param {string} facetName name of the attribute used for faceting + * @return {string[]} list of refinements + */ + getHierarchicalRefinement: function(facetName) { + // we send an array but we currently do not support multiple + // hierarchicalRefinements for a hierarchicalFacet + return this.hierarchicalFacetsRefinements[facetName] || []; + }, + /** + * Get the list of exclude refinements for a single facet + * @param {string} facetName name of the attribute used for faceting + * @return {string[]} list of refinements + */ + getExcludeRefinements: function(facetName) { + if (!this.isConjunctiveFacet(facetName)) { + throw new Error(facetName + ' is not defined in the facets attribute of the helper configuration'); + } + return this.facetsExcludes[facetName] || []; + }, - var axiosKeys = valueFromConfig2Keys - .concat(mergeDeepPropertiesKeys) - .concat(defaultToConfig2Keys); + /** + * Remove all the numeric filter for a given (attribute, operator) + * @method + * @param {string} attribute attribute to set the filter on + * @param {string} [operator] operator of the filter (possible values: =, >, >=, <, <=, !=) + * @param {number} [number] the value to be removed + * @return {SearchParameters} + */ + removeNumericRefinement: function(attribute, operator, paramValue) { + if (paramValue !== undefined) { + var paramValueAsNumber = valToNumber(paramValue); + if (!this.isNumericRefined(attribute, operator, paramValueAsNumber)) return this; + return this.setQueryParameters({ + numericRefinements: this._clearNumericRefinements(function(value, key) { + return key === attribute && value.op === operator && isEqual(value.val, paramValueAsNumber); + }) + }); + } else if (operator !== undefined) { + if (!this.isNumericRefined(attribute, operator)) return this; + return this.setQueryParameters({ + numericRefinements: this._clearNumericRefinements(function(value, key) { + return key === attribute && value.op === operator; + }) + }); + } - var otherKeys = Object - .keys(config2) - .filter(function filterAxiosKeys(key) { - return axiosKeys.indexOf(key) === -1; + if (!this.isNumericRefined(attribute)) return this; + return this.setQueryParameters({ + numericRefinements: this._clearNumericRefinements(function(value, key) { + return key === attribute; + }) }); + }, + /** + * Get the list of numeric refinements for a single facet + * @param {string} facetName name of the attribute used for faceting + * @return {SearchParameters.OperatorList[]} list of refinements + */ + getNumericRefinements: function(facetName) { + return this.numericRefinements[facetName] || {}; + }, + /** + * Return the current refinement for the (attribute, operator) + * @param {string} attribute attribute in the record + * @param {string} operator operator applied on the refined values + * @return {Array.} refined values + */ + getNumericRefinement: function(attribute, operator) { + return this.numericRefinements[attribute] && this.numericRefinements[attribute][operator]; + }, + /** + * Clear numeric filters. + * @method + * @private + * @param {string|SearchParameters.clearCallback} [attribute] optional string or function + * - If not given, means to clear all the filters. + * - If `string`, means to clear all refinements for the `attribute` named filter. + * - If `function`, means to clear all the refinements that return truthy values. + * @return {Object.} + */ + _clearNumericRefinements: function _clearNumericRefinements(attribute) { + if (isUndefined(attribute)) { + if (isEmpty(this.numericRefinements)) return this.numericRefinements; + return {}; + } else if (isString(attribute)) { + if (isEmpty(this.numericRefinements[attribute])) return this.numericRefinements; + return omit(this.numericRefinements, attribute); + } else if (isFunction(attribute)) { + var hasChanged = false; + var newNumericRefinements = reduce(this.numericRefinements, function(memo, operators, key) { + var operatorList = {}; + + forEach(operators, function(values, operator) { + var outValues = []; + forEach(values, function(value) { + var predicateResult = attribute({val: value, op: operator}, key, 'numeric'); + if (!predicateResult) outValues.push(value); + }); + if (!isEmpty(outValues)) { + if (outValues.length !== values.length) hasChanged = true; + operatorList[operator] = outValues; + } + else hasChanged = true; + }); - utils.forEach(otherKeys, function otherKeysDefaultToConfig2(prop) { - if (typeof config2[prop] !== 'undefined') { - config[prop] = config2[prop]; - } else if (typeof config1[prop] !== 'undefined') { - config[prop] = config1[prop]; + if (!isEmpty(operatorList)) memo[key] = operatorList; + + return memo; + }, {}); + + if (hasChanged) return newNumericRefinements; + return this.numericRefinements; + } + }, + /** + * Add a facet to the facets attribute of the helper configuration, if it + * isn't already present. + * @method + * @param {string} facet facet name to add + * @return {SearchParameters} + */ + addFacet: function addFacet(facet) { + if (this.isConjunctiveFacet(facet)) { + return this; } - }); - return config; -}; + return this.setQueryParameters({ + facets: this.facets.concat([facet]) + }); + }, + /** + * Add a disjunctive facet to the disjunctiveFacets attribute of the helper + * configuration, if it isn't already present. + * @method + * @param {string} facet disjunctive facet name to add + * @return {SearchParameters} + */ + addDisjunctiveFacet: function addDisjunctiveFacet(facet) { + if (this.isDisjunctiveFacet(facet)) { + return this; + } + return this.setQueryParameters({ + disjunctiveFacets: this.disjunctiveFacets.concat([facet]) + }); + }, + /** + * Add a hierarchical facet to the hierarchicalFacets attribute of the helper + * configuration. + * @method + * @param {object} hierarchicalFacet hierarchical facet to add + * @return {SearchParameters} + * @throws will throw an error if a hierarchical facet with the same name was already declared + */ + addHierarchicalFacet: function addHierarchicalFacet(hierarchicalFacet) { + if (this.isHierarchicalFacet(hierarchicalFacet.name)) { + throw new Error( + 'Cannot declare two hierarchical facets with the same name: `' + hierarchicalFacet.name + '`'); + } -/***/ }), + return this.setQueryParameters({ + hierarchicalFacets: this.hierarchicalFacets.concat([hierarchicalFacet]) + }); + }, + /** + * Add a refinement on a "normal" facet + * @method + * @param {string} facet attribute to apply the faceting on + * @param {string} value value of the attribute (will be converted to string) + * @return {SearchParameters} + */ + addFacetRefinement: function addFacetRefinement(facet, value) { + if (!this.isConjunctiveFacet(facet)) { + throw new Error(facet + ' is not defined in the facets attribute of the helper configuration'); + } + if (RefinementList.isRefined(this.facetsRefinements, facet, value)) return this; -/***/ "./node_modules/axios/lib/core/settle.js": -/*!***********************************************!*\ - !*** ./node_modules/axios/lib/core/settle.js ***! - \***********************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { + return this.setQueryParameters({ + facetsRefinements: RefinementList.addRefinement(this.facetsRefinements, facet, value) + }); + }, + /** + * Exclude a value from a "normal" facet + * @method + * @param {string} facet attribute to apply the exclusion on + * @param {string} value value of the attribute (will be converted to string) + * @return {SearchParameters} + */ + addExcludeRefinement: function addExcludeRefinement(facet, value) { + if (!this.isConjunctiveFacet(facet)) { + throw new Error(facet + ' is not defined in the facets attribute of the helper configuration'); + } + if (RefinementList.isRefined(this.facetsExcludes, facet, value)) return this; -"use strict"; + return this.setQueryParameters({ + facetsExcludes: RefinementList.addRefinement(this.facetsExcludes, facet, value) + }); + }, + /** + * Adds a refinement on a disjunctive facet. + * @method + * @param {string} facet attribute to apply the faceting on + * @param {string} value value of the attribute (will be converted to string) + * @return {SearchParameters} + */ + addDisjunctiveFacetRefinement: function addDisjunctiveFacetRefinement(facet, value) { + if (!this.isDisjunctiveFacet(facet)) { + throw new Error( + facet + ' is not defined in the disjunctiveFacets attribute of the helper configuration'); + } + if (RefinementList.isRefined(this.disjunctiveFacetsRefinements, facet, value)) return this; -var createError = __webpack_require__(/*! ./createError */ "./node_modules/axios/lib/core/createError.js"); + return this.setQueryParameters({ + disjunctiveFacetsRefinements: RefinementList.addRefinement( + this.disjunctiveFacetsRefinements, facet, value) + }); + }, + /** + * addTagRefinement adds a tag to the list used to filter the results + * @param {string} tag tag to be added + * @return {SearchParameters} + */ + addTagRefinement: function addTagRefinement(tag) { + if (this.isTagRefined(tag)) return this; -/** - * Resolve or reject a Promise based on response status. - * - * @param {Function} resolve A function that resolves the promise. - * @param {Function} reject A function that rejects the promise. - * @param {object} response The response. - */ -module.exports = function settle(resolve, reject, response) { - var validateStatus = response.config.validateStatus; - if (!validateStatus || validateStatus(response.status)) { - resolve(response); - } else { - reject(createError( - 'Request failed with status code ' + response.status, - response.config, - null, - response.request, - response - )); - } -}; + var modification = { + tagRefinements: this.tagRefinements.concat(tag) + }; + return this.setQueryParameters(modification); + }, + /** + * Remove a facet from the facets attribute of the helper configuration, if it + * is present. + * @method + * @param {string} facet facet name to remove + * @return {SearchParameters} + */ + removeFacet: function removeFacet(facet) { + if (!this.isConjunctiveFacet(facet)) { + return this; + } -/***/ }), + return this.clearRefinements(facet).setQueryParameters({ + facets: filter(this.facets, function(f) { + return f !== facet; + }) + }); + }, + /** + * Remove a disjunctive facet from the disjunctiveFacets attribute of the + * helper configuration, if it is present. + * @method + * @param {string} facet disjunctive facet name to remove + * @return {SearchParameters} + */ + removeDisjunctiveFacet: function removeDisjunctiveFacet(facet) { + if (!this.isDisjunctiveFacet(facet)) { + return this; + } -/***/ "./node_modules/axios/lib/core/transformData.js": -/*!******************************************************!*\ - !*** ./node_modules/axios/lib/core/transformData.js ***! - \******************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { + return this.clearRefinements(facet).setQueryParameters({ + disjunctiveFacets: filter(this.disjunctiveFacets, function(f) { + return f !== facet; + }) + }); + }, + /** + * Remove a hierarchical facet from the hierarchicalFacets attribute of the + * helper configuration, if it is present. + * @method + * @param {string} facet hierarchical facet name to remove + * @return {SearchParameters} + */ + removeHierarchicalFacet: function removeHierarchicalFacet(facet) { + if (!this.isHierarchicalFacet(facet)) { + return this; + } -"use strict"; + return this.clearRefinements(facet).setQueryParameters({ + hierarchicalFacets: filter(this.hierarchicalFacets, function(f) { + return f.name !== facet; + }) + }); + }, + /** + * Remove a refinement set on facet. If a value is provided, it will clear the + * refinement for the given value, otherwise it will clear all the refinement + * values for the faceted attribute. + * @method + * @param {string} facet name of the attribute used for faceting + * @param {string} [value] value used to filter + * @return {SearchParameters} + */ + removeFacetRefinement: function removeFacetRefinement(facet, value) { + if (!this.isConjunctiveFacet(facet)) { + throw new Error(facet + ' is not defined in the facets attribute of the helper configuration'); + } + if (!RefinementList.isRefined(this.facetsRefinements, facet, value)) return this; + return this.setQueryParameters({ + facetsRefinements: RefinementList.removeRefinement(this.facetsRefinements, facet, value) + }); + }, + /** + * Remove a negative refinement on a facet + * @method + * @param {string} facet name of the attribute used for faceting + * @param {string} value value used to filter + * @return {SearchParameters} + */ + removeExcludeRefinement: function removeExcludeRefinement(facet, value) { + if (!this.isConjunctiveFacet(facet)) { + throw new Error(facet + ' is not defined in the facets attribute of the helper configuration'); + } + if (!RefinementList.isRefined(this.facetsExcludes, facet, value)) return this; -var utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js"); + return this.setQueryParameters({ + facetsExcludes: RefinementList.removeRefinement(this.facetsExcludes, facet, value) + }); + }, + /** + * Remove a refinement on a disjunctive facet + * @method + * @param {string} facet name of the attribute used for faceting + * @param {string} value value used to filter + * @return {SearchParameters} + */ + removeDisjunctiveFacetRefinement: function removeDisjunctiveFacetRefinement(facet, value) { + if (!this.isDisjunctiveFacet(facet)) { + throw new Error( + facet + ' is not defined in the disjunctiveFacets attribute of the helper configuration'); + } + if (!RefinementList.isRefined(this.disjunctiveFacetsRefinements, facet, value)) return this; -/** - * Transform the data for a request or a response - * - * @param {Object|String} data The data to be transformed - * @param {Array} headers The headers for the request or response - * @param {Array|Function} fns A single function or Array of functions - * @returns {*} The resulting transformed data - */ -module.exports = function transformData(data, headers, fns) { - /*eslint no-param-reassign:0*/ - utils.forEach(fns, function transform(fn) { - data = fn(data, headers); - }); + return this.setQueryParameters({ + disjunctiveFacetsRefinements: RefinementList.removeRefinement( + this.disjunctiveFacetsRefinements, facet, value) + }); + }, + /** + * Remove a tag from the list of tag refinements + * @method + * @param {string} tag the tag to remove + * @return {SearchParameters} + */ + removeTagRefinement: function removeTagRefinement(tag) { + if (!this.isTagRefined(tag)) return this; - return data; -}; + var modification = { + tagRefinements: filter(this.tagRefinements, function(t) { return t !== tag; }) + }; + return this.setQueryParameters(modification); + }, + /** + * Generic toggle refinement method to use with facet, disjunctive facets + * and hierarchical facets + * @param {string} facet the facet to refine + * @param {string} value the associated value + * @return {SearchParameters} + * @throws will throw an error if the facet is not declared in the settings of the helper + * @deprecated since version 2.19.0, see {@link SearchParameters#toggleFacetRefinement} + */ + toggleRefinement: function toggleRefinement(facet, value) { + return this.toggleFacetRefinement(facet, value); + }, + /** + * Generic toggle refinement method to use with facet, disjunctive facets + * and hierarchical facets + * @param {string} facet the facet to refine + * @param {string} value the associated value + * @return {SearchParameters} + * @throws will throw an error if the facet is not declared in the settings of the helper + */ + toggleFacetRefinement: function toggleFacetRefinement(facet, value) { + if (this.isHierarchicalFacet(facet)) { + return this.toggleHierarchicalFacetRefinement(facet, value); + } else if (this.isConjunctiveFacet(facet)) { + return this.toggleConjunctiveFacetRefinement(facet, value); + } else if (this.isDisjunctiveFacet(facet)) { + return this.toggleDisjunctiveFacetRefinement(facet, value); + } -/***/ }), + throw new Error('Cannot refine the undeclared facet ' + facet + + '; it should be added to the helper options facets, disjunctiveFacets or hierarchicalFacets'); + }, + /** + * Switch the refinement applied over a facet/value + * @method + * @param {string} facet name of the attribute used for faceting + * @param {value} value value used for filtering + * @return {SearchParameters} + */ + toggleConjunctiveFacetRefinement: function toggleConjunctiveFacetRefinement(facet, value) { + if (!this.isConjunctiveFacet(facet)) { + throw new Error(facet + ' is not defined in the facets attribute of the helper configuration'); + } -/***/ "./node_modules/axios/lib/defaults.js": -/*!********************************************!*\ - !*** ./node_modules/axios/lib/defaults.js ***! - \********************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { + return this.setQueryParameters({ + facetsRefinements: RefinementList.toggleRefinement(this.facetsRefinements, facet, value) + }); + }, + /** + * Switch the refinement applied over a facet/value + * @method + * @param {string} facet name of the attribute used for faceting + * @param {value} value value used for filtering + * @return {SearchParameters} + */ + toggleExcludeFacetRefinement: function toggleExcludeFacetRefinement(facet, value) { + if (!this.isConjunctiveFacet(facet)) { + throw new Error(facet + ' is not defined in the facets attribute of the helper configuration'); + } -"use strict"; -/* WEBPACK VAR INJECTION */(function(process) { + return this.setQueryParameters({ + facetsExcludes: RefinementList.toggleRefinement(this.facetsExcludes, facet, value) + }); + }, + /** + * Switch the refinement applied over a facet/value + * @method + * @param {string} facet name of the attribute used for faceting + * @param {value} value value used for filtering + * @return {SearchParameters} + */ + toggleDisjunctiveFacetRefinement: function toggleDisjunctiveFacetRefinement(facet, value) { + if (!this.isDisjunctiveFacet(facet)) { + throw new Error( + facet + ' is not defined in the disjunctiveFacets attribute of the helper configuration'); + } -var utils = __webpack_require__(/*! ./utils */ "./node_modules/axios/lib/utils.js"); -var normalizeHeaderName = __webpack_require__(/*! ./helpers/normalizeHeaderName */ "./node_modules/axios/lib/helpers/normalizeHeaderName.js"); + return this.setQueryParameters({ + disjunctiveFacetsRefinements: RefinementList.toggleRefinement( + this.disjunctiveFacetsRefinements, facet, value) + }); + }, + /** + * Switch the refinement applied over a facet/value + * @method + * @param {string} facet name of the attribute used for faceting + * @param {value} value value used for filtering + * @return {SearchParameters} + */ + toggleHierarchicalFacetRefinement: function toggleHierarchicalFacetRefinement(facet, value) { + if (!this.isHierarchicalFacet(facet)) { + throw new Error( + facet + ' is not defined in the hierarchicalFacets attribute of the helper configuration'); + } -var DEFAULT_CONTENT_TYPE = { - 'Content-Type': 'application/x-www-form-urlencoded' -}; + var separator = this._getHierarchicalFacetSeparator(this.getHierarchicalFacetByName(facet)); -function setContentTypeIfUnset(headers, value) { - if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) { - headers['Content-Type'] = value; - } -} + var mod = {}; -function getDefaultAdapter() { - var adapter; - if (typeof XMLHttpRequest !== 'undefined') { - // For browsers use XHR adapter - adapter = __webpack_require__(/*! ./adapters/xhr */ "./node_modules/axios/lib/adapters/xhr.js"); - } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') { - // For node use HTTP adapter - adapter = __webpack_require__(/*! ./adapters/http */ "./node_modules/axios/lib/adapters/xhr.js"); - } - return adapter; -} + var upOneOrMultipleLevel = this.hierarchicalFacetsRefinements[facet] !== undefined && + this.hierarchicalFacetsRefinements[facet].length > 0 && ( + // remove current refinement: + // refinement was 'beer > IPA', call is toggleRefine('beer > IPA'), refinement should be `beer` + this.hierarchicalFacetsRefinements[facet][0] === value || + // remove a parent refinement of the current refinement: + // - refinement was 'beer > IPA > Flying dog' + // - call is toggleRefine('beer > IPA') + // - refinement should be `beer` + this.hierarchicalFacetsRefinements[facet][0].indexOf(value + separator) === 0 + ); -var defaults = { - adapter: getDefaultAdapter(), + if (upOneOrMultipleLevel) { + if (value.indexOf(separator) === -1) { + // go back to root level + mod[facet] = []; + } else { + mod[facet] = [value.slice(0, value.lastIndexOf(separator))]; + } + } else { + mod[facet] = [value]; + } - transformRequest: [function transformRequest(data, headers) { - normalizeHeaderName(headers, 'Accept'); - normalizeHeaderName(headers, 'Content-Type'); - if (utils.isFormData(data) || - utils.isArrayBuffer(data) || - utils.isBuffer(data) || - utils.isStream(data) || - utils.isFile(data) || - utils.isBlob(data) - ) { - return data; + return this.setQueryParameters({ + hierarchicalFacetsRefinements: defaults({}, mod, this.hierarchicalFacetsRefinements) + }); + }, + + /** + * Adds a refinement on a hierarchical facet. + * @param {string} facet the facet name + * @param {string} path the hierarchical facet path + * @return {SearchParameter} the new state + * @throws Error if the facet is not defined or if the facet is refined + */ + addHierarchicalFacetRefinement: function(facet, path) { + if (this.isHierarchicalFacetRefined(facet)) { + throw new Error(facet + ' is already refined.'); + } + var mod = {}; + mod[facet] = [path]; + return this.setQueryParameters({ + hierarchicalFacetsRefinements: defaults({}, mod, this.hierarchicalFacetsRefinements) + }); + }, + + /** + * Removes the refinement set on a hierarchical facet. + * @param {string} facet the facet name + * @return {SearchParameter} the new state + * @throws Error if the facet is not defined or if the facet is not refined + */ + removeHierarchicalFacetRefinement: function(facet) { + if (!this.isHierarchicalFacetRefined(facet)) { + throw new Error(facet + ' is not refined.'); + } + var mod = {}; + mod[facet] = []; + return this.setQueryParameters({ + hierarchicalFacetsRefinements: defaults({}, mod, this.hierarchicalFacetsRefinements) + }); + }, + /** + * Switch the tag refinement + * @method + * @param {string} tag the tag to remove or add + * @return {SearchParameters} + */ + toggleTagRefinement: function toggleTagRefinement(tag) { + if (this.isTagRefined(tag)) { + return this.removeTagRefinement(tag); } - if (utils.isArrayBufferView(data)) { - return data.buffer; + + return this.addTagRefinement(tag); + }, + /** + * Test if the facet name is from one of the disjunctive facets + * @method + * @param {string} facet facet name to test + * @return {boolean} + */ + isDisjunctiveFacet: function(facet) { + return indexOf(this.disjunctiveFacets, facet) > -1; + }, + /** + * Test if the facet name is from one of the hierarchical facets + * @method + * @param {string} facetName facet name to test + * @return {boolean} + */ + isHierarchicalFacet: function(facetName) { + return this.getHierarchicalFacetByName(facetName) !== undefined; + }, + /** + * Test if the facet name is from one of the conjunctive/normal facets + * @method + * @param {string} facet facet name to test + * @return {boolean} + */ + isConjunctiveFacet: function(facet) { + return indexOf(this.facets, facet) > -1; + }, + /** + * Returns true if the facet is refined, either for a specific value or in + * general. + * @method + * @param {string} facet name of the attribute for used for faceting + * @param {string} value, optional value. If passed will test that this value + * is filtering the given facet. + * @return {boolean} returns true if refined + */ + isFacetRefined: function isFacetRefined(facet, value) { + if (!this.isConjunctiveFacet(facet)) { + throw new Error(facet + ' is not defined in the facets attribute of the helper configuration'); } - if (utils.isURLSearchParams(data)) { - setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8'); - return data.toString(); + return RefinementList.isRefined(this.facetsRefinements, facet, value); + }, + /** + * Returns true if the facet contains exclusions or if a specific value is + * excluded. + * + * @method + * @param {string} facet name of the attribute for used for faceting + * @param {string} [value] optional value. If passed will test that this value + * is filtering the given facet. + * @return {boolean} returns true if refined + */ + isExcludeRefined: function isExcludeRefined(facet, value) { + if (!this.isConjunctiveFacet(facet)) { + throw new Error(facet + ' is not defined in the facets attribute of the helper configuration'); } - if (utils.isObject(data)) { - setContentTypeIfUnset(headers, 'application/json;charset=utf-8'); - return JSON.stringify(data); + return RefinementList.isRefined(this.facetsExcludes, facet, value); + }, + /** + * Returns true if the facet contains a refinement, or if a value passed is a + * refinement for the facet. + * @method + * @param {string} facet name of the attribute for used for faceting + * @param {string} value optional, will test if the value is used for refinement + * if there is one, otherwise will test if the facet contains any refinement + * @return {boolean} + */ + isDisjunctiveFacetRefined: function isDisjunctiveFacetRefined(facet, value) { + if (!this.isDisjunctiveFacet(facet)) { + throw new Error( + facet + ' is not defined in the disjunctiveFacets attribute of the helper configuration'); + } + return RefinementList.isRefined(this.disjunctiveFacetsRefinements, facet, value); + }, + /** + * Returns true if the facet contains a refinement, or if a value passed is a + * refinement for the facet. + * @method + * @param {string} facet name of the attribute for used for faceting + * @param {string} value optional, will test if the value is used for refinement + * if there is one, otherwise will test if the facet contains any refinement + * @return {boolean} + */ + isHierarchicalFacetRefined: function isHierarchicalFacetRefined(facet, value) { + if (!this.isHierarchicalFacet(facet)) { + throw new Error( + facet + ' is not defined in the hierarchicalFacets attribute of the helper configuration'); } - return data; - }], - transformResponse: [function transformResponse(data) { - /*eslint no-param-reassign:0*/ - if (typeof data === 'string') { - try { - data = JSON.parse(data); - } catch (e) { /* Ignore */ } + var refinements = this.getHierarchicalRefinement(facet); + + if (!value) { + return refinements.length > 0; } - return data; - }], + return indexOf(refinements, value) !== -1; + }, /** - * A timeout in milliseconds to abort a request. If set to 0 (default) a - * timeout is not created. + * Test if the triple (attribute, operator, value) is already refined. + * If only the attribute and the operator are provided, it tests if the + * contains any refinement value. + * @method + * @param {string} attribute attribute for which the refinement is applied + * @param {string} [operator] operator of the refinement + * @param {string} [value] value of the refinement + * @return {boolean} true if it is refined */ - timeout: 0, + isNumericRefined: function isNumericRefined(attribute, operator, value) { + if (isUndefined(value) && isUndefined(operator)) { + return !!this.numericRefinements[attribute]; + } - xsrfCookieName: 'XSRF-TOKEN', - xsrfHeaderName: 'X-XSRF-TOKEN', + var isOperatorDefined = this.numericRefinements[attribute] && + !isUndefined(this.numericRefinements[attribute][operator]); - maxContentLength: -1, + if (isUndefined(value) || !isOperatorDefined) { + return isOperatorDefined; + } - validateStatus: function validateStatus(status) { - return status >= 200 && status < 300; - } -}; + var parsedValue = valToNumber(value); + var isAttributeValueDefined = !isUndefined( + findArray(this.numericRefinements[attribute][operator], parsedValue) + ); -defaults.headers = { - common: { - 'Accept': 'application/json, text/plain, */*' - } -}; + return isOperatorDefined && isAttributeValueDefined; + }, + /** + * Returns true if the tag refined, false otherwise + * @method + * @param {string} tag the tag to check + * @return {boolean} + */ + isTagRefined: function isTagRefined(tag) { + return indexOf(this.tagRefinements, tag) !== -1; + }, + /** + * Returns the list of all disjunctive facets refined + * @method + * @param {string} facet name of the attribute used for faceting + * @param {value} value value used for filtering + * @return {string[]} + */ + getRefinedDisjunctiveFacets: function getRefinedDisjunctiveFacets() { + // attributes used for numeric filter can also be disjunctive + var disjunctiveNumericRefinedFacets = intersection( + keys(this.numericRefinements), + this.disjunctiveFacets + ); -utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) { - defaults.headers[method] = {}; -}); + return keys(this.disjunctiveFacetsRefinements) + .concat(disjunctiveNumericRefinedFacets) + .concat(this.getRefinedHierarchicalFacets()); + }, + /** + * Returns the list of all disjunctive facets refined + * @method + * @param {string} facet name of the attribute used for faceting + * @param {value} value value used for filtering + * @return {string[]} + */ + getRefinedHierarchicalFacets: function getRefinedHierarchicalFacets() { + return intersection( + // enforce the order between the two arrays, + // so that refinement name index === hierarchical facet index + map(this.hierarchicalFacets, 'name'), + keys(this.hierarchicalFacetsRefinements) + ); + }, + /** + * Returned the list of all disjunctive facets not refined + * @method + * @return {string[]} + */ + getUnrefinedDisjunctiveFacets: function() { + var refinedFacets = this.getRefinedDisjunctiveFacets(); -utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { - defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE); -}); + return filter(this.disjunctiveFacets, function(f) { + return indexOf(refinedFacets, f) === -1; + }); + }, -module.exports = defaults; + managedParameters: [ + 'index', + 'facets', 'disjunctiveFacets', 'facetsRefinements', + 'facetsExcludes', 'disjunctiveFacetsRefinements', + 'numericRefinements', 'tagRefinements', 'hierarchicalFacets', 'hierarchicalFacetsRefinements' + ], + getQueryParams: function getQueryParams() { + var managedParameters = this.managedParameters; -/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../process/browser.js */ "./node_modules/process/browser.js"))) + var queryParams = {}; -/***/ }), + forOwn(this, function(paramValue, paramName) { + if (indexOf(managedParameters, paramName) === -1 && paramValue !== undefined) { + queryParams[paramName] = paramValue; + } + }); -/***/ "./node_modules/axios/lib/helpers/bind.js": -/*!************************************************!*\ - !*** ./node_modules/axios/lib/helpers/bind.js ***! - \************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { + return queryParams; + }, + /** + * Let the user retrieve any parameter value from the SearchParameters + * @param {string} paramName name of the parameter + * @return {any} the value of the parameter + */ + getQueryParameter: function getQueryParameter(paramName) { + if (!this.hasOwnProperty(paramName)) { + throw new Error( + "Parameter '" + paramName + "' is not an attribute of SearchParameters " + + '(http://algolia.github.io/algoliasearch-helper-js/docs/SearchParameters.html)'); + } -"use strict"; + return this[paramName]; + }, + /** + * Let the user set a specific value for a given parameter. Will return the + * same instance if the parameter is invalid or if the value is the same as the + * previous one. + * @method + * @param {string} parameter the parameter name + * @param {any} value the value to be set, must be compliant with the definition + * of the attribute on the object + * @return {SearchParameters} the updated state + */ + setQueryParameter: function setParameter(parameter, value) { + if (this[parameter] === value) return this; + var modification = {}; -module.exports = function bind(fn, thisArg) { - return function wrap() { - var args = new Array(arguments.length); - for (var i = 0; i < args.length; i++) { - args[i] = arguments[i]; - } - return fn.apply(thisArg, args); - }; -}; + modification[parameter] = value; + return this.setQueryParameters(modification); + }, + /** + * Let the user set any of the parameters with a plain object. + * @method + * @param {object} params all the keys and the values to be updated + * @return {SearchParameters} a new updated instance + */ + setQueryParameters: function setQueryParameters(params) { + if (!params) return this; -/***/ }), + var error = SearchParameters.validate(this, params); -/***/ "./node_modules/axios/lib/helpers/buildURL.js": -/*!****************************************************!*\ - !*** ./node_modules/axios/lib/helpers/buildURL.js ***! - \****************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { + if (error) { + throw error; + } -"use strict"; + var parsedParams = SearchParameters._parseNumbers(params); + return this.mutateMe(function mergeWith(newInstance) { + var ks = keys(params); -var utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js"); + forEach(ks, function(k) { + newInstance[k] = parsedParams[k]; + }); -function encode(val) { - return encodeURIComponent(val). - replace(/%40/gi, '@'). - replace(/%3A/gi, ':'). - replace(/%24/g, '$'). - replace(/%2C/gi, ','). - replace(/%20/g, '+'). - replace(/%5B/gi, '['). - replace(/%5D/gi, ']'); -} + return newInstance; + }); + }, -/** - * Build a URL by appending params to the end - * - * @param {string} url The base of the url (e.g., http://www.google.com) - * @param {object} [params] The params to be appended - * @returns {string} The formatted url - */ -module.exports = function buildURL(url, params, paramsSerializer) { - /*eslint no-param-reassign:0*/ - if (!params) { - return url; - } + /** + * Returns an object with only the selected attributes. + * @param {string[]} filters filters to retrieve only a subset of the state. It + * accepts strings that can be either attributes of the SearchParameters (e.g. hitsPerPage) + * or attributes of the index with the notation 'attribute:nameOfMyAttribute' + * @return {object} + */ + filter: function(filters) { + return filterState(this, filters); + }, + /** + * Helper function to make it easier to build new instances from a mutating + * function + * @private + * @param {function} fn newMutableState -> previousState -> () function that will + * change the value of the newMutable to the desired state + * @return {SearchParameters} a new instance with the specified modifications applied + */ + mutateMe: function mutateMe(fn) { + var newState = new this.constructor(this); - var serializedParams; - if (paramsSerializer) { - serializedParams = paramsSerializer(params); - } else if (utils.isURLSearchParams(params)) { - serializedParams = params.toString(); - } else { - var parts = []; + fn(newState, this); + return newState; + }, - utils.forEach(params, function serialize(val, key) { - if (val === null || typeof val === 'undefined') { - return; - } + /** + * Helper function to get the hierarchicalFacet separator or the default one (`>`) + * @param {object} hierarchicalFacet + * @return {string} returns the hierarchicalFacet.separator or `>` as default + */ + _getHierarchicalFacetSortBy: function(hierarchicalFacet) { + return hierarchicalFacet.sortBy || ['isRefined:desc', 'name:asc']; + }, - if (utils.isArray(val)) { - key = key + '[]'; - } else { - val = [val]; - } + /** + * Helper function to get the hierarchicalFacet separator or the default one (`>`) + * @private + * @param {object} hierarchicalFacet + * @return {string} returns the hierarchicalFacet.separator or `>` as default + */ + _getHierarchicalFacetSeparator: function(hierarchicalFacet) { + return hierarchicalFacet.separator || ' > '; + }, - utils.forEach(val, function parseValue(v) { - if (utils.isDate(v)) { - v = v.toISOString(); - } else if (utils.isObject(v)) { - v = JSON.stringify(v); - } - parts.push(encode(key) + '=' + encode(v)); - }); - }); + /** + * Helper function to get the hierarchicalFacet prefix path or null + * @private + * @param {object} hierarchicalFacet + * @return {string} returns the hierarchicalFacet.rootPath or null as default + */ + _getHierarchicalRootPath: function(hierarchicalFacet) { + return hierarchicalFacet.rootPath || null; + }, - serializedParams = parts.join('&'); - } + /** + * Helper function to check if we show the parent level of the hierarchicalFacet + * @private + * @param {object} hierarchicalFacet + * @return {string} returns the hierarchicalFacet.showParentLevel or true as default + */ + _getHierarchicalShowParentLevel: function(hierarchicalFacet) { + if (typeof hierarchicalFacet.showParentLevel === 'boolean') { + return hierarchicalFacet.showParentLevel; + } + return true; + }, - if (serializedParams) { - var hashmarkIndex = url.indexOf('#'); - if (hashmarkIndex !== -1) { - url = url.slice(0, hashmarkIndex); + /** + * Helper function to get the hierarchicalFacet by it's name + * @param {string} hierarchicalFacetName + * @return {object} a hierarchicalFacet + */ + getHierarchicalFacetByName: function(hierarchicalFacetName) { + return find( + this.hierarchicalFacets, + {name: hierarchicalFacetName} + ); + }, + + /** + * Get the current breadcrumb for a hierarchical facet, as an array + * @param {string} facetName Hierarchical facet name + * @return {array.} the path as an array of string + */ + getHierarchicalFacetBreadcrumb: function(facetName) { + if (!this.isHierarchicalFacet(facetName)) { + throw new Error( + 'Cannot get the breadcrumb of an unknown hierarchical facet: `' + facetName + '`'); } - url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams; - } + var refinement = this.getHierarchicalRefinement(facetName)[0]; + if (!refinement) return []; - return url; + var separator = this._getHierarchicalFacetSeparator( + this.getHierarchicalFacetByName(facetName) + ); + var path = refinement.split(separator); + return map(path, trim); + }, + + toString: function() { + return JSON.stringify(this, null, 2); + } }; +/** + * Callback used for clearRefinement method + * @callback SearchParameters.clearCallback + * @param {OperatorList|FacetList} value the value of the filter + * @param {string} key the current attribute name + * @param {string} type `numeric`, `disjunctiveFacet`, `conjunctiveFacet`, `hierarchicalFacet` or `exclude` + * depending on the type of facet + * @return {boolean} `true` if the element should be removed. `false` otherwise. + */ +module.exports = SearchParameters; + /***/ }), -/***/ "./node_modules/axios/lib/helpers/combineURLs.js": -/*!*******************************************************!*\ - !*** ./node_modules/axios/lib/helpers/combineURLs.js ***! - \*******************************************************/ +/***/ "./node_modules/algoliasearch-helper/src/SearchParameters/shortener.js": +/*!*****************************************************************************!*\ + !*** ./node_modules/algoliasearch-helper/src/SearchParameters/shortener.js ***! + \*****************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -/** - * Creates a new URL by combining the specified URLs - * - * @param {string} baseURL The base URL - * @param {string} relativeURL The relative URL - * @returns {string} The combined URL - */ -module.exports = function combineURLs(baseURL, relativeURL) { - return relativeURL - ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') - : baseURL; +var invert = __webpack_require__(/*! lodash/invert */ "./node_modules/lodash/invert.js"); +var keys = __webpack_require__(/*! lodash/keys */ "./node_modules/lodash/keys.js"); + +var keys2Short = { + advancedSyntax: 'aS', + allowTyposOnNumericTokens: 'aTONT', + analyticsTags: 'aT', + analytics: 'a', + aroundLatLngViaIP: 'aLLVIP', + aroundLatLng: 'aLL', + aroundPrecision: 'aP', + aroundRadius: 'aR', + attributesToHighlight: 'aTH', + attributesToRetrieve: 'aTR', + attributesToSnippet: 'aTS', + disjunctiveFacetsRefinements: 'dFR', + disjunctiveFacets: 'dF', + distinct: 'd', + facetsExcludes: 'fE', + facetsRefinements: 'fR', + facets: 'f', + getRankingInfo: 'gRI', + hierarchicalFacetsRefinements: 'hFR', + hierarchicalFacets: 'hF', + highlightPostTag: 'hPoT', + highlightPreTag: 'hPrT', + hitsPerPage: 'hPP', + ignorePlurals: 'iP', + index: 'idx', + insideBoundingBox: 'iBB', + insidePolygon: 'iPg', + length: 'l', + maxValuesPerFacet: 'mVPF', + minimumAroundRadius: 'mAR', + minProximity: 'mP', + minWordSizefor1Typo: 'mWS1T', + minWordSizefor2Typos: 'mWS2T', + numericFilters: 'nF', + numericRefinements: 'nR', + offset: 'o', + optionalWords: 'oW', + page: 'p', + queryType: 'qT', + query: 'q', + removeWordsIfNoResults: 'rWINR', + replaceSynonymsInHighlight: 'rSIH', + restrictSearchableAttributes: 'rSA', + synonyms: 's', + tagFilters: 'tF', + tagRefinements: 'tR', + typoTolerance: 'tT', + optionalTagFilters: 'oTF', + optionalFacetFilters: 'oFF', + snippetEllipsisText: 'sET', + disableExactOnAttributes: 'dEOA', + enableExactOnSingleWordQuery: 'eEOSWQ' +}; + +var short2Keys = invert(keys2Short); + +module.exports = { + /** + * All the keys of the state, encoded. + * @const + */ + ENCODED_PARAMETERS: keys(short2Keys), + /** + * Decode a shorten attribute + * @param {string} shortKey the shorten attribute + * @return {string} the decoded attribute, undefined otherwise + */ + decode: function(shortKey) { + return short2Keys[shortKey]; + }, + /** + * Encode an attribute into a short version + * @param {string} key the attribute + * @return {string} the shorten attribute + */ + encode: function(key) { + return keys2Short[key]; + } }; /***/ }), -/***/ "./node_modules/axios/lib/helpers/cookies.js": -/*!***************************************************!*\ - !*** ./node_modules/axios/lib/helpers/cookies.js ***! - \***************************************************/ +/***/ "./node_modules/algoliasearch-helper/src/SearchResults/generate-hierarchical-tree.js": +/*!*******************************************************************************************!*\ + !*** ./node_modules/algoliasearch-helper/src/SearchResults/generate-hierarchical-tree.js ***! + \*******************************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js"); +module.exports = generateTrees; -module.exports = ( - utils.isStandardBrowserEnv() ? +var last = __webpack_require__(/*! lodash/last */ "./node_modules/lodash/last.js"); +var map = __webpack_require__(/*! lodash/map */ "./node_modules/lodash/map.js"); +var reduce = __webpack_require__(/*! lodash/reduce */ "./node_modules/lodash/reduce.js"); +var orderBy = __webpack_require__(/*! lodash/orderBy */ "./node_modules/lodash/orderBy.js"); +var trim = __webpack_require__(/*! lodash/trim */ "./node_modules/lodash/trim.js"); +var find = __webpack_require__(/*! lodash/find */ "./node_modules/lodash/find.js"); +var pickBy = __webpack_require__(/*! lodash/pickBy */ "./node_modules/lodash/pickBy.js"); - // Standard browser envs support document.cookie - (function standardBrowserEnv() { - return { - write: function write(name, value, expires, path, domain, secure) { - var cookie = []; - cookie.push(name + '=' + encodeURIComponent(value)); +var prepareHierarchicalFacetSortBy = __webpack_require__(/*! ../functions/formatSort */ "./node_modules/algoliasearch-helper/src/functions/formatSort.js"); - if (utils.isNumber(expires)) { - cookie.push('expires=' + new Date(expires).toGMTString()); - } +function generateTrees(state) { + return function generate(hierarchicalFacetResult, hierarchicalFacetIndex) { + var hierarchicalFacet = state.hierarchicalFacets[hierarchicalFacetIndex]; + var hierarchicalFacetRefinement = state.hierarchicalFacetsRefinements[hierarchicalFacet.name] && + state.hierarchicalFacetsRefinements[hierarchicalFacet.name][0] || ''; + var hierarchicalSeparator = state._getHierarchicalFacetSeparator(hierarchicalFacet); + var hierarchicalRootPath = state._getHierarchicalRootPath(hierarchicalFacet); + var hierarchicalShowParentLevel = state._getHierarchicalShowParentLevel(hierarchicalFacet); + var sortBy = prepareHierarchicalFacetSortBy(state._getHierarchicalFacetSortBy(hierarchicalFacet)); - if (utils.isString(path)) { - cookie.push('path=' + path); - } + var generateTreeFn = generateHierarchicalTree(sortBy, hierarchicalSeparator, hierarchicalRootPath, + hierarchicalShowParentLevel, hierarchicalFacetRefinement); - if (utils.isString(domain)) { - cookie.push('domain=' + domain); - } + var results = hierarchicalFacetResult; - if (secure === true) { - cookie.push('secure'); - } + if (hierarchicalRootPath) { + results = hierarchicalFacetResult.slice(hierarchicalRootPath.split(hierarchicalSeparator).length); + } - document.cookie = cookie.join('; '); - }, + return reduce(results, generateTreeFn, { + name: state.hierarchicalFacets[hierarchicalFacetIndex].name, + count: null, // root level, no count + isRefined: true, // root level, always refined + path: null, // root level, no path + data: null + }); + }; +} - read: function read(name) { - var match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)')); - return (match ? decodeURIComponent(match[3]) : null); - }, +function generateHierarchicalTree(sortBy, hierarchicalSeparator, hierarchicalRootPath, + hierarchicalShowParentLevel, currentRefinement) { + return function generateTree(hierarchicalTree, hierarchicalFacetResult, currentHierarchicalLevel) { + var parent = hierarchicalTree; - remove: function remove(name) { - this.write(name, '', Date.now() - 86400000); - } - }; - })() : + if (currentHierarchicalLevel > 0) { + var level = 0; - // Non standard browser env (web workers, react-native) lack needed support. - (function nonStandardBrowserEnv() { - return { - write: function write() {}, - read: function read() { return null; }, - remove: function remove() {} - }; - })() -); + parent = hierarchicalTree; + + while (level < currentHierarchicalLevel) { + parent = parent && find(parent.data, {isRefined: true}); + level++; + } + } + + // we found a refined parent, let's add current level data under it + if (parent) { + // filter values in case an object has multiple categories: + // { + // categories: { + // level0: ['beers', 'bières'], + // level1: ['beers > IPA', 'bières > Belges'] + // } + // } + // + // If parent refinement is `beers`, then we do not want to have `bières > Belges` + // showing up + + var onlyMatchingValuesFn = filterFacetValues(parent.path || hierarchicalRootPath, + currentRefinement, hierarchicalSeparator, hierarchicalRootPath, hierarchicalShowParentLevel); + + parent.data = orderBy( + map( + pickBy(hierarchicalFacetResult.data, onlyMatchingValuesFn), + formatHierarchicalFacetValue(hierarchicalSeparator, currentRefinement) + ), + sortBy[0], sortBy[1] + ); + } + + return hierarchicalTree; + }; +} + +function filterFacetValues(parentPath, currentRefinement, hierarchicalSeparator, hierarchicalRootPath, + hierarchicalShowParentLevel) { + return function(facetCount, facetValue) { + // we want the facetValue is a child of hierarchicalRootPath + if (hierarchicalRootPath && + (facetValue.indexOf(hierarchicalRootPath) !== 0 || hierarchicalRootPath === facetValue)) { + return false; + } + + // we always want root levels (only when there is no prefix path) + return !hierarchicalRootPath && facetValue.indexOf(hierarchicalSeparator) === -1 || + // if there is a rootPath, being root level mean 1 level under rootPath + hierarchicalRootPath && + facetValue.split(hierarchicalSeparator).length - hierarchicalRootPath.split(hierarchicalSeparator).length === 1 || + // if current refinement is a root level and current facetValue is a root level, + // keep the facetValue + facetValue.indexOf(hierarchicalSeparator) === -1 && + currentRefinement.indexOf(hierarchicalSeparator) === -1 || + // currentRefinement is a child of the facet value + currentRefinement.indexOf(facetValue) === 0 || + // facetValue is a child of the current parent, add it + facetValue.indexOf(parentPath + hierarchicalSeparator) === 0 && + (hierarchicalShowParentLevel || facetValue.indexOf(currentRefinement) === 0); + }; +} + +function formatHierarchicalFacetValue(hierarchicalSeparator, currentRefinement) { + return function format(facetCount, facetValue) { + return { + name: trim(last(facetValue.split(hierarchicalSeparator))), + path: facetValue, + count: facetCount, + isRefined: currentRefinement === facetValue || currentRefinement.indexOf(facetValue + hierarchicalSeparator) === 0, + data: null + }; + }; +} /***/ }), -/***/ "./node_modules/axios/lib/helpers/isAbsoluteURL.js": -/*!*********************************************************!*\ - !*** ./node_modules/axios/lib/helpers/isAbsoluteURL.js ***! - \*********************************************************/ +/***/ "./node_modules/algoliasearch-helper/src/SearchResults/index.js": +/*!**********************************************************************!*\ + !*** ./node_modules/algoliasearch-helper/src/SearchResults/index.js ***! + \**********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; +var forEach = __webpack_require__(/*! lodash/forEach */ "./node_modules/lodash/forEach.js"); +var compact = __webpack_require__(/*! lodash/compact */ "./node_modules/lodash/compact.js"); +var indexOf = __webpack_require__(/*! lodash/indexOf */ "./node_modules/lodash/indexOf.js"); +var findIndex = __webpack_require__(/*! lodash/findIndex */ "./node_modules/lodash/findIndex.js"); +var get = __webpack_require__(/*! lodash/get */ "./node_modules/lodash/get.js"); + +var sumBy = __webpack_require__(/*! lodash/sumBy */ "./node_modules/lodash/sumBy.js"); +var find = __webpack_require__(/*! lodash/find */ "./node_modules/lodash/find.js"); +var includes = __webpack_require__(/*! lodash/includes */ "./node_modules/lodash/includes.js"); +var map = __webpack_require__(/*! lodash/map */ "./node_modules/lodash/map.js"); +var orderBy = __webpack_require__(/*! lodash/orderBy */ "./node_modules/lodash/orderBy.js"); + +var defaults = __webpack_require__(/*! lodash/defaults */ "./node_modules/lodash/defaults.js"); +var merge = __webpack_require__(/*! lodash/merge */ "./node_modules/lodash/merge.js"); + +var isFunction = __webpack_require__(/*! lodash/isFunction */ "./node_modules/lodash/isFunction.js"); + +var partial = __webpack_require__(/*! lodash/partial */ "./node_modules/lodash/partial.js"); +var partialRight = __webpack_require__(/*! lodash/partialRight */ "./node_modules/lodash/partialRight.js"); + +var formatSort = __webpack_require__(/*! ../functions/formatSort */ "./node_modules/algoliasearch-helper/src/functions/formatSort.js"); + +var generateHierarchicalTree = __webpack_require__(/*! ./generate-hierarchical-tree */ "./node_modules/algoliasearch-helper/src/SearchResults/generate-hierarchical-tree.js"); + /** - * Determines whether the specified URL is absolute - * - * @param {string} url The URL to test - * @returns {boolean} True if the specified URL is absolute, otherwise false + * @typedef SearchResults.Facet + * @type {object} + * @property {string} name name of the attribute in the record + * @property {object} data the faceting data: value, number of entries + * @property {object} stats undefined unless facet_stats is retrieved from algolia */ -module.exports = function isAbsoluteURL(url) { - // A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL). - // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed - // by any combination of letters, digits, plus, period, or hyphen. - return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url); -}; +/** + * @typedef SearchResults.HierarchicalFacet + * @type {object} + * @property {string} name name of the current value given the hierarchical level, trimmed. + * If root node, you get the facet name + * @property {number} count number of objects matching this hierarchical value + * @property {string} path the current hierarchical value full path + * @property {boolean} isRefined `true` if the current value was refined, `false` otherwise + * @property {HierarchicalFacet[]} data sub values for the current level + */ -/***/ }), - -/***/ "./node_modules/axios/lib/helpers/isURLSameOrigin.js": -/*!***********************************************************!*\ - !*** ./node_modules/axios/lib/helpers/isURLSameOrigin.js ***! - \***********************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { +/** + * @typedef SearchResults.FacetValue + * @type {object} + * @property {string} name the facet value itself + * @property {number} count times this facet appears in the results + * @property {boolean} isRefined is the facet currently selected + * @property {boolean} isExcluded is the facet currently excluded (only for conjunctive facets) + */ -"use strict"; +/** + * @typedef Refinement + * @type {object} + * @property {string} type the type of filter used: + * `numeric`, `facet`, `exclude`, `disjunctive`, `hierarchical` + * @property {string} attributeName name of the attribute used for filtering + * @property {string} name the value of the filter + * @property {number} numericValue the value as a number. Only for numeric filters. + * @property {string} operator the operator used. Only for numeric filters. + * @property {number} count the number of computed hits for this filter. Only on facets. + * @property {boolean} exhaustive if the count is exhaustive + */ +function getIndices(obj) { + var indices = {}; -var utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js"); + forEach(obj, function(val, idx) { indices[val] = idx; }); -module.exports = ( - utils.isStandardBrowserEnv() ? + return indices; +} - // Standard browser envs have full support of the APIs needed to test - // whether the request URL is of the same origin as current location. - (function standardBrowserEnv() { - var msie = /(msie|trident)/i.test(navigator.userAgent); - var urlParsingNode = document.createElement('a'); - var originURL; +function assignFacetStats(dest, facetStats, key) { + if (facetStats && facetStats[key]) { + dest.stats = facetStats[key]; + } +} - /** - * Parse a URL to discover it's components - * - * @param {String} url The URL to be parsed - * @returns {Object} - */ - function resolveURL(url) { - var href = url; +function findMatchingHierarchicalFacetFromAttributeName(hierarchicalFacets, hierarchicalAttributeName) { + return find( + hierarchicalFacets, + function facetKeyMatchesAttribute(hierarchicalFacet) { + return includes(hierarchicalFacet.attributes, hierarchicalAttributeName); + } + ); +} - if (msie) { - // IE needs attribute set twice to normalize properties - urlParsingNode.setAttribute('href', href); - href = urlParsingNode.href; - } +/*eslint-disable */ +/** + * Constructor for SearchResults + * @class + * @classdesc SearchResults contains the results of a query to Algolia using the + * {@link AlgoliaSearchHelper}. + * @param {SearchParameters} state state that led to the response + * @param {array.} results the results from algolia client + * @example SearchResults of the first query in + * the instant search demo +{ + "hitsPerPage": 10, + "processingTimeMS": 2, + "facets": [ + { + "name": "type", + "data": { + "HardGood": 6627, + "BlackTie": 550, + "Music": 665, + "Software": 131, + "Game": 456, + "Movie": 1571 + }, + "exhaustive": false + }, + { + "exhaustive": false, + "data": { + "Free shipping": 5507 + }, + "name": "shipping" + } + ], + "hits": [ + { + "thumbnailImage": "http://img.bbystatic.com/BestBuy_US/images/products/1688/1688832_54x108_s.gif", + "_highlightResult": { + "shortDescription": { + "matchLevel": "none", + "value": "Safeguard your PC, Mac, Android and iOS devices with comprehensive Internet protection", + "matchedWords": [] + }, + "category": { + "matchLevel": "none", + "value": "Computer Security Software", + "matchedWords": [] + }, + "manufacturer": { + "matchedWords": [], + "value": "Webroot", + "matchLevel": "none" + }, + "name": { + "value": "Webroot SecureAnywhere Internet Security (3-Device) (1-Year Subscription) - Mac/Windows", + "matchedWords": [], + "matchLevel": "none" + } + }, + "image": "http://img.bbystatic.com/BestBuy_US/images/products/1688/1688832_105x210_sc.jpg", + "shipping": "Free shipping", + "bestSellingRank": 4, + "shortDescription": "Safeguard your PC, Mac, Android and iOS devices with comprehensive Internet protection", + "url": "http://www.bestbuy.com/site/webroot-secureanywhere-internet-security-3-devi…d=1219060687969&skuId=1688832&cmp=RMX&ky=2d3GfEmNIzjA0vkzveHdZEBgpPCyMnLTJ", + "name": "Webroot SecureAnywhere Internet Security (3-Device) (1-Year Subscription) - Mac/Windows", + "category": "Computer Security Software", + "salePrice_range": "1 - 50", + "objectID": "1688832", + "type": "Software", + "customerReviewCount": 5980, + "salePrice": 49.99, + "manufacturer": "Webroot" + }, + .... + ], + "nbHits": 10000, + "disjunctiveFacets": [ + { + "exhaustive": false, + "data": { + "5": 183, + "12": 112, + "7": 149, + ... + }, + "name": "customerReviewCount", + "stats": { + "max": 7461, + "avg": 157.939, + "min": 1 + } + }, + { + "data": { + "Printer Ink": 142, + "Wireless Speakers": 60, + "Point & Shoot Cameras": 48, + ... + }, + "name": "category", + "exhaustive": false + }, + { + "exhaustive": false, + "data": { + "> 5000": 2, + "1 - 50": 6524, + "501 - 2000": 566, + "201 - 500": 1501, + "101 - 200": 1360, + "2001 - 5000": 47 + }, + "name": "salePrice_range" + }, + { + "data": { + "Dynex™": 202, + "Insignia™": 230, + "PNY": 72, + ... + }, + "name": "manufacturer", + "exhaustive": false + } + ], + "query": "", + "nbPages": 100, + "page": 0, + "index": "bestbuy" +} + **/ +/*eslint-enable */ +function SearchResults(state, results) { + var mainSubResponse = results[0]; - urlParsingNode.setAttribute('href', href); + this._rawResults = results; - // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils - return { - href: urlParsingNode.href, - protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '', - host: urlParsingNode.host, - search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '', - hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '', - hostname: urlParsingNode.hostname, - port: urlParsingNode.port, - pathname: (urlParsingNode.pathname.charAt(0) === '/') ? - urlParsingNode.pathname : - '/' + urlParsingNode.pathname - }; - } + /** + * query used to generate the results + * @member {string} + */ + this.query = mainSubResponse.query; + /** + * The query as parsed by the engine given all the rules. + * @member {string} + */ + this.parsedQuery = mainSubResponse.parsedQuery; + /** + * all the records that match the search parameters. Each record is + * augmented with a new attribute `_highlightResult` + * which is an object keyed by attribute and with the following properties: + * - `value` : the value of the facet highlighted (html) + * - `matchLevel`: full, partial or none depending on how the query terms match + * @member {object[]} + */ + this.hits = mainSubResponse.hits; + /** + * index where the results come from + * @member {string} + */ + this.index = mainSubResponse.index; + /** + * number of hits per page requested + * @member {number} + */ + this.hitsPerPage = mainSubResponse.hitsPerPage; + /** + * total number of hits of this query on the index + * @member {number} + */ + this.nbHits = mainSubResponse.nbHits; + /** + * total number of pages with respect to the number of hits per page and the total number of hits + * @member {number} + */ + this.nbPages = mainSubResponse.nbPages; + /** + * current page + * @member {number} + */ + this.page = mainSubResponse.page; + /** + * sum of the processing time of all the queries + * @member {number} + */ + this.processingTimeMS = sumBy(results, 'processingTimeMS'); + /** + * The position if the position was guessed by IP. + * @member {string} + * @example "48.8637,2.3615", + */ + this.aroundLatLng = mainSubResponse.aroundLatLng; + /** + * The radius computed by Algolia. + * @member {string} + * @example "126792922", + */ + this.automaticRadius = mainSubResponse.automaticRadius; + /** + * String identifying the server used to serve this request. + * @member {string} + * @example "c7-use-2.algolia.net", + */ + this.serverUsed = mainSubResponse.serverUsed; + /** + * Boolean that indicates if the computation of the counts did time out. + * @deprecated + * @member {boolean} + */ + this.timeoutCounts = mainSubResponse.timeoutCounts; + /** + * Boolean that indicates if the computation of the hits did time out. + * @deprecated + * @member {boolean} + */ + this.timeoutHits = mainSubResponse.timeoutHits; - originURL = resolveURL(window.location.href); + /** + * True if the counts of the facets is exhaustive + * @member {boolean} + */ + this.exhaustiveFacetsCount = mainSubResponse.exhaustiveFacetsCount; - /** - * Determine if a URL shares the same origin as the current location - * - * @param {String} requestURL The URL to test - * @returns {boolean} True if URL shares the same origin, otherwise false - */ - return function isURLSameOrigin(requestURL) { - var parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL; - return (parsed.protocol === originURL.protocol && - parsed.host === originURL.host); - }; - })() : + /** + * True if the number of hits is exhaustive + * @member {boolean} + */ + this.exhaustiveNbHits = mainSubResponse.exhaustiveNbHits; - // Non standard browser envs (web workers, react-native) lack needed support. - (function nonStandardBrowserEnv() { - return function isURLSameOrigin() { - return true; - }; - })() -); + /** + * Contains the userData if they are set by a [query rule](https://www.algolia.com/doc/guides/query-rules/query-rules-overview/). + * @member {object[]} + */ + this.userData = mainSubResponse.userData; -/***/ }), + /** + * queryID is the unique identifier of the query used to generate the current search results. + * This value is only available if the `clickAnalytics` search parameter is set to `true`. + * @member {string} + */ + this.queryID = mainSubResponse.queryID; -/***/ "./node_modules/axios/lib/helpers/normalizeHeaderName.js": -/*!***************************************************************!*\ - !*** ./node_modules/axios/lib/helpers/normalizeHeaderName.js ***! - \***************************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { + /** + * disjunctive facets results + * @member {SearchResults.Facet[]} + */ + this.disjunctiveFacets = []; + /** + * disjunctive facets results + * @member {SearchResults.HierarchicalFacet[]} + */ + this.hierarchicalFacets = map(state.hierarchicalFacets, function initFutureTree() { + return []; + }); + /** + * other facets results + * @member {SearchResults.Facet[]} + */ + this.facets = []; -"use strict"; + var disjunctiveFacets = state.getRefinedDisjunctiveFacets(); + var facetsIndices = getIndices(state.facets); + var disjunctiveFacetsIndices = getIndices(state.disjunctiveFacets); + var nextDisjunctiveResult = 1; -var utils = __webpack_require__(/*! ../utils */ "./node_modules/axios/lib/utils.js"); + var self = this; + // Since we send request only for disjunctive facets that have been refined, + // we get the facets informations from the first, general, response. + forEach(mainSubResponse.facets, function(facetValueObject, facetKey) { + var hierarchicalFacet = findMatchingHierarchicalFacetFromAttributeName( + state.hierarchicalFacets, + facetKey + ); -module.exports = function normalizeHeaderName(headers, normalizedName) { - utils.forEach(headers, function processHeader(value, name) { - if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) { - headers[normalizedName] = value; - delete headers[name]; + if (hierarchicalFacet) { + // Place the hierarchicalFacet data at the correct index depending on + // the attributes order that was defined at the helper initialization + var facetIndex = hierarchicalFacet.attributes.indexOf(facetKey); + var idxAttributeName = findIndex(state.hierarchicalFacets, {name: hierarchicalFacet.name}); + self.hierarchicalFacets[idxAttributeName][facetIndex] = { + attribute: facetKey, + data: facetValueObject, + exhaustive: mainSubResponse.exhaustiveFacetsCount + }; + } else { + var isFacetDisjunctive = indexOf(state.disjunctiveFacets, facetKey) !== -1; + var isFacetConjunctive = indexOf(state.facets, facetKey) !== -1; + var position; + + if (isFacetDisjunctive) { + position = disjunctiveFacetsIndices[facetKey]; + self.disjunctiveFacets[position] = { + name: facetKey, + data: facetValueObject, + exhaustive: mainSubResponse.exhaustiveFacetsCount + }; + assignFacetStats(self.disjunctiveFacets[position], mainSubResponse.facets_stats, facetKey); + } + if (isFacetConjunctive) { + position = facetsIndices[facetKey]; + self.facets[position] = { + name: facetKey, + data: facetValueObject, + exhaustive: mainSubResponse.exhaustiveFacetsCount + }; + assignFacetStats(self.facets[position], mainSubResponse.facets_stats, facetKey); + } } }); -}; + // Make sure we do not keep holes within the hierarchical facets + this.hierarchicalFacets = compact(this.hierarchicalFacets); -/***/ }), + // aggregate the refined disjunctive facets + forEach(disjunctiveFacets, function(disjunctiveFacet) { + var result = results[nextDisjunctiveResult]; + var hierarchicalFacet = state.getHierarchicalFacetByName(disjunctiveFacet); -/***/ "./node_modules/axios/lib/helpers/parseHeaders.js": -/*!********************************************************!*\ - !*** ./node_modules/axios/lib/helpers/parseHeaders.js ***! - \********************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { + // There should be only item in facets. + forEach(result.facets, function(facetResults, dfacet) { + var position; -"use strict"; + if (hierarchicalFacet) { + position = findIndex(state.hierarchicalFacets, {name: hierarchicalFacet.name}); + var attributeIndex = findIndex(self.hierarchicalFacets[position], {attribute: dfacet}); + // previous refinements and no results so not able to find it + if (attributeIndex === -1) { + return; + } -var utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js"); + self.hierarchicalFacets[position][attributeIndex].data = merge( + {}, + self.hierarchicalFacets[position][attributeIndex].data, + facetResults + ); + } else { + position = disjunctiveFacetsIndices[dfacet]; -// Headers whose duplicates are ignored by node -// c.f. https://nodejs.org/api/http.html#http_message_headers -var ignoreDuplicateOf = [ - 'age', 'authorization', 'content-length', 'content-type', 'etag', - 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since', - 'last-modified', 'location', 'max-forwards', 'proxy-authorization', - 'referer', 'retry-after', 'user-agent' -]; + var dataFromMainRequest = mainSubResponse.facets && mainSubResponse.facets[dfacet] || {}; -/** - * Parse headers into an object - * - * ``` - * Date: Wed, 27 Aug 2014 08:58:49 GMT - * Content-Type: application/json - * Connection: keep-alive - * Transfer-Encoding: chunked - * ``` - * - * @param {String} headers Headers needing to be parsed - * @returns {Object} Headers parsed into an object - */ -module.exports = function parseHeaders(headers) { - var parsed = {}; - var key; - var val; - var i; + self.disjunctiveFacets[position] = { + name: dfacet, + data: defaults({}, facetResults, dataFromMainRequest), + exhaustive: result.exhaustiveFacetsCount + }; + assignFacetStats(self.disjunctiveFacets[position], result.facets_stats, dfacet); + + if (state.disjunctiveFacetsRefinements[dfacet]) { + forEach(state.disjunctiveFacetsRefinements[dfacet], function(refinementValue) { + // add the disjunctive refinements if it is no more retrieved + if (!self.disjunctiveFacets[position].data[refinementValue] && + indexOf(state.disjunctiveFacetsRefinements[dfacet], refinementValue) > -1) { + self.disjunctiveFacets[position].data[refinementValue] = 0; + } + }); + } + } + }); + nextDisjunctiveResult++; + }); - if (!headers) { return parsed; } + // if we have some root level values for hierarchical facets, merge them + forEach(state.getRefinedHierarchicalFacets(), function(refinedFacet) { + var hierarchicalFacet = state.getHierarchicalFacetByName(refinedFacet); + var separator = state._getHierarchicalFacetSeparator(hierarchicalFacet); - utils.forEach(headers.split('\n'), function parser(line) { - i = line.indexOf(':'); - key = utils.trim(line.substr(0, i)).toLowerCase(); - val = utils.trim(line.substr(i + 1)); + var currentRefinement = state.getHierarchicalRefinement(refinedFacet); + // if we are already at a root refinement (or no refinement at all), there is no + // root level values request + if (currentRefinement.length === 0 || currentRefinement[0].split(separator).length < 2) { + return; + } - if (key) { - if (parsed[key] && ignoreDuplicateOf.indexOf(key) >= 0) { + var result = results[nextDisjunctiveResult]; + + forEach(result.facets, function(facetResults, dfacet) { + var position = findIndex(state.hierarchicalFacets, {name: hierarchicalFacet.name}); + var attributeIndex = findIndex(self.hierarchicalFacets[position], {attribute: dfacet}); + + // previous refinements and no results so not able to find it + if (attributeIndex === -1) { return; } - if (key === 'set-cookie') { - parsed[key] = (parsed[key] ? parsed[key] : []).concat([val]); - } else { - parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; + + // when we always get root levels, if the hits refinement is `beers > IPA` (count: 5), + // then the disjunctive values will be `beers` (count: 100), + // but we do not want to display + // | beers (100) + // > IPA (5) + // We want + // | beers (5) + // > IPA (5) + var defaultData = {}; + + if (currentRefinement.length > 0) { + var root = currentRefinement[0].split(separator)[0]; + defaultData[root] = self.hierarchicalFacets[position][attributeIndex].data[root]; } - } + + self.hierarchicalFacets[position][attributeIndex].data = defaults( + defaultData, + facetResults, + self.hierarchicalFacets[position][attributeIndex].data + ); + }); + + nextDisjunctiveResult++; }); - return parsed; + // add the excludes + forEach(state.facetsExcludes, function(excludes, facetName) { + var position = facetsIndices[facetName]; + + self.facets[position] = { + name: facetName, + data: mainSubResponse.facets[facetName], + exhaustive: mainSubResponse.exhaustiveFacetsCount + }; + forEach(excludes, function(facetValue) { + self.facets[position] = self.facets[position] || {name: facetName}; + self.facets[position].data = self.facets[position].data || {}; + self.facets[position].data[facetValue] = 0; + }); + }); + + this.hierarchicalFacets = map(this.hierarchicalFacets, generateHierarchicalTree(state)); + + this.facets = compact(this.facets); + this.disjunctiveFacets = compact(this.disjunctiveFacets); + + this._state = state; +} + +/** + * Get a facet object with its name + * @deprecated + * @param {string} name name of the faceted attribute + * @return {SearchResults.Facet} the facet object + */ +SearchResults.prototype.getFacetByName = function(name) { + var predicate = {name: name}; + + return find(this.facets, predicate) || + find(this.disjunctiveFacets, predicate) || + find(this.hierarchicalFacets, predicate); }; +/** + * Get the facet values of a specified attribute from a SearchResults object. + * @private + * @param {SearchResults} results the search results to search in + * @param {string} attribute name of the faceted attribute to search for + * @return {array|object} facet values. For the hierarchical facets it is an object. + */ +function extractNormalizedFacetValues(results, attribute) { + var predicate = {name: attribute}; + if (results._state.isConjunctiveFacet(attribute)) { + var facet = find(results.facets, predicate); + if (!facet) return []; -/***/ }), + return map(facet.data, function(v, k) { + return { + name: k, + count: v, + isRefined: results._state.isFacetRefined(attribute, k), + isExcluded: results._state.isExcludeRefined(attribute, k) + }; + }); + } else if (results._state.isDisjunctiveFacet(attribute)) { + var disjunctiveFacet = find(results.disjunctiveFacets, predicate); + if (!disjunctiveFacet) return []; -/***/ "./node_modules/axios/lib/helpers/spread.js": -/*!**************************************************!*\ - !*** ./node_modules/axios/lib/helpers/spread.js ***! - \**************************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { + return map(disjunctiveFacet.data, function(v, k) { + return { + name: k, + count: v, + isRefined: results._state.isDisjunctiveFacetRefined(attribute, k) + }; + }); + } else if (results._state.isHierarchicalFacet(attribute)) { + return find(results.hierarchicalFacets, predicate); + } +} -"use strict"; +/** + * Sort nodes of a hierarchical facet results + * @private + * @param {HierarchicalFacet} node node to upon which we want to apply the sort + */ +function recSort(sortFn, node) { + if (!node.data || node.data.length === 0) { + return node; + } + var children = map(node.data, partial(recSort, sortFn)); + var sortedChildren = sortFn(children); + var newNode = merge({}, node, {data: sortedChildren}); + return newNode; +} + +SearchResults.DEFAULT_SORT = ['isRefined:desc', 'count:desc', 'name:asc']; +function vanillaSortFn(order, data) { + return data.sort(order); +} /** - * Syntactic sugar for invoking a function and expanding an array for arguments. + * Get a the list of values for a given facet attribute. Those values are sorted + * refinement first, descending count (bigger value on top), and name ascending + * (alphabetical order). The sort formula can overridden using either string based + * predicates or a function. * - * Common use case would be to use `Function.prototype.apply`. + * This method will return all the values returned by the Algolia engine plus all + * the values already refined. This means that it can happen that the + * `maxValuesPerFacet` [configuration](https://www.algolia.com/doc/rest-api/search#param-maxValuesPerFacet) + * might not be respected if you have facet values that are already refined. + * @param {string} attribute attribute name + * @param {object} opts configuration options. + * @param {Array. | function} opts.sortBy + * When using strings, it consists of + * the name of the [FacetValue](#SearchResults.FacetValue) or the + * [HierarchicalFacet](#SearchResults.HierarchicalFacet) attributes with the + * order (`asc` or `desc`). For example to order the value by count, the + * argument would be `['count:asc']`. * - * ```js - * function f(x, y, z) {} - * var args = [1, 2, 3]; - * f.apply(null, args); - * ``` + * If only the attribute name is specified, the ordering defaults to the one + * specified in the default value for this attribute. * - * With `spread` this example can be re-written. + * When not specified, the order is + * ascending. This parameter can also be a function which takes two facet + * values and should return a number, 0 if equal, 1 if the first argument is + * bigger or -1 otherwise. * - * ```js - * spread(function(x, y, z) {})([1, 2, 3]); - * ``` + * The default value for this attribute `['isRefined:desc', 'count:desc', 'name:asc']` + * @return {FacetValue[]|HierarchicalFacet} depending on the type of facet of + * the attribute requested (hierarchical, disjunctive or conjunctive) + * @example + * helper.on('results', function(content){ + * //get values ordered only by name ascending using the string predicate + * content.getFacetValues('city', {sortBy: ['name:asc']}); + * //get values ordered only by count ascending using a function + * content.getFacetValues('city', { + * // this is equivalent to ['count:asc'] + * sortBy: function(a, b) { + * if (a.count === b.count) return 0; + * if (a.count > b.count) return 1; + * if (b.count > a.count) return -1; + * } + * }); + * }); + */ +SearchResults.prototype.getFacetValues = function(attribute, opts) { + var facetValues = extractNormalizedFacetValues(this, attribute); + if (!facetValues) throw new Error(attribute + ' is not a retrieved facet.'); + + var options = defaults({}, opts, {sortBy: SearchResults.DEFAULT_SORT}); + + if (Array.isArray(options.sortBy)) { + var order = formatSort(options.sortBy, SearchResults.DEFAULT_SORT); + if (Array.isArray(facetValues)) { + return orderBy(facetValues, order[0], order[1]); + } + // If facetValues is not an array, it's an object thus a hierarchical facet object + return recSort(partialRight(orderBy, order[0], order[1]), facetValues); + } else if (isFunction(options.sortBy)) { + if (Array.isArray(facetValues)) { + return facetValues.sort(options.sortBy); + } + // If facetValues is not an array, it's an object thus a hierarchical facet object + return recSort(partial(vanillaSortFn, options.sortBy), facetValues); + } + throw new Error( + 'options.sortBy is optional but if defined it must be ' + + 'either an array of string (predicates) or a sorting function' + ); +}; + +/** + * Returns the facet stats if attribute is defined and the facet contains some. + * Otherwise returns undefined. + * @param {string} attribute name of the faceted attribute + * @return {object} The stats of the facet + */ +SearchResults.prototype.getFacetStats = function(attribute) { + if (this._state.isConjunctiveFacet(attribute)) { + return getFacetStatsIfAvailable(this.facets, attribute); + } else if (this._state.isDisjunctiveFacet(attribute)) { + return getFacetStatsIfAvailable(this.disjunctiveFacets, attribute); + } + + throw new Error(attribute + ' is not present in `facets` or `disjunctiveFacets`'); +}; + +function getFacetStatsIfAvailable(facetList, facetName) { + var data = find(facetList, {name: facetName}); + return data && data.stats; +} + +/** + * Returns all refinements for all filters + tags. It also provides + * additional information: count and exhausistivity for each filter. * - * @param {Function} callback - * @returns {Function} + * See the [refinement type](#Refinement) for an exhaustive view of the available + * data. + * + * @return {Array.} all the refinements */ -module.exports = function spread(callback) { - return function wrap(arr) { - return callback.apply(null, arr); - }; +SearchResults.prototype.getRefinements = function() { + var state = this._state; + var results = this; + var res = []; + + forEach(state.facetsRefinements, function(refinements, attributeName) { + forEach(refinements, function(name) { + res.push(getRefinement(state, 'facet', attributeName, name, results.facets)); + }); + }); + + forEach(state.facetsExcludes, function(refinements, attributeName) { + forEach(refinements, function(name) { + res.push(getRefinement(state, 'exclude', attributeName, name, results.facets)); + }); + }); + + forEach(state.disjunctiveFacetsRefinements, function(refinements, attributeName) { + forEach(refinements, function(name) { + res.push(getRefinement(state, 'disjunctive', attributeName, name, results.disjunctiveFacets)); + }); + }); + + forEach(state.hierarchicalFacetsRefinements, function(refinements, attributeName) { + forEach(refinements, function(name) { + res.push(getHierarchicalRefinement(state, attributeName, name, results.hierarchicalFacets)); + }); + }); + + forEach(state.numericRefinements, function(operators, attributeName) { + forEach(operators, function(values, operator) { + forEach(values, function(value) { + res.push({ + type: 'numeric', + attributeName: attributeName, + name: value, + numericValue: value, + operator: operator + }); + }); + }); + }); + + forEach(state.tagRefinements, function(name) { + res.push({type: 'tag', attributeName: '_tags', name: name}); + }); + + return res; }; +function getRefinement(state, type, attributeName, name, resultsFacets) { + var facet = find(resultsFacets, {name: attributeName}); + var count = get(facet, 'data[' + name + ']'); + var exhaustive = get(facet, 'exhaustive'); + return { + type: type, + attributeName: attributeName, + name: name, + count: count || 0, + exhaustive: exhaustive || false + }; +} + +function getHierarchicalRefinement(state, attributeName, name, resultsFacets) { + var facet = find(resultsFacets, {name: attributeName}); + var facetDeclaration = state.getHierarchicalFacetByName(attributeName); + var splitted = name.split(facetDeclaration.separator); + var configuredName = splitted[splitted.length - 1]; + for (var i = 0; facet !== undefined && i < splitted.length; ++i) { + facet = find(facet.data, {name: splitted[i]}); + } + var count = get(facet, 'count'); + var exhaustive = get(facet, 'exhaustive'); + return { + type: 'hierarchical', + attributeName: attributeName, + name: configuredName, + count: count || 0, + exhaustive: exhaustive || false + }; +} + +module.exports = SearchResults; + /***/ }), -/***/ "./node_modules/axios/lib/utils.js": -/*!*****************************************!*\ - !*** ./node_modules/axios/lib/utils.js ***! - \*****************************************/ +/***/ "./node_modules/algoliasearch-helper/src/algoliasearch.helper.js": +/*!***********************************************************************!*\ + !*** ./node_modules/algoliasearch-helper/src/algoliasearch.helper.js ***! + \***********************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { "use strict"; -var bind = __webpack_require__(/*! ./helpers/bind */ "./node_modules/axios/lib/helpers/bind.js"); +var SearchParameters = __webpack_require__(/*! ./SearchParameters */ "./node_modules/algoliasearch-helper/src/SearchParameters/index.js"); +var SearchResults = __webpack_require__(/*! ./SearchResults */ "./node_modules/algoliasearch-helper/src/SearchResults/index.js"); +var DerivedHelper = __webpack_require__(/*! ./DerivedHelper */ "./node_modules/algoliasearch-helper/src/DerivedHelper/index.js"); +var requestBuilder = __webpack_require__(/*! ./requestBuilder */ "./node_modules/algoliasearch-helper/src/requestBuilder.js"); -/*global toString:true*/ +var events = __webpack_require__(/*! events */ "./node_modules/events/events.js"); +var inherits = __webpack_require__(/*! ./functions/inherits */ "./node_modules/algoliasearch-helper/src/functions/inherits.js"); -// utils is a library of generic helper functions non-specific to axios +var flatten = __webpack_require__(/*! lodash/flatten */ "./node_modules/lodash/flatten.js"); +var forEach = __webpack_require__(/*! lodash/forEach */ "./node_modules/lodash/forEach.js"); +var isEmpty = __webpack_require__(/*! lodash/isEmpty */ "./node_modules/lodash/isEmpty.js"); +var map = __webpack_require__(/*! lodash/map */ "./node_modules/lodash/map.js"); -var toString = Object.prototype.toString; +var url = __webpack_require__(/*! ./url */ "./node_modules/algoliasearch-helper/src/url.js"); +var version = __webpack_require__(/*! ./version */ "./node_modules/algoliasearch-helper/src/version.js"); /** - * Determine if a value is an Array - * - * @param {Object} val The value to test - * @returns {boolean} True if value is an Array, otherwise false + * Event triggered when a parameter is set or updated + * @event AlgoliaSearchHelper#event:change + * @property {SearchParameters} state the current parameters with the latest changes applied + * @property {SearchResults} lastResults the previous results received from Algolia. `null` before + * the first request + * @example + * helper.on('change', function(state, lastResults) { + * console.log('The parameters have changed'); + * }); */ -function isArray(val) { - return toString.call(val) === '[object Array]'; -} /** - * Determine if a value is undefined - * - * @param {Object} val The value to test - * @returns {boolean} True if the value is undefined, otherwise false + * Event triggered when a main search is sent to Algolia + * @event AlgoliaSearchHelper#event:search + * @property {SearchParameters} state the parameters used for this search + * @property {SearchResults} lastResults the results from the previous search. `null` if + * it is the first search. + * @example + * helper.on('search', function(state, lastResults) { + * console.log('Search sent'); + * }); */ -function isUndefined(val) { - return typeof val === 'undefined'; -} /** - * Determine if a value is a Buffer - * - * @param {Object} val The value to test - * @returns {boolean} True if value is a Buffer, otherwise false + * Event triggered when a search using `searchForFacetValues` is sent to Algolia + * @event AlgoliaSearchHelper#event:searchForFacetValues + * @property {SearchParameters} state the parameters used for this search + * it is the first search. + * @property {string} facet the facet searched into + * @property {string} query the query used to search in the facets + * @example + * helper.on('searchForFacetValues', function(state, facet, query) { + * console.log('searchForFacetValues sent'); + * }); */ -function isBuffer(val) { - return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor) - && typeof val.constructor.isBuffer === 'function' && val.constructor.isBuffer(val); -} /** - * Determine if a value is an ArrayBuffer - * - * @param {Object} val The value to test - * @returns {boolean} True if value is an ArrayBuffer, otherwise false + * Event triggered when a search using `searchOnce` is sent to Algolia + * @event AlgoliaSearchHelper#event:searchOnce + * @property {SearchParameters} state the parameters used for this search + * it is the first search. + * @example + * helper.on('searchOnce', function(state) { + * console.log('searchOnce sent'); + * }); */ -function isArrayBuffer(val) { - return toString.call(val) === '[object ArrayBuffer]'; -} /** - * Determine if a value is a FormData - * - * @param {Object} val The value to test - * @returns {boolean} True if value is an FormData, otherwise false + * Event triggered when the results are retrieved from Algolia + * @event AlgoliaSearchHelper#event:result + * @property {SearchResults} results the results received from Algolia + * @property {SearchParameters} state the parameters used to query Algolia. Those might + * be different from the one in the helper instance (for example if the network is unreliable). + * @example + * helper.on('result', function(results, state) { + * console.log('Search results received'); + * }); */ -function isFormData(val) { - return (typeof FormData !== 'undefined') && (val instanceof FormData); -} /** - * Determine if a value is a view on an ArrayBuffer - * - * @param {Object} val The value to test - * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false + * Event triggered when Algolia sends back an error. For example, if an unknown parameter is + * used, the error can be caught using this event. + * @event AlgoliaSearchHelper#event:error + * @property {Error} error the error returned by the Algolia. + * @example + * helper.on('error', function(error) { + * console.log('Houston we got a problem.'); + * }); */ -function isArrayBufferView(val) { - var result; - if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) { - result = ArrayBuffer.isView(val); - } else { - result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer); - } - return result; -} /** - * Determine if a value is a String + * Event triggered when the queue of queries have been depleted (with any result or outdated queries) + * @event AlgoliaSearchHelper#event:searchQueueEmpty + * @example + * helper.on('searchQueueEmpty', function() { + * console.log('No more search pending'); + * // This is received before the result event if we're not expecting new results + * }); * - * @param {Object} val The value to test - * @returns {boolean} True if value is a String, otherwise false + * helper.search(); */ -function isString(val) { - return typeof val === 'string'; -} /** - * Determine if a value is a Number - * - * @param {Object} val The value to test - * @returns {boolean} True if value is a Number, otherwise false + * Initialize a new AlgoliaSearchHelper + * @class + * @classdesc The AlgoliaSearchHelper is a class that ease the management of the + * search. It provides an event based interface for search callbacks: + * - change: when the internal search state is changed. + * This event contains a {@link SearchParameters} object and the + * {@link SearchResults} of the last result if any. + * - search: when a search is triggered using the `search()` method. + * - result: when the response is retrieved from Algolia and is processed. + * This event contains a {@link SearchResults} object and the + * {@link SearchParameters} corresponding to this answer. + * - error: when the response is an error. This event contains the error returned by the server. + * @param {AlgoliaSearch} client an AlgoliaSearch client + * @param {string} index the index name to query + * @param {SearchParameters | object} options an object defining the initial + * config of the search. It doesn't have to be a {SearchParameters}, + * just an object containing the properties you need from it. */ -function isNumber(val) { - return typeof val === 'number'; +function AlgoliaSearchHelper(client, index, options) { + if (client.addAlgoliaAgent && !doesClientAgentContainsHelper(client)) { + client.addAlgoliaAgent('JS Helper (' + version + ')'); + } + + this.setClient(client); + var opts = options || {}; + opts.index = index; + this.state = SearchParameters.make(opts); + this.lastResults = null; + this._queryId = 0; + this._lastQueryIdReceived = -1; + this.derivedHelpers = []; + this._currentNbQueries = 0; } +inherits(AlgoliaSearchHelper, events.EventEmitter); + /** - * Determine if a value is an Object - * - * @param {Object} val The value to test - * @returns {boolean} True if value is an Object, otherwise false + * Start the search with the parameters set in the state. When the + * method is called, it triggers a `search` event. The results will + * be available through the `result` event. If an error occurs, an + * `error` will be fired instead. + * @return {AlgoliaSearchHelper} + * @fires search + * @fires result + * @fires error + * @chainable */ -function isObject(val) { - return val !== null && typeof val === 'object'; -} +AlgoliaSearchHelper.prototype.search = function() { + this._search(); + return this; +}; /** - * Determine if a value is a Date - * - * @param {Object} val The value to test - * @returns {boolean} True if value is a Date, otherwise false + * Gets the search query parameters that would be sent to the Algolia Client + * for the hits + * @return {object} Query Parameters */ -function isDate(val) { - return toString.call(val) === '[object Date]'; -} +AlgoliaSearchHelper.prototype.getQuery = function() { + var state = this.state; + return requestBuilder._getHitsSearchParams(state); +}; /** - * Determine if a value is a File + * Start a search using a modified version of the current state. This method does + * not trigger the helper lifecycle and does not modify the state kept internally + * by the helper. This second aspect means that the next search call will be the + * same as a search call before calling searchOnce. + * @param {object} options can contain all the parameters that can be set to SearchParameters + * plus the index + * @param {function} [callback] optional callback executed when the response from the + * server is back. + * @return {promise|undefined} if a callback is passed the method returns undefined + * otherwise it returns a promise containing an object with two keys : + * - content with a SearchResults + * - state with the state used for the query as a SearchParameters + * @example + * // Changing the number of records returned per page to 1 + * // This example uses the callback API + * var state = helper.searchOnce({hitsPerPage: 1}, + * function(error, content, state) { + * // if an error occurred it will be passed in error, otherwise its value is null + * // content contains the results formatted as a SearchResults + * // state is the instance of SearchParameters used for this search + * }); + * @example + * // Changing the number of records returned per page to 1 + * // This example uses the promise API + * var state1 = helper.searchOnce({hitsPerPage: 1}) + * .then(promiseHandler); * - * @param {Object} val The value to test - * @returns {boolean} True if value is a File, otherwise false + * function promiseHandler(res) { + * // res contains + * // { + * // content : SearchResults + * // state : SearchParameters (the one used for this specific search) + * // } + * } */ -function isFile(val) { - return toString.call(val) === '[object File]'; -} +AlgoliaSearchHelper.prototype.searchOnce = function(options, cb) { + var tempState = !options ? this.state : this.state.setQueryParameters(options); + var queries = requestBuilder._getQueries(tempState.index, tempState); + var self = this; + + this._currentNbQueries++; + + this.emit('searchOnce', tempState); + + if (cb) { + this.client + .search(queries) + .then(function(content) { + self._currentNbQueries--; + if (self._currentNbQueries === 0) { + self.emit('searchQueueEmpty'); + } + + cb(null, new SearchResults(tempState, content.results), tempState); + }) + .catch(function(err) { + self._currentNbQueries--; + if (self._currentNbQueries === 0) { + self.emit('searchQueueEmpty'); + } + + cb(err, null, tempState); + }); + + return undefined; + } + + return this.client.search(queries).then(function(content) { + self._currentNbQueries--; + if (self._currentNbQueries === 0) self.emit('searchQueueEmpty'); + return { + content: new SearchResults(tempState, content.results), + state: tempState, + _originalResponse: content + }; + }, function(e) { + self._currentNbQueries--; + if (self._currentNbQueries === 0) self.emit('searchQueueEmpty'); + throw e; + }); +}; /** - * Determine if a value is a Blob - * - * @param {Object} val The value to test - * @returns {boolean} True if value is a Blob, otherwise false + * Structure of each result when using + * [`searchForFacetValues()`](reference.html#AlgoliaSearchHelper#searchForFacetValues) + * @typedef FacetSearchHit + * @type {object} + * @property {string} value the facet value + * @property {string} highlighted the facet value highlighted with the query string + * @property {number} count number of occurrence of this facet value + * @property {boolean} isRefined true if the value is already refined */ -function isBlob(val) { - return toString.call(val) === '[object Blob]'; -} /** - * Determine if a value is a Function - * - * @param {Object} val The value to test - * @returns {boolean} True if value is a Function, otherwise false + * Structure of the data resolved by the + * [`searchForFacetValues()`](reference.html#AlgoliaSearchHelper#searchForFacetValues) + * promise. + * @typedef FacetSearchResult + * @type {object} + * @property {FacetSearchHit} facetHits the results for this search for facet values + * @property {number} processingTimeMS time taken by the query inside the engine */ -function isFunction(val) { - return toString.call(val) === '[object Function]'; -} /** - * Determine if a value is a Stream + * Search for facet values based on an query and the name of a faceted attribute. This + * triggers a search and will return a promise. On top of using the query, it also sends + * the parameters from the state so that the search is narrowed down to only the possible values. * - * @param {Object} val The value to test - * @returns {boolean} True if value is a Stream, otherwise false + * See the description of [FacetSearchResult](reference.html#FacetSearchResult) + * @param {string} facet the name of the faceted attribute + * @param {string} query the string query for the search + * @param {number} [maxFacetHits] the maximum number values returned. Should be > 0 and <= 100 + * @param {object} [userState] the set of custom parameters to use on top of the current state. Setting a property to `undefined` removes + * it in the generated query. + * @return {promise.} the results of the search */ -function isStream(val) { - return isObject(val) && isFunction(val.pipe); -} +AlgoliaSearchHelper.prototype.searchForFacetValues = function(facet, query, maxFacetHits, userState) { + var clientHasSFFV = typeof this.client.searchForFacetValues === 'function'; + if ( + !clientHasSFFV && + typeof this.client.initIndex !== 'function' + ) { + throw new Error( + 'search for facet values (searchable) was called, but this client does not have a function client.searchForFacetValues or client.initIndex(index).searchForFacetValues' + ); + } + var state = this.state.setQueryParameters(userState || {}); + var isDisjunctive = state.isDisjunctiveFacet(facet); + var algoliaQuery = requestBuilder.getSearchForFacetQuery(facet, query, maxFacetHits, state); + + this._currentNbQueries++; + var self = this; + + this.emit('searchForFacetValues', state, facet, query); + var searchForFacetValuesPromise = clientHasSFFV + ? this.client.searchForFacetValues([{indexName: state.index, params: algoliaQuery}]) + : this.client.initIndex(state.index).searchForFacetValues(algoliaQuery); + + return searchForFacetValuesPromise.then(function addIsRefined(content) { + self._currentNbQueries--; + if (self._currentNbQueries === 0) self.emit('searchQueueEmpty'); + + content = Array.isArray(content) ? content[0] : content; + + content.facetHits = forEach(content.facetHits, function(f) { + f.isRefined = isDisjunctive ? + state.isDisjunctiveFacetRefined(facet, f.value) : + state.isFacetRefined(facet, f.value); + }); + + return content; + }, function(e) { + self._currentNbQueries--; + if (self._currentNbQueries === 0) self.emit('searchQueueEmpty'); + throw e; + }); +}; /** - * Determine if a value is a URLSearchParams object + * Sets the text query used for the search. * - * @param {Object} val The value to test - * @returns {boolean} True if value is a URLSearchParams object, otherwise false + * This method resets the current page to 0. + * @param {string} q the user query + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable */ -function isURLSearchParams(val) { - return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams; -} +AlgoliaSearchHelper.prototype.setQuery = function(q) { + this._change(this.state.setPage(0).setQuery(q)); + return this; +}; /** - * Trim excess whitespace off the beginning and end of a string + * Remove all the types of refinements except tags. A string can be provided to remove + * only the refinements of a specific attribute. For more advanced use case, you can + * provide a function instead. This function should follow the + * [clearCallback definition](#SearchParameters.clearCallback). * - * @param {String} str The String to trim - * @returns {String} The String freed of excess whitespace + * This method resets the current page to 0. + * @param {string} [name] optional name of the facet / attribute on which we want to remove all refinements + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable + * @example + * // Removing all the refinements + * helper.clearRefinements().search(); + * @example + * // Removing all the filters on a the category attribute. + * helper.clearRefinements('category').search(); + * @example + * // Removing only the exclude filters on the category facet. + * helper.clearRefinements(function(value, attribute, type) { + * return type === 'exclude' && attribute === 'category'; + * }).search(); */ -function trim(str) { - return str.replace(/^\s*/, '').replace(/\s*$/, ''); -} +AlgoliaSearchHelper.prototype.clearRefinements = function(name) { + this._change(this.state.setPage(0).clearRefinements(name)); + return this; +}; /** - * Determine if we're running in a standard browser environment - * - * This allows axios to run in a web worker, and react-native. - * Both environments support XMLHttpRequest, but not fully standard globals. + * Remove all the tag filters. * - * web workers: - * typeof window -> undefined - * typeof document -> undefined + * This method resets the current page to 0. + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable + */ +AlgoliaSearchHelper.prototype.clearTags = function() { + this._change(this.state.setPage(0).clearTags()); + return this; +}; + +/** + * Adds a disjunctive filter to a faceted attribute with the `value` provided. If the + * filter is already set, it doesn't change the filters. * - * react-native: - * navigator.product -> 'ReactNative' - * nativescript - * navigator.product -> 'NativeScript' or 'NS' + * This method resets the current page to 0. + * @param {string} facet the facet to refine + * @param {string} value the associated value (will be converted to string) + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable */ -function isStandardBrowserEnv() { - if (typeof navigator !== 'undefined' && (navigator.product === 'ReactNative' || - navigator.product === 'NativeScript' || - navigator.product === 'NS')) { - return false; - } - return ( - typeof window !== 'undefined' && - typeof document !== 'undefined' - ); -} +AlgoliaSearchHelper.prototype.addDisjunctiveFacetRefinement = function(facet, value) { + this._change(this.state.setPage(0).addDisjunctiveFacetRefinement(facet, value)); + return this; +}; /** - * Iterate over an Array or an Object invoking a function for each item. + * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#addDisjunctiveFacetRefinement} + */ +AlgoliaSearchHelper.prototype.addDisjunctiveRefine = function() { + return this.addDisjunctiveFacetRefinement.apply(this, arguments); +}; + +/** + * Adds a refinement on a hierarchical facet. It will throw + * an exception if the facet is not defined or if the facet + * is already refined. * - * If `obj` is an Array callback will be called passing - * the value, index, and complete array for each item. + * This method resets the current page to 0. + * @param {string} facet the facet name + * @param {string} path the hierarchical facet path + * @return {AlgoliaSearchHelper} + * @throws Error if the facet is not defined or if the facet is refined + * @chainable + * @fires change + */ +AlgoliaSearchHelper.prototype.addHierarchicalFacetRefinement = function(facet, value) { + this._change(this.state.setPage(0).addHierarchicalFacetRefinement(facet, value)); + return this; +}; + +/** + * Adds a an numeric filter to an attribute with the `operator` and `value` provided. If the + * filter is already set, it doesn't change the filters. * - * If 'obj' is an Object callback will be called passing - * the value, key, and complete object for each property. + * This method resets the current page to 0. + * @param {string} attribute the attribute on which the numeric filter applies + * @param {string} operator the operator of the filter + * @param {number} value the value of the filter + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable + */ +AlgoliaSearchHelper.prototype.addNumericRefinement = function(attribute, operator, value) { + this._change(this.state.setPage(0).addNumericRefinement(attribute, operator, value)); + return this; +}; + +/** + * Adds a filter to a faceted attribute with the `value` provided. If the + * filter is already set, it doesn't change the filters. * - * @param {Object|Array} obj The object to iterate - * @param {Function} fn The callback to invoke for each item + * This method resets the current page to 0. + * @param {string} facet the facet to refine + * @param {string} value the associated value (will be converted to string) + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable */ -function forEach(obj, fn) { - // Don't bother if no value provided - if (obj === null || typeof obj === 'undefined') { - return; - } +AlgoliaSearchHelper.prototype.addFacetRefinement = function(facet, value) { + this._change(this.state.setPage(0).addFacetRefinement(facet, value)); + return this; +}; - // Force an array if not already something iterable - if (typeof obj !== 'object') { - /*eslint no-param-reassign:0*/ - obj = [obj]; - } +/** + * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#addFacetRefinement} + */ +AlgoliaSearchHelper.prototype.addRefine = function() { + return this.addFacetRefinement.apply(this, arguments); +}; - if (isArray(obj)) { - // Iterate over array values - for (var i = 0, l = obj.length; i < l; i++) { - fn.call(null, obj[i], i, obj); - } - } else { - // Iterate over object keys - for (var key in obj) { - if (Object.prototype.hasOwnProperty.call(obj, key)) { - fn.call(null, obj[key], key, obj); - } - } - } -} /** - * Accepts varargs expecting each argument to be an object, then - * immutably merges the properties of each object and returns result. + * Adds a an exclusion filter to a faceted attribute with the `value` provided. If the + * filter is already set, it doesn't change the filters. * - * When multiple objects contain the same key the later object in - * the arguments list will take precedence. + * This method resets the current page to 0. + * @param {string} facet the facet to refine + * @param {string} value the associated value (will be converted to string) + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable + */ +AlgoliaSearchHelper.prototype.addFacetExclusion = function(facet, value) { + this._change(this.state.setPage(0).addExcludeRefinement(facet, value)); + return this; +}; + +/** + * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#addFacetExclusion} + */ +AlgoliaSearchHelper.prototype.addExclude = function() { + return this.addFacetExclusion.apply(this, arguments); +}; + +/** + * Adds a tag filter with the `tag` provided. If the + * filter is already set, it doesn't change the filters. * - * Example: + * This method resets the current page to 0. + * @param {string} tag the tag to add to the filter + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable + */ +AlgoliaSearchHelper.prototype.addTag = function(tag) { + this._change(this.state.setPage(0).addTagRefinement(tag)); + return this; +}; + +/** + * Removes an numeric filter to an attribute with the `operator` and `value` provided. If the + * filter is not set, it doesn't change the filters. * - * ```js - * var result = merge({foo: 123}, {foo: 456}); - * console.log(result.foo); // outputs 456 - * ``` + * Some parameters are optional, triggering different behavior: + * - if the value is not provided, then all the numeric value will be removed for the + * specified attribute/operator couple. + * - if the operator is not provided either, then all the numeric filter on this attribute + * will be removed. * - * @param {Object} obj1 Object to merge - * @returns {Object} Result of all merge properties + * This method resets the current page to 0. + * @param {string} attribute the attribute on which the numeric filter applies + * @param {string} [operator] the operator of the filter + * @param {number} [value] the value of the filter + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable */ -function merge(/* obj1, obj2, obj3, ... */) { - var result = {}; - function assignValue(val, key) { - if (typeof result[key] === 'object' && typeof val === 'object') { - result[key] = merge(result[key], val); - } else { - result[key] = val; - } - } +AlgoliaSearchHelper.prototype.removeNumericRefinement = function(attribute, operator, value) { + this._change(this.state.setPage(0).removeNumericRefinement(attribute, operator, value)); + return this; +}; - for (var i = 0, l = arguments.length; i < l; i++) { - forEach(arguments[i], assignValue); - } - return result; -} +/** + * Removes a disjunctive filter to a faceted attribute with the `value` provided. If the + * filter is not set, it doesn't change the filters. + * + * If the value is omitted, then this method will remove all the filters for the + * attribute. + * + * This method resets the current page to 0. + * @param {string} facet the facet to refine + * @param {string} [value] the associated value + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable + */ +AlgoliaSearchHelper.prototype.removeDisjunctiveFacetRefinement = function(facet, value) { + this._change(this.state.setPage(0).removeDisjunctiveFacetRefinement(facet, value)); + return this; +}; /** - * Function equal to merge with the difference being that no reference - * to original objects is kept. + * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#removeDisjunctiveFacetRefinement} + */ +AlgoliaSearchHelper.prototype.removeDisjunctiveRefine = function() { + return this.removeDisjunctiveFacetRefinement.apply(this, arguments); +}; + +/** + * Removes the refinement set on a hierarchical facet. + * @param {string} facet the facet name + * @return {AlgoliaSearchHelper} + * @throws Error if the facet is not defined or if the facet is not refined + * @fires change + * @chainable + */ +AlgoliaSearchHelper.prototype.removeHierarchicalFacetRefinement = function(facet) { + this._change(this.state.setPage(0).removeHierarchicalFacetRefinement(facet)); + + return this; +}; + +/** + * Removes a filter to a faceted attribute with the `value` provided. If the + * filter is not set, it doesn't change the filters. * - * @see merge - * @param {Object} obj1 Object to merge - * @returns {Object} Result of all merge properties + * If the value is omitted, then this method will remove all the filters for the + * attribute. + * + * This method resets the current page to 0. + * @param {string} facet the facet to refine + * @param {string} [value] the associated value + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable */ -function deepMerge(/* obj1, obj2, obj3, ... */) { - var result = {}; - function assignValue(val, key) { - if (typeof result[key] === 'object' && typeof val === 'object') { - result[key] = deepMerge(result[key], val); - } else if (typeof val === 'object') { - result[key] = deepMerge({}, val); - } else { - result[key] = val; - } - } +AlgoliaSearchHelper.prototype.removeFacetRefinement = function(facet, value) { + this._change(this.state.setPage(0).removeFacetRefinement(facet, value)); + return this; +}; - for (var i = 0, l = arguments.length; i < l; i++) { - forEach(arguments[i], assignValue); - } - return result; -} +/** + * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#removeFacetRefinement} + */ +AlgoliaSearchHelper.prototype.removeRefine = function() { + return this.removeFacetRefinement.apply(this, arguments); +}; /** - * Extends object a by mutably adding to it the properties of object b. + * Removes an exclusion filter to a faceted attribute with the `value` provided. If the + * filter is not set, it doesn't change the filters. * - * @param {Object} a The object to be extended - * @param {Object} b The object to copy properties from - * @param {Object} thisArg The object to bind function to - * @return {Object} The resulting value of object a + * If the value is omitted, then this method will remove all the filters for the + * attribute. + * + * This method resets the current page to 0. + * @param {string} facet the facet to refine + * @param {string} [value] the associated value + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable */ -function extend(a, b, thisArg) { - forEach(b, function assignValue(val, key) { - if (thisArg && typeof val === 'function') { - a[key] = bind(val, thisArg); - } else { - a[key] = val; - } - }); - return a; -} +AlgoliaSearchHelper.prototype.removeFacetExclusion = function(facet, value) { + this._change(this.state.setPage(0).removeExcludeRefinement(facet, value)); + return this; +}; -module.exports = { - isArray: isArray, - isArrayBuffer: isArrayBuffer, - isBuffer: isBuffer, - isFormData: isFormData, - isArrayBufferView: isArrayBufferView, - isString: isString, - isNumber: isNumber, - isObject: isObject, - isUndefined: isUndefined, - isDate: isDate, - isFile: isFile, - isBlob: isBlob, - isFunction: isFunction, - isStream: isStream, - isURLSearchParams: isURLSearchParams, - isStandardBrowserEnv: isStandardBrowserEnv, - forEach: forEach, - merge: merge, - deepMerge: deepMerge, - extend: extend, - trim: trim +/** + * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#removeFacetExclusion} + */ +AlgoliaSearchHelper.prototype.removeExclude = function() { + return this.removeFacetExclusion.apply(this, arguments); }; +/** + * Removes a tag filter with the `tag` provided. If the + * filter is not set, it doesn't change the filters. + * + * This method resets the current page to 0. + * @param {string} tag tag to remove from the filter + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable + */ +AlgoliaSearchHelper.prototype.removeTag = function(tag) { + this._change(this.state.setPage(0).removeTagRefinement(tag)); + return this; +}; -/***/ }), +/** + * Adds or removes an exclusion filter to a faceted attribute with the `value` provided. If + * the value is set then it removes it, otherwise it adds the filter. + * + * This method resets the current page to 0. + * @param {string} facet the facet to refine + * @param {string} value the associated value + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable + */ +AlgoliaSearchHelper.prototype.toggleFacetExclusion = function(facet, value) { + this._change(this.state.setPage(0).toggleExcludeFacetRefinement(facet, value)); + return this; +}; -/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/Links/GenerateLink.vue?vue&type=script&lang=js&": -/*!*****************************************************************************************************************************************************************************!*\ - !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/Links/GenerateLink.vue?vue&type=script&lang=js& ***! - \*****************************************************************************************************************************************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { +/** + * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#toggleFacetExclusion} + */ +AlgoliaSearchHelper.prototype.toggleExclude = function() { + return this.toggleFacetExclusion.apply(this, arguments); +}; -"use strict"; -__webpack_require__.r(__webpack_exports__); -// -// -// -// -// -// -// -// -/* harmony default export */ __webpack_exports__["default"] = ({ - components: {}, - data: function data() { - return {}; - }, - mounted: function mounted() {}, - methods: {} -}); +/** + * Adds or removes a filter to a faceted attribute with the `value` provided. If + * the value is set then it removes it, otherwise it adds the filter. + * + * This method can be used for conjunctive, disjunctive and hierarchical filters. + * + * This method resets the current page to 0. + * @param {string} facet the facet to refine + * @param {string} value the associated value + * @return {AlgoliaSearchHelper} + * @throws Error will throw an error if the facet is not declared in the settings of the helper + * @fires change + * @chainable + * @deprecated since version 2.19.0, see {@link AlgoliaSearchHelper#toggleFacetRefinement} + */ +AlgoliaSearchHelper.prototype.toggleRefinement = function(facet, value) { + return this.toggleFacetRefinement(facet, value); +}; -/***/ }), +/** + * Adds or removes a filter to a faceted attribute with the `value` provided. If + * the value is set then it removes it, otherwise it adds the filter. + * + * This method can be used for conjunctive, disjunctive and hierarchical filters. + * + * This method resets the current page to 0. + * @param {string} facet the facet to refine + * @param {string} value the associated value + * @return {AlgoliaSearchHelper} + * @throws Error will throw an error if the facet is not declared in the settings of the helper + * @fires change + * @chainable + */ +AlgoliaSearchHelper.prototype.toggleFacetRefinement = function(facet, value) { + this._change(this.state.setPage(0).toggleFacetRefinement(facet, value)); + return this; +}; -/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/LiveStats.vue?vue&type=script&lang=js&": -/*!********************************************************************************************************************************************************************!*\ - !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/LiveStats.vue?vue&type=script&lang=js& ***! - \********************************************************************************************************************************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { +/** + * @deprecated since version 2.4.0, see {@link AlgoliaSearchHelper#toggleFacetRefinement} + */ +AlgoliaSearchHelper.prototype.toggleRefine = function() { + return this.toggleFacetRefinement.apply(this, arguments); +}; -"use strict"; -__webpack_require__.r(__webpack_exports__); -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -/* harmony default export */ __webpack_exports__["default"] = ({ - components: {}, - data: function data() { - return {}; - }, - mounted: function mounted() {// Echo.private('emailBatch.1') - // .listen('.mailgun.event', (e) => { - // console.log(e); - // }) - // .listen('.batch.status', (e) => { - // console.log(e); - // }) - }, - methods: {} -}); +/** + * Adds or removes a tag filter with the `value` provided. If + * the value is set then it removes it, otherwise it adds the filter. + * + * This method resets the current page to 0. + * @param {string} tag tag to remove or add + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable + */ +AlgoliaSearchHelper.prototype.toggleTag = function(tag) { + this._change(this.state.setPage(0).toggleTagRefinement(tag)); + return this; +}; -/***/ }), +/** + * Increments the page number by one. + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable + * @example + * helper.setPage(0).nextPage().getPage(); + * // returns 1 + */ +AlgoliaSearchHelper.prototype.nextPage = function() { + return this.setPage(this.state.page + 1); +}; -/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/Publish/Publish.vue?vue&type=script&lang=js&": -/*!**************************************************************************************************************************************************************************!*\ - !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/Publish/Publish.vue?vue&type=script&lang=js& ***! - \**************************************************************************************************************************************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { +/** + * Decrements the page number by one. + * @fires change + * @return {AlgoliaSearchHelper} + * @chainable + * @example + * helper.setPage(1).previousPage().getPage(); + * // returns 0 + */ +AlgoliaSearchHelper.prototype.previousPage = function() { + return this.setPage(this.state.page - 1); +}; -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var vue_stepper__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue-stepper */ "./node_modules/vue-stepper/src/index.js"); -/* harmony import */ var vue_stepper__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(vue_stepper__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var _Step1UploadFile__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Step1UploadFile */ "./resources/js/components/Publish/Step1UploadFile.vue"); -/* harmony import */ var _Step2PrepareMail__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Step2PrepareMail */ "./resources/js/components/Publish/Step2PrepareMail.vue"); -/* harmony import */ var _Step3Send__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Step3Send */ "./resources/js/components/Publish/Step3Send.vue"); -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// +/** + * @private + */ +function setCurrentPage(page) { + if (page < 0) throw new Error('Page requested below 0.'); + + this._change(this.state.setPage(page)); + return this; +} /** - * Step 1 : Upload PDF and preview (add title, tags) - * Step 2 : Add email subject and content - * Step 3 : Review, send and track + * Change the current page + * @deprecated + * @param {number} page The page number + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable */ +AlgoliaSearchHelper.prototype.setCurrentPage = setCurrentPage; +/** + * Updates the current page. + * @function + * @param {number} page The page number + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable + */ +AlgoliaSearchHelper.prototype.setPage = setCurrentPage; +/** + * Updates the name of the index that will be targeted by the query. + * + * This method resets the current page to 0. + * @param {string} name the index name + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable + */ +AlgoliaSearchHelper.prototype.setIndex = function(name) { + this._change(this.state.setPage(0).setIndex(name)); + return this; +}; +/** + * Update a parameter of the search. This method reset the page + * + * The complete list of parameters is available on the + * [Algolia website](https://www.algolia.com/doc/rest#query-an-index). + * The most commonly used parameters have their own [shortcuts](#query-parameters-shortcuts) + * or benefit from higher-level APIs (all the kind of filters and facets have their own API) + * + * This method resets the current page to 0. + * @param {string} parameter name of the parameter to update + * @param {any} value new value of the parameter + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable + * @example + * helper.setQueryParameter('hitsPerPage', 20).search(); + */ +AlgoliaSearchHelper.prototype.setQueryParameter = function(parameter, value) { + this._change(this.state.setPage(0).setQueryParameter(parameter, value)); + return this; +}; -/* harmony default export */ __webpack_exports__["default"] = ({ - components: { - HorizontalStepper: vue_stepper__WEBPACK_IMPORTED_MODULE_0___default.a - }, - data: function data() { - return { - steps: [{ - icon: 'cloud_upload', - name: 'upload', - title: 'Mise en ligne du PDF', - subtitle: 'Création de la liseuse', - component: _Step1UploadFile__WEBPACK_IMPORTED_MODULE_1__["default"], - completed: false - }, { - icon: 'mail', - name: 'email', - title: 'Mise en forme du message', - subtitle: '', - component: _Step2PrepareMail__WEBPACK_IMPORTED_MODULE_2__["default"], - completed: false - }, { - icon: 'send', - name: 'review', - title: 'Récapitulatif et envoi', - subtitle: 'Suivi des envois', - component: _Step3Send__WEBPACK_IMPORTED_MODULE_3__["default"], - completed: false - }] - }; - }, - mounted: function mounted() {}, - methods: { - // Executed when @completed-step event is triggered - completeStep: function completeStep(payload) { - this.steps.forEach(function (step) { - if (step.name === payload.name) { - step.completed = true; - } - }); - }, - // Executed when @active-step event is triggered - isStepActive: function isStepActive(payload) { - this.steps.forEach(function (step) { - if (step.name === payload.name) { - if (step.completed === true) { - step.completed = false; - } - } - }); - }, - // Executed when @stepper-finished event is triggered - alert: function (_alert) { - function alert(_x) { - return _alert.apply(this, arguments); - } +/** + * Set the whole state (warning: will erase previous state) + * @param {SearchParameters} newState the whole new state + * @return {AlgoliaSearchHelper} + * @fires change + * @chainable + */ +AlgoliaSearchHelper.prototype.setState = function(newState) { + this._change(SearchParameters.make(newState)); + return this; +}; - alert.toString = function () { - return _alert.toString(); - }; +/** + * Get the current search state stored in the helper. This object is immutable. + * @param {string[]} [filters] optional filters to retrieve only a subset of the state + * @return {SearchParameters|object} if filters is specified a plain object is + * returned containing only the requested fields, otherwise return the unfiltered + * state + * @example + * // Get the complete state as stored in the helper + * helper.getState(); + * @example + * // Get a part of the state with all the refinements on attributes and the query + * helper.getState(['query', 'attribute:category']); + */ +AlgoliaSearchHelper.prototype.getState = function(filters) { + if (filters === undefined) return this.state; + return this.state.filter(filters); +}; - return alert; - }(function (payload) { - alert('end'); - }) +/** + * DEPRECATED Get part of the state as a query string. By default, the output keys will not + * be prefixed and will only take the applied refinements and the query. + * @deprecated + * @param {object} [options] May contain the following parameters : + * + * **filters** : possible values are all the keys of the [SearchParameters](#searchparameters), `index` for + * the index, all the refinements with `attribute:*` or for some specific attributes with + * `attribute:theAttribute` + * + * **prefix** : prefix in front of the keys + * + * **moreAttributes** : more values to be added in the query string. Those values + * won't be prefixed. + * @return {string} the query string + */ +AlgoliaSearchHelper.prototype.getStateAsQueryString = function getStateAsQueryString(options) { + var filters = options && options.filters || ['query', 'attribute:*']; + var partialState = this.getState(filters); + + return url.getQueryStringFromState(partialState, options); +}; + +/** + * DEPRECATED Read a query string and return an object containing the state. Use + * url module. + * @deprecated + * @static + * @param {string} queryString the query string that will be decoded + * @param {object} options accepted options : + * - prefix : the prefix used for the saved attributes, you have to provide the + * same that was used for serialization + * @return {object} partial search parameters object (same properties than in the + * SearchParameters but not exhaustive) + * @see {@link url#getStateFromQueryString} + */ +AlgoliaSearchHelper.getConfigurationFromQueryString = url.getStateFromQueryString; + +/** + * DEPRECATED Retrieve an object of all the properties that are not understandable as helper + * parameters. Use url module. + * @deprecated + * @static + * @param {string} queryString the query string to read + * @param {object} options the options + * - prefixForParameters : prefix used for the helper configuration keys + * @return {object} the object containing the parsed configuration that doesn't + * to the helper + */ +AlgoliaSearchHelper.getForeignConfigurationInQueryString = url.getUnrecognizedParametersInQueryString; + +/** + * DEPRECATED Overrides part of the state with the properties stored in the provided query + * string. + * @deprecated + * @param {string} queryString the query string containing the informations to url the state + * @param {object} options optional parameters : + * - prefix : prefix used for the algolia parameters + * - triggerChange : if set to true the state update will trigger a change event + */ +AlgoliaSearchHelper.prototype.setStateFromQueryString = function(queryString, options) { + var triggerChange = options && options.triggerChange || false; + var configuration = url.getStateFromQueryString(queryString, options); + var updatedState = this.state.setQueryParameters(configuration); + + if (triggerChange) this.setState(updatedState); + else this.overrideStateWithoutTriggeringChangeEvent(updatedState); +}; + +/** + * Override the current state without triggering a change event. + * Do not use this method unless you know what you are doing. (see the example + * for a legit use case) + * @param {SearchParameters} newState the whole new state + * @return {AlgoliaSearchHelper} + * @example + * helper.on('change', function(state){ + * // In this function you might want to find a way to store the state in the url/history + * updateYourURL(state) + * }) + * window.onpopstate = function(event){ + * // This is naive though as you should check if the state is really defined etc. + * helper.overrideStateWithoutTriggeringChangeEvent(event.state).search() + * } + * @chainable + */ +AlgoliaSearchHelper.prototype.overrideStateWithoutTriggeringChangeEvent = function(newState) { + this.state = new SearchParameters(newState); + return this; +}; + +/** + * @deprecated since 2.4.0, see {@link AlgoliaSearchHelper#hasRefinements} + */ +AlgoliaSearchHelper.prototype.isRefined = function(facet, value) { + if (this.state.isConjunctiveFacet(facet)) { + return this.state.isFacetRefined(facet, value); + } else if (this.state.isDisjunctiveFacet(facet)) { + return this.state.isDisjunctiveFacetRefined(facet, value); } -}); -/***/ }), + throw new Error(facet + + ' is not properly defined in this helper configuration' + + '(use the facets or disjunctiveFacets keys to configure it)'); +}; -/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/Publish/Step1UploadFile.vue?vue&type=script&lang=js&": -/*!**********************************************************************************************************************************************************************************!*\ - !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/Publish/Step1UploadFile.vue?vue&type=script&lang=js& ***! - \**********************************************************************************************************************************************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { +/** + * Check if an attribute has any numeric, conjunctive, disjunctive or hierarchical filters. + * @param {string} attribute the name of the attribute + * @return {boolean} true if the attribute is filtered by at least one value + * @example + * // hasRefinements works with numeric, conjunctive, disjunctive and hierarchical filters + * helper.hasRefinements('price'); // false + * helper.addNumericRefinement('price', '>', 100); + * helper.hasRefinements('price'); // true + * + * helper.hasRefinements('color'); // false + * helper.addFacetRefinement('color', 'blue'); + * helper.hasRefinements('color'); // true + * + * helper.hasRefinements('material'); // false + * helper.addDisjunctiveFacetRefinement('material', 'plastic'); + * helper.hasRefinements('material'); // true + * + * helper.hasRefinements('categories'); // false + * helper.toggleFacetRefinement('categories', 'kitchen > knife'); + * helper.hasRefinements('categories'); // true + * + */ +AlgoliaSearchHelper.prototype.hasRefinements = function(attribute) { + if (!isEmpty(this.state.getNumericRefinements(attribute))) { + return true; + } else if (this.state.isConjunctiveFacet(attribute)) { + return this.state.isFacetRefined(attribute); + } else if (this.state.isDisjunctiveFacet(attribute)) { + return this.state.isDisjunctiveFacetRefined(attribute); + } else if (this.state.isHierarchicalFacet(attribute)) { + return this.state.isHierarchicalFacetRefined(attribute); + } + + // there's currently no way to know that the user did call `addNumericRefinement` at some point + // thus we cannot distinguish if there once was a numeric refinement that was cleared + // so we will return false in every other situations to be consistent + // while what we should do here is throw because we did not find the attribute in any type + // of refinement + return false; +}; -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var vue_upload_component__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue-upload-component */ "./node_modules/vue-upload-component/dist/vue-upload-component.js"); -/* harmony import */ var vue_upload_component__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(vue_upload_component__WEBPACK_IMPORTED_MODULE_0__); -/* harmony import */ var vue_simple_progress__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vue-simple-progress */ "./node_modules/vue-simple-progress/dist/vue-simple-progress.js"); -/* harmony import */ var vue_simple_progress__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(vue_simple_progress__WEBPACK_IMPORTED_MODULE_1__); -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// +/** + * Check if a value is excluded for a specific faceted attribute. If the value + * is omitted then the function checks if there is any excluding refinements. + * + * @param {string} facet name of the attribute for used for faceting + * @param {string} [value] optional value. If passed will test that this value + * is filtering the given facet. + * @return {boolean} true if refined + * @example + * helper.isExcludeRefined('color'); // false + * helper.isExcludeRefined('color', 'blue') // false + * helper.isExcludeRefined('color', 'red') // false + * + * helper.addFacetExclusion('color', 'red'); + * + * helper.isExcludeRefined('color'); // true + * helper.isExcludeRefined('color', 'blue') // false + * helper.isExcludeRefined('color', 'red') // true + */ +AlgoliaSearchHelper.prototype.isExcluded = function(facet, value) { + return this.state.isExcludeRefined(facet, value); +}; +/** + * @deprecated since 2.4.0, see {@link AlgoliaSearchHelper#hasRefinements} + */ +AlgoliaSearchHelper.prototype.isDisjunctiveRefined = function(facet, value) { + return this.state.isDisjunctiveFacetRefined(facet, value); +}; -/* harmony default export */ __webpack_exports__["default"] = ({ - components: { - FileUpload: vue_upload_component__WEBPACK_IMPORTED_MODULE_0___default.a, - ProgressBar: vue_simple_progress__WEBPACK_IMPORTED_MODULE_1___default.a - }, - data: function data() { - return { - files: [], - collections: [], - tags: [], - file_collection: 1, - file_ref: null, - csrf: document.querySelectorAll('meta[name="csrf-token"]')[0].content - }; - }, - computed: { - fileValid: function fileValid() { - if (this.files.length < 1) return; - return this.checkFileValid(this.files[0]); - }, - file_data: function file_data() { - return { - collection_id: this.file_collection, - ref: this.file_ref, - tags: this.tags - }; - } - }, - methods: { - checkFileValid: function checkFileValid(file) { - return file.type === 'application/pdf'; - }, - inputFile: function inputFile(newFile, oldFile) { - if (newFile && (Boolean(newFile) !== Boolean(oldFile) || oldFile.error !== newFile.error) && !this.$refs.upload.active && this.checkFileValid(newFile)) { - this.$refs.upload.active = true; - } +/** + * Check if the string is a currently filtering tag. + * @param {string} tag tag to check + * @return {boolean} + */ +AlgoliaSearchHelper.prototype.hasTag = function(tag) { + return this.state.isTagRefined(tag); +}; - if (newFile.success === true) { - this.$emit('can-continue', { - value: true - }); - this.$root.publishState.file = newFile.response.data; - } - } - }, - mounted: function mounted() { - var _this = this; +/** + * @deprecated since 2.4.0, see {@link AlgoliaSearchHelper#hasTag} + */ +AlgoliaSearchHelper.prototype.isTagRefined = function() { + return this.hasTagRefinements.apply(this, arguments); +}; - this.$emit('can-continue', { - value: true + +/** + * Get the name of the currently used index. + * @return {string} + * @example + * helper.setIndex('highestPrice_products').getIndex(); + * // returns 'highestPrice_products' + */ +AlgoliaSearchHelper.prototype.getIndex = function() { + return this.state.index; +}; + +function getCurrentPage() { + return this.state.page; +} + +/** + * Get the currently selected page + * @deprecated + * @return {number} the current page + */ +AlgoliaSearchHelper.prototype.getCurrentPage = getCurrentPage; +/** + * Get the currently selected page + * @function + * @return {number} the current page + */ +AlgoliaSearchHelper.prototype.getPage = getCurrentPage; + +/** + * Get all the tags currently set to filters the results. + * + * @return {string[]} The list of tags currently set. + */ +AlgoliaSearchHelper.prototype.getTags = function() { + return this.state.tagRefinements; +}; + +/** + * Get a parameter of the search by its name. It is possible that a parameter is directly + * defined in the index dashboard, but it will be undefined using this method. + * + * The complete list of parameters is + * available on the + * [Algolia website](https://www.algolia.com/doc/rest#query-an-index). + * The most commonly used parameters have their own [shortcuts](#query-parameters-shortcuts) + * or benefit from higher-level APIs (all the kind of filters have their own API) + * @param {string} parameterName the parameter name + * @return {any} the parameter value + * @example + * var hitsPerPage = helper.getQueryParameter('hitsPerPage'); + */ +AlgoliaSearchHelper.prototype.getQueryParameter = function(parameterName) { + return this.state.getQueryParameter(parameterName); +}; + +/** + * Get the list of refinements for a given attribute. This method works with + * conjunctive, disjunctive, excluding and numerical filters. + * + * See also SearchResults#getRefinements + * + * @param {string} facetName attribute name used for faceting + * @return {Array.} All Refinement are objects that contain a value, and + * a type. Numeric also contains an operator. + * @example + * helper.addNumericRefinement('price', '>', 100); + * helper.getRefinements('price'); + * // [ + * // { + * // "value": [ + * // 100 + * // ], + * // "operator": ">", + * // "type": "numeric" + * // } + * // ] + * @example + * helper.addFacetRefinement('color', 'blue'); + * helper.addFacetExclusion('color', 'red'); + * helper.getRefinements('color'); + * // [ + * // { + * // "value": "blue", + * // "type": "conjunctive" + * // }, + * // { + * // "value": "red", + * // "type": "exclude" + * // } + * // ] + * @example + * helper.addDisjunctiveFacetRefinement('material', 'plastic'); + * // [ + * // { + * // "value": "plastic", + * // "type": "disjunctive" + * // } + * // ] + */ +AlgoliaSearchHelper.prototype.getRefinements = function(facetName) { + var refinements = []; + + if (this.state.isConjunctiveFacet(facetName)) { + var conjRefinements = this.state.getConjunctiveRefinements(facetName); + + forEach(conjRefinements, function(r) { + refinements.push({ + value: r, + type: 'conjunctive' + }); }); - axios.get('/publish/collections').then(function (d) { - return _this.collections = d.data.data; + + var excludeRefinements = this.state.getExcludeRefinements(facetName); + + forEach(excludeRefinements, function(r) { + refinements.push({ + value: r, + type: 'exclude' + }); }); - axios.get('/publish/tags').then(function (d) { - var tags = d.data.data; - $("#file_tags").selectize({ - placeholder: 'Mots-clés pour la recherche', - persist: false, - createOnBlur: true, - create: true, - options: tags, - plugins: ['remove_button'], - onChange: function onChange(v) { - return _this.tags = v; - } + } else if (this.state.isDisjunctiveFacet(facetName)) { + var disjRefinements = this.state.getDisjunctiveRefinements(facetName); + + forEach(disjRefinements, function(r) { + refinements.push({ + value: r, + type: 'disjunctive' }); }); } -}); -/***/ }), + var numericRefinements = this.state.getNumericRefinements(facetName); -/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/Publish/Step2PrepareMail.vue?vue&type=script&lang=js&": -/*!***********************************************************************************************************************************************************************************!*\ - !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/Publish/Step2PrepareMail.vue?vue&type=script&lang=js& ***! - \***********************************************************************************************************************************************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { + forEach(numericRefinements, function(value, operator) { + refinements.push({ + value: value, + operator: operator, + type: 'numeric' + }); + }); -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var _ckeditor_ckeditor5_build_classic__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @ckeditor/ckeditor5-build-classic */ "./node_modules/@ckeditor/ckeditor5-build-classic/build/ckeditor.js"); -/* harmony import */ var _ckeditor_ckeditor5_build_classic__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_ckeditor_ckeditor5_build_classic__WEBPACK_IMPORTED_MODULE_0__); -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// + return refinements; +}; -/* harmony default export */ __webpack_exports__["default"] = ({ - components: {}, - data: function data() { - return { - upload_result: this.$root.publishState.file, - editor: _ckeditor_ckeditor5_build_classic__WEBPACK_IMPORTED_MODULE_0___default.a, - email: { - content: "", - subject: "" - }, - csrf: document.querySelectorAll('meta[name="csrf-token"]')[0].content, - editorConfig: {} - }; - }, - watch: { - email: { - deep: true, - handler: function handler(val, old) { - if (val.editorData !== '' && val.subject !== '') { - this.$root.publishState.email = val; - this.$emit('can-continue', { - value: true - }); - } else { - this.$emit('can-continue', { - value: false - }); - } - } - } - }, - methods: {}, - mounted: function mounted() { - $('#previewModal').on('show.bs.modal', this.showModal); - } -}); +/** + * Return the current refinement for the (attribute, operator) + * @param {string} attribute attribute in the record + * @param {string} operator operator applied on the refined values + * @return {Array.} refined values + */ +AlgoliaSearchHelper.prototype.getNumericRefinement = function(attribute, operator) { + return this.state.getNumericRefinement(attribute, operator); +}; -/***/ }), +/** + * Get the current breadcrumb for a hierarchical facet, as an array + * @param {string} facetName Hierarchical facet name + * @return {array.} the path as an array of string + */ +AlgoliaSearchHelper.prototype.getHierarchicalFacetBreadcrumb = function(facetName) { + return this.state.getHierarchicalFacetBreadcrumb(facetName); +}; -/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/Publish/Step3Send.vue?vue&type=script&lang=js&": -/*!****************************************************************************************************************************************************************************!*\ - !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/Publish/Step3Send.vue?vue&type=script&lang=js& ***! - \****************************************************************************************************************************************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { +// /////////// PRIVATE -"use strict"; -__webpack_require__.r(__webpack_exports__); -/* harmony import */ var vue_simple_progress__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue-simple-progress */ "./node_modules/vue-simple-progress/dist/vue-simple-progress.js"); -/* harmony import */ var vue_simple_progress__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(vue_simple_progress__WEBPACK_IMPORTED_MODULE_0__); -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// +/** + * Perform the underlying queries + * @private + * @return {undefined} + * @fires search + * @fires result + * @fires error + */ +AlgoliaSearchHelper.prototype._search = function() { + var state = this.state; + var mainQueries = requestBuilder._getQueries(state.index, state); + + var states = [{ + state: state, + queriesCount: mainQueries.length, + helper: this + }]; + + this.emit('search', state, this.lastResults); + + var derivedQueries = map(this.derivedHelpers, function(derivedHelper) { + var derivedState = derivedHelper.getModifiedState(state); + var queries = requestBuilder._getQueries(derivedState.index, derivedState); + states.push({ + state: derivedState, + queriesCount: queries.length, + helper: derivedHelper + }); + derivedHelper.emit('search', derivedState, derivedHelper.lastResults); + return queries; + }); -/* harmony default export */ __webpack_exports__["default"] = ({ - components: { - ProgressBar: vue_simple_progress__WEBPACK_IMPORTED_MODULE_0___default.a - }, - data: function data() { - return { - upload_result: this.$root.publishState.file, - recipients_count: 0, - status: 'En attente', - counters: { - delivered: 0, - opened: 0, - clicked: 0 - }, - publishing: false, - done: false, - statusData: { - status: null, - current: 0, - total: 0 - } - }; - }, - computed: { - progress: function progress() { - if (this.statusData.status === 'init' || this.statusData.total == 0) { - return 0; - } + var queries = mainQueries.concat(flatten(derivedQueries)); + var queryId = this._queryId++; - return Math.ceil(this.statusData.current * 100 / this.statusData.total); - } - }, - methods: { - processMailEvent: function processMailEvent(e) { - if (e.data.event === 'delivered') this.counters.delivered++; - if (e.data.event === 'opened') this.counters.opened++; - }, - processProgressEvent: function processProgressEvent(e) { - if (this.done) return; - this.statusData = e.data; + this._currentNbQueries++; - switch (e.data.status) { - case 'init': - this.status = "Préparation en cours"; - break; + try { + this.client.search(queries) + .then(this._dispatchAlgoliaResponse.bind(this, states, queryId)) + .catch(this._dispatchAlgoliaError.bind(this, queryId)); + } catch (err) { + // If we reach this part, we're in an internal error state + this.emit('error', err); + } +}; - case 'processing': - this.status = "Traitement en cours : (".concat(e.data.current, " / ").concat(e.data.total, ")"); - break; +/** + * Transform the responses as sent by the server and transform them into a user + * usable object that merge the results of all the batch requests. It will dispatch + * over the different helper + derived helpers (when there are some). + * @private + * @param {array.<{SearchParameters, AlgoliaQueries, AlgoliaSearchHelper}>} + * state state used for to generate the request + * @param {number} queryId id of the current request + * @param {object} content content of the response + * @return {undefined} + */ +AlgoliaSearchHelper.prototype._dispatchAlgoliaResponse = function(states, queryId, content) { + // FIXME remove the number of outdated queries discarded instead of just one - case 'done': - this.status = "Termin\xE9, ".concat(e.data.total, " emails envoy\xE9s"); - this.done = true; - this.$emit('can-continue', { - value: true - }); - } - }, - publish: function publish() { - var _this = this; + if (queryId < this._lastQueryIdReceived) { + // Outdated answer + return; + } - axios({ - method: 'post', - url: '/publish', - data: { - data: this.$root.publishState - } - }).then(function (d) { - Echo["private"]("emailBatch.".concat(d.data.data)).listen('.mailgun.event', _this.processMailEvent).listen('.batch.status', _this.processProgressEvent); - _this.publishing = true; - }); - } - }, - mounted: function mounted() { - var _this2 = this; + this._currentNbQueries -= (queryId - this._lastQueryIdReceived); + this._lastQueryIdReceived = queryId; - axios.get('publish/recipients').then(function (d) { - return _this2.recipients_count = d.data.data; - }); + if (this._currentNbQueries === 0) this.emit('searchQueueEmpty'); + + var results = content.results.slice(); + forEach(states, function(s) { + var state = s.state; + var queriesCount = s.queriesCount; + var helper = s.helper; + var specificResults = results.splice(0, queriesCount); + + var formattedResponse = helper.lastResults = new SearchResults(state, specificResults); + helper.emit('result', formattedResponse, state); + }); +}; + +AlgoliaSearchHelper.prototype._dispatchAlgoliaError = function(queryId, err) { + if (queryId < this._lastQueryIdReceived) { + // Outdated answer + return; } -}); -/***/ }), + this._currentNbQueries -= queryId - this._lastQueryIdReceived; + this._lastQueryIdReceived = queryId; -/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/Stats/MgStats.vue?vue&type=script&lang=js&": -/*!************************************************************************************************************************************************************************!*\ - !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/Stats/MgStats.vue?vue&type=script&lang=js& ***! - \************************************************************************************************************************************************************************/ -/*! exports provided: default */ -/***/ (function(module, __webpack_exports__, __webpack_require__) { + this.emit('error', err); -"use strict"; -__webpack_require__.r(__webpack_exports__); -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -// -/* harmony default export */ __webpack_exports__["default"] = ({ - components: {}, - props: ['icon', 'current', 'total', 'text'], - data: function data() { - return {}; - }, - mounted: function mounted() { - Echo["private"]('emailBatch.1').listen('.mailgun.event', function (e) { - console.log(e); - }).listen('.batch.status', function (e) { - console.log(e); - }); - }, - methods: {} -}); + if (this._currentNbQueries === 0) this.emit('searchQueueEmpty'); +}; -/***/ }), +AlgoliaSearchHelper.prototype.containsRefinement = function(query, facetFilters, numericFilters, tagFilters) { + return query || + facetFilters.length !== 0 || + numericFilters.length !== 0 || + tagFilters.length !== 0; +}; -/***/ "./node_modules/base64-js/index.js": -/*!*****************************************!*\ - !*** ./node_modules/base64-js/index.js ***! - \*****************************************/ -/*! no static exports found */ -/***/ (function(module, exports, __webpack_require__) { +/** + * Test if there are some disjunctive refinements on the facet + * @private + * @param {string} facet the attribute to test + * @return {boolean} + */ +AlgoliaSearchHelper.prototype._hasDisjunctiveRefinements = function(facet) { + return this.state.disjunctiveRefinements[facet] && + this.state.disjunctiveRefinements[facet].length > 0; +}; -"use strict"; +AlgoliaSearchHelper.prototype._change = function(newState) { + if (newState !== this.state) { + this.state = newState; + this.emit('change', this.state, this.lastResults); + } +}; +/** + * Clears the cache of the underlying Algolia client. + * @return {AlgoliaSearchHelper} + */ +AlgoliaSearchHelper.prototype.clearCache = function() { + this.client.clearCache && this.client.clearCache(); + return this; +}; -exports.byteLength = byteLength -exports.toByteArray = toByteArray -exports.fromByteArray = fromByteArray +/** + * Updates the internal client instance. If the reference of the clients + * are equal then no update is actually done. + * @param {AlgoliaSearch} newClient an AlgoliaSearch client + * @return {AlgoliaSearchHelper} + */ +AlgoliaSearchHelper.prototype.setClient = function(newClient) { + if (this.client === newClient) return this; -var lookup = [] -var revLookup = [] -var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array + if (newClient.addAlgoliaAgent && !doesClientAgentContainsHelper(newClient)) { + newClient.addAlgoliaAgent('JS Helper (' + version + ')'); + } + this.client = newClient; -var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' -for (var i = 0, len = code.length; i < len; ++i) { - lookup[i] = code[i] - revLookup[code.charCodeAt(i)] = i -} + return this; +}; -// Support decoding URL-safe base64 strings, as Node.js does. -// See: https://en.wikipedia.org/wiki/Base64#URL_applications -revLookup['-'.charCodeAt(0)] = 62 -revLookup['_'.charCodeAt(0)] = 63 +/** + * Gets the instance of the currently used client. + * @return {AlgoliaSearch} + */ +AlgoliaSearchHelper.prototype.getClient = function() { + return this.client; +}; -function getLens (b64) { - var len = b64.length +/** + * Creates an derived instance of the Helper. A derived helper + * is a way to request other indices synchronised with the lifecycle + * of the main Helper. This mechanism uses the multiqueries feature + * of Algolia to aggregate all the requests in a single network call. + * + * This method takes a function that is used to create a new SearchParameter + * that will be used to create requests to Algolia. Those new requests + * are created just before the `search` event. The signature of the function + * is `SearchParameters -> SearchParameters`. + * + * This method returns a new DerivedHelper which is an EventEmitter + * that fires the same `search`, `result` and `error` events. Those + * events, however, will receive data specific to this DerivedHelper + * and the SearchParameters that is returned by the call of the + * parameter function. + * @param {function} fn SearchParameters -> SearchParameters + * @return {DerivedHelper} + */ +AlgoliaSearchHelper.prototype.derive = function(fn) { + var derivedHelper = new DerivedHelper(this, fn); + this.derivedHelpers.push(derivedHelper); + return derivedHelper; +}; - if (len % 4 > 0) { - throw new Error('Invalid string. Length must be a multiple of 4') - } +/** + * This method detaches a derived Helper from the main one. Prefer using the one from the + * derived helper itself, to remove the event listeners too. + * @private + * @return {undefined} + * @throws Error + */ +AlgoliaSearchHelper.prototype.detachDerivedHelper = function(derivedHelper) { + var pos = this.derivedHelpers.indexOf(derivedHelper); + if (pos === -1) throw new Error('Derived helper already detached'); + this.derivedHelpers.splice(pos, 1); +}; - // Trim off extra bytes after placeholder bytes are found - // See: https://github.com/beatgammit/base64-js/issues/42 - var validLen = b64.indexOf('=') - if (validLen === -1) validLen = len +/** + * This method returns true if there is currently at least one on-going search. + * @return {boolean} true if there is a search pending + */ +AlgoliaSearchHelper.prototype.hasPendingRequests = function() { + return this._currentNbQueries > 0; +}; - var placeHoldersLen = validLen === len - ? 0 - : 4 - (validLen % 4) +/** + * @typedef AlgoliaSearchHelper.NumericRefinement + * @type {object} + * @property {number[]} value the numbers that are used for filtering this attribute with + * the operator specified. + * @property {string} operator the faceting data: value, number of entries + * @property {string} type will be 'numeric' + */ - return [validLen, placeHoldersLen] -} +/** + * @typedef AlgoliaSearchHelper.FacetRefinement + * @type {object} + * @property {string} value the string use to filter the attribute + * @property {string} type the type of filter: 'conjunctive', 'disjunctive', 'exclude' + */ -// base64 is 4/3 + up to two characters of the original data -function byteLength (b64) { - var lens = getLens(b64) - var validLen = lens[0] - var placeHoldersLen = lens[1] - return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen -} -function _byteLength (b64, validLen, placeHoldersLen) { - return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +/* + * This function tests if the _ua parameter of the client + * already contains the JS Helper UA + */ +function doesClientAgentContainsHelper(client) { + // this relies on JS Client internal variable, this might break if implementation changes + var currentAgent = client._ua; + return !currentAgent ? false : + currentAgent.indexOf('JS Helper') !== -1; } -function toByteArray (b64) { - var tmp - var lens = getLens(b64) - var validLen = lens[0] - var placeHoldersLen = lens[1] +module.exports = AlgoliaSearchHelper; - var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) - var curByte = 0 +/***/ }), - // if there are placeholders, only get up to the last complete 4 chars - var len = placeHoldersLen > 0 - ? validLen - 4 - : validLen +/***/ "./node_modules/algoliasearch-helper/src/functions/formatSort.js": +/*!***********************************************************************!*\ + !*** ./node_modules/algoliasearch-helper/src/functions/formatSort.js ***! + \***********************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - var i - for (i = 0; i < len; i += 4) { - tmp = - (revLookup[b64.charCodeAt(i)] << 18) | - (revLookup[b64.charCodeAt(i + 1)] << 12) | - (revLookup[b64.charCodeAt(i + 2)] << 6) | - revLookup[b64.charCodeAt(i + 3)] - arr[curByte++] = (tmp >> 16) & 0xFF - arr[curByte++] = (tmp >> 8) & 0xFF - arr[curByte++] = tmp & 0xFF - } +"use strict"; - if (placeHoldersLen === 2) { - tmp = - (revLookup[b64.charCodeAt(i)] << 2) | - (revLookup[b64.charCodeAt(i + 1)] >> 4) - arr[curByte++] = tmp & 0xFF - } - if (placeHoldersLen === 1) { - tmp = - (revLookup[b64.charCodeAt(i)] << 10) | - (revLookup[b64.charCodeAt(i + 1)] << 4) | - (revLookup[b64.charCodeAt(i + 2)] >> 2) - arr[curByte++] = (tmp >> 8) & 0xFF - arr[curByte++] = tmp & 0xFF - } +var reduce = __webpack_require__(/*! lodash/reduce */ "./node_modules/lodash/reduce.js"); +var find = __webpack_require__(/*! lodash/find */ "./node_modules/lodash/find.js"); +var startsWith = __webpack_require__(/*! lodash/startsWith */ "./node_modules/lodash/startsWith.js"); - return arr -} +/** + * Transform sort format from user friendly notation to lodash format + * @param {string[]} sortBy array of predicate of the form "attribute:order" + * @return {array.} array containing 2 elements : attributes, orders + */ +module.exports = function formatSort(sortBy, defaults) { + return reduce(sortBy, function preparePredicate(out, sortInstruction) { + var sortInstructions = sortInstruction.split(':'); + if (defaults && sortInstructions.length === 1) { + var similarDefault = find(defaults, function(predicate) { + return startsWith(predicate, sortInstruction[0]); + }); + if (similarDefault) { + sortInstructions = similarDefault.split(':'); + } + } + out[0].push(sortInstructions[0]); + out[1].push(sortInstructions[1]); + return out; + }, [[], []]); +}; -function tripletToBase64 (num) { - return lookup[num >> 18 & 0x3F] + - lookup[num >> 12 & 0x3F] + - lookup[num >> 6 & 0x3F] + - lookup[num & 0x3F] -} -function encodeChunk (uint8, start, end) { - var tmp - var output = [] - for (var i = start; i < end; i += 3) { - tmp = - ((uint8[i] << 16) & 0xFF0000) + - ((uint8[i + 1] << 8) & 0xFF00) + - (uint8[i + 2] & 0xFF) - output.push(tripletToBase64(tmp)) - } - return output.join('') -} +/***/ }), -function fromByteArray (uint8) { - var tmp - var len = uint8.length - var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes - var parts = [] - var maxChunkLength = 16383 // must be multiple of 3 +/***/ "./node_modules/algoliasearch-helper/src/functions/inherits.js": +/*!*********************************************************************!*\ + !*** ./node_modules/algoliasearch-helper/src/functions/inherits.js ***! + \*********************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - // go through the array every three bytes, we'll deal with trailing stuff later - for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { - parts.push(encodeChunk( - uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) - )) - } +"use strict"; - // pad the end with zeros, but make sure to not forget the extra bytes - if (extraBytes === 1) { - tmp = uint8[len - 1] - parts.push( - lookup[tmp >> 2] + - lookup[(tmp << 4) & 0x3F] + - '==' - ) - } else if (extraBytes === 2) { - tmp = (uint8[len - 2] << 8) + uint8[len - 1] - parts.push( - lookup[tmp >> 10] + - lookup[(tmp >> 4) & 0x3F] + - lookup[(tmp << 2) & 0x3F] + - '=' - ) - } - return parts.join('') +function inherits(ctor, superCtor) { + ctor.prototype = Object.create(superCtor.prototype, { + constructor: { + value: ctor, + enumerable: false, + writable: true, + configurable: true + } + }); } +module.exports = inherits; + /***/ }), -/***/ "./node_modules/bootstrap/dist/js/bootstrap.js": -/*!*****************************************************!*\ - !*** ./node_modules/bootstrap/dist/js/bootstrap.js ***! - \*****************************************************/ +/***/ "./node_modules/algoliasearch-helper/src/functions/valToNumber.js": +/*!************************************************************************!*\ + !*** ./node_modules/algoliasearch-helper/src/functions/valToNumber.js ***! + \************************************************************************/ /*! no static exports found */ /***/ (function(module, exports, __webpack_require__) { -/*! - * Bootstrap v4.4.1 (https://getbootstrap.com/) - * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - */ -(function (global, factory) { - true ? factory(exports, __webpack_require__(/*! jquery */ "./node_modules/jquery/dist/jquery.js"), __webpack_require__(/*! popper.js */ "./node_modules/popper.js/dist/esm/popper.js")) : - undefined; -}(this, (function (exports, $, Popper) { 'use strict'; +"use strict"; - $ = $ && $.hasOwnProperty('default') ? $['default'] : $; - Popper = Popper && Popper.hasOwnProperty('default') ? Popper['default'] : Popper; - function _defineProperties(target, props) { - for (var i = 0; i < props.length; i++) { - var descriptor = props[i]; - descriptor.enumerable = descriptor.enumerable || false; - descriptor.configurable = true; - if ("value" in descriptor) descriptor.writable = true; - Object.defineProperty(target, descriptor.key, descriptor); - } +var map = __webpack_require__(/*! lodash/map */ "./node_modules/lodash/map.js"); +var isNumber = __webpack_require__(/*! lodash/isNumber */ "./node_modules/lodash/isNumber.js"); +var isString = __webpack_require__(/*! lodash/isString */ "./node_modules/lodash/isString.js"); +function valToNumber(v) { + if (isNumber(v)) { + return v; + } else if (isString(v)) { + return parseFloat(v); + } else if (Array.isArray(v)) { + return map(v, valToNumber); } - function _createClass(Constructor, protoProps, staticProps) { - if (protoProps) _defineProperties(Constructor.prototype, protoProps); - if (staticProps) _defineProperties(Constructor, staticProps); - return Constructor; - } + throw new Error('The value should be a number, a parseable string or an array of those.'); +} - function _defineProperty(obj, key, value) { - if (key in obj) { - Object.defineProperty(obj, key, { - value: value, - enumerable: true, - configurable: true, - writable: true - }); - } else { - obj[key] = value; - } +module.exports = valToNumber; - return obj; - } - function ownKeys(object, enumerableOnly) { - var keys = Object.keys(object); +/***/ }), - if (Object.getOwnPropertySymbols) { - var symbols = Object.getOwnPropertySymbols(object); - if (enumerableOnly) symbols = symbols.filter(function (sym) { - return Object.getOwnPropertyDescriptor(object, sym).enumerable; - }); - keys.push.apply(keys, symbols); - } +/***/ "./node_modules/algoliasearch-helper/src/requestBuilder.js": +/*!*****************************************************************!*\ + !*** ./node_modules/algoliasearch-helper/src/requestBuilder.js ***! + \*****************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - return keys; - } +"use strict"; - function _objectSpread2(target) { - for (var i = 1; i < arguments.length; i++) { - var source = arguments[i] != null ? arguments[i] : {}; - if (i % 2) { - ownKeys(Object(source), true).forEach(function (key) { - _defineProperty(target, key, source[key]); - }); - } else if (Object.getOwnPropertyDescriptors) { - Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); - } else { - ownKeys(Object(source)).forEach(function (key) { - Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); +var forEach = __webpack_require__(/*! lodash/forEach */ "./node_modules/lodash/forEach.js"); +var map = __webpack_require__(/*! lodash/map */ "./node_modules/lodash/map.js"); +var reduce = __webpack_require__(/*! lodash/reduce */ "./node_modules/lodash/reduce.js"); +var merge = __webpack_require__(/*! lodash/merge */ "./node_modules/lodash/merge.js"); + +var requestBuilder = { + /** + * Get all the queries to send to the client, those queries can used directly + * with the Algolia client. + * @private + * @return {object[]} The queries + */ + _getQueries: function getQueries(index, state) { + var queries = []; + + // One query for the hits + queries.push({ + indexName: index, + params: requestBuilder._getHitsSearchParams(state) + }); + + // One for each disjunctive facets + forEach(state.getRefinedDisjunctiveFacets(), function(refinedFacet) { + queries.push({ + indexName: index, + params: requestBuilder._getDisjunctiveFacetSearchParams(state, refinedFacet) + }); + }); + + // maybe more to get the root level of hierarchical facets when activated + forEach(state.getRefinedHierarchicalFacets(), function(refinedFacet) { + var hierarchicalFacet = state.getHierarchicalFacetByName(refinedFacet); + + var currentRefinement = state.getHierarchicalRefinement(refinedFacet); + // if we are deeper than level 0 (starting from `beer > IPA`) + // we want to get the root values + var separator = state._getHierarchicalFacetSeparator(hierarchicalFacet); + if (currentRefinement.length > 0 && currentRefinement[0].split(separator).length > 1) { + queries.push({ + indexName: index, + params: requestBuilder._getDisjunctiveFacetSearchParams(state, refinedFacet, true) }); } + }); + + return queries; + }, + + /** + * Build search parameters used to fetch hits + * @private + * @return {object.} + */ + _getHitsSearchParams: function(state) { + var facets = state.facets + .concat(state.disjunctiveFacets) + .concat(requestBuilder._getHitsHierarchicalFacetsAttributes(state)); + + + var facetFilters = requestBuilder._getFacetFilters(state); + var numericFilters = requestBuilder._getNumericFilters(state); + var tagFilters = requestBuilder._getTagFilters(state); + var additionalParams = { + facets: facets, + tagFilters: tagFilters + }; + + if (facetFilters.length > 0) { + additionalParams.facetFilters = facetFilters; } - return target; - } + if (numericFilters.length > 0) { + additionalParams.numericFilters = numericFilters; + } - function _inheritsLoose(subClass, superClass) { - subClass.prototype = Object.create(superClass.prototype); - subClass.prototype.constructor = subClass; - subClass.__proto__ = superClass; - } + return merge(state.getQueryParams(), additionalParams); + }, /** - * -------------------------------------------------------------------------- - * Bootstrap (v4.4.1): util.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * -------------------------------------------------------------------------- + * Build search parameters used to fetch a disjunctive facet + * @private + * @param {string} facet the associated facet name + * @param {boolean} hierarchicalRootLevel ?? FIXME + * @return {object} */ + _getDisjunctiveFacetSearchParams: function(state, facet, hierarchicalRootLevel) { + var facetFilters = requestBuilder._getFacetFilters(state, facet, hierarchicalRootLevel); + var numericFilters = requestBuilder._getNumericFilters(state, facet); + var tagFilters = requestBuilder._getTagFilters(state); + var additionalParams = { + hitsPerPage: 1, + page: 0, + attributesToRetrieve: [], + attributesToHighlight: [], + attributesToSnippet: [], + tagFilters: tagFilters, + analytics: false, + clickAnalytics: false + }; + + var hierarchicalFacet = state.getHierarchicalFacetByName(facet); + + if (hierarchicalFacet) { + additionalParams.facets = requestBuilder._getDisjunctiveHierarchicalFacetAttribute( + state, + hierarchicalFacet, + hierarchicalRootLevel + ); + } else { + additionalParams.facets = facet; + } + + if (numericFilters.length > 0) { + additionalParams.numericFilters = numericFilters; + } + + if (facetFilters.length > 0) { + additionalParams.facetFilters = facetFilters; + } + + return merge(state.getQueryParams(), additionalParams); + }, + /** - * ------------------------------------------------------------------------ - * Private TransitionEnd Helpers - * ------------------------------------------------------------------------ + * Return the numeric filters in an algolia request fashion + * @private + * @param {string} [facetName] the name of the attribute for which the filters should be excluded + * @return {string[]} the numeric filters in the algolia format */ + _getNumericFilters: function(state, facetName) { + if (state.numericFilters) { + return state.numericFilters; + } - var TRANSITION_END = 'transitionend'; - var MAX_UID = 1000000; - var MILLISECONDS_MULTIPLIER = 1000; // Shoutout AngusCroll (https://goo.gl/pxwQGp) - - function toType(obj) { - return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase(); - } + var numericFilters = []; - function getSpecialTransitionEndEvent() { - return { - bindType: TRANSITION_END, - delegateType: TRANSITION_END, - handle: function handle(event) { - if ($(event.target).is(this)) { - return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params + forEach(state.numericRefinements, function(operators, attribute) { + forEach(operators, function(values, operator) { + if (facetName !== attribute) { + forEach(values, function(value) { + if (Array.isArray(value)) { + var vs = map(value, function(v) { + return attribute + operator + v; + }); + numericFilters.push(vs); + } else { + numericFilters.push(attribute + operator + value); + } + }); } + }); + }); - return undefined; // eslint-disable-line no-undefined - } - }; - } + return numericFilters; + }, - function transitionEndEmulator(duration) { - var _this = this; + /** + * Return the tags filters depending + * @private + * @return {string} + */ + _getTagFilters: function(state) { + if (state.tagFilters) { + return state.tagFilters; + } + + return state.tagRefinements.join(','); + }, - var called = false; - $(this).one(Util.TRANSITION_END, function () { - called = true; - }); - setTimeout(function () { - if (!called) { - Util.triggerTransitionEnd(_this); - } - }, duration); - return this; - } - function setTransitionEndSupport() { - $.fn.emulateTransitionEnd = transitionEndEmulator; - $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent(); - } /** - * -------------------------------------------------------------------------- - * Public Util Api - * -------------------------------------------------------------------------- + * Build facetFilters parameter based on current refinements. The array returned + * contains strings representing the facet filters in the algolia format. + * @private + * @param {string} [facet] if set, the current disjunctive facet + * @return {array.} */ + _getFacetFilters: function(state, facet, hierarchicalRootLevel) { + var facetFilters = []; + forEach(state.facetsRefinements, function(facetValues, facetName) { + forEach(facetValues, function(facetValue) { + facetFilters.push(facetName + ':' + facetValue); + }); + }); - var Util = { - TRANSITION_END: 'bsTransitionEnd', - getUID: function getUID(prefix) { - do { - // eslint-disable-next-line no-bitwise - prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here - } while (document.getElementById(prefix)); + forEach(state.facetsExcludes, function(facetValues, facetName) { + forEach(facetValues, function(facetValue) { + facetFilters.push(facetName + ':-' + facetValue); + }); + }); - return prefix; - }, - getSelectorFromElement: function getSelectorFromElement(element) { - var selector = element.getAttribute('data-target'); + forEach(state.disjunctiveFacetsRefinements, function(facetValues, facetName) { + if (facetName === facet || !facetValues || facetValues.length === 0) return; + var orFilters = []; - if (!selector || selector === '#') { - var hrefAttr = element.getAttribute('href'); - selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : ''; - } + forEach(facetValues, function(facetValue) { + orFilters.push(facetName + ':' + facetValue); + }); - try { - return document.querySelector(selector) ? selector : null; - } catch (err) { - return null; + facetFilters.push(orFilters); + }); + + forEach(state.hierarchicalFacetsRefinements, function(facetValues, facetName) { + var facetValue = facetValues[0]; + + if (facetValue === undefined) { + return; } - }, - getTransitionDurationFromElement: function getTransitionDurationFromElement(element) { - if (!element) { - return 0; - } // Get transition-duration of the element + var hierarchicalFacet = state.getHierarchicalFacetByName(facetName); + var separator = state._getHierarchicalFacetSeparator(hierarchicalFacet); + var rootPath = state._getHierarchicalRootPath(hierarchicalFacet); + var attributeToRefine; + var attributesIndex; - var transitionDuration = $(element).css('transition-duration'); - var transitionDelay = $(element).css('transition-delay'); - var floatTransitionDuration = parseFloat(transitionDuration); - var floatTransitionDelay = parseFloat(transitionDelay); // Return 0 if element or transition duration is not found + // we ask for parent facet values only when the `facet` is the current hierarchical facet + if (facet === facetName) { + // if we are at the root level already, no need to ask for facet values, we get them from + // the hits query + if (facetValue.indexOf(separator) === -1 || (!rootPath && hierarchicalRootLevel === true) || + (rootPath && rootPath.split(separator).length === facetValue.split(separator).length)) { + return; + } - if (!floatTransitionDuration && !floatTransitionDelay) { - return 0; - } // If multiple durations are defined, take the first + if (!rootPath) { + attributesIndex = facetValue.split(separator).length - 2; + facetValue = facetValue.slice(0, facetValue.lastIndexOf(separator)); + } else { + attributesIndex = rootPath.split(separator).length - 1; + facetValue = rootPath; + } + attributeToRefine = hierarchicalFacet.attributes[attributesIndex]; + } else { + attributesIndex = facetValue.split(separator).length - 1; - transitionDuration = transitionDuration.split(',')[0]; - transitionDelay = transitionDelay.split(',')[0]; - return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER; - }, - reflow: function reflow(element) { - return element.offsetHeight; - }, - triggerTransitionEnd: function triggerTransitionEnd(element) { - $(element).trigger(TRANSITION_END); - }, - // TODO: Remove in v5 - supportsTransitionEnd: function supportsTransitionEnd() { - return Boolean(TRANSITION_END); - }, - isElement: function isElement(obj) { - return (obj[0] || obj).nodeType; - }, - typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) { - for (var property in configTypes) { - if (Object.prototype.hasOwnProperty.call(configTypes, property)) { - var expectedTypes = configTypes[property]; - var value = config[property]; - var valueType = value && Util.isElement(value) ? 'element' : toType(value); + attributeToRefine = hierarchicalFacet.attributes[attributesIndex]; + } - if (!new RegExp(expectedTypes).test(valueType)) { - throw new Error(componentName.toUpperCase() + ": " + ("Option \"" + property + "\" provided type \"" + valueType + "\" ") + ("but expected type \"" + expectedTypes + "\".")); - } - } + if (attributeToRefine) { + facetFilters.push([attributeToRefine + ':' + facetValue]); } - }, - findShadowRoot: function findShadowRoot(element) { - if (!document.documentElement.attachShadow) { - return null; - } // Can find the shadow root otherwise it'll return the document + }); + return facetFilters; + }, - if (typeof element.getRootNode === 'function') { - var root = element.getRootNode(); - return root instanceof ShadowRoot ? root : null; - } + _getHitsHierarchicalFacetsAttributes: function(state) { + var out = []; - if (element instanceof ShadowRoot) { - return element; - } // when we don't find a shadow root + return reduce( + state.hierarchicalFacets, + // ask for as much levels as there's hierarchical refinements + function getHitsAttributesForHierarchicalFacet(allAttributes, hierarchicalFacet) { + var hierarchicalRefinement = state.getHierarchicalRefinement(hierarchicalFacet.name)[0]; + // if no refinement, ask for root level + if (!hierarchicalRefinement) { + allAttributes.push(hierarchicalFacet.attributes[0]); + return allAttributes; + } - if (!element.parentNode) { - return null; - } + var separator = state._getHierarchicalFacetSeparator(hierarchicalFacet); + var level = hierarchicalRefinement.split(separator).length; + var newAttributes = hierarchicalFacet.attributes.slice(0, level + 1); - return Util.findShadowRoot(element.parentNode); - }, - jQueryDetection: function jQueryDetection() { - if (typeof $ === 'undefined') { - throw new TypeError('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.'); - } + return allAttributes.concat(newAttributes); + }, out); + }, - var version = $.fn.jquery.split(' ')[0].split('.'); - var minMajor = 1; - var ltMajor = 2; - var minMinor = 9; - var minPatch = 1; - var maxMajor = 4; + _getDisjunctiveHierarchicalFacetAttribute: function(state, hierarchicalFacet, rootLevel) { + var separator = state._getHierarchicalFacetSeparator(hierarchicalFacet); + if (rootLevel === true) { + var rootPath = state._getHierarchicalRootPath(hierarchicalFacet); + var attributeIndex = 0; - if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) { - throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0'); + if (rootPath) { + attributeIndex = rootPath.split(separator).length; } + return [hierarchicalFacet.attributes[attributeIndex]]; } - }; - Util.jQueryDetection(); - setTransitionEndSupport(); - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ + var hierarchicalRefinement = state.getHierarchicalRefinement(hierarchicalFacet.name)[0] || ''; + // if refinement is 'beers > IPA > Flying dog', + // then we want `facets: ['beers > IPA']` as disjunctive facet (parent level values) - var NAME = 'alert'; - var VERSION = '4.4.1'; - var DATA_KEY = 'bs.alert'; - var EVENT_KEY = "." + DATA_KEY; - var DATA_API_KEY = '.data-api'; - var JQUERY_NO_CONFLICT = $.fn[NAME]; - var Selector = { - DISMISS: '[data-dismiss="alert"]' - }; - var Event = { - CLOSE: "close" + EVENT_KEY, - CLOSED: "closed" + EVENT_KEY, - CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY - }; - var ClassName = { - ALERT: 'alert', - FADE: 'fade', - SHOW: 'show' - }; - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ + var parentLevel = hierarchicalRefinement.split(separator).length - 1; + return hierarchicalFacet.attributes.slice(0, parentLevel + 1); + }, - var Alert = - /*#__PURE__*/ - function () { - function Alert(element) { - this._element = element; - } // Getters + getSearchForFacetQuery: function(facetName, query, maxFacetHits, state) { + var stateForSearchForFacetValues = state.isDisjunctiveFacet(facetName) ? + state.clearRefinements(facetName) : + state; + var searchForFacetSearchParameters = { + facetQuery: query, + facetName: facetName + }; + if (typeof maxFacetHits === 'number') { + searchForFacetSearchParameters.maxFacetHits = maxFacetHits; + } + var queries = merge(requestBuilder._getHitsSearchParams(stateForSearchForFacetValues), searchForFacetSearchParameters); + return queries; + } +}; +module.exports = requestBuilder; - var _proto = Alert.prototype; - // Public - _proto.close = function close(element) { - var rootElement = this._element; +/***/ }), - if (element) { - rootElement = this._getRootElement(element); - } +/***/ "./node_modules/algoliasearch-helper/src/url.js": +/*!******************************************************!*\ + !*** ./node_modules/algoliasearch-helper/src/url.js ***! + \******************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - var customEvent = this._triggerCloseEvent(rootElement); +"use strict"; - if (customEvent.isDefaultPrevented()) { - return; - } - this._removeElement(rootElement); - }; +/** + * Module containing the functions to serialize and deserialize + * {SearchParameters} in the query string format + * @module algoliasearchHelper.url + */ - _proto.dispose = function dispose() { - $.removeData(this._element, DATA_KEY); - this._element = null; - } // Private - ; +var shortener = __webpack_require__(/*! ./SearchParameters/shortener */ "./node_modules/algoliasearch-helper/src/SearchParameters/shortener.js"); +var SearchParameters = __webpack_require__(/*! ./SearchParameters */ "./node_modules/algoliasearch-helper/src/SearchParameters/index.js"); - _proto._getRootElement = function _getRootElement(element) { - var selector = Util.getSelectorFromElement(element); - var parent = false; +var qs = __webpack_require__(/*! qs */ "./node_modules/qs/lib/index.js"); - if (selector) { - parent = document.querySelector(selector); - } +var bind = __webpack_require__(/*! lodash/bind */ "./node_modules/lodash/bind.js"); +var forEach = __webpack_require__(/*! lodash/forEach */ "./node_modules/lodash/forEach.js"); +var pick = __webpack_require__(/*! lodash/pick */ "./node_modules/lodash/pick.js"); +var map = __webpack_require__(/*! lodash/map */ "./node_modules/lodash/map.js"); +var mapKeys = __webpack_require__(/*! lodash/mapKeys */ "./node_modules/lodash/mapKeys.js"); +var mapValues = __webpack_require__(/*! lodash/mapValues */ "./node_modules/lodash/mapValues.js"); +var isString = __webpack_require__(/*! lodash/isString */ "./node_modules/lodash/isString.js"); +var isPlainObject = __webpack_require__(/*! lodash/isPlainObject */ "./node_modules/lodash/isPlainObject.js"); +var isEmpty = __webpack_require__(/*! lodash/isEmpty */ "./node_modules/lodash/isEmpty.js"); +var invert = __webpack_require__(/*! lodash/invert */ "./node_modules/lodash/invert.js"); - if (!parent) { - parent = $(element).closest("." + ClassName.ALERT)[0]; - } +var encode = __webpack_require__(/*! qs/lib/utils */ "./node_modules/qs/lib/utils.js").encode; - return parent; - }; +function recursiveEncode(input) { + if (isPlainObject(input)) { + return mapValues(input, recursiveEncode); + } + if (Array.isArray(input)) { + return map(input, recursiveEncode); + } + if (isString(input)) { + return encode(input); + } + return input; +} - _proto._triggerCloseEvent = function _triggerCloseEvent(element) { - var closeEvent = $.Event(Event.CLOSE); - $(element).trigger(closeEvent); - return closeEvent; - }; +var refinementsParameters = ['dFR', 'fR', 'nR', 'hFR', 'tR']; +var stateKeys = shortener.ENCODED_PARAMETERS; +function sortQueryStringValues(prefixRegexp, invertedMapping, a, b) { + if (prefixRegexp !== null) { + a = a.replace(prefixRegexp, ''); + b = b.replace(prefixRegexp, ''); + } - _proto._removeElement = function _removeElement(element) { - var _this = this; + a = invertedMapping[a] || a; + b = invertedMapping[b] || b; - $(element).removeClass(ClassName.SHOW); + if (stateKeys.indexOf(a) !== -1 || stateKeys.indexOf(b) !== -1) { + if (a === 'q') return -1; + if (b === 'q') return 1; - if (!$(element).hasClass(ClassName.FADE)) { - this._destroyElement(element); + var isARefinements = refinementsParameters.indexOf(a) !== -1; + var isBRefinements = refinementsParameters.indexOf(b) !== -1; + if (isARefinements && !isBRefinements) { + return 1; + } else if (isBRefinements && !isARefinements) { + return -1; + } + } - return; - } + return a.localeCompare(b); +} - var transitionDuration = Util.getTransitionDurationFromElement(element); - $(element).one(Util.TRANSITION_END, function (event) { - return _this._destroyElement(element, event); - }).emulateTransitionEnd(transitionDuration); - }; +/** + * Read a query string and return an object containing the state + * @param {string} queryString the query string that will be decoded + * @param {object} [options] accepted options : + * - prefix : the prefix used for the saved attributes, you have to provide the + * same that was used for serialization + * - mapping : map short attributes to another value e.g. {q: 'query'} + * @return {object} partial search parameters object (same properties than in the + * SearchParameters but not exhaustive) + */ +exports.getStateFromQueryString = function(queryString, options) { + var prefixForParameters = options && options.prefix || ''; + var mapping = options && options.mapping || {}; + var invertedMapping = invert(mapping); + + var partialStateWithPrefix = qs.parse(queryString); + var prefixRegexp = new RegExp('^' + prefixForParameters); + var partialState = mapKeys( + partialStateWithPrefix, + function(v, k) { + var hasPrefix = prefixForParameters && prefixRegexp.test(k); + var unprefixedKey = hasPrefix ? k.replace(prefixRegexp, '') : k; + var decodedKey = shortener.decode(invertedMapping[unprefixedKey] || unprefixedKey); + return decodedKey || unprefixedKey; + } + ); - _proto._destroyElement = function _destroyElement(element) { - $(element).detach().trigger(Event.CLOSED).remove(); - } // Static - ; + var partialStateWithParsedNumbers = SearchParameters._parseNumbers(partialState); - Alert._jQueryInterface = function _jQueryInterface(config) { - return this.each(function () { - var $element = $(this); - var data = $element.data(DATA_KEY); + return pick(partialStateWithParsedNumbers, SearchParameters.PARAMETERS); +}; - if (!data) { - data = new Alert(this); - $element.data(DATA_KEY, data); - } +/** + * Retrieve an object of all the properties that are not understandable as helper + * parameters. + * @param {string} queryString the query string to read + * @param {object} [options] the options + * - prefixForParameters : prefix used for the helper configuration keys + * - mapping : map short attributes to another value e.g. {q: 'query'} + * @return {object} the object containing the parsed configuration that doesn't + * to the helper + */ +exports.getUnrecognizedParametersInQueryString = function(queryString, options) { + var prefixForParameters = options && options.prefix; + var mapping = options && options.mapping || {}; + var invertedMapping = invert(mapping); + + var foreignConfig = {}; + var config = qs.parse(queryString); + if (prefixForParameters) { + var prefixRegexp = new RegExp('^' + prefixForParameters); + forEach(config, function(v, key) { + if (!prefixRegexp.test(key)) foreignConfig[key] = v; + }); + } else { + forEach(config, function(v, key) { + if (!shortener.decode(invertedMapping[key] || key)) foreignConfig[key] = v; + }); + } - if (config === 'close') { - data[config](this); - } - }); - }; + return foreignConfig; +}; - Alert._handleDismiss = function _handleDismiss(alertInstance) { - return function (event) { - if (event) { - event.preventDefault(); - } +/** + * Generate a query string for the state passed according to the options + * @param {SearchParameters} state state to serialize + * @param {object} [options] May contain the following parameters : + * - prefix : prefix in front of the keys + * - mapping : map short attributes to another value e.g. {q: 'query'} + * - moreAttributes : more values to be added in the query string. Those values + * won't be prefixed. + * - safe : get safe urls for use in emails, chat apps or any application auto linking urls. + * All parameters and values will be encoded in a way that it's safe to share them. + * Default to false for legacy reasons () + * @return {string} the query string + */ +exports.getQueryStringFromState = function(state, options) { + var moreAttributes = options && options.moreAttributes; + var prefixForParameters = options && options.prefix || ''; + var mapping = options && options.mapping || {}; + var safe = options && options.safe || false; + var invertedMapping = invert(mapping); - alertInstance.close(this); - }; - }; + var stateForUrl = safe ? state : recursiveEncode(state); - _createClass(Alert, null, [{ - key: "VERSION", - get: function get() { - return VERSION; - } - }]); + var encodedState = mapKeys( + stateForUrl, + function(v, k) { + var shortK = shortener.encode(k); + return prefixForParameters + (mapping[shortK] || shortK); + } + ); - return Alert; - }(); - /** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ + var prefixRegexp = prefixForParameters === '' ? null : new RegExp('^' + prefixForParameters); + var sort = bind(sortQueryStringValues, null, prefixRegexp, invertedMapping); + if (!isEmpty(moreAttributes)) { + var stateQs = qs.stringify(encodedState, {encode: safe, sort: sort}); + var moreQs = qs.stringify(moreAttributes, {encode: safe}); + if (!stateQs) return moreQs; + return stateQs + '&' + moreQs; + } + return qs.stringify(encodedState, {encode: safe, sort: sort}); +}; - $(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert())); - /** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - */ - $.fn[NAME] = Alert._jQueryInterface; - $.fn[NAME].Constructor = Alert; +/***/ }), - $.fn[NAME].noConflict = function () { - $.fn[NAME] = JQUERY_NO_CONFLICT; - return Alert._jQueryInterface; - }; +/***/ "./node_modules/algoliasearch-helper/src/version.js": +/*!**********************************************************!*\ + !*** ./node_modules/algoliasearch-helper/src/version.js ***! + \**********************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ +"use strict"; - var NAME$1 = 'button'; - var VERSION$1 = '4.4.1'; - var DATA_KEY$1 = 'bs.button'; - var EVENT_KEY$1 = "." + DATA_KEY$1; - var DATA_API_KEY$1 = '.data-api'; - var JQUERY_NO_CONFLICT$1 = $.fn[NAME$1]; - var ClassName$1 = { - ACTIVE: 'active', - BUTTON: 'btn', - FOCUS: 'focus' - }; - var Selector$1 = { - DATA_TOGGLE_CARROT: '[data-toggle^="button"]', - DATA_TOGGLES: '[data-toggle="buttons"]', - DATA_TOGGLE: '[data-toggle="button"]', - DATA_TOGGLES_BUTTONS: '[data-toggle="buttons"] .btn', - INPUT: 'input:not([type="hidden"])', - ACTIVE: '.active', - BUTTON: '.btn' - }; - var Event$1 = { - CLICK_DATA_API: "click" + EVENT_KEY$1 + DATA_API_KEY$1, - FOCUS_BLUR_DATA_API: "focus" + EVENT_KEY$1 + DATA_API_KEY$1 + " " + ("blur" + EVENT_KEY$1 + DATA_API_KEY$1), - LOAD_DATA_API: "load" + EVENT_KEY$1 + DATA_API_KEY$1 - }; - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ - var Button = - /*#__PURE__*/ - function () { - function Button(element) { - this._element = element; - } // Getters +module.exports = '2.28.1'; - var _proto = Button.prototype; +/***/ }), - // Public - _proto.toggle = function toggle() { - var triggerChangeEvent = true; - var addAriaPressed = true; - var rootElement = $(this._element).closest(Selector$1.DATA_TOGGLES)[0]; +/***/ "./node_modules/algoliasearch/dist/algoliasearch-lite.umd.js": +/*!*******************************************************************!*\ + !*** ./node_modules/algoliasearch/dist/algoliasearch-lite.umd.js ***! + \*******************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - if (rootElement) { - var input = this._element.querySelector(Selector$1.INPUT); +/*! algoliasearch-lite.umd.js | 4.1.0 | © Algolia, inc. | https://github.com/algolia/algoliasearch-client-javascript */ +!function(e,t){ true?module.exports=t():undefined}(this,(function(){"use strict";function e(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function t(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function r(r){for(var n=1;n=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}function o(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){if(!(Symbol.iterator in Object(e)||"[object Arguments]"===Object.prototype.toString.call(e)))return;var r=[],n=!0,o=!1,a=void 0;try{for(var u,i=e[Symbol.iterator]();!(n=(u=i.next()).done)&&(r.push(u.value),!t||r.length!==t);n=!0);}catch(e){o=!0,a=e}finally{try{n||null==i.return||i.return()}finally{if(o)throw a}}return r}(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function a(e){return function(e){if(Array.isArray(e)){for(var t=0,r=new Array(e.length);t2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return Promise.resolve().then((function(){var r=JSON.stringify(e),n=a()[r];return Promise.all([n||t(),void 0!==n])})).then((function(e){var t=o(e,2),n=t[0],a=t[1];return Promise.all([n,a||r.miss(n)])})).then((function(e){return o(e,1)[0]}))},set:function(e,t){return Promise.resolve().then((function(){var o=a();return o[JSON.stringify(e)]=t,n().setItem(r,JSON.stringify(o)),t}))},delete:function(e){return Promise.resolve().then((function(){var t=a();delete t[JSON.stringify(e)],n().setItem(r,JSON.stringify(t))}))},clear:function(){return Promise.resolve().then((function(){n().removeItem(r)}))}}}function i(e){var t=a(e.caches),r=t.shift();return void 0===r?{get:function(e,t){var r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}},n=t();return n.then((function(e){return Promise.all([e,r.miss(e)])})).then((function(e){return o(e,1)[0]}))},set:function(e,t){return Promise.resolve(t)},delete:function(e){return Promise.resolve()},clear:function(){return Promise.resolve()}}:{get:function(e,n){var o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}};return r.get(e,n,o).catch((function(){return i({caches:t}).get(e,n,o)}))},set:function(e,n){return r.set(e,n).catch((function(){return i({caches:t}).set(e,n)}))},delete:function(e){return r.delete(e).catch((function(){return i({caches:t}).delete(e)}))},clear:function(){return r.clear().catch((function(){return i({caches:t}).clear()}))}}}function s(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{serializable:!0},t={};return{get:function(r,n){var o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{miss:function(){return Promise.resolve()}},a=JSON.stringify(r);if(a in t)return Promise.resolve(e.serializable?JSON.parse(t[a]):t[a]);var u=n(),i=o&&o.miss||function(){return Promise.resolve()};return u.then((function(e){return i(e)})).then((function(){return u}))},set:function(r,n){return t[JSON.stringify(r)]=e.serializable?JSON.stringify(n):n,Promise.resolve(n)},delete:function(e){return delete t[JSON.stringify(e)],Promise.resolve()},clear:function(){return t={},Promise.resolve()}}}function c(e){for(var t=e.length-1;t>0;t--){var r=Math.floor(Math.random()*(t+1)),n=e[t];e[t]=e[r],e[r]=n}return e}function l(e,t){return Object.keys(void 0!==t?t:{}).forEach((function(r){e[r]=t[r](e)})),e}function f(e){for(var t=arguments.length,r=new Array(t>1?t-1:0),n=1;n0?n:void 0,timeout:r.timeout||t,headers:r.headers||{},queryParameters:r.queryParameters||{},cacheable:r.cacheable}}var m={Read:1,Write:2,Any:3},p=1,v=2,g=3;function y(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:p;return r({},e,{status:t,lastUpdate:Date.now()})}function b(e){return{protocol:e.protocol||"https",url:e.url,accept:e.accept||m.Any}}var O="GET",P="POST";function q(e,t){return Promise.all(t.map((function(t){return e.get(t,(function(){return Promise.resolve(y(t))}))}))).then((function(e){var r=e.filter((function(e){return function(e){return e.status===p||Date.now()-e.lastUpdate>12e4}(e)})),n=e.filter((function(e){return function(e){return e.status===g&&Date.now()-e.lastUpdate<=12e4}(e)})),o=[].concat(a(r),a(n));return{getTimeout:function(e,t){return(0===n.length&&0===e?1:n.length+3+e)*t},statelessHosts:o.length>0?o.map((function(e){return b(e)})):t}}))}function j(e,t,n,o){var u=[],i=function(e,t){if(e.method===O||void 0===e.data&&void 0===t.data)return;var n=Array.isArray(e.data)?e.data:r({},e.data,{},t.data);return JSON.stringify(n)}(n,o),s=function(e,t){var n=r({},e.headers,{},t.headers),o={};return Object.keys(n).forEach((function(e){var t=n[e];o[e.toLowerCase()]=t})),o}(e,o),c=n.method,l=n.method!==O?{}:r({},n.data,{},o.data),f=r({"x-algolia-agent":e.userAgent.value},e.queryParameters,{},l,{},o.queryParameters),h=0,d=function t(r,a){var l=r.pop();if(void 0===l)throw{name:"RetryError",message:"Unreachable hosts - your application id may be incorrect. If the error persists, contact support@algolia.com.",transporterStackTrace:A(u)};var d={data:i,headers:s,method:c,url:w(l,n.path,f),connectTimeout:a(h,e.timeouts.connect),responseTimeout:a(h,o.timeout)},m=function(e){var t={request:d,response:e,host:l,triesLeft:r.length};return u.push(t),t},p={onSucess:function(e){return function(e){try{return JSON.parse(e.content)}catch(t){throw function(e,t){return{name:"DeserializationError",message:e,response:t}}(t.message,e)}}(e)},onRetry:function(n){var o=m(n);return n.isTimedOut&&h++,Promise.all([e.logger.info("Retryable failure",x(o)),e.hostsCache.set(l,y(l,n.isTimedOut?g:v))]).then((function(){return t(r,a)}))},onFail:function(e){throw m(e),function(e,t){var r=e.content,n=e.status,o=r;try{o=JSON.parse(r).message}catch(e){}return function(e,t,r){return{name:"ApiError",message:e,status:t,transporterStackTrace:r}}(o,n,t)}(e,A(u))}};return e.requester.send(d).then((function(e){return function(e,t){return function(e){var t=e.status;return e.isTimedOut||function(e){var t=e.isTimedOut,r=e.status;return!t&&0==~~r}(e)||2!=~~(t/100)&&4!=~~(t/100)}(e)?t.onRetry(e):2==~~(e.status/100)?t.onSucess(e):t.onFail(e)}(e,p)}))};return q(e.hostsCache,t).then((function(e){return d(a(e.statelessHosts).reverse(),e.getTimeout)}))}function S(e){var t={value:"Algolia for JavaScript (".concat(e,")"),add:function(e){var r="; ".concat(e.segment).concat(void 0!==e.version?" (".concat(e.version,")"):"");return-1===t.value.indexOf(r)&&(t.value="".concat(t.value).concat(r)),t}};return t}function w(e,t,r){var n=T(r),o="".concat(e.protocol,"://").concat(e.url,"/").concat("/"===t.charAt(0)?t.substr(1):t);return n.length&&(o+="?".concat(n)),o}function T(e){return Object.keys(e).map((function(t){return f("%s=%s",t,(r=e[t],"[object Object]"===Object.prototype.toString.call(r)||"[object Array]"===Object.prototype.toString.call(r)?JSON.stringify(e[t]):e[t]));var r})).join("&")}function A(e){return e.map((function(e){return x(e)}))}function x(e){var t=e.request.headers["x-algolia-api-key"]?{"x-algolia-api-key":"*****"}:{};return r({},e,{request:r({},e.request,{headers:r({},e.request.headers,{},t)})})}var C=function(e){var t=e.appId,n=function(e,t,r){var n={"x-algolia-api-key":r,"x-algolia-application-id":t};return{headers:function(){return e===h.WithinHeaders?n:{}},queryParameters:function(){return e===h.WithinQueryParameters?n:{}}}}(void 0!==e.authMode?e.authMode:h.WithinHeaders,t,e.apiKey),a=function(e){var t=e.hostsCache,r=e.logger,n=e.requester,a=e.requestsCache,u=e.responsesCache,i=e.timeouts,s=e.userAgent,c=e.hosts,l=e.queryParameters,f={hostsCache:t,logger:r,requester:n,requestsCache:a,responsesCache:u,timeouts:i,userAgent:s,headers:e.headers,queryParameters:l,hosts:c.map((function(e){return b(e)})),read:function(e,t){var r=d(t,f.timeouts.read),n=function(){return j(f,f.hosts.filter((function(e){return 0!=(e.accept&m.Read)})),e,r)};if(!0!==(void 0!==r.cacheable?r.cacheable:e.cacheable))return n();var a={request:e,mappedRequestOptions:r,transporter:{queryParameters:f.queryParameters,headers:f.headers}};return f.responsesCache.get(a,(function(){return f.requestsCache.get(a,(function(){return f.requestsCache.set(a,n()).then((function(e){return Promise.all([f.requestsCache.delete(a),e])}),(function(e){return Promise.all([f.requestsCache.delete(a),Promise.reject(e)])})).then((function(e){var t=o(e,2);t[0];return t[1]}))}))}),{miss:function(e){return f.responsesCache.set(a,e)}})},write:function(e,t){return j(f,f.hosts.filter((function(e){return 0!=(e.accept&m.Write)})),e,d(t,f.timeouts.write))}};return f}(r({hosts:[{url:"".concat(t,"-dsn.algolia.net"),accept:m.Read},{url:"".concat(t,".algolia.net"),accept:m.Write}].concat(c([{url:"".concat(t,"-1.algolianet.com")},{url:"".concat(t,"-2.algolianet.com")},{url:"".concat(t,"-3.algolianet.com")}]))},e,{headers:r({},n.headers(),{},{"content-type":"application/x-www-form-urlencoded"},{},e.headers),queryParameters:r({},n.queryParameters(),{},e.queryParameters)}));return l({transporter:a,appId:t,addAlgoliaAgent:function(e,t){a.userAgent.add({segment:e,version:t})},clearCache:function(){return Promise.all([a.requestsCache.clear(),a.responsesCache.clear()]).then((function(){}))}},e.methods)},N=function(e){return function(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},n={transporter:e.transporter,appId:e.appId,indexName:t};return l(n,r.methods)}},k=function(e){return function(t,n){var o=t.map((function(e){return r({},e,{params:T(e.params||{})})}));return e.transporter.read({method:P,path:"1/indexes/*/queries",data:{requests:o},cacheable:!0},n)}},J=function(e){return function(t,o){return Promise.all(t.map((function(t){var a=t.params,u=a.facetName,i=a.facetQuery,s=n(a,["facetName","facetQuery"]);return N(e)(t.indexName,{methods:{searchForFacetValues:I}}).searchForFacetValues(u,i,r({},o,{},s))})))}},E=function(e){return function(t,r){return e.transporter.read({method:P,path:f("1/indexes/%s/query",e.indexName),data:{query:t},cacheable:!0},r)}},I=function(e){return function(t,r,n){return e.transporter.read({method:P,path:f("1/indexes/%s/facets/%s/query",e.indexName,t),data:{facetQuery:r},cacheable:!0},n)}},F=1,R=2,D=3;function W(e,t,n){var o,a={appId:e,apiKey:t,timeouts:{connect:1,read:2,write:30},requester:{send:function(e){return new Promise((function(t){var r=new XMLHttpRequest;r.open(e.method,e.url,!0),Object.keys(e.headers).forEach((function(t){return r.setRequestHeader(t,e.headers[t])}));var n,o=function(e,n){return setTimeout((function(){r.abort(),t({status:0,content:n,isTimedOut:!0})}),1e3*e)},a=o(e.connectTimeout,"Connection timeout");r.onreadystatechange=function(){r.readyState>r.OPENED&&void 0===n&&(clearTimeout(a),n=o(e.responseTimeout,"Socket timeout"))},r.onerror=function(){0===r.status&&(clearTimeout(a),clearTimeout(n),t({content:r.responseText||"Network request failed",status:r.status,isTimedOut:!1}))},r.onload=function(){clearTimeout(a),clearTimeout(n),t({content:r.responseText,status:r.status,isTimedOut:!1})},r.send(e.data)}))}},logger:(o=D,{debug:function(e,t){return F>=o&&console.debug(e,t),Promise.resolve()},info:function(e,t){return R>=o&&console.info(e,t),Promise.resolve()},error:function(e,t){return console.error(e,t),Promise.resolve()}}),responsesCache:s(),requestsCache:s({serializable:!1}),hostsCache:i({caches:[u({key:"".concat("4.1.0","-").concat(e)}),s()]}),userAgent:S("4.1.0").add({segment:"Browser",version:"lite"}),authMode:h.WithinQueryParameters};return C(r({},a,{},n,{methods:{search:k,searchForFacetValues:J,multipleQueries:k,multipleSearchForFacetValues:J,initIndex:function(e){return function(t){return N(e)(t,{methods:{search:E,searchForFacetValues:I}})}}}}))}return W.version="4.1.0",W})); - if (input) { - if (input.type === 'radio') { - if (input.checked && this._element.classList.contains(ClassName$1.ACTIVE)) { - triggerChangeEvent = false; - } else { - var activeElement = rootElement.querySelector(Selector$1.ACTIVE); - if (activeElement) { - $(activeElement).removeClass(ClassName$1.ACTIVE); - } - } - } else if (input.type === 'checkbox') { - if (this._element.tagName === 'LABEL' && input.checked === this._element.classList.contains(ClassName$1.ACTIVE)) { - triggerChangeEvent = false; - } - } else { - // if it's not a radio button or checkbox don't add a pointless/invalid checked property to the input - triggerChangeEvent = false; - } +/***/ }), - if (triggerChangeEvent) { - input.checked = !this._element.classList.contains(ClassName$1.ACTIVE); - $(input).trigger('change'); - } +/***/ "./node_modules/axios/index.js": +/*!*************************************!*\ + !*** ./node_modules/axios/index.js ***! + \*************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - input.focus(); - addAriaPressed = false; - } - } +module.exports = __webpack_require__(/*! ./lib/axios */ "./node_modules/axios/lib/axios.js"); - if (!(this._element.hasAttribute('disabled') || this._element.classList.contains('disabled'))) { - if (addAriaPressed) { - this._element.setAttribute('aria-pressed', !this._element.classList.contains(ClassName$1.ACTIVE)); - } +/***/ }), - if (triggerChangeEvent) { - $(this._element).toggleClass(ClassName$1.ACTIVE); - } - } - }; +/***/ "./node_modules/axios/lib/adapters/xhr.js": +/*!************************************************!*\ + !*** ./node_modules/axios/lib/adapters/xhr.js ***! + \************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - _proto.dispose = function dispose() { - $.removeData(this._element, DATA_KEY$1); - this._element = null; - } // Static - ; +"use strict"; - Button._jQueryInterface = function _jQueryInterface(config) { - return this.each(function () { - var data = $(this).data(DATA_KEY$1); - if (!data) { - data = new Button(this); - $(this).data(DATA_KEY$1, data); - } +var utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js"); +var settle = __webpack_require__(/*! ./../core/settle */ "./node_modules/axios/lib/core/settle.js"); +var buildURL = __webpack_require__(/*! ./../helpers/buildURL */ "./node_modules/axios/lib/helpers/buildURL.js"); +var buildFullPath = __webpack_require__(/*! ../core/buildFullPath */ "./node_modules/axios/lib/core/buildFullPath.js"); +var parseHeaders = __webpack_require__(/*! ./../helpers/parseHeaders */ "./node_modules/axios/lib/helpers/parseHeaders.js"); +var isURLSameOrigin = __webpack_require__(/*! ./../helpers/isURLSameOrigin */ "./node_modules/axios/lib/helpers/isURLSameOrigin.js"); +var createError = __webpack_require__(/*! ../core/createError */ "./node_modules/axios/lib/core/createError.js"); - if (config === 'toggle') { - data[config](); - } - }); - }; +module.exports = function xhrAdapter(config) { + return new Promise(function dispatchXhrRequest(resolve, reject) { + var requestData = config.data; + var requestHeaders = config.headers; - _createClass(Button, null, [{ - key: "VERSION", - get: function get() { - return VERSION$1; - } - }]); + if (utils.isFormData(requestData)) { + delete requestHeaders['Content-Type']; // Let the browser set it + } - return Button; - }(); - /** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ + var request = new XMLHttpRequest(); + // HTTP basic authentication + if (config.auth) { + var username = config.auth.username || ''; + var password = config.auth.password || ''; + requestHeaders.Authorization = 'Basic ' + btoa(username + ':' + password); + } - $(document).on(Event$1.CLICK_DATA_API, Selector$1.DATA_TOGGLE_CARROT, function (event) { - var button = event.target; + var fullPath = buildFullPath(config.baseURL, config.url); + request.open(config.method.toUpperCase(), buildURL(fullPath, config.params, config.paramsSerializer), true); - if (!$(button).hasClass(ClassName$1.BUTTON)) { - button = $(button).closest(Selector$1.BUTTON)[0]; - } + // Set the request timeout in MS + request.timeout = config.timeout; - if (!button || button.hasAttribute('disabled') || button.classList.contains('disabled')) { - event.preventDefault(); // work around Firefox bug #1540995 - } else { - var inputBtn = button.querySelector(Selector$1.INPUT); + // Listen for ready state + request.onreadystatechange = function handleLoad() { + if (!request || request.readyState !== 4) { + return; + } - if (inputBtn && (inputBtn.hasAttribute('disabled') || inputBtn.classList.contains('disabled'))) { - event.preventDefault(); // work around Firefox bug #1540995 + // The request errored out and we didn't get a response, this will be + // handled by onerror instead + // With one exception: request that using file: protocol, most browsers + // will return status as 0 even though it's a successful request + if (request.status === 0 && !(request.responseURL && request.responseURL.indexOf('file:') === 0)) { + return; + } + + // Prepare the response + var responseHeaders = 'getAllResponseHeaders' in request ? parseHeaders(request.getAllResponseHeaders()) : null; + var responseData = !config.responseType || config.responseType === 'text' ? request.responseText : request.response; + var response = { + data: responseData, + status: request.status, + statusText: request.statusText, + headers: responseHeaders, + config: config, + request: request + }; + + settle(resolve, reject, response); + + // Clean up request + request = null; + }; + // Handle browser request cancellation (as opposed to a manual cancellation) + request.onabort = function handleAbort() { + if (!request) { return; } - Button._jQueryInterface.call($(button), 'toggle'); - } - }).on(Event$1.FOCUS_BLUR_DATA_API, Selector$1.DATA_TOGGLE_CARROT, function (event) { - var button = $(event.target).closest(Selector$1.BUTTON)[0]; - $(button).toggleClass(ClassName$1.FOCUS, /^focus(in)?$/.test(event.type)); - }); - $(window).on(Event$1.LOAD_DATA_API, function () { - // ensure correct active class is set to match the controls' actual values/states - // find all checkboxes/readio buttons inside data-toggle groups - var buttons = [].slice.call(document.querySelectorAll(Selector$1.DATA_TOGGLES_BUTTONS)); + reject(createError('Request aborted', config, 'ECONNABORTED', request)); - for (var i = 0, len = buttons.length; i < len; i++) { - var button = buttons[i]; - var input = button.querySelector(Selector$1.INPUT); + // Clean up request + request = null; + }; - if (input.checked || input.hasAttribute('checked')) { - button.classList.add(ClassName$1.ACTIVE); - } else { - button.classList.remove(ClassName$1.ACTIVE); + // Handle low level network errors + request.onerror = function handleError() { + // Real errors are hidden from us by the browser + // onerror should only fire if it's a network error + reject(createError('Network Error', config, null, request)); + + // Clean up request + request = null; + }; + + // Handle timeout + request.ontimeout = function handleTimeout() { + var timeoutErrorMessage = 'timeout of ' + config.timeout + 'ms exceeded'; + if (config.timeoutErrorMessage) { + timeoutErrorMessage = config.timeoutErrorMessage; } - } // find all button toggles + reject(createError(timeoutErrorMessage, config, 'ECONNABORTED', + request)); + // Clean up request + request = null; + }; - buttons = [].slice.call(document.querySelectorAll(Selector$1.DATA_TOGGLE)); + // Add xsrf header + // This is only done if running in a standard browser environment. + // Specifically not if we're in a web worker, or react-native. + if (utils.isStandardBrowserEnv()) { + var cookies = __webpack_require__(/*! ./../helpers/cookies */ "./node_modules/axios/lib/helpers/cookies.js"); - for (var _i = 0, _len = buttons.length; _i < _len; _i++) { - var _button = buttons[_i]; + // Add xsrf header + var xsrfValue = (config.withCredentials || isURLSameOrigin(fullPath)) && config.xsrfCookieName ? + cookies.read(config.xsrfCookieName) : + undefined; - if (_button.getAttribute('aria-pressed') === 'true') { - _button.classList.add(ClassName$1.ACTIVE); - } else { - _button.classList.remove(ClassName$1.ACTIVE); + if (xsrfValue) { + requestHeaders[config.xsrfHeaderName] = xsrfValue; } } - }); - /** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - */ - $.fn[NAME$1] = Button._jQueryInterface; - $.fn[NAME$1].Constructor = Button; + // Add headers to the request + if ('setRequestHeader' in request) { + utils.forEach(requestHeaders, function setRequestHeader(val, key) { + if (typeof requestData === 'undefined' && key.toLowerCase() === 'content-type') { + // Remove Content-Type if data is undefined + delete requestHeaders[key]; + } else { + // Otherwise add header to the request + request.setRequestHeader(key, val); + } + }); + } - $.fn[NAME$1].noConflict = function () { - $.fn[NAME$1] = JQUERY_NO_CONFLICT$1; - return Button._jQueryInterface; - }; + // Add withCredentials to request if needed + if (!utils.isUndefined(config.withCredentials)) { + request.withCredentials = !!config.withCredentials; + } - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ + // Add responseType to request if needed + if (config.responseType) { + try { + request.responseType = config.responseType; + } catch (e) { + // Expected DOMException thrown by browsers not compatible XMLHttpRequest Level 2. + // But, this can be suppressed for 'json' type as it can be parsed by default 'transformResponse' function. + if (config.responseType !== 'json') { + throw e; + } + } + } - var NAME$2 = 'carousel'; - var VERSION$2 = '4.4.1'; - var DATA_KEY$2 = 'bs.carousel'; - var EVENT_KEY$2 = "." + DATA_KEY$2; - var DATA_API_KEY$2 = '.data-api'; - var JQUERY_NO_CONFLICT$2 = $.fn[NAME$2]; - var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key + // Handle progress if needed + if (typeof config.onDownloadProgress === 'function') { + request.addEventListener('progress', config.onDownloadProgress); + } - var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key + // Not all browsers support upload events + if (typeof config.onUploadProgress === 'function' && request.upload) { + request.upload.addEventListener('progress', config.onUploadProgress); + } - var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch + if (config.cancelToken) { + // Handle cancellation + config.cancelToken.promise.then(function onCanceled(cancel) { + if (!request) { + return; + } - var SWIPE_THRESHOLD = 40; - var Default = { - interval: 5000, - keyboard: true, - slide: false, - pause: 'hover', - wrap: true, - touch: true - }; - var DefaultType = { - interval: '(number|boolean)', - keyboard: 'boolean', - slide: '(boolean|string)', - pause: '(string|boolean)', - wrap: 'boolean', - touch: 'boolean' - }; - var Direction = { - NEXT: 'next', - PREV: 'prev', - LEFT: 'left', - RIGHT: 'right' - }; - var Event$2 = { - SLIDE: "slide" + EVENT_KEY$2, - SLID: "slid" + EVENT_KEY$2, - KEYDOWN: "keydown" + EVENT_KEY$2, - MOUSEENTER: "mouseenter" + EVENT_KEY$2, - MOUSELEAVE: "mouseleave" + EVENT_KEY$2, - TOUCHSTART: "touchstart" + EVENT_KEY$2, - TOUCHMOVE: "touchmove" + EVENT_KEY$2, - TOUCHEND: "touchend" + EVENT_KEY$2, - POINTERDOWN: "pointerdown" + EVENT_KEY$2, - POINTERUP: "pointerup" + EVENT_KEY$2, - DRAG_START: "dragstart" + EVENT_KEY$2, - LOAD_DATA_API: "load" + EVENT_KEY$2 + DATA_API_KEY$2, - CLICK_DATA_API: "click" + EVENT_KEY$2 + DATA_API_KEY$2 - }; - var ClassName$2 = { - CAROUSEL: 'carousel', - ACTIVE: 'active', - SLIDE: 'slide', - RIGHT: 'carousel-item-right', - LEFT: 'carousel-item-left', - NEXT: 'carousel-item-next', - PREV: 'carousel-item-prev', - ITEM: 'carousel-item', - POINTER_EVENT: 'pointer-event' - }; - var Selector$2 = { - ACTIVE: '.active', - ACTIVE_ITEM: '.active.carousel-item', - ITEM: '.carousel-item', - ITEM_IMG: '.carousel-item img', - NEXT_PREV: '.carousel-item-next, .carousel-item-prev', - INDICATORS: '.carousel-indicators', - DATA_SLIDE: '[data-slide], [data-slide-to]', - DATA_RIDE: '[data-ride="carousel"]' - }; - var PointerType = { - TOUCH: 'touch', - PEN: 'pen' - }; - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ - - var Carousel = - /*#__PURE__*/ - function () { - function Carousel(element, config) { - this._items = null; - this._interval = null; - this._activeElement = null; - this._isPaused = false; - this._isSliding = false; - this.touchTimeout = null; - this.touchStartX = 0; - this.touchDeltaX = 0; - this._config = this._getConfig(config); - this._element = element; - this._indicatorsElement = this._element.querySelector(Selector$2.INDICATORS); - this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0; - this._pointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent); + request.abort(); + reject(cancel); + // Clean up request + request = null; + }); + } - this._addEventListeners(); - } // Getters + if (requestData === undefined) { + requestData = null; + } + // Send the request + request.send(requestData); + }); +}; - var _proto = Carousel.prototype; - // Public - _proto.next = function next() { - if (!this._isSliding) { - this._slide(Direction.NEXT); - } - }; +/***/ }), - _proto.nextWhenVisible = function nextWhenVisible() { - // Don't call next when the page isn't visible - // or the carousel or its parent isn't visible - if (!document.hidden && $(this._element).is(':visible') && $(this._element).css('visibility') !== 'hidden') { - this.next(); - } - }; +/***/ "./node_modules/axios/lib/axios.js": +/*!*****************************************!*\ + !*** ./node_modules/axios/lib/axios.js ***! + \*****************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - _proto.prev = function prev() { - if (!this._isSliding) { - this._slide(Direction.PREV); - } - }; +"use strict"; - _proto.pause = function pause(event) { - if (!event) { - this._isPaused = true; - } - if (this._element.querySelector(Selector$2.NEXT_PREV)) { - Util.triggerTransitionEnd(this._element); - this.cycle(true); - } +var utils = __webpack_require__(/*! ./utils */ "./node_modules/axios/lib/utils.js"); +var bind = __webpack_require__(/*! ./helpers/bind */ "./node_modules/axios/lib/helpers/bind.js"); +var Axios = __webpack_require__(/*! ./core/Axios */ "./node_modules/axios/lib/core/Axios.js"); +var mergeConfig = __webpack_require__(/*! ./core/mergeConfig */ "./node_modules/axios/lib/core/mergeConfig.js"); +var defaults = __webpack_require__(/*! ./defaults */ "./node_modules/axios/lib/defaults.js"); - clearInterval(this._interval); - this._interval = null; - }; +/** + * Create an instance of Axios + * + * @param {Object} defaultConfig The default config for the instance + * @return {Axios} A new instance of Axios + */ +function createInstance(defaultConfig) { + var context = new Axios(defaultConfig); + var instance = bind(Axios.prototype.request, context); - _proto.cycle = function cycle(event) { - if (!event) { - this._isPaused = false; - } + // Copy axios.prototype to instance + utils.extend(instance, Axios.prototype, context); - if (this._interval) { - clearInterval(this._interval); - this._interval = null; - } + // Copy context to instance + utils.extend(instance, context); - if (this._config.interval && !this._isPaused) { - this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval); - } - }; + return instance; +} - _proto.to = function to(index) { - var _this = this; +// Create the default instance to be exported +var axios = createInstance(defaults); - this._activeElement = this._element.querySelector(Selector$2.ACTIVE_ITEM); +// Expose Axios class to allow class inheritance +axios.Axios = Axios; - var activeIndex = this._getItemIndex(this._activeElement); +// Factory for creating new instances +axios.create = function create(instanceConfig) { + return createInstance(mergeConfig(axios.defaults, instanceConfig)); +}; - if (index > this._items.length - 1 || index < 0) { - return; - } +// Expose Cancel & CancelToken +axios.Cancel = __webpack_require__(/*! ./cancel/Cancel */ "./node_modules/axios/lib/cancel/Cancel.js"); +axios.CancelToken = __webpack_require__(/*! ./cancel/CancelToken */ "./node_modules/axios/lib/cancel/CancelToken.js"); +axios.isCancel = __webpack_require__(/*! ./cancel/isCancel */ "./node_modules/axios/lib/cancel/isCancel.js"); - if (this._isSliding) { - $(this._element).one(Event$2.SLID, function () { - return _this.to(index); - }); - return; - } +// Expose all/spread +axios.all = function all(promises) { + return Promise.all(promises); +}; +axios.spread = __webpack_require__(/*! ./helpers/spread */ "./node_modules/axios/lib/helpers/spread.js"); - if (activeIndex === index) { - this.pause(); - this.cycle(); - return; - } +module.exports = axios; - var direction = index > activeIndex ? Direction.NEXT : Direction.PREV; +// Allow use of default import syntax in TypeScript +module.exports.default = axios; - this._slide(direction, this._items[index]); - }; - _proto.dispose = function dispose() { - $(this._element).off(EVENT_KEY$2); - $.removeData(this._element, DATA_KEY$2); - this._items = null; - this._config = null; - this._element = null; - this._interval = null; - this._isPaused = null; - this._isSliding = null; - this._activeElement = null; - this._indicatorsElement = null; - } // Private - ; +/***/ }), - _proto._getConfig = function _getConfig(config) { - config = _objectSpread2({}, Default, {}, config); - Util.typeCheckConfig(NAME$2, config, DefaultType); - return config; - }; +/***/ "./node_modules/axios/lib/cancel/Cancel.js": +/*!*************************************************!*\ + !*** ./node_modules/axios/lib/cancel/Cancel.js ***! + \*************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - _proto._handleSwipe = function _handleSwipe() { - var absDeltax = Math.abs(this.touchDeltaX); +"use strict"; - if (absDeltax <= SWIPE_THRESHOLD) { - return; - } - var direction = absDeltax / this.touchDeltaX; - this.touchDeltaX = 0; // swipe left +/** + * A `Cancel` is an object that is thrown when an operation is canceled. + * + * @class + * @param {string=} message The message. + */ +function Cancel(message) { + this.message = message; +} - if (direction > 0) { - this.prev(); - } // swipe right +Cancel.prototype.toString = function toString() { + return 'Cancel' + (this.message ? ': ' + this.message : ''); +}; +Cancel.prototype.__CANCEL__ = true; - if (direction < 0) { - this.next(); - } - }; +module.exports = Cancel; - _proto._addEventListeners = function _addEventListeners() { - var _this2 = this; - if (this._config.keyboard) { - $(this._element).on(Event$2.KEYDOWN, function (event) { - return _this2._keydown(event); - }); - } +/***/ }), - if (this._config.pause === 'hover') { - $(this._element).on(Event$2.MOUSEENTER, function (event) { - return _this2.pause(event); - }).on(Event$2.MOUSELEAVE, function (event) { - return _this2.cycle(event); - }); - } +/***/ "./node_modules/axios/lib/cancel/CancelToken.js": +/*!******************************************************!*\ + !*** ./node_modules/axios/lib/cancel/CancelToken.js ***! + \******************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - if (this._config.touch) { - this._addTouchEventListeners(); - } - }; +"use strict"; - _proto._addTouchEventListeners = function _addTouchEventListeners() { - var _this3 = this; - if (!this._touchSupported) { - return; - } +var Cancel = __webpack_require__(/*! ./Cancel */ "./node_modules/axios/lib/cancel/Cancel.js"); - var start = function start(event) { - if (_this3._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) { - _this3.touchStartX = event.originalEvent.clientX; - } else if (!_this3._pointerEvent) { - _this3.touchStartX = event.originalEvent.touches[0].clientX; - } - }; +/** + * A `CancelToken` is an object that can be used to request cancellation of an operation. + * + * @class + * @param {Function} executor The executor function. + */ +function CancelToken(executor) { + if (typeof executor !== 'function') { + throw new TypeError('executor must be a function.'); + } - var move = function move(event) { - // ensure swiping with one touch and not pinching - if (event.originalEvent.touches && event.originalEvent.touches.length > 1) { - _this3.touchDeltaX = 0; - } else { - _this3.touchDeltaX = event.originalEvent.touches[0].clientX - _this3.touchStartX; - } - }; + var resolvePromise; + this.promise = new Promise(function promiseExecutor(resolve) { + resolvePromise = resolve; + }); - var end = function end(event) { - if (_this3._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) { - _this3.touchDeltaX = event.originalEvent.clientX - _this3.touchStartX; - } + var token = this; + executor(function cancel(message) { + if (token.reason) { + // Cancellation has already been requested + return; + } - _this3._handleSwipe(); + token.reason = new Cancel(message); + resolvePromise(token.reason); + }); +} - if (_this3._config.pause === 'hover') { - // If it's a touch-enabled device, mouseenter/leave are fired as - // part of the mouse compatibility events on first tap - the carousel - // would stop cycling until user tapped out of it; - // here, we listen for touchend, explicitly pause the carousel - // (as if it's the second time we tap on it, mouseenter compat event - // is NOT fired) and after a timeout (to allow for mouse compatibility - // events to fire) we explicitly restart cycling - _this3.pause(); +/** + * Throws a `Cancel` if cancellation has been requested. + */ +CancelToken.prototype.throwIfRequested = function throwIfRequested() { + if (this.reason) { + throw this.reason; + } +}; - if (_this3.touchTimeout) { - clearTimeout(_this3.touchTimeout); - } +/** + * Returns an object that contains a new `CancelToken` and a function that, when called, + * cancels the `CancelToken`. + */ +CancelToken.source = function source() { + var cancel; + var token = new CancelToken(function executor(c) { + cancel = c; + }); + return { + token: token, + cancel: cancel + }; +}; - _this3.touchTimeout = setTimeout(function (event) { - return _this3.cycle(event); - }, TOUCHEVENT_COMPAT_WAIT + _this3._config.interval); - } - }; +module.exports = CancelToken; - $(this._element.querySelectorAll(Selector$2.ITEM_IMG)).on(Event$2.DRAG_START, function (e) { - return e.preventDefault(); - }); - if (this._pointerEvent) { - $(this._element).on(Event$2.POINTERDOWN, function (event) { - return start(event); - }); - $(this._element).on(Event$2.POINTERUP, function (event) { - return end(event); - }); +/***/ }), - this._element.classList.add(ClassName$2.POINTER_EVENT); - } else { - $(this._element).on(Event$2.TOUCHSTART, function (event) { - return start(event); - }); - $(this._element).on(Event$2.TOUCHMOVE, function (event) { - return move(event); - }); - $(this._element).on(Event$2.TOUCHEND, function (event) { - return end(event); - }); - } - }; +/***/ "./node_modules/axios/lib/cancel/isCancel.js": +/*!***************************************************!*\ + !*** ./node_modules/axios/lib/cancel/isCancel.js ***! + \***************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - _proto._keydown = function _keydown(event) { - if (/input|textarea/i.test(event.target.tagName)) { - return; - } +"use strict"; - switch (event.which) { - case ARROW_LEFT_KEYCODE: - event.preventDefault(); - this.prev(); - break; - case ARROW_RIGHT_KEYCODE: - event.preventDefault(); - this.next(); - break; - } - }; +module.exports = function isCancel(value) { + return !!(value && value.__CANCEL__); +}; - _proto._getItemIndex = function _getItemIndex(element) { - this._items = element && element.parentNode ? [].slice.call(element.parentNode.querySelectorAll(Selector$2.ITEM)) : []; - return this._items.indexOf(element); - }; - _proto._getItemByDirection = function _getItemByDirection(direction, activeElement) { - var isNextDirection = direction === Direction.NEXT; - var isPrevDirection = direction === Direction.PREV; +/***/ }), - var activeIndex = this._getItemIndex(activeElement); +/***/ "./node_modules/axios/lib/core/Axios.js": +/*!**********************************************!*\ + !*** ./node_modules/axios/lib/core/Axios.js ***! + \**********************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - var lastItemIndex = this._items.length - 1; - var isGoingToWrap = isPrevDirection && activeIndex === 0 || isNextDirection && activeIndex === lastItemIndex; +"use strict"; - if (isGoingToWrap && !this._config.wrap) { - return activeElement; - } - var delta = direction === Direction.PREV ? -1 : 1; - var itemIndex = (activeIndex + delta) % this._items.length; - return itemIndex === -1 ? this._items[this._items.length - 1] : this._items[itemIndex]; - }; +var utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js"); +var buildURL = __webpack_require__(/*! ../helpers/buildURL */ "./node_modules/axios/lib/helpers/buildURL.js"); +var InterceptorManager = __webpack_require__(/*! ./InterceptorManager */ "./node_modules/axios/lib/core/InterceptorManager.js"); +var dispatchRequest = __webpack_require__(/*! ./dispatchRequest */ "./node_modules/axios/lib/core/dispatchRequest.js"); +var mergeConfig = __webpack_require__(/*! ./mergeConfig */ "./node_modules/axios/lib/core/mergeConfig.js"); - _proto._triggerSlideEvent = function _triggerSlideEvent(relatedTarget, eventDirectionName) { - var targetIndex = this._getItemIndex(relatedTarget); +/** + * Create a new instance of Axios + * + * @param {Object} instanceConfig The default config for the instance + */ +function Axios(instanceConfig) { + this.defaults = instanceConfig; + this.interceptors = { + request: new InterceptorManager(), + response: new InterceptorManager() + }; +} - var fromIndex = this._getItemIndex(this._element.querySelector(Selector$2.ACTIVE_ITEM)); +/** + * Dispatch a request + * + * @param {Object} config The config specific for this request (merged with this.defaults) + */ +Axios.prototype.request = function request(config) { + /*eslint no-param-reassign:0*/ + // Allow for axios('example/url'[, config]) a la fetch API + if (typeof config === 'string') { + config = arguments[1] || {}; + config.url = arguments[0]; + } else { + config = config || {}; + } - var slideEvent = $.Event(Event$2.SLIDE, { - relatedTarget: relatedTarget, - direction: eventDirectionName, - from: fromIndex, - to: targetIndex - }); - $(this._element).trigger(slideEvent); - return slideEvent; - }; + config = mergeConfig(this.defaults, config); - _proto._setActiveIndicatorElement = function _setActiveIndicatorElement(element) { - if (this._indicatorsElement) { - var indicators = [].slice.call(this._indicatorsElement.querySelectorAll(Selector$2.ACTIVE)); - $(indicators).removeClass(ClassName$2.ACTIVE); + // Set config.method + if (config.method) { + config.method = config.method.toLowerCase(); + } else if (this.defaults.method) { + config.method = this.defaults.method.toLowerCase(); + } else { + config.method = 'get'; + } - var nextIndicator = this._indicatorsElement.children[this._getItemIndex(element)]; + // Hook up interceptors middleware + var chain = [dispatchRequest, undefined]; + var promise = Promise.resolve(config); - if (nextIndicator) { - $(nextIndicator).addClass(ClassName$2.ACTIVE); - } - } - }; + this.interceptors.request.forEach(function unshiftRequestInterceptors(interceptor) { + chain.unshift(interceptor.fulfilled, interceptor.rejected); + }); - _proto._slide = function _slide(direction, element) { - var _this4 = this; + this.interceptors.response.forEach(function pushResponseInterceptors(interceptor) { + chain.push(interceptor.fulfilled, interceptor.rejected); + }); - var activeElement = this._element.querySelector(Selector$2.ACTIVE_ITEM); + while (chain.length) { + promise = promise.then(chain.shift(), chain.shift()); + } - var activeElementIndex = this._getItemIndex(activeElement); + return promise; +}; - var nextElement = element || activeElement && this._getItemByDirection(direction, activeElement); +Axios.prototype.getUri = function getUri(config) { + config = mergeConfig(this.defaults, config); + return buildURL(config.url, config.params, config.paramsSerializer).replace(/^\?/, ''); +}; - var nextElementIndex = this._getItemIndex(nextElement); +// Provide aliases for supported request methods +utils.forEach(['delete', 'get', 'head', 'options'], function forEachMethodNoData(method) { + /*eslint func-names:0*/ + Axios.prototype[method] = function(url, config) { + return this.request(utils.merge(config || {}, { + method: method, + url: url + })); + }; +}); - var isCycling = Boolean(this._interval); - var directionalClassName; - var orderClassName; - var eventDirectionName; +utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { + /*eslint func-names:0*/ + Axios.prototype[method] = function(url, data, config) { + return this.request(utils.merge(config || {}, { + method: method, + url: url, + data: data + })); + }; +}); - if (direction === Direction.NEXT) { - directionalClassName = ClassName$2.LEFT; - orderClassName = ClassName$2.NEXT; - eventDirectionName = Direction.LEFT; - } else { - directionalClassName = ClassName$2.RIGHT; - orderClassName = ClassName$2.PREV; - eventDirectionName = Direction.RIGHT; - } +module.exports = Axios; - if (nextElement && $(nextElement).hasClass(ClassName$2.ACTIVE)) { - this._isSliding = false; - return; - } - var slideEvent = this._triggerSlideEvent(nextElement, eventDirectionName); +/***/ }), - if (slideEvent.isDefaultPrevented()) { - return; - } +/***/ "./node_modules/axios/lib/core/InterceptorManager.js": +/*!***********************************************************!*\ + !*** ./node_modules/axios/lib/core/InterceptorManager.js ***! + \***********************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - if (!activeElement || !nextElement) { - // Some weirdness is happening, so we bail - return; - } +"use strict"; - this._isSliding = true; - if (isCycling) { - this.pause(); - } +var utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js"); - this._setActiveIndicatorElement(nextElement); +function InterceptorManager() { + this.handlers = []; +} - var slidEvent = $.Event(Event$2.SLID, { - relatedTarget: nextElement, - direction: eventDirectionName, - from: activeElementIndex, - to: nextElementIndex - }); +/** + * Add a new interceptor to the stack + * + * @param {Function} fulfilled The function to handle `then` for a `Promise` + * @param {Function} rejected The function to handle `reject` for a `Promise` + * + * @return {Number} An ID used to remove interceptor later + */ +InterceptorManager.prototype.use = function use(fulfilled, rejected) { + this.handlers.push({ + fulfilled: fulfilled, + rejected: rejected + }); + return this.handlers.length - 1; +}; - if ($(this._element).hasClass(ClassName$2.SLIDE)) { - $(nextElement).addClass(orderClassName); - Util.reflow(nextElement); - $(activeElement).addClass(directionalClassName); - $(nextElement).addClass(directionalClassName); - var nextElementInterval = parseInt(nextElement.getAttribute('data-interval'), 10); +/** + * Remove an interceptor from the stack + * + * @param {Number} id The ID that was returned by `use` + */ +InterceptorManager.prototype.eject = function eject(id) { + if (this.handlers[id]) { + this.handlers[id] = null; + } +}; - if (nextElementInterval) { - this._config.defaultInterval = this._config.defaultInterval || this._config.interval; - this._config.interval = nextElementInterval; - } else { - this._config.interval = this._config.defaultInterval || this._config.interval; - } +/** + * Iterate over all the registered interceptors + * + * This method is particularly useful for skipping over any + * interceptors that may have become `null` calling `eject`. + * + * @param {Function} fn The function to call for each interceptor + */ +InterceptorManager.prototype.forEach = function forEach(fn) { + utils.forEach(this.handlers, function forEachHandler(h) { + if (h !== null) { + fn(h); + } + }); +}; - var transitionDuration = Util.getTransitionDurationFromElement(activeElement); - $(activeElement).one(Util.TRANSITION_END, function () { - $(nextElement).removeClass(directionalClassName + " " + orderClassName).addClass(ClassName$2.ACTIVE); - $(activeElement).removeClass(ClassName$2.ACTIVE + " " + orderClassName + " " + directionalClassName); - _this4._isSliding = false; - setTimeout(function () { - return $(_this4._element).trigger(slidEvent); - }, 0); - }).emulateTransitionEnd(transitionDuration); - } else { - $(activeElement).removeClass(ClassName$2.ACTIVE); - $(nextElement).addClass(ClassName$2.ACTIVE); - this._isSliding = false; - $(this._element).trigger(slidEvent); - } +module.exports = InterceptorManager; - if (isCycling) { - this.cycle(); - } - } // Static - ; - Carousel._jQueryInterface = function _jQueryInterface(config) { - return this.each(function () { - var data = $(this).data(DATA_KEY$2); +/***/ }), - var _config = _objectSpread2({}, Default, {}, $(this).data()); +/***/ "./node_modules/axios/lib/core/buildFullPath.js": +/*!******************************************************!*\ + !*** ./node_modules/axios/lib/core/buildFullPath.js ***! + \******************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - if (typeof config === 'object') { - _config = _objectSpread2({}, _config, {}, config); - } +"use strict"; - var action = typeof config === 'string' ? config : _config.slide; - if (!data) { - data = new Carousel(this, _config); - $(this).data(DATA_KEY$2, data); - } +var isAbsoluteURL = __webpack_require__(/*! ../helpers/isAbsoluteURL */ "./node_modules/axios/lib/helpers/isAbsoluteURL.js"); +var combineURLs = __webpack_require__(/*! ../helpers/combineURLs */ "./node_modules/axios/lib/helpers/combineURLs.js"); - if (typeof config === 'number') { - data.to(config); - } else if (typeof action === 'string') { - if (typeof data[action] === 'undefined') { - throw new TypeError("No method named \"" + action + "\""); - } +/** + * Creates a new URL by combining the baseURL with the requestedURL, + * only when the requestedURL is not already an absolute URL. + * If the requestURL is absolute, this function returns the requestedURL untouched. + * + * @param {string} baseURL The base URL + * @param {string} requestedURL Absolute or relative URL to combine + * @returns {string} The combined full path + */ +module.exports = function buildFullPath(baseURL, requestedURL) { + if (baseURL && !isAbsoluteURL(requestedURL)) { + return combineURLs(baseURL, requestedURL); + } + return requestedURL; +}; - data[action](); - } else if (_config.interval && _config.ride) { - data.pause(); - data.cycle(); - } - }); - }; - Carousel._dataApiClickHandler = function _dataApiClickHandler(event) { - var selector = Util.getSelectorFromElement(this); +/***/ }), - if (!selector) { - return; - } +/***/ "./node_modules/axios/lib/core/createError.js": +/*!****************************************************!*\ + !*** ./node_modules/axios/lib/core/createError.js ***! + \****************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - var target = $(selector)[0]; +"use strict"; - if (!target || !$(target).hasClass(ClassName$2.CAROUSEL)) { - return; - } - var config = _objectSpread2({}, $(target).data(), {}, $(this).data()); +var enhanceError = __webpack_require__(/*! ./enhanceError */ "./node_modules/axios/lib/core/enhanceError.js"); - var slideIndex = this.getAttribute('data-slide-to'); +/** + * Create an Error with the specified message, config, error code, request and response. + * + * @param {string} message The error message. + * @param {Object} config The config. + * @param {string} [code] The error code (for example, 'ECONNABORTED'). + * @param {Object} [request] The request. + * @param {Object} [response] The response. + * @returns {Error} The created error. + */ +module.exports = function createError(message, config, code, request, response) { + var error = new Error(message); + return enhanceError(error, config, code, request, response); +}; - if (slideIndex) { - config.interval = false; - } - Carousel._jQueryInterface.call($(target), config); +/***/ }), - if (slideIndex) { - $(target).data(DATA_KEY$2).to(slideIndex); - } +/***/ "./node_modules/axios/lib/core/dispatchRequest.js": +/*!********************************************************!*\ + !*** ./node_modules/axios/lib/core/dispatchRequest.js ***! + \********************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - event.preventDefault(); - }; +"use strict"; - _createClass(Carousel, null, [{ - key: "VERSION", - get: function get() { - return VERSION$2; - } - }, { - key: "Default", - get: function get() { - return Default; - } - }]); - return Carousel; - }(); - /** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ +var utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js"); +var transformData = __webpack_require__(/*! ./transformData */ "./node_modules/axios/lib/core/transformData.js"); +var isCancel = __webpack_require__(/*! ../cancel/isCancel */ "./node_modules/axios/lib/cancel/isCancel.js"); +var defaults = __webpack_require__(/*! ../defaults */ "./node_modules/axios/lib/defaults.js"); +/** + * Throws a `Cancel` if cancellation has been requested. + */ +function throwIfCancellationRequested(config) { + if (config.cancelToken) { + config.cancelToken.throwIfRequested(); + } +} - $(document).on(Event$2.CLICK_DATA_API, Selector$2.DATA_SLIDE, Carousel._dataApiClickHandler); - $(window).on(Event$2.LOAD_DATA_API, function () { - var carousels = [].slice.call(document.querySelectorAll(Selector$2.DATA_RIDE)); +/** + * Dispatch a request to the server using the configured adapter. + * + * @param {object} config The config that is to be used for the request + * @returns {Promise} The Promise to be fulfilled + */ +module.exports = function dispatchRequest(config) { + throwIfCancellationRequested(config); - for (var i = 0, len = carousels.length; i < len; i++) { - var $carousel = $(carousels[i]); + // Ensure headers exist + config.headers = config.headers || {}; - Carousel._jQueryInterface.call($carousel, $carousel.data()); + // Transform request data + config.data = transformData( + config.data, + config.headers, + config.transformRequest + ); + + // Flatten headers + config.headers = utils.merge( + config.headers.common || {}, + config.headers[config.method] || {}, + config.headers + ); + + utils.forEach( + ['delete', 'get', 'head', 'post', 'put', 'patch', 'common'], + function cleanHeaderConfig(method) { + delete config.headers[method]; } - }); - /** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - */ + ); - $.fn[NAME$2] = Carousel._jQueryInterface; - $.fn[NAME$2].Constructor = Carousel; + var adapter = config.adapter || defaults.adapter; - $.fn[NAME$2].noConflict = function () { - $.fn[NAME$2] = JQUERY_NO_CONFLICT$2; - return Carousel._jQueryInterface; - }; + return adapter(config).then(function onAdapterResolution(response) { + throwIfCancellationRequested(config); - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ + // Transform response data + response.data = transformData( + response.data, + response.headers, + config.transformResponse + ); - var NAME$3 = 'collapse'; - var VERSION$3 = '4.4.1'; - var DATA_KEY$3 = 'bs.collapse'; - var EVENT_KEY$3 = "." + DATA_KEY$3; - var DATA_API_KEY$3 = '.data-api'; - var JQUERY_NO_CONFLICT$3 = $.fn[NAME$3]; - var Default$1 = { - toggle: true, - parent: '' - }; - var DefaultType$1 = { - toggle: 'boolean', - parent: '(string|element)' - }; - var Event$3 = { - SHOW: "show" + EVENT_KEY$3, - SHOWN: "shown" + EVENT_KEY$3, - HIDE: "hide" + EVENT_KEY$3, - HIDDEN: "hidden" + EVENT_KEY$3, - CLICK_DATA_API: "click" + EVENT_KEY$3 + DATA_API_KEY$3 - }; - var ClassName$3 = { - SHOW: 'show', - COLLAPSE: 'collapse', - COLLAPSING: 'collapsing', - COLLAPSED: 'collapsed' - }; - var Dimension = { - WIDTH: 'width', - HEIGHT: 'height' - }; - var Selector$3 = { - ACTIVES: '.show, .collapsing', - DATA_TOGGLE: '[data-toggle="collapse"]' - }; - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ + return response; + }, function onAdapterRejection(reason) { + if (!isCancel(reason)) { + throwIfCancellationRequested(config); - var Collapse = - /*#__PURE__*/ - function () { - function Collapse(element, config) { - this._isTransitioning = false; - this._element = element; - this._config = this._getConfig(config); - this._triggerArray = [].slice.call(document.querySelectorAll("[data-toggle=\"collapse\"][href=\"#" + element.id + "\"]," + ("[data-toggle=\"collapse\"][data-target=\"#" + element.id + "\"]"))); - var toggleList = [].slice.call(document.querySelectorAll(Selector$3.DATA_TOGGLE)); + // Transform response data + if (reason && reason.response) { + reason.response.data = transformData( + reason.response.data, + reason.response.headers, + config.transformResponse + ); + } + } - for (var i = 0, len = toggleList.length; i < len; i++) { - var elem = toggleList[i]; - var selector = Util.getSelectorFromElement(elem); - var filterElement = [].slice.call(document.querySelectorAll(selector)).filter(function (foundElem) { - return foundElem === element; - }); + return Promise.reject(reason); + }); +}; - if (selector !== null && filterElement.length > 0) { - this._selector = selector; - this._triggerArray.push(elem); - } - } +/***/ }), - this._parent = this._config.parent ? this._getParent() : null; +/***/ "./node_modules/axios/lib/core/enhanceError.js": +/*!*****************************************************!*\ + !*** ./node_modules/axios/lib/core/enhanceError.js ***! + \*****************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - if (!this._config.parent) { - this._addAriaAndCollapsedClass(this._element, this._triggerArray); - } +"use strict"; - if (this._config.toggle) { - this.toggle(); - } - } // Getters +/** + * Update an Error with the specified config, error code, and response. + * + * @param {Error} error The error to update. + * @param {Object} config The config. + * @param {string} [code] The error code (for example, 'ECONNABORTED'). + * @param {Object} [request] The request. + * @param {Object} [response] The response. + * @returns {Error} The error. + */ +module.exports = function enhanceError(error, config, code, request, response) { + error.config = config; + if (code) { + error.code = code; + } - var _proto = Collapse.prototype; + error.request = request; + error.response = response; + error.isAxiosError = true; - // Public - _proto.toggle = function toggle() { - if ($(this._element).hasClass(ClassName$3.SHOW)) { - this.hide(); - } else { - this.show(); - } + error.toJSON = function() { + return { + // Standard + message: this.message, + name: this.name, + // Microsoft + description: this.description, + number: this.number, + // Mozilla + fileName: this.fileName, + lineNumber: this.lineNumber, + columnNumber: this.columnNumber, + stack: this.stack, + // Axios + config: this.config, + code: this.code }; + }; + return error; +}; - _proto.show = function show() { - var _this = this; - if (this._isTransitioning || $(this._element).hasClass(ClassName$3.SHOW)) { - return; - } +/***/ }), - var actives; - var activesData; +/***/ "./node_modules/axios/lib/core/mergeConfig.js": +/*!****************************************************!*\ + !*** ./node_modules/axios/lib/core/mergeConfig.js ***! + \****************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - if (this._parent) { - actives = [].slice.call(this._parent.querySelectorAll(Selector$3.ACTIVES)).filter(function (elem) { - if (typeof _this._config.parent === 'string') { - return elem.getAttribute('data-parent') === _this._config.parent; - } - - return elem.classList.contains(ClassName$3.COLLAPSE); - }); +"use strict"; - if (actives.length === 0) { - actives = null; - } - } - if (actives) { - activesData = $(actives).not(this._selector).data(DATA_KEY$3); +var utils = __webpack_require__(/*! ../utils */ "./node_modules/axios/lib/utils.js"); - if (activesData && activesData._isTransitioning) { - return; - } - } +/** + * Config-specific merge-function which creates a new config-object + * by merging two configuration objects together. + * + * @param {Object} config1 + * @param {Object} config2 + * @returns {Object} New object resulting from merging config2 to config1 + */ +module.exports = function mergeConfig(config1, config2) { + // eslint-disable-next-line no-param-reassign + config2 = config2 || {}; + var config = {}; - var startEvent = $.Event(Event$3.SHOW); - $(this._element).trigger(startEvent); + var valueFromConfig2Keys = ['url', 'method', 'params', 'data']; + var mergeDeepPropertiesKeys = ['headers', 'auth', 'proxy']; + var defaultToConfig2Keys = [ + 'baseURL', 'url', 'transformRequest', 'transformResponse', 'paramsSerializer', + 'timeout', 'withCredentials', 'adapter', 'responseType', 'xsrfCookieName', + 'xsrfHeaderName', 'onUploadProgress', 'onDownloadProgress', + 'maxContentLength', 'validateStatus', 'maxRedirects', 'httpAgent', + 'httpsAgent', 'cancelToken', 'socketPath' + ]; - if (startEvent.isDefaultPrevented()) { - return; - } + utils.forEach(valueFromConfig2Keys, function valueFromConfig2(prop) { + if (typeof config2[prop] !== 'undefined') { + config[prop] = config2[prop]; + } + }); - if (actives) { - Collapse._jQueryInterface.call($(actives).not(this._selector), 'hide'); + utils.forEach(mergeDeepPropertiesKeys, function mergeDeepProperties(prop) { + if (utils.isObject(config2[prop])) { + config[prop] = utils.deepMerge(config1[prop], config2[prop]); + } else if (typeof config2[prop] !== 'undefined') { + config[prop] = config2[prop]; + } else if (utils.isObject(config1[prop])) { + config[prop] = utils.deepMerge(config1[prop]); + } else if (typeof config1[prop] !== 'undefined') { + config[prop] = config1[prop]; + } + }); - if (!activesData) { - $(actives).data(DATA_KEY$3, null); - } - } + utils.forEach(defaultToConfig2Keys, function defaultToConfig2(prop) { + if (typeof config2[prop] !== 'undefined') { + config[prop] = config2[prop]; + } else if (typeof config1[prop] !== 'undefined') { + config[prop] = config1[prop]; + } + }); - var dimension = this._getDimension(); + var axiosKeys = valueFromConfig2Keys + .concat(mergeDeepPropertiesKeys) + .concat(defaultToConfig2Keys); - $(this._element).removeClass(ClassName$3.COLLAPSE).addClass(ClassName$3.COLLAPSING); - this._element.style[dimension] = 0; + var otherKeys = Object + .keys(config2) + .filter(function filterAxiosKeys(key) { + return axiosKeys.indexOf(key) === -1; + }); - if (this._triggerArray.length) { - $(this._triggerArray).removeClass(ClassName$3.COLLAPSED).attr('aria-expanded', true); - } + utils.forEach(otherKeys, function otherKeysDefaultToConfig2(prop) { + if (typeof config2[prop] !== 'undefined') { + config[prop] = config2[prop]; + } else if (typeof config1[prop] !== 'undefined') { + config[prop] = config1[prop]; + } + }); - this.setTransitioning(true); + return config; +}; - var complete = function complete() { - $(_this._element).removeClass(ClassName$3.COLLAPSING).addClass(ClassName$3.COLLAPSE).addClass(ClassName$3.SHOW); - _this._element.style[dimension] = ''; - _this.setTransitioning(false); +/***/ }), - $(_this._element).trigger(Event$3.SHOWN); - }; +/***/ "./node_modules/axios/lib/core/settle.js": +/*!***********************************************!*\ + !*** ./node_modules/axios/lib/core/settle.js ***! + \***********************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - var capitalizedDimension = dimension[0].toUpperCase() + dimension.slice(1); - var scrollSize = "scroll" + capitalizedDimension; - var transitionDuration = Util.getTransitionDurationFromElement(this._element); - $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); - this._element.style[dimension] = this._element[scrollSize] + "px"; - }; +"use strict"; - _proto.hide = function hide() { - var _this2 = this; - if (this._isTransitioning || !$(this._element).hasClass(ClassName$3.SHOW)) { - return; - } +var createError = __webpack_require__(/*! ./createError */ "./node_modules/axios/lib/core/createError.js"); - var startEvent = $.Event(Event$3.HIDE); - $(this._element).trigger(startEvent); +/** + * Resolve or reject a Promise based on response status. + * + * @param {Function} resolve A function that resolves the promise. + * @param {Function} reject A function that rejects the promise. + * @param {object} response The response. + */ +module.exports = function settle(resolve, reject, response) { + var validateStatus = response.config.validateStatus; + if (!validateStatus || validateStatus(response.status)) { + resolve(response); + } else { + reject(createError( + 'Request failed with status code ' + response.status, + response.config, + null, + response.request, + response + )); + } +}; - if (startEvent.isDefaultPrevented()) { - return; - } - var dimension = this._getDimension(); +/***/ }), - this._element.style[dimension] = this._element.getBoundingClientRect()[dimension] + "px"; - Util.reflow(this._element); - $(this._element).addClass(ClassName$3.COLLAPSING).removeClass(ClassName$3.COLLAPSE).removeClass(ClassName$3.SHOW); - var triggerArrayLength = this._triggerArray.length; +/***/ "./node_modules/axios/lib/core/transformData.js": +/*!******************************************************!*\ + !*** ./node_modules/axios/lib/core/transformData.js ***! + \******************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - if (triggerArrayLength > 0) { - for (var i = 0; i < triggerArrayLength; i++) { - var trigger = this._triggerArray[i]; - var selector = Util.getSelectorFromElement(trigger); +"use strict"; - if (selector !== null) { - var $elem = $([].slice.call(document.querySelectorAll(selector))); - if (!$elem.hasClass(ClassName$3.SHOW)) { - $(trigger).addClass(ClassName$3.COLLAPSED).attr('aria-expanded', false); - } - } - } - } +var utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js"); - this.setTransitioning(true); +/** + * Transform the data for a request or a response + * + * @param {Object|String} data The data to be transformed + * @param {Array} headers The headers for the request or response + * @param {Array|Function} fns A single function or Array of functions + * @returns {*} The resulting transformed data + */ +module.exports = function transformData(data, headers, fns) { + /*eslint no-param-reassign:0*/ + utils.forEach(fns, function transform(fn) { + data = fn(data, headers); + }); - var complete = function complete() { - _this2.setTransitioning(false); + return data; +}; - $(_this2._element).removeClass(ClassName$3.COLLAPSING).addClass(ClassName$3.COLLAPSE).trigger(Event$3.HIDDEN); - }; - this._element.style[dimension] = ''; - var transitionDuration = Util.getTransitionDurationFromElement(this._element); - $(this._element).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); - }; +/***/ }), - _proto.setTransitioning = function setTransitioning(isTransitioning) { - this._isTransitioning = isTransitioning; - }; +/***/ "./node_modules/axios/lib/defaults.js": +/*!********************************************!*\ + !*** ./node_modules/axios/lib/defaults.js ***! + \********************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - _proto.dispose = function dispose() { - $.removeData(this._element, DATA_KEY$3); - this._config = null; - this._parent = null; - this._element = null; - this._triggerArray = null; - this._isTransitioning = null; - } // Private - ; +"use strict"; +/* WEBPACK VAR INJECTION */(function(process) { - _proto._getConfig = function _getConfig(config) { - config = _objectSpread2({}, Default$1, {}, config); - config.toggle = Boolean(config.toggle); // Coerce string values +var utils = __webpack_require__(/*! ./utils */ "./node_modules/axios/lib/utils.js"); +var normalizeHeaderName = __webpack_require__(/*! ./helpers/normalizeHeaderName */ "./node_modules/axios/lib/helpers/normalizeHeaderName.js"); - Util.typeCheckConfig(NAME$3, config, DefaultType$1); - return config; - }; +var DEFAULT_CONTENT_TYPE = { + 'Content-Type': 'application/x-www-form-urlencoded' +}; - _proto._getDimension = function _getDimension() { - var hasWidth = $(this._element).hasClass(Dimension.WIDTH); - return hasWidth ? Dimension.WIDTH : Dimension.HEIGHT; - }; +function setContentTypeIfUnset(headers, value) { + if (!utils.isUndefined(headers) && utils.isUndefined(headers['Content-Type'])) { + headers['Content-Type'] = value; + } +} - _proto._getParent = function _getParent() { - var _this3 = this; +function getDefaultAdapter() { + var adapter; + if (typeof XMLHttpRequest !== 'undefined') { + // For browsers use XHR adapter + adapter = __webpack_require__(/*! ./adapters/xhr */ "./node_modules/axios/lib/adapters/xhr.js"); + } else if (typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]') { + // For node use HTTP adapter + adapter = __webpack_require__(/*! ./adapters/http */ "./node_modules/axios/lib/adapters/xhr.js"); + } + return adapter; +} - var parent; +var defaults = { + adapter: getDefaultAdapter(), - if (Util.isElement(this._config.parent)) { - parent = this._config.parent; // It's a jQuery object + transformRequest: [function transformRequest(data, headers) { + normalizeHeaderName(headers, 'Accept'); + normalizeHeaderName(headers, 'Content-Type'); + if (utils.isFormData(data) || + utils.isArrayBuffer(data) || + utils.isBuffer(data) || + utils.isStream(data) || + utils.isFile(data) || + utils.isBlob(data) + ) { + return data; + } + if (utils.isArrayBufferView(data)) { + return data.buffer; + } + if (utils.isURLSearchParams(data)) { + setContentTypeIfUnset(headers, 'application/x-www-form-urlencoded;charset=utf-8'); + return data.toString(); + } + if (utils.isObject(data)) { + setContentTypeIfUnset(headers, 'application/json;charset=utf-8'); + return JSON.stringify(data); + } + return data; + }], - if (typeof this._config.parent.jquery !== 'undefined') { - parent = this._config.parent[0]; - } - } else { - parent = document.querySelector(this._config.parent); - } + transformResponse: [function transformResponse(data) { + /*eslint no-param-reassign:0*/ + if (typeof data === 'string') { + try { + data = JSON.parse(data); + } catch (e) { /* Ignore */ } + } + return data; + }], - var selector = "[data-toggle=\"collapse\"][data-parent=\"" + this._config.parent + "\"]"; - var children = [].slice.call(parent.querySelectorAll(selector)); - $(children).each(function (i, element) { - _this3._addAriaAndCollapsedClass(Collapse._getTargetFromElement(element), [element]); - }); - return parent; - }; + /** + * A timeout in milliseconds to abort a request. If set to 0 (default) a + * timeout is not created. + */ + timeout: 0, - _proto._addAriaAndCollapsedClass = function _addAriaAndCollapsedClass(element, triggerArray) { - var isOpen = $(element).hasClass(ClassName$3.SHOW); + xsrfCookieName: 'XSRF-TOKEN', + xsrfHeaderName: 'X-XSRF-TOKEN', - if (triggerArray.length) { - $(triggerArray).toggleClass(ClassName$3.COLLAPSED, !isOpen).attr('aria-expanded', isOpen); - } - } // Static - ; + maxContentLength: -1, - Collapse._getTargetFromElement = function _getTargetFromElement(element) { - var selector = Util.getSelectorFromElement(element); - return selector ? document.querySelector(selector) : null; - }; + validateStatus: function validateStatus(status) { + return status >= 200 && status < 300; + } +}; - Collapse._jQueryInterface = function _jQueryInterface(config) { - return this.each(function () { - var $this = $(this); - var data = $this.data(DATA_KEY$3); +defaults.headers = { + common: { + 'Accept': 'application/json, text/plain, */*' + } +}; - var _config = _objectSpread2({}, Default$1, {}, $this.data(), {}, typeof config === 'object' && config ? config : {}); +utils.forEach(['delete', 'get', 'head'], function forEachMethodNoData(method) { + defaults.headers[method] = {}; +}); - if (!data && _config.toggle && /show|hide/.test(config)) { - _config.toggle = false; - } +utils.forEach(['post', 'put', 'patch'], function forEachMethodWithData(method) { + defaults.headers[method] = utils.merge(DEFAULT_CONTENT_TYPE); +}); - if (!data) { - data = new Collapse(this, _config); - $this.data(DATA_KEY$3, data); - } +module.exports = defaults; - if (typeof config === 'string') { - if (typeof data[config] === 'undefined') { - throw new TypeError("No method named \"" + config + "\""); - } +/* WEBPACK VAR INJECTION */}.call(this, __webpack_require__(/*! ./../../process/browser.js */ "./node_modules/process/browser.js"))) - data[config](); - } - }); - }; +/***/ }), - _createClass(Collapse, null, [{ - key: "VERSION", - get: function get() { - return VERSION$3; - } - }, { - key: "Default", - get: function get() { - return Default$1; - } - }]); +/***/ "./node_modules/axios/lib/helpers/bind.js": +/*!************************************************!*\ + !*** ./node_modules/axios/lib/helpers/bind.js ***! + \************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - return Collapse; - }(); - /** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ +"use strict"; - $(document).on(Event$3.CLICK_DATA_API, Selector$3.DATA_TOGGLE, function (event) { - // preventDefault only for elements (which change the URL) not inside the collapsible element - if (event.currentTarget.tagName === 'A') { - event.preventDefault(); +module.exports = function bind(fn, thisArg) { + return function wrap() { + var args = new Array(arguments.length); + for (var i = 0; i < args.length; i++) { + args[i] = arguments[i]; } + return fn.apply(thisArg, args); + }; +}; - var $trigger = $(this); - var selector = Util.getSelectorFromElement(this); - var selectors = [].slice.call(document.querySelectorAll(selector)); - $(selectors).each(function () { - var $target = $(this); - var data = $target.data(DATA_KEY$3); - var config = data ? 'toggle' : $trigger.data(); - Collapse._jQueryInterface.call($target, config); - }); - }); - /** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - */ +/***/ }), - $.fn[NAME$3] = Collapse._jQueryInterface; - $.fn[NAME$3].Constructor = Collapse; +/***/ "./node_modules/axios/lib/helpers/buildURL.js": +/*!****************************************************!*\ + !*** ./node_modules/axios/lib/helpers/buildURL.js ***! + \****************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - $.fn[NAME$3].noConflict = function () { - $.fn[NAME$3] = JQUERY_NO_CONFLICT$3; - return Collapse._jQueryInterface; - }; +"use strict"; - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ - var NAME$4 = 'dropdown'; - var VERSION$4 = '4.4.1'; - var DATA_KEY$4 = 'bs.dropdown'; - var EVENT_KEY$4 = "." + DATA_KEY$4; - var DATA_API_KEY$4 = '.data-api'; - var JQUERY_NO_CONFLICT$4 = $.fn[NAME$4]; - var ESCAPE_KEYCODE = 27; // KeyboardEvent.which value for Escape (Esc) key +var utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js"); - var SPACE_KEYCODE = 32; // KeyboardEvent.which value for space key +function encode(val) { + return encodeURIComponent(val). + replace(/%40/gi, '@'). + replace(/%3A/gi, ':'). + replace(/%24/g, '$'). + replace(/%2C/gi, ','). + replace(/%20/g, '+'). + replace(/%5B/gi, '['). + replace(/%5D/gi, ']'); +} - var TAB_KEYCODE = 9; // KeyboardEvent.which value for tab key +/** + * Build a URL by appending params to the end + * + * @param {string} url The base of the url (e.g., http://www.google.com) + * @param {object} [params] The params to be appended + * @returns {string} The formatted url + */ +module.exports = function buildURL(url, params, paramsSerializer) { + /*eslint no-param-reassign:0*/ + if (!params) { + return url; + } - var ARROW_UP_KEYCODE = 38; // KeyboardEvent.which value for up arrow key + var serializedParams; + if (paramsSerializer) { + serializedParams = paramsSerializer(params); + } else if (utils.isURLSearchParams(params)) { + serializedParams = params.toString(); + } else { + var parts = []; - var ARROW_DOWN_KEYCODE = 40; // KeyboardEvent.which value for down arrow key + utils.forEach(params, function serialize(val, key) { + if (val === null || typeof val === 'undefined') { + return; + } - var RIGHT_MOUSE_BUTTON_WHICH = 3; // MouseEvent.which value for the right button (assuming a right-handed mouse) + if (utils.isArray(val)) { + key = key + '[]'; + } else { + val = [val]; + } - var REGEXP_KEYDOWN = new RegExp(ARROW_UP_KEYCODE + "|" + ARROW_DOWN_KEYCODE + "|" + ESCAPE_KEYCODE); - var Event$4 = { - HIDE: "hide" + EVENT_KEY$4, - HIDDEN: "hidden" + EVENT_KEY$4, - SHOW: "show" + EVENT_KEY$4, - SHOWN: "shown" + EVENT_KEY$4, - CLICK: "click" + EVENT_KEY$4, - CLICK_DATA_API: "click" + EVENT_KEY$4 + DATA_API_KEY$4, - KEYDOWN_DATA_API: "keydown" + EVENT_KEY$4 + DATA_API_KEY$4, - KEYUP_DATA_API: "keyup" + EVENT_KEY$4 + DATA_API_KEY$4 - }; - var ClassName$4 = { - DISABLED: 'disabled', - SHOW: 'show', - DROPUP: 'dropup', - DROPRIGHT: 'dropright', - DROPLEFT: 'dropleft', - MENURIGHT: 'dropdown-menu-right', - MENULEFT: 'dropdown-menu-left', - POSITION_STATIC: 'position-static' - }; - var Selector$4 = { - DATA_TOGGLE: '[data-toggle="dropdown"]', - FORM_CHILD: '.dropdown form', - MENU: '.dropdown-menu', - NAVBAR_NAV: '.navbar-nav', - VISIBLE_ITEMS: '.dropdown-menu .dropdown-item:not(.disabled):not(:disabled)' - }; - var AttachmentMap = { - TOP: 'top-start', - TOPEND: 'top-end', - BOTTOM: 'bottom-start', - BOTTOMEND: 'bottom-end', - RIGHT: 'right-start', - RIGHTEND: 'right-end', - LEFT: 'left-start', - LEFTEND: 'left-end' - }; - var Default$2 = { - offset: 0, - flip: true, - boundary: 'scrollParent', - reference: 'toggle', - display: 'dynamic', - popperConfig: null - }; - var DefaultType$2 = { - offset: '(number|string|function)', - flip: 'boolean', - boundary: '(string|element)', - reference: '(string|element)', - display: 'string', - popperConfig: '(null|object)' - }; - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ + utils.forEach(val, function parseValue(v) { + if (utils.isDate(v)) { + v = v.toISOString(); + } else if (utils.isObject(v)) { + v = JSON.stringify(v); + } + parts.push(encode(key) + '=' + encode(v)); + }); + }); - var Dropdown = - /*#__PURE__*/ - function () { - function Dropdown(element, config) { - this._element = element; - this._popper = null; - this._config = this._getConfig(config); - this._menu = this._getMenuElement(); - this._inNavbar = this._detectNavbar(); + serializedParams = parts.join('&'); + } - this._addEventListeners(); - } // Getters + if (serializedParams) { + var hashmarkIndex = url.indexOf('#'); + if (hashmarkIndex !== -1) { + url = url.slice(0, hashmarkIndex); + } + url += (url.indexOf('?') === -1 ? '?' : '&') + serializedParams; + } - var _proto = Dropdown.prototype; + return url; +}; - // Public - _proto.toggle = function toggle() { - if (this._element.disabled || $(this._element).hasClass(ClassName$4.DISABLED)) { - return; - } - var isActive = $(this._menu).hasClass(ClassName$4.SHOW); +/***/ }), - Dropdown._clearMenus(); +/***/ "./node_modules/axios/lib/helpers/combineURLs.js": +/*!*******************************************************!*\ + !*** ./node_modules/axios/lib/helpers/combineURLs.js ***! + \*******************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - if (isActive) { - return; - } +"use strict"; - this.show(true); - }; - _proto.show = function show(usePopper) { - if (usePopper === void 0) { - usePopper = false; - } +/** + * Creates a new URL by combining the specified URLs + * + * @param {string} baseURL The base URL + * @param {string} relativeURL The relative URL + * @returns {string} The combined URL + */ +module.exports = function combineURLs(baseURL, relativeURL) { + return relativeURL + ? baseURL.replace(/\/+$/, '') + '/' + relativeURL.replace(/^\/+/, '') + : baseURL; +}; - if (this._element.disabled || $(this._element).hasClass(ClassName$4.DISABLED) || $(this._menu).hasClass(ClassName$4.SHOW)) { - return; - } - var relatedTarget = { - relatedTarget: this._element - }; - var showEvent = $.Event(Event$4.SHOW, relatedTarget); +/***/ }), - var parent = Dropdown._getParentFromElement(this._element); +/***/ "./node_modules/axios/lib/helpers/cookies.js": +/*!***************************************************!*\ + !*** ./node_modules/axios/lib/helpers/cookies.js ***! + \***************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - $(parent).trigger(showEvent); +"use strict"; - if (showEvent.isDefaultPrevented()) { - return; - } // Disable totally Popper.js for Dropdown in Navbar +var utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js"); - if (!this._inNavbar && usePopper) { - /** - * Check for Popper dependency - * Popper - https://popper.js.org - */ - if (typeof Popper === 'undefined') { - throw new TypeError('Bootstrap\'s dropdowns require Popper.js (https://popper.js.org/)'); - } +module.exports = ( + utils.isStandardBrowserEnv() ? - var referenceElement = this._element; + // Standard browser envs support document.cookie + (function standardBrowserEnv() { + return { + write: function write(name, value, expires, path, domain, secure) { + var cookie = []; + cookie.push(name + '=' + encodeURIComponent(value)); - if (this._config.reference === 'parent') { - referenceElement = parent; - } else if (Util.isElement(this._config.reference)) { - referenceElement = this._config.reference; // Check if it's jQuery element + if (utils.isNumber(expires)) { + cookie.push('expires=' + new Date(expires).toGMTString()); + } - if (typeof this._config.reference.jquery !== 'undefined') { - referenceElement = this._config.reference[0]; + if (utils.isString(path)) { + cookie.push('path=' + path); } - } // If boundary is not `scrollParent`, then set position to `static` - // to allow the menu to "escape" the scroll parent's boundaries - // https://github.com/twbs/bootstrap/issues/24251 + if (utils.isString(domain)) { + cookie.push('domain=' + domain); + } - if (this._config.boundary !== 'scrollParent') { - $(parent).addClass(ClassName$4.POSITION_STATIC); - } + if (secure === true) { + cookie.push('secure'); + } - this._popper = new Popper(referenceElement, this._menu, this._getPopperConfig()); - } // If this is a touch-enabled device we add extra - // empty mouseover listeners to the body's immediate children; - // only needed because of broken event delegation on iOS - // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html + document.cookie = cookie.join('; '); + }, + read: function read(name) { + var match = document.cookie.match(new RegExp('(^|;\\s*)(' + name + ')=([^;]*)')); + return (match ? decodeURIComponent(match[3]) : null); + }, - if ('ontouchstart' in document.documentElement && $(parent).closest(Selector$4.NAVBAR_NAV).length === 0) { - $(document.body).children().on('mouseover', null, $.noop); - } + remove: function remove(name) { + this.write(name, '', Date.now() - 86400000); + } + }; + })() : - this._element.focus(); + // Non standard browser env (web workers, react-native) lack needed support. + (function nonStandardBrowserEnv() { + return { + write: function write() {}, + read: function read() { return null; }, + remove: function remove() {} + }; + })() +); - this._element.setAttribute('aria-expanded', true); - $(this._menu).toggleClass(ClassName$4.SHOW); - $(parent).toggleClass(ClassName$4.SHOW).trigger($.Event(Event$4.SHOWN, relatedTarget)); - }; +/***/ }), - _proto.hide = function hide() { - if (this._element.disabled || $(this._element).hasClass(ClassName$4.DISABLED) || !$(this._menu).hasClass(ClassName$4.SHOW)) { - return; - } +/***/ "./node_modules/axios/lib/helpers/isAbsoluteURL.js": +/*!*********************************************************!*\ + !*** ./node_modules/axios/lib/helpers/isAbsoluteURL.js ***! + \*********************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - var relatedTarget = { - relatedTarget: this._element - }; - var hideEvent = $.Event(Event$4.HIDE, relatedTarget); +"use strict"; - var parent = Dropdown._getParentFromElement(this._element); - $(parent).trigger(hideEvent); +/** + * Determines whether the specified URL is absolute + * + * @param {string} url The URL to test + * @returns {boolean} True if the specified URL is absolute, otherwise false + */ +module.exports = function isAbsoluteURL(url) { + // A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL). + // RFC 3986 defines scheme name as a sequence of characters beginning with a letter and followed + // by any combination of letters, digits, plus, period, or hyphen. + return /^([a-z][a-z\d\+\-\.]*:)?\/\//i.test(url); +}; - if (hideEvent.isDefaultPrevented()) { - return; - } - if (this._popper) { - this._popper.destroy(); - } +/***/ }), - $(this._menu).toggleClass(ClassName$4.SHOW); - $(parent).toggleClass(ClassName$4.SHOW).trigger($.Event(Event$4.HIDDEN, relatedTarget)); - }; +/***/ "./node_modules/axios/lib/helpers/isURLSameOrigin.js": +/*!***********************************************************!*\ + !*** ./node_modules/axios/lib/helpers/isURLSameOrigin.js ***! + \***********************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - _proto.dispose = function dispose() { - $.removeData(this._element, DATA_KEY$4); - $(this._element).off(EVENT_KEY$4); - this._element = null; - this._menu = null; +"use strict"; - if (this._popper !== null) { - this._popper.destroy(); - this._popper = null; - } - }; +var utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js"); - _proto.update = function update() { - this._inNavbar = this._detectNavbar(); +module.exports = ( + utils.isStandardBrowserEnv() ? - if (this._popper !== null) { - this._popper.scheduleUpdate(); - } - } // Private - ; + // Standard browser envs have full support of the APIs needed to test + // whether the request URL is of the same origin as current location. + (function standardBrowserEnv() { + var msie = /(msie|trident)/i.test(navigator.userAgent); + var urlParsingNode = document.createElement('a'); + var originURL; - _proto._addEventListeners = function _addEventListeners() { - var _this = this; + /** + * Parse a URL to discover it's components + * + * @param {String} url The URL to be parsed + * @returns {Object} + */ + function resolveURL(url) { + var href = url; - $(this._element).on(Event$4.CLICK, function (event) { - event.preventDefault(); - event.stopPropagation(); + if (msie) { + // IE needs attribute set twice to normalize properties + urlParsingNode.setAttribute('href', href); + href = urlParsingNode.href; + } - _this.toggle(); - }); - }; + urlParsingNode.setAttribute('href', href); - _proto._getConfig = function _getConfig(config) { - config = _objectSpread2({}, this.constructor.Default, {}, $(this._element).data(), {}, config); - Util.typeCheckConfig(NAME$4, config, this.constructor.DefaultType); - return config; - }; + // urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils + return { + href: urlParsingNode.href, + protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '', + host: urlParsingNode.host, + search: urlParsingNode.search ? urlParsingNode.search.replace(/^\?/, '') : '', + hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '', + hostname: urlParsingNode.hostname, + port: urlParsingNode.port, + pathname: (urlParsingNode.pathname.charAt(0) === '/') ? + urlParsingNode.pathname : + '/' + urlParsingNode.pathname + }; + } - _proto._getMenuElement = function _getMenuElement() { - if (!this._menu) { - var parent = Dropdown._getParentFromElement(this._element); + originURL = resolveURL(window.location.href); - if (parent) { - this._menu = parent.querySelector(Selector$4.MENU); - } - } + /** + * Determine if a URL shares the same origin as the current location + * + * @param {String} requestURL The URL to test + * @returns {boolean} True if URL shares the same origin, otherwise false + */ + return function isURLSameOrigin(requestURL) { + var parsed = (utils.isString(requestURL)) ? resolveURL(requestURL) : requestURL; + return (parsed.protocol === originURL.protocol && + parsed.host === originURL.host); + }; + })() : - return this._menu; - }; + // Non standard browser envs (web workers, react-native) lack needed support. + (function nonStandardBrowserEnv() { + return function isURLSameOrigin() { + return true; + }; + })() +); - _proto._getPlacement = function _getPlacement() { - var $parentDropdown = $(this._element.parentNode); - var placement = AttachmentMap.BOTTOM; // Handle dropup - if ($parentDropdown.hasClass(ClassName$4.DROPUP)) { - placement = AttachmentMap.TOP; +/***/ }), - if ($(this._menu).hasClass(ClassName$4.MENURIGHT)) { - placement = AttachmentMap.TOPEND; - } - } else if ($parentDropdown.hasClass(ClassName$4.DROPRIGHT)) { - placement = AttachmentMap.RIGHT; - } else if ($parentDropdown.hasClass(ClassName$4.DROPLEFT)) { - placement = AttachmentMap.LEFT; - } else if ($(this._menu).hasClass(ClassName$4.MENURIGHT)) { - placement = AttachmentMap.BOTTOMEND; - } +/***/ "./node_modules/axios/lib/helpers/normalizeHeaderName.js": +/*!***************************************************************!*\ + !*** ./node_modules/axios/lib/helpers/normalizeHeaderName.js ***! + \***************************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - return placement; - }; +"use strict"; - _proto._detectNavbar = function _detectNavbar() { - return $(this._element).closest('.navbar').length > 0; - }; - _proto._getOffset = function _getOffset() { - var _this2 = this; +var utils = __webpack_require__(/*! ../utils */ "./node_modules/axios/lib/utils.js"); - var offset = {}; +module.exports = function normalizeHeaderName(headers, normalizedName) { + utils.forEach(headers, function processHeader(value, name) { + if (name !== normalizedName && name.toUpperCase() === normalizedName.toUpperCase()) { + headers[normalizedName] = value; + delete headers[name]; + } + }); +}; - if (typeof this._config.offset === 'function') { - offset.fn = function (data) { - data.offsets = _objectSpread2({}, data.offsets, {}, _this2._config.offset(data.offsets, _this2._element) || {}); - return data; - }; - } else { - offset.offset = this._config.offset; - } - return offset; - }; +/***/ }), - _proto._getPopperConfig = function _getPopperConfig() { - var popperConfig = { - placement: this._getPlacement(), - modifiers: { - offset: this._getOffset(), - flip: { - enabled: this._config.flip - }, - preventOverflow: { - boundariesElement: this._config.boundary - } - } - }; // Disable Popper.js if we have a static display +/***/ "./node_modules/axios/lib/helpers/parseHeaders.js": +/*!********************************************************!*\ + !*** ./node_modules/axios/lib/helpers/parseHeaders.js ***! + \********************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - if (this._config.display === 'static') { - popperConfig.modifiers.applyStyle = { - enabled: false - }; - } +"use strict"; - return _objectSpread2({}, popperConfig, {}, this._config.popperConfig); - } // Static - ; - Dropdown._jQueryInterface = function _jQueryInterface(config) { - return this.each(function () { - var data = $(this).data(DATA_KEY$4); +var utils = __webpack_require__(/*! ./../utils */ "./node_modules/axios/lib/utils.js"); - var _config = typeof config === 'object' ? config : null; +// Headers whose duplicates are ignored by node +// c.f. https://nodejs.org/api/http.html#http_message_headers +var ignoreDuplicateOf = [ + 'age', 'authorization', 'content-length', 'content-type', 'etag', + 'expires', 'from', 'host', 'if-modified-since', 'if-unmodified-since', + 'last-modified', 'location', 'max-forwards', 'proxy-authorization', + 'referer', 'retry-after', 'user-agent' +]; - if (!data) { - data = new Dropdown(this, _config); - $(this).data(DATA_KEY$4, data); - } +/** + * Parse headers into an object + * + * ``` + * Date: Wed, 27 Aug 2014 08:58:49 GMT + * Content-Type: application/json + * Connection: keep-alive + * Transfer-Encoding: chunked + * ``` + * + * @param {String} headers Headers needing to be parsed + * @returns {Object} Headers parsed into an object + */ +module.exports = function parseHeaders(headers) { + var parsed = {}; + var key; + var val; + var i; - if (typeof config === 'string') { - if (typeof data[config] === 'undefined') { - throw new TypeError("No method named \"" + config + "\""); - } + if (!headers) { return parsed; } - data[config](); - } - }); - }; + utils.forEach(headers.split('\n'), function parser(line) { + i = line.indexOf(':'); + key = utils.trim(line.substr(0, i)).toLowerCase(); + val = utils.trim(line.substr(i + 1)); - Dropdown._clearMenus = function _clearMenus(event) { - if (event && (event.which === RIGHT_MOUSE_BUTTON_WHICH || event.type === 'keyup' && event.which !== TAB_KEYCODE)) { + if (key) { + if (parsed[key] && ignoreDuplicateOf.indexOf(key) >= 0) { return; } + if (key === 'set-cookie') { + parsed[key] = (parsed[key] ? parsed[key] : []).concat([val]); + } else { + parsed[key] = parsed[key] ? parsed[key] + ', ' + val : val; + } + } + }); - var toggles = [].slice.call(document.querySelectorAll(Selector$4.DATA_TOGGLE)); - - for (var i = 0, len = toggles.length; i < len; i++) { - var parent = Dropdown._getParentFromElement(toggles[i]); - - var context = $(toggles[i]).data(DATA_KEY$4); - var relatedTarget = { - relatedTarget: toggles[i] - }; - - if (event && event.type === 'click') { - relatedTarget.clickEvent = event; - } + return parsed; +}; - if (!context) { - continue; - } - var dropdownMenu = context._menu; +/***/ }), - if (!$(parent).hasClass(ClassName$4.SHOW)) { - continue; - } +/***/ "./node_modules/axios/lib/helpers/spread.js": +/*!**************************************************!*\ + !*** ./node_modules/axios/lib/helpers/spread.js ***! + \**************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - if (event && (event.type === 'click' && /input|textarea/i.test(event.target.tagName) || event.type === 'keyup' && event.which === TAB_KEYCODE) && $.contains(parent, event.target)) { - continue; - } +"use strict"; - var hideEvent = $.Event(Event$4.HIDE, relatedTarget); - $(parent).trigger(hideEvent); - if (hideEvent.isDefaultPrevented()) { - continue; - } // If this is a touch-enabled device we remove the extra - // empty mouseover listeners we added for iOS support - - - if ('ontouchstart' in document.documentElement) { - $(document.body).children().off('mouseover', null, $.noop); - } +/** + * Syntactic sugar for invoking a function and expanding an array for arguments. + * + * Common use case would be to use `Function.prototype.apply`. + * + * ```js + * function f(x, y, z) {} + * var args = [1, 2, 3]; + * f.apply(null, args); + * ``` + * + * With `spread` this example can be re-written. + * + * ```js + * spread(function(x, y, z) {})([1, 2, 3]); + * ``` + * + * @param {Function} callback + * @returns {Function} + */ +module.exports = function spread(callback) { + return function wrap(arr) { + return callback.apply(null, arr); + }; +}; - toggles[i].setAttribute('aria-expanded', 'false'); - if (context._popper) { - context._popper.destroy(); - } +/***/ }), - $(dropdownMenu).removeClass(ClassName$4.SHOW); - $(parent).removeClass(ClassName$4.SHOW).trigger($.Event(Event$4.HIDDEN, relatedTarget)); - } - }; +/***/ "./node_modules/axios/lib/utils.js": +/*!*****************************************!*\ + !*** ./node_modules/axios/lib/utils.js ***! + \*****************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - Dropdown._getParentFromElement = function _getParentFromElement(element) { - var parent; - var selector = Util.getSelectorFromElement(element); +"use strict"; - if (selector) { - parent = document.querySelector(selector); - } - return parent || element.parentNode; - } // eslint-disable-next-line complexity - ; +var bind = __webpack_require__(/*! ./helpers/bind */ "./node_modules/axios/lib/helpers/bind.js"); - Dropdown._dataApiKeydownHandler = function _dataApiKeydownHandler(event) { - // If not input/textarea: - // - And not a key in REGEXP_KEYDOWN => not a dropdown command - // If input/textarea: - // - If space key => not a dropdown command - // - If key is other than escape - // - If key is not up or down => not a dropdown command - // - If trigger inside the menu => not a dropdown command - if (/input|textarea/i.test(event.target.tagName) ? event.which === SPACE_KEYCODE || event.which !== ESCAPE_KEYCODE && (event.which !== ARROW_DOWN_KEYCODE && event.which !== ARROW_UP_KEYCODE || $(event.target).closest(Selector$4.MENU).length) : !REGEXP_KEYDOWN.test(event.which)) { - return; - } +/*global toString:true*/ - event.preventDefault(); - event.stopPropagation(); +// utils is a library of generic helper functions non-specific to axios - if (this.disabled || $(this).hasClass(ClassName$4.DISABLED)) { - return; - } +var toString = Object.prototype.toString; - var parent = Dropdown._getParentFromElement(this); +/** + * Determine if a value is an Array + * + * @param {Object} val The value to test + * @returns {boolean} True if value is an Array, otherwise false + */ +function isArray(val) { + return toString.call(val) === '[object Array]'; +} - var isActive = $(parent).hasClass(ClassName$4.SHOW); +/** + * Determine if a value is undefined + * + * @param {Object} val The value to test + * @returns {boolean} True if the value is undefined, otherwise false + */ +function isUndefined(val) { + return typeof val === 'undefined'; +} - if (!isActive && event.which === ESCAPE_KEYCODE) { - return; - } +/** + * Determine if a value is a Buffer + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Buffer, otherwise false + */ +function isBuffer(val) { + return val !== null && !isUndefined(val) && val.constructor !== null && !isUndefined(val.constructor) + && typeof val.constructor.isBuffer === 'function' && val.constructor.isBuffer(val); +} - if (!isActive || isActive && (event.which === ESCAPE_KEYCODE || event.which === SPACE_KEYCODE)) { - if (event.which === ESCAPE_KEYCODE) { - var toggle = parent.querySelector(Selector$4.DATA_TOGGLE); - $(toggle).trigger('focus'); - } +/** + * Determine if a value is an ArrayBuffer + * + * @param {Object} val The value to test + * @returns {boolean} True if value is an ArrayBuffer, otherwise false + */ +function isArrayBuffer(val) { + return toString.call(val) === '[object ArrayBuffer]'; +} - $(this).trigger('click'); - return; - } +/** + * Determine if a value is a FormData + * + * @param {Object} val The value to test + * @returns {boolean} True if value is an FormData, otherwise false + */ +function isFormData(val) { + return (typeof FormData !== 'undefined') && (val instanceof FormData); +} - var items = [].slice.call(parent.querySelectorAll(Selector$4.VISIBLE_ITEMS)).filter(function (item) { - return $(item).is(':visible'); - }); +/** + * Determine if a value is a view on an ArrayBuffer + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a view on an ArrayBuffer, otherwise false + */ +function isArrayBufferView(val) { + var result; + if ((typeof ArrayBuffer !== 'undefined') && (ArrayBuffer.isView)) { + result = ArrayBuffer.isView(val); + } else { + result = (val) && (val.buffer) && (val.buffer instanceof ArrayBuffer); + } + return result; +} - if (items.length === 0) { - return; - } +/** + * Determine if a value is a String + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a String, otherwise false + */ +function isString(val) { + return typeof val === 'string'; +} - var index = items.indexOf(event.target); +/** + * Determine if a value is a Number + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Number, otherwise false + */ +function isNumber(val) { + return typeof val === 'number'; +} - if (event.which === ARROW_UP_KEYCODE && index > 0) { - // Up - index--; - } +/** + * Determine if a value is an Object + * + * @param {Object} val The value to test + * @returns {boolean} True if value is an Object, otherwise false + */ +function isObject(val) { + return val !== null && typeof val === 'object'; +} - if (event.which === ARROW_DOWN_KEYCODE && index < items.length - 1) { - // Down - index++; - } +/** + * Determine if a value is a Date + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Date, otherwise false + */ +function isDate(val) { + return toString.call(val) === '[object Date]'; +} - if (index < 0) { - index = 0; - } +/** + * Determine if a value is a File + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a File, otherwise false + */ +function isFile(val) { + return toString.call(val) === '[object File]'; +} - items[index].focus(); - }; +/** + * Determine if a value is a Blob + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Blob, otherwise false + */ +function isBlob(val) { + return toString.call(val) === '[object Blob]'; +} - _createClass(Dropdown, null, [{ - key: "VERSION", - get: function get() { - return VERSION$4; - } - }, { - key: "Default", - get: function get() { - return Default$2; - } - }, { - key: "DefaultType", - get: function get() { - return DefaultType$2; - } - }]); +/** + * Determine if a value is a Function + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Function, otherwise false + */ +function isFunction(val) { + return toString.call(val) === '[object Function]'; +} - return Dropdown; - }(); - /** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ +/** + * Determine if a value is a Stream + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a Stream, otherwise false + */ +function isStream(val) { + return isObject(val) && isFunction(val.pipe); +} +/** + * Determine if a value is a URLSearchParams object + * + * @param {Object} val The value to test + * @returns {boolean} True if value is a URLSearchParams object, otherwise false + */ +function isURLSearchParams(val) { + return typeof URLSearchParams !== 'undefined' && val instanceof URLSearchParams; +} - $(document).on(Event$4.KEYDOWN_DATA_API, Selector$4.DATA_TOGGLE, Dropdown._dataApiKeydownHandler).on(Event$4.KEYDOWN_DATA_API, Selector$4.MENU, Dropdown._dataApiKeydownHandler).on(Event$4.CLICK_DATA_API + " " + Event$4.KEYUP_DATA_API, Dropdown._clearMenus).on(Event$4.CLICK_DATA_API, Selector$4.DATA_TOGGLE, function (event) { - event.preventDefault(); - event.stopPropagation(); +/** + * Trim excess whitespace off the beginning and end of a string + * + * @param {String} str The String to trim + * @returns {String} The String freed of excess whitespace + */ +function trim(str) { + return str.replace(/^\s*/, '').replace(/\s*$/, ''); +} - Dropdown._jQueryInterface.call($(this), 'toggle'); - }).on(Event$4.CLICK_DATA_API, Selector$4.FORM_CHILD, function (e) { - e.stopPropagation(); - }); - /** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - */ +/** + * Determine if we're running in a standard browser environment + * + * This allows axios to run in a web worker, and react-native. + * Both environments support XMLHttpRequest, but not fully standard globals. + * + * web workers: + * typeof window -> undefined + * typeof document -> undefined + * + * react-native: + * navigator.product -> 'ReactNative' + * nativescript + * navigator.product -> 'NativeScript' or 'NS' + */ +function isStandardBrowserEnv() { + if (typeof navigator !== 'undefined' && (navigator.product === 'ReactNative' || + navigator.product === 'NativeScript' || + navigator.product === 'NS')) { + return false; + } + return ( + typeof window !== 'undefined' && + typeof document !== 'undefined' + ); +} - $.fn[NAME$4] = Dropdown._jQueryInterface; - $.fn[NAME$4].Constructor = Dropdown; +/** + * Iterate over an Array or an Object invoking a function for each item. + * + * If `obj` is an Array callback will be called passing + * the value, index, and complete array for each item. + * + * If 'obj' is an Object callback will be called passing + * the value, key, and complete object for each property. + * + * @param {Object|Array} obj The object to iterate + * @param {Function} fn The callback to invoke for each item + */ +function forEach(obj, fn) { + // Don't bother if no value provided + if (obj === null || typeof obj === 'undefined') { + return; + } - $.fn[NAME$4].noConflict = function () { - $.fn[NAME$4] = JQUERY_NO_CONFLICT$4; - return Dropdown._jQueryInterface; - }; + // Force an array if not already something iterable + if (typeof obj !== 'object') { + /*eslint no-param-reassign:0*/ + obj = [obj]; + } - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ + if (isArray(obj)) { + // Iterate over array values + for (var i = 0, l = obj.length; i < l; i++) { + fn.call(null, obj[i], i, obj); + } + } else { + // Iterate over object keys + for (var key in obj) { + if (Object.prototype.hasOwnProperty.call(obj, key)) { + fn.call(null, obj[key], key, obj); + } + } + } +} - var NAME$5 = 'modal'; - var VERSION$5 = '4.4.1'; - var DATA_KEY$5 = 'bs.modal'; - var EVENT_KEY$5 = "." + DATA_KEY$5; - var DATA_API_KEY$5 = '.data-api'; - var JQUERY_NO_CONFLICT$5 = $.fn[NAME$5]; - var ESCAPE_KEYCODE$1 = 27; // KeyboardEvent.which value for Escape (Esc) key +/** + * Accepts varargs expecting each argument to be an object, then + * immutably merges the properties of each object and returns result. + * + * When multiple objects contain the same key the later object in + * the arguments list will take precedence. + * + * Example: + * + * ```js + * var result = merge({foo: 123}, {foo: 456}); + * console.log(result.foo); // outputs 456 + * ``` + * + * @param {Object} obj1 Object to merge + * @returns {Object} Result of all merge properties + */ +function merge(/* obj1, obj2, obj3, ... */) { + var result = {}; + function assignValue(val, key) { + if (typeof result[key] === 'object' && typeof val === 'object') { + result[key] = merge(result[key], val); + } else { + result[key] = val; + } + } - var Default$3 = { - backdrop: true, - keyboard: true, - focus: true, - show: true - }; - var DefaultType$3 = { - backdrop: '(boolean|string)', - keyboard: 'boolean', - focus: 'boolean', - show: 'boolean' - }; - var Event$5 = { - HIDE: "hide" + EVENT_KEY$5, - HIDE_PREVENTED: "hidePrevented" + EVENT_KEY$5, - HIDDEN: "hidden" + EVENT_KEY$5, - SHOW: "show" + EVENT_KEY$5, - SHOWN: "shown" + EVENT_KEY$5, - FOCUSIN: "focusin" + EVENT_KEY$5, - RESIZE: "resize" + EVENT_KEY$5, - CLICK_DISMISS: "click.dismiss" + EVENT_KEY$5, - KEYDOWN_DISMISS: "keydown.dismiss" + EVENT_KEY$5, - MOUSEUP_DISMISS: "mouseup.dismiss" + EVENT_KEY$5, - MOUSEDOWN_DISMISS: "mousedown.dismiss" + EVENT_KEY$5, - CLICK_DATA_API: "click" + EVENT_KEY$5 + DATA_API_KEY$5 - }; - var ClassName$5 = { - SCROLLABLE: 'modal-dialog-scrollable', - SCROLLBAR_MEASURER: 'modal-scrollbar-measure', - BACKDROP: 'modal-backdrop', - OPEN: 'modal-open', - FADE: 'fade', - SHOW: 'show', - STATIC: 'modal-static' - }; - var Selector$5 = { - DIALOG: '.modal-dialog', - MODAL_BODY: '.modal-body', - DATA_TOGGLE: '[data-toggle="modal"]', - DATA_DISMISS: '[data-dismiss="modal"]', - FIXED_CONTENT: '.fixed-top, .fixed-bottom, .is-fixed, .sticky-top', - STICKY_CONTENT: '.sticky-top' - }; - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ + for (var i = 0, l = arguments.length; i < l; i++) { + forEach(arguments[i], assignValue); + } + return result; +} - var Modal = - /*#__PURE__*/ - function () { - function Modal(element, config) { - this._config = this._getConfig(config); - this._element = element; - this._dialog = element.querySelector(Selector$5.DIALOG); - this._backdrop = null; - this._isShown = false; - this._isBodyOverflowing = false; - this._ignoreBackdropClick = false; - this._isTransitioning = false; - this._scrollbarWidth = 0; - } // Getters +/** + * Function equal to merge with the difference being that no reference + * to original objects is kept. + * + * @see merge + * @param {Object} obj1 Object to merge + * @returns {Object} Result of all merge properties + */ +function deepMerge(/* obj1, obj2, obj3, ... */) { + var result = {}; + function assignValue(val, key) { + if (typeof result[key] === 'object' && typeof val === 'object') { + result[key] = deepMerge(result[key], val); + } else if (typeof val === 'object') { + result[key] = deepMerge({}, val); + } else { + result[key] = val; + } + } + for (var i = 0, l = arguments.length; i < l; i++) { + forEach(arguments[i], assignValue); + } + return result; +} - var _proto = Modal.prototype; +/** + * Extends object a by mutably adding to it the properties of object b. + * + * @param {Object} a The object to be extended + * @param {Object} b The object to copy properties from + * @param {Object} thisArg The object to bind function to + * @return {Object} The resulting value of object a + */ +function extend(a, b, thisArg) { + forEach(b, function assignValue(val, key) { + if (thisArg && typeof val === 'function') { + a[key] = bind(val, thisArg); + } else { + a[key] = val; + } + }); + return a; +} - // Public - _proto.toggle = function toggle(relatedTarget) { - return this._isShown ? this.hide() : this.show(relatedTarget); - }; - - _proto.show = function show(relatedTarget) { - var _this = this; - - if (this._isShown || this._isTransitioning) { - return; - } - - if ($(this._element).hasClass(ClassName$5.FADE)) { - this._isTransitioning = true; - } - - var showEvent = $.Event(Event$5.SHOW, { - relatedTarget: relatedTarget - }); - $(this._element).trigger(showEvent); - - if (this._isShown || showEvent.isDefaultPrevented()) { - return; - } - - this._isShown = true; +module.exports = { + isArray: isArray, + isArrayBuffer: isArrayBuffer, + isBuffer: isBuffer, + isFormData: isFormData, + isArrayBufferView: isArrayBufferView, + isString: isString, + isNumber: isNumber, + isObject: isObject, + isUndefined: isUndefined, + isDate: isDate, + isFile: isFile, + isBlob: isBlob, + isFunction: isFunction, + isStream: isStream, + isURLSearchParams: isURLSearchParams, + isStandardBrowserEnv: isStandardBrowserEnv, + forEach: forEach, + merge: merge, + deepMerge: deepMerge, + extend: extend, + trim: trim +}; - this._checkScrollbar(); - this._setScrollbar(); +/***/ }), - this._adjustDialog(); +/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/FileSearch/FileHit.vue?vue&type=script&lang=js&": +/*!*****************************************************************************************************************************************************************************!*\ + !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/FileSearch/FileHit.vue?vue&type=script&lang=js& ***! + \*****************************************************************************************************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { - this._setEscapeEvent(); +"use strict"; +__webpack_require__.r(__webpack_exports__); +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +/* harmony default export */ __webpack_exports__["default"] = ({ + name: "FileHit", + props: ['hit'], + data: function data() { + return {}; + }, + computed: { + imgLink: function imgLink() { + return "/files/".concat(this.hit.file.slug, "/cover"); + }, + viewLink: function viewLink() { + return "/view/".concat(this.hit.file.slug); + } + } +}); - this._setResizeEvent(); +/***/ }), - $(this._element).on(Event$5.CLICK_DISMISS, Selector$5.DATA_DISMISS, function (event) { - return _this.hide(event); - }); - $(this._dialog).on(Event$5.MOUSEDOWN_DISMISS, function () { - $(_this._element).one(Event$5.MOUSEUP_DISMISS, function (event) { - if ($(event.target).is(_this._element)) { - _this._ignoreBackdropClick = true; - } - }); - }); +/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/FileSearch/FileInstantSearch.vue?vue&type=script&lang=js&": +/*!***************************************************************************************************************************************************************************************!*\ + !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/FileSearch/FileInstantSearch.vue?vue&type=script&lang=js& ***! + \***************************************************************************************************************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { - this._showBackdrop(function () { - return _this._showElement(relatedTarget); - }); - }; +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _mixins_SearchMixin__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ../../mixins/SearchMixin */ "./resources/js/mixins/SearchMixin.js"); +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// - _proto.hide = function hide(event) { - var _this2 = this; +/* harmony default export */ __webpack_exports__["default"] = ({ + mixins: [_mixins_SearchMixin__WEBPACK_IMPORTED_MODULE_0__["default"]], + mounted: function mounted() {}, + computed: {} +}); - if (event) { - event.preventDefault(); - } +/***/ }), - if (!this._isShown || this._isTransitioning) { - return; - } +/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/Links/GenerateLink.vue?vue&type=script&lang=js&": +/*!*****************************************************************************************************************************************************************************!*\ + !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/Links/GenerateLink.vue?vue&type=script&lang=js& ***! + \*****************************************************************************************************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { - var hideEvent = $.Event(Event$5.HIDE); - $(this._element).trigger(hideEvent); +"use strict"; +__webpack_require__.r(__webpack_exports__); +// +// +// +// +// +// +// +// +/* harmony default export */ __webpack_exports__["default"] = ({ + components: {}, + data: function data() { + return {}; + }, + mounted: function mounted() {}, + methods: {} +}); - if (!this._isShown || hideEvent.isDefaultPrevented()) { - return; - } +/***/ }), - this._isShown = false; - var transition = $(this._element).hasClass(ClassName$5.FADE); +/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/LiveStats.vue?vue&type=script&lang=js&": +/*!********************************************************************************************************************************************************************!*\ + !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/LiveStats.vue?vue&type=script&lang=js& ***! + \********************************************************************************************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { - if (transition) { - this._isTransitioning = true; - } +"use strict"; +__webpack_require__.r(__webpack_exports__); +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +/* harmony default export */ __webpack_exports__["default"] = ({ + components: {}, + data: function data() { + return {}; + }, + mounted: function mounted() {// Echo.private('emailBatch.1') + // .listen('.mailgun.event', (e) => { + // console.log(e); + // }) + // .listen('.batch.status', (e) => { + // console.log(e); + // }) + }, + methods: {} +}); - this._setEscapeEvent(); +/***/ }), - this._setResizeEvent(); +/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/Publish/Publish.vue?vue&type=script&lang=js&": +/*!**************************************************************************************************************************************************************************!*\ + !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/Publish/Publish.vue?vue&type=script&lang=js& ***! + \**************************************************************************************************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { - $(document).off(Event$5.FOCUSIN); - $(this._element).removeClass(ClassName$5.SHOW); - $(this._element).off(Event$5.CLICK_DISMISS); - $(this._dialog).off(Event$5.MOUSEDOWN_DISMISS); +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var vue_stepper__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue-stepper */ "./node_modules/vue-stepper/src/index.js"); +/* harmony import */ var vue_stepper__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(vue_stepper__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var _Step1UploadFile__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Step1UploadFile */ "./resources/js/components/Publish/Step1UploadFile.vue"); +/* harmony import */ var _Step2PrepareMail__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./Step2PrepareMail */ "./resources/js/components/Publish/Step2PrepareMail.vue"); +/* harmony import */ var _Step3Send__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ./Step3Send */ "./resources/js/components/Publish/Step3Send.vue"); +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// - if (transition) { - var transitionDuration = Util.getTransitionDurationFromElement(this._element); - $(this._element).one(Util.TRANSITION_END, function (event) { - return _this2._hideModal(event); - }).emulateTransitionEnd(transitionDuration); - } else { - this._hideModal(); - } - }; +/** + * Step 1 : Upload PDF and preview (add title, tags) + * Step 2 : Add email subject and content + * Step 3 : Review, send and track + */ - _proto.dispose = function dispose() { - [window, this._element, this._dialog].forEach(function (htmlElement) { - return $(htmlElement).off(EVENT_KEY$5); - }); - /** - * `document` has 2 events `Event.FOCUSIN` and `Event.CLICK_DATA_API` - * Do not move `document` in `htmlElements` array - * It will remove `Event.CLICK_DATA_API` event that should remain - */ - $(document).off(Event$5.FOCUSIN); - $.removeData(this._element, DATA_KEY$5); - this._config = null; - this._element = null; - this._dialog = null; - this._backdrop = null; - this._isShown = null; - this._isBodyOverflowing = null; - this._ignoreBackdropClick = null; - this._isTransitioning = null; - this._scrollbarWidth = null; - }; - _proto.handleUpdate = function handleUpdate() { - this._adjustDialog(); - } // Private - ; - _proto._getConfig = function _getConfig(config) { - config = _objectSpread2({}, Default$3, {}, config); - Util.typeCheckConfig(NAME$5, config, DefaultType$3); - return config; +/* harmony default export */ __webpack_exports__["default"] = ({ + components: { + HorizontalStepper: vue_stepper__WEBPACK_IMPORTED_MODULE_0___default.a + }, + data: function data() { + return { + steps: [{ + icon: 'cloud_upload', + name: 'upload', + title: 'Mise en ligne du PDF', + subtitle: 'Création de la liseuse', + component: _Step1UploadFile__WEBPACK_IMPORTED_MODULE_1__["default"], + completed: false + }, { + icon: 'mail', + name: 'email', + title: 'Mise en forme du message', + subtitle: '', + component: _Step2PrepareMail__WEBPACK_IMPORTED_MODULE_2__["default"], + completed: false + }, { + icon: 'send', + name: 'review', + title: 'Récapitulatif et envoi', + subtitle: 'Suivi des envois', + component: _Step3Send__WEBPACK_IMPORTED_MODULE_3__["default"], + completed: false + }] }; - - _proto._triggerBackdropTransition = function _triggerBackdropTransition() { - var _this3 = this; - - if (this._config.backdrop === 'static') { - var hideEventPrevented = $.Event(Event$5.HIDE_PREVENTED); - $(this._element).trigger(hideEventPrevented); - - if (hideEventPrevented.defaultPrevented) { - return; + }, + mounted: function mounted() {}, + methods: { + // Executed when @completed-step event is triggered + completeStep: function completeStep(payload) { + this.steps.forEach(function (step) { + if (step.name === payload.name) { + step.completed = true; } - - this._element.classList.add(ClassName$5.STATIC); - - var modalTransitionDuration = Util.getTransitionDurationFromElement(this._element); - $(this._element).one(Util.TRANSITION_END, function () { - _this3._element.classList.remove(ClassName$5.STATIC); - }).emulateTransitionEnd(modalTransitionDuration); - - this._element.focus(); - } else { - this.hide(); - } - }; - - _proto._showElement = function _showElement(relatedTarget) { - var _this4 = this; - - var transition = $(this._element).hasClass(ClassName$5.FADE); - var modalBody = this._dialog ? this._dialog.querySelector(Selector$5.MODAL_BODY) : null; - - if (!this._element.parentNode || this._element.parentNode.nodeType !== Node.ELEMENT_NODE) { - // Don't move modal's DOM position - document.body.appendChild(this._element); - } - - this._element.style.display = 'block'; - - this._element.removeAttribute('aria-hidden'); - - this._element.setAttribute('aria-modal', true); - - if ($(this._dialog).hasClass(ClassName$5.SCROLLABLE) && modalBody) { - modalBody.scrollTop = 0; - } else { - this._element.scrollTop = 0; - } - - if (transition) { - Util.reflow(this._element); - } - - $(this._element).addClass(ClassName$5.SHOW); - - if (this._config.focus) { - this._enforceFocus(); - } - - var shownEvent = $.Event(Event$5.SHOWN, { - relatedTarget: relatedTarget }); - - var transitionComplete = function transitionComplete() { - if (_this4._config.focus) { - _this4._element.focus(); - } - - _this4._isTransitioning = false; - $(_this4._element).trigger(shownEvent); - }; - - if (transition) { - var transitionDuration = Util.getTransitionDurationFromElement(this._dialog); - $(this._dialog).one(Util.TRANSITION_END, transitionComplete).emulateTransitionEnd(transitionDuration); - } else { - transitionComplete(); - } - }; - - _proto._enforceFocus = function _enforceFocus() { - var _this5 = this; - - $(document).off(Event$5.FOCUSIN) // Guard against infinite focus loop - .on(Event$5.FOCUSIN, function (event) { - if (document !== event.target && _this5._element !== event.target && $(_this5._element).has(event.target).length === 0) { - _this5._element.focus(); + }, + // Executed when @active-step event is triggered + isStepActive: function isStepActive(payload) { + this.steps.forEach(function (step) { + if (step.name === payload.name) { + if (step.completed === true) { + step.completed = false; + } } }); - }; - - _proto._setEscapeEvent = function _setEscapeEvent() { - var _this6 = this; - - if (this._isShown && this._config.keyboard) { - $(this._element).on(Event$5.KEYDOWN_DISMISS, function (event) { - if (event.which === ESCAPE_KEYCODE$1) { - _this6._triggerBackdropTransition(); - } - }); - } else if (!this._isShown) { - $(this._element).off(Event$5.KEYDOWN_DISMISS); - } - }; - - _proto._setResizeEvent = function _setResizeEvent() { - var _this7 = this; - - if (this._isShown) { - $(window).on(Event$5.RESIZE, function (event) { - return _this7.handleUpdate(event); - }); - } else { - $(window).off(Event$5.RESIZE); + }, + // Executed when @stepper-finished event is triggered + alert: function (_alert) { + function alert(_x) { + return _alert.apply(this, arguments); } - }; - - _proto._hideModal = function _hideModal() { - var _this8 = this; - - this._element.style.display = 'none'; - this._element.setAttribute('aria-hidden', true); + alert.toString = function () { + return _alert.toString(); + }; - this._element.removeAttribute('aria-modal'); + return alert; + }(function (payload) { + alert('end'); + }) + } +}); - this._isTransitioning = false; +/***/ }), - this._showBackdrop(function () { - $(document.body).removeClass(ClassName$5.OPEN); +/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/Publish/Step1UploadFile.vue?vue&type=script&lang=js&": +/*!**********************************************************************************************************************************************************************************!*\ + !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/Publish/Step1UploadFile.vue?vue&type=script&lang=js& ***! + \**********************************************************************************************************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { - _this8._resetAdjustments(); +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var vue_upload_component__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue-upload-component */ "./node_modules/vue-upload-component/dist/vue-upload-component.js"); +/* harmony import */ var vue_upload_component__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(vue_upload_component__WEBPACK_IMPORTED_MODULE_0__); +/* harmony import */ var vue_simple_progress__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! vue-simple-progress */ "./node_modules/vue-simple-progress/dist/vue-simple-progress.js"); +/* harmony import */ var vue_simple_progress__WEBPACK_IMPORTED_MODULE_1___default = /*#__PURE__*/__webpack_require__.n(vue_simple_progress__WEBPACK_IMPORTED_MODULE_1__); +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// - _this8._resetScrollbar(); - $(_this8._element).trigger(Event$5.HIDDEN); - }); +/* harmony default export */ __webpack_exports__["default"] = ({ + components: { + FileUpload: vue_upload_component__WEBPACK_IMPORTED_MODULE_0___default.a, + ProgressBar: vue_simple_progress__WEBPACK_IMPORTED_MODULE_1___default.a + }, + data: function data() { + return { + files: [], + collections: [], + tags: [], + file_collection: 1, + file_ref: null, + csrf: document.querySelectorAll('meta[name="csrf-token"]')[0].content }; - - _proto._removeBackdrop = function _removeBackdrop() { - if (this._backdrop) { - $(this._backdrop).remove(); - this._backdrop = null; + }, + computed: { + fileValid: function fileValid() { + if (this.files.length < 1) return; + return this.checkFileValid(this.files[0]); + }, + file_data: function file_data() { + return { + collection_id: this.file_collection, + ref: this.file_ref, + tags: this.tags + }; + } + }, + methods: { + checkFileValid: function checkFileValid(file) { + return file.type === 'application/pdf'; + }, + inputFile: function inputFile(newFile, oldFile) { + if (newFile && (Boolean(newFile) !== Boolean(oldFile) || oldFile.error !== newFile.error) && !this.$refs.upload.active && this.checkFileValid(newFile)) { + this.$refs.upload.active = true; } - }; - - _proto._showBackdrop = function _showBackdrop(callback) { - var _this9 = this; - - var animate = $(this._element).hasClass(ClassName$5.FADE) ? ClassName$5.FADE : ''; - - if (this._isShown && this._config.backdrop) { - this._backdrop = document.createElement('div'); - this._backdrop.className = ClassName$5.BACKDROP; - - if (animate) { - this._backdrop.classList.add(animate); - } - $(this._backdrop).appendTo(document.body); - $(this._element).on(Event$5.CLICK_DISMISS, function (event) { - if (_this9._ignoreBackdropClick) { - _this9._ignoreBackdropClick = false; - return; - } - - if (event.target !== event.currentTarget) { - return; - } - - _this9._triggerBackdropTransition(); + if (newFile.success === true) { + this.$emit('can-continue', { + value: true }); + this.$root.publishState.file = newFile.response.data; + } + } + }, + mounted: function mounted() { + var _this = this; - if (animate) { - Util.reflow(this._backdrop); - } - - $(this._backdrop).addClass(ClassName$5.SHOW); - - if (!callback) { - return; - } - - if (!animate) { - callback(); - return; + this.$emit('can-continue', { + value: true + }); + axios.get('/publish/collections').then(function (d) { + return _this.collections = d.data.data; + }); + axios.get('/publish/tags').then(function (d) { + var tags = d.data.data; + $("#file_tags").selectize({ + placeholder: 'Mots-clés pour la recherche', + persist: false, + createOnBlur: true, + create: true, + options: tags, + plugins: ['remove_button'], + onChange: function onChange(v) { + return _this.tags = v; } + }); + }); + } +}); - var backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop); - $(this._backdrop).one(Util.TRANSITION_END, callback).emulateTransitionEnd(backdropTransitionDuration); - } else if (!this._isShown && this._backdrop) { - $(this._backdrop).removeClass(ClassName$5.SHOW); - - var callbackRemove = function callbackRemove() { - _this9._removeBackdrop(); +/***/ }), - if (callback) { - callback(); - } - }; +/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/Publish/Step2PrepareMail.vue?vue&type=script&lang=js&": +/*!***********************************************************************************************************************************************************************************!*\ + !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/Publish/Step2PrepareMail.vue?vue&type=script&lang=js& ***! + \***********************************************************************************************************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { - if ($(this._element).hasClass(ClassName$5.FADE)) { - var _backdropTransitionDuration = Util.getTransitionDurationFromElement(this._backdrop); +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var _ckeditor_ckeditor5_build_classic__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @ckeditor/ckeditor5-build-classic */ "./node_modules/@ckeditor/ckeditor5-build-classic/build/ckeditor.js"); +/* harmony import */ var _ckeditor_ckeditor5_build_classic__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(_ckeditor_ckeditor5_build_classic__WEBPACK_IMPORTED_MODULE_0__); +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// - $(this._backdrop).one(Util.TRANSITION_END, callbackRemove).emulateTransitionEnd(_backdropTransitionDuration); +/* harmony default export */ __webpack_exports__["default"] = ({ + components: {}, + data: function data() { + return { + upload_result: this.$root.publishState.file, + editor: _ckeditor_ckeditor5_build_classic__WEBPACK_IMPORTED_MODULE_0___default.a, + email: { + content: "", + subject: "" + }, + csrf: document.querySelectorAll('meta[name="csrf-token"]')[0].content, + editorConfig: {} + }; + }, + watch: { + email: { + deep: true, + handler: function handler(val, old) { + if (val.editorData !== '' && val.subject !== '') { + this.$root.publishState.email = val; + this.$emit('can-continue', { + value: true + }); } else { - callbackRemove(); + this.$emit('can-continue', { + value: false + }); } - } else if (callback) { - callback(); } - } // ---------------------------------------------------------------------- - // the following methods are used to handle overflowing modals - // todo (fat): these should probably be refactored out of modal.js - // ---------------------------------------------------------------------- - ; + } + }, + methods: {}, + mounted: function mounted() { + $('#previewModal').on('show.bs.modal', this.showModal); + } +}); - _proto._adjustDialog = function _adjustDialog() { - var isModalOverflowing = this._element.scrollHeight > document.documentElement.clientHeight; +/***/ }), - if (!this._isBodyOverflowing && isModalOverflowing) { - this._element.style.paddingLeft = this._scrollbarWidth + "px"; - } +/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/Publish/Step3Send.vue?vue&type=script&lang=js&": +/*!****************************************************************************************************************************************************************************!*\ + !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/Publish/Step3Send.vue?vue&type=script&lang=js& ***! + \****************************************************************************************************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { - if (this._isBodyOverflowing && !isModalOverflowing) { - this._element.style.paddingRight = this._scrollbarWidth + "px"; - } - }; +"use strict"; +__webpack_require__.r(__webpack_exports__); +/* harmony import */ var vue_simple_progress__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue-simple-progress */ "./node_modules/vue-simple-progress/dist/vue-simple-progress.js"); +/* harmony import */ var vue_simple_progress__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(vue_simple_progress__WEBPACK_IMPORTED_MODULE_0__); +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// - _proto._resetAdjustments = function _resetAdjustments() { - this._element.style.paddingLeft = ''; - this._element.style.paddingRight = ''; +/* harmony default export */ __webpack_exports__["default"] = ({ + components: { + ProgressBar: vue_simple_progress__WEBPACK_IMPORTED_MODULE_0___default.a + }, + data: function data() { + return { + upload_result: this.$root.publishState.file, + recipients_count: 0, + status: 'En attente', + counters: { + delivered: 0, + opened: 0, + clicked: 0 + }, + publishing: false, + done: false, + statusData: { + status: null, + current: 0, + total: 0 + } }; + }, + computed: { + progress: function progress() { + if (this.statusData.status === 'init' || this.statusData.total == 0) { + return 0; + } - _proto._checkScrollbar = function _checkScrollbar() { - var rect = document.body.getBoundingClientRect(); - this._isBodyOverflowing = rect.left + rect.right < window.innerWidth; - this._scrollbarWidth = this._getScrollbarWidth(); - }; + return Math.ceil(this.statusData.current * 100 / this.statusData.total); + } + }, + methods: { + processMailEvent: function processMailEvent(e) { + if (e.data.event === 'delivered') this.counters.delivered++; + if (e.data.event === 'opened') this.counters.opened++; + if (e.data.event === 'clicked') this.counters.clicked++; + }, + processProgressEvent: function processProgressEvent(e) { + if (this.done) return; + this.statusData = e.data; - _proto._setScrollbar = function _setScrollbar() { - var _this10 = this; + switch (e.data.status) { + case 'init': + this.status = "Préparation en cours"; + break; - if (this._isBodyOverflowing) { - // Note: DOMNode.style.paddingRight returns the actual value or '' if not set - // while $(DOMNode).css('padding-right') returns the calculated value or 0 if not set - var fixedContent = [].slice.call(document.querySelectorAll(Selector$5.FIXED_CONTENT)); - var stickyContent = [].slice.call(document.querySelectorAll(Selector$5.STICKY_CONTENT)); // Adjust fixed content padding + case 'processing': + this.status = "Traitement en cours : (".concat(e.data.current, " / ").concat(e.data.total, ")"); + break; - $(fixedContent).each(function (index, element) { - var actualPadding = element.style.paddingRight; - var calculatedPadding = $(element).css('padding-right'); - $(element).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + _this10._scrollbarWidth + "px"); - }); // Adjust sticky content margin - - $(stickyContent).each(function (index, element) { - var actualMargin = element.style.marginRight; - var calculatedMargin = $(element).css('margin-right'); - $(element).data('margin-right', actualMargin).css('margin-right', parseFloat(calculatedMargin) - _this10._scrollbarWidth + "px"); - }); // Adjust body padding - - var actualPadding = document.body.style.paddingRight; - var calculatedPadding = $(document.body).css('padding-right'); - $(document.body).data('padding-right', actualPadding).css('padding-right', parseFloat(calculatedPadding) + this._scrollbarWidth + "px"); + case 'done': + this.status = "Termin\xE9, ".concat(e.data.total, " emails envoy\xE9s"); + this.done = true; + this.$emit('can-continue', { + value: true + }); } + }, + publish: function publish() { + var _this = this; - $(document.body).addClass(ClassName$5.OPEN); - }; + axios({ + method: 'post', + url: '/publish', + data: { + data: this.$root.publishState + } + }).then(function (d) { + Echo["private"]("emailBatch.".concat(d.data.data)).listen('.mailgun.event', _this.processMailEvent).listen('.batch.status', _this.processProgressEvent); + _this.publishing = true; + }); + } + }, + mounted: function mounted() { + var _this2 = this; - _proto._resetScrollbar = function _resetScrollbar() { - // Restore fixed content padding - var fixedContent = [].slice.call(document.querySelectorAll(Selector$5.FIXED_CONTENT)); - $(fixedContent).each(function (index, element) { - var padding = $(element).data('padding-right'); - $(element).removeData('padding-right'); - element.style.paddingRight = padding ? padding : ''; - }); // Restore sticky content + axios.get('publish/recipients').then(function (d) { + return _this2.recipients_count = d.data.data; + }); + } +}); - var elements = [].slice.call(document.querySelectorAll("" + Selector$5.STICKY_CONTENT)); - $(elements).each(function (index, element) { - var margin = $(element).data('margin-right'); +/***/ }), - if (typeof margin !== 'undefined') { - $(element).css('margin-right', margin).removeData('margin-right'); - } - }); // Restore body padding +/***/ "./node_modules/babel-loader/lib/index.js?!./node_modules/vue-loader/lib/index.js?!./resources/js/components/Stats/MgStats.vue?vue&type=script&lang=js&": +/*!************************************************************************************************************************************************************************!*\ + !*** ./node_modules/babel-loader/lib??ref--4-0!./node_modules/vue-loader/lib??vue-loader-options!./resources/js/components/Stats/MgStats.vue?vue&type=script&lang=js& ***! + \************************************************************************************************************************************************************************/ +/*! exports provided: default */ +/***/ (function(module, __webpack_exports__, __webpack_require__) { - var padding = $(document.body).data('padding-right'); - $(document.body).removeData('padding-right'); - document.body.style.paddingRight = padding ? padding : ''; - }; +"use strict"; +__webpack_require__.r(__webpack_exports__); +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +// +/* harmony default export */ __webpack_exports__["default"] = ({ + components: {}, + props: ['icon', 'current', 'total', 'text'], + data: function data() { + return {}; + }, + mounted: function mounted() { + Echo["private"]('emailBatch.1').listen('.mailgun.event', function (e) { + console.log(e); + }).listen('.batch.status', function (e) { + console.log(e); + }); + }, + methods: {} +}); - _proto._getScrollbarWidth = function _getScrollbarWidth() { - // thx d.walsh - var scrollDiv = document.createElement('div'); - scrollDiv.className = ClassName$5.SCROLLBAR_MEASURER; - document.body.appendChild(scrollDiv); - var scrollbarWidth = scrollDiv.getBoundingClientRect().width - scrollDiv.clientWidth; - document.body.removeChild(scrollDiv); - return scrollbarWidth; - } // Static - ; +/***/ }), - Modal._jQueryInterface = function _jQueryInterface(config, relatedTarget) { - return this.each(function () { - var data = $(this).data(DATA_KEY$5); +/***/ "./node_modules/base64-js/index.js": +/*!*****************************************!*\ + !*** ./node_modules/base64-js/index.js ***! + \*****************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - var _config = _objectSpread2({}, Default$3, {}, $(this).data(), {}, typeof config === 'object' && config ? config : {}); +"use strict"; - if (!data) { - data = new Modal(this, _config); - $(this).data(DATA_KEY$5, data); - } - if (typeof config === 'string') { - if (typeof data[config] === 'undefined') { - throw new TypeError("No method named \"" + config + "\""); - } +exports.byteLength = byteLength +exports.toByteArray = toByteArray +exports.fromByteArray = fromByteArray - data[config](relatedTarget); - } else if (_config.show) { - data.show(relatedTarget); - } - }); - }; +var lookup = [] +var revLookup = [] +var Arr = typeof Uint8Array !== 'undefined' ? Uint8Array : Array - _createClass(Modal, null, [{ - key: "VERSION", - get: function get() { - return VERSION$5; - } - }, { - key: "Default", - get: function get() { - return Default$3; - } - }]); +var code = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/' +for (var i = 0, len = code.length; i < len; ++i) { + lookup[i] = code[i] + revLookup[code.charCodeAt(i)] = i +} - return Modal; - }(); - /** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ +// Support decoding URL-safe base64 strings, as Node.js does. +// See: https://en.wikipedia.org/wiki/Base64#URL_applications +revLookup['-'.charCodeAt(0)] = 62 +revLookup['_'.charCodeAt(0)] = 63 +function getLens (b64) { + var len = b64.length - $(document).on(Event$5.CLICK_DATA_API, Selector$5.DATA_TOGGLE, function (event) { - var _this11 = this; + if (len % 4 > 0) { + throw new Error('Invalid string. Length must be a multiple of 4') + } - var target; - var selector = Util.getSelectorFromElement(this); + // Trim off extra bytes after placeholder bytes are found + // See: https://github.com/beatgammit/base64-js/issues/42 + var validLen = b64.indexOf('=') + if (validLen === -1) validLen = len - if (selector) { - target = document.querySelector(selector); - } + var placeHoldersLen = validLen === len + ? 0 + : 4 - (validLen % 4) - var config = $(target).data(DATA_KEY$5) ? 'toggle' : _objectSpread2({}, $(target).data(), {}, $(this).data()); + return [validLen, placeHoldersLen] +} - if (this.tagName === 'A' || this.tagName === 'AREA') { - event.preventDefault(); - } +// base64 is 4/3 + up to two characters of the original data +function byteLength (b64) { + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} - var $target = $(target).one(Event$5.SHOW, function (showEvent) { - if (showEvent.isDefaultPrevented()) { - // Only register focus restorer if modal will actually get shown - return; - } +function _byteLength (b64, validLen, placeHoldersLen) { + return ((validLen + placeHoldersLen) * 3 / 4) - placeHoldersLen +} - $target.one(Event$5.HIDDEN, function () { - if ($(_this11).is(':visible')) { - _this11.focus(); - } - }); - }); +function toByteArray (b64) { + var tmp + var lens = getLens(b64) + var validLen = lens[0] + var placeHoldersLen = lens[1] - Modal._jQueryInterface.call($(target), config, this); - }); - /** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - */ + var arr = new Arr(_byteLength(b64, validLen, placeHoldersLen)) - $.fn[NAME$5] = Modal._jQueryInterface; - $.fn[NAME$5].Constructor = Modal; + var curByte = 0 - $.fn[NAME$5].noConflict = function () { - $.fn[NAME$5] = JQUERY_NO_CONFLICT$5; - return Modal._jQueryInterface; - }; + // if there are placeholders, only get up to the last complete 4 chars + var len = placeHoldersLen > 0 + ? validLen - 4 + : validLen - /** - * -------------------------------------------------------------------------- - * Bootstrap (v4.4.1): tools/sanitizer.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * -------------------------------------------------------------------------- - */ - var uriAttrs = ['background', 'cite', 'href', 'itemtype', 'longdesc', 'poster', 'src', 'xlink:href']; - var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i; - var DefaultWhitelist = { - // Global attributes allowed on any supplied element below. - '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN], - a: ['target', 'href', 'title', 'rel'], - area: [], - b: [], - br: [], - col: [], - code: [], - div: [], - em: [], - hr: [], - h1: [], - h2: [], - h3: [], - h4: [], - h5: [], - h6: [], - i: [], - img: ['src', 'alt', 'title', 'width', 'height'], - li: [], - ol: [], - p: [], - pre: [], - s: [], - small: [], - span: [], - sub: [], - sup: [], - strong: [], - u: [], - ul: [] - }; - /** - * A pattern that recognizes a commonly useful subset of URLs that are safe. - * - * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts - */ + var i + for (i = 0; i < len; i += 4) { + tmp = + (revLookup[b64.charCodeAt(i)] << 18) | + (revLookup[b64.charCodeAt(i + 1)] << 12) | + (revLookup[b64.charCodeAt(i + 2)] << 6) | + revLookup[b64.charCodeAt(i + 3)] + arr[curByte++] = (tmp >> 16) & 0xFF + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } - var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi; - /** - * A pattern that matches safe data URLs. Only matches image, video and audio types. - * - * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts - */ + if (placeHoldersLen === 2) { + tmp = + (revLookup[b64.charCodeAt(i)] << 2) | + (revLookup[b64.charCodeAt(i + 1)] >> 4) + arr[curByte++] = tmp & 0xFF + } - var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i; + if (placeHoldersLen === 1) { + tmp = + (revLookup[b64.charCodeAt(i)] << 10) | + (revLookup[b64.charCodeAt(i + 1)] << 4) | + (revLookup[b64.charCodeAt(i + 2)] >> 2) + arr[curByte++] = (tmp >> 8) & 0xFF + arr[curByte++] = tmp & 0xFF + } - function allowedAttribute(attr, allowedAttributeList) { - var attrName = attr.nodeName.toLowerCase(); + return arr +} - if (allowedAttributeList.indexOf(attrName) !== -1) { - if (uriAttrs.indexOf(attrName) !== -1) { - return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN)); - } +function tripletToBase64 (num) { + return lookup[num >> 18 & 0x3F] + + lookup[num >> 12 & 0x3F] + + lookup[num >> 6 & 0x3F] + + lookup[num & 0x3F] +} - return true; - } +function encodeChunk (uint8, start, end) { + var tmp + var output = [] + for (var i = start; i < end; i += 3) { + tmp = + ((uint8[i] << 16) & 0xFF0000) + + ((uint8[i + 1] << 8) & 0xFF00) + + (uint8[i + 2] & 0xFF) + output.push(tripletToBase64(tmp)) + } + return output.join('') +} - var regExp = allowedAttributeList.filter(function (attrRegex) { - return attrRegex instanceof RegExp; - }); // Check if a regular expression validates the attribute. +function fromByteArray (uint8) { + var tmp + var len = uint8.length + var extraBytes = len % 3 // if we have 1 byte left, pad 2 bytes + var parts = [] + var maxChunkLength = 16383 // must be multiple of 3 - for (var i = 0, l = regExp.length; i < l; i++) { - if (attrName.match(regExp[i])) { - return true; - } - } + // go through the array every three bytes, we'll deal with trailing stuff later + for (var i = 0, len2 = len - extraBytes; i < len2; i += maxChunkLength) { + parts.push(encodeChunk( + uint8, i, (i + maxChunkLength) > len2 ? len2 : (i + maxChunkLength) + )) + } - return false; + // pad the end with zeros, but make sure to not forget the extra bytes + if (extraBytes === 1) { + tmp = uint8[len - 1] + parts.push( + lookup[tmp >> 2] + + lookup[(tmp << 4) & 0x3F] + + '==' + ) + } else if (extraBytes === 2) { + tmp = (uint8[len - 2] << 8) + uint8[len - 1] + parts.push( + lookup[tmp >> 10] + + lookup[(tmp >> 4) & 0x3F] + + lookup[(tmp << 2) & 0x3F] + + '=' + ) } - function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) { - if (unsafeHtml.length === 0) { - return unsafeHtml; - } + return parts.join('') +} - if (sanitizeFn && typeof sanitizeFn === 'function') { - return sanitizeFn(unsafeHtml); - } - var domParser = new window.DOMParser(); - var createdDocument = domParser.parseFromString(unsafeHtml, 'text/html'); - var whitelistKeys = Object.keys(whiteList); - var elements = [].slice.call(createdDocument.body.querySelectorAll('*')); +/***/ }), - var _loop = function _loop(i, len) { - var el = elements[i]; - var elName = el.nodeName.toLowerCase(); +/***/ "./node_modules/bootstrap/dist/js/bootstrap.js": +/*!*****************************************************!*\ + !*** ./node_modules/bootstrap/dist/js/bootstrap.js ***! + \*****************************************************/ +/*! no static exports found */ +/***/ (function(module, exports, __webpack_require__) { - if (whitelistKeys.indexOf(el.nodeName.toLowerCase()) === -1) { - el.parentNode.removeChild(el); - return "continue"; - } +/*! + * Bootstrap v4.4.1 (https://getbootstrap.com/) + * Copyright 2011-2019 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors) + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + */ +(function (global, factory) { + true ? factory(exports, __webpack_require__(/*! jquery */ "./node_modules/jquery/dist/jquery.js"), __webpack_require__(/*! popper.js */ "./node_modules/popper.js/dist/esm/popper.js")) : + undefined; +}(this, (function (exports, $, Popper) { 'use strict'; - var attributeList = [].slice.call(el.attributes); - var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || []); - attributeList.forEach(function (attr) { - if (!allowedAttribute(attr, whitelistedAttributes)) { - el.removeAttribute(attr.nodeName); - } + $ = $ && $.hasOwnProperty('default') ? $['default'] : $; + Popper = Popper && Popper.hasOwnProperty('default') ? Popper['default'] : Popper; + + function _defineProperties(target, props) { + for (var i = 0; i < props.length; i++) { + var descriptor = props[i]; + descriptor.enumerable = descriptor.enumerable || false; + descriptor.configurable = true; + if ("value" in descriptor) descriptor.writable = true; + Object.defineProperty(target, descriptor.key, descriptor); + } + } + + function _createClass(Constructor, protoProps, staticProps) { + if (protoProps) _defineProperties(Constructor.prototype, protoProps); + if (staticProps) _defineProperties(Constructor, staticProps); + return Constructor; + } + + function _defineProperty(obj, key, value) { + if (key in obj) { + Object.defineProperty(obj, key, { + value: value, + enumerable: true, + configurable: true, + writable: true }); - }; + } else { + obj[key] = value; + } - for (var i = 0, len = elements.length; i < len; i++) { - var _ret = _loop(i); + return obj; + } - if (_ret === "continue") continue; + function ownKeys(object, enumerableOnly) { + var keys = Object.keys(object); + + if (Object.getOwnPropertySymbols) { + var symbols = Object.getOwnPropertySymbols(object); + if (enumerableOnly) symbols = symbols.filter(function (sym) { + return Object.getOwnPropertyDescriptor(object, sym).enumerable; + }); + keys.push.apply(keys, symbols); } - return createdDocument.body.innerHTML; + return keys; } - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ + function _objectSpread2(target) { + for (var i = 1; i < arguments.length; i++) { + var source = arguments[i] != null ? arguments[i] : {}; + + if (i % 2) { + ownKeys(Object(source), true).forEach(function (key) { + _defineProperty(target, key, source[key]); + }); + } else if (Object.getOwnPropertyDescriptors) { + Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); + } else { + ownKeys(Object(source)).forEach(function (key) { + Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); + }); + } + } + + return target; + } + + function _inheritsLoose(subClass, superClass) { + subClass.prototype = Object.create(superClass.prototype); + subClass.prototype.constructor = subClass; + subClass.__proto__ = superClass; + } - var NAME$6 = 'tooltip'; - var VERSION$6 = '4.4.1'; - var DATA_KEY$6 = 'bs.tooltip'; - var EVENT_KEY$6 = "." + DATA_KEY$6; - var JQUERY_NO_CONFLICT$6 = $.fn[NAME$6]; - var CLASS_PREFIX = 'bs-tooltip'; - var BSCLS_PREFIX_REGEX = new RegExp("(^|\\s)" + CLASS_PREFIX + "\\S+", 'g'); - var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn']; - var DefaultType$4 = { - animation: 'boolean', - template: 'string', - title: '(string|element|function)', - trigger: 'string', - delay: '(number|object)', - html: 'boolean', - selector: '(string|boolean)', - placement: '(string|function)', - offset: '(number|string|function)', - container: '(string|element|boolean)', - fallbackPlacement: '(string|array)', - boundary: '(string|element)', - sanitize: 'boolean', - sanitizeFn: '(null|function)', - whiteList: 'object', - popperConfig: '(null|object)' - }; - var AttachmentMap$1 = { - AUTO: 'auto', - TOP: 'top', - RIGHT: 'right', - BOTTOM: 'bottom', - LEFT: 'left' - }; - var Default$4 = { - animation: true, - template: '', - trigger: 'hover focus', - title: '', - delay: 0, - html: false, - selector: false, - placement: 'top', - offset: 0, - container: false, - fallbackPlacement: 'flip', - boundary: 'scrollParent', - sanitize: true, - sanitizeFn: null, - whiteList: DefaultWhitelist, - popperConfig: null - }; - var HoverState = { - SHOW: 'show', - OUT: 'out' - }; - var Event$6 = { - HIDE: "hide" + EVENT_KEY$6, - HIDDEN: "hidden" + EVENT_KEY$6, - SHOW: "show" + EVENT_KEY$6, - SHOWN: "shown" + EVENT_KEY$6, - INSERTED: "inserted" + EVENT_KEY$6, - CLICK: "click" + EVENT_KEY$6, - FOCUSIN: "focusin" + EVENT_KEY$6, - FOCUSOUT: "focusout" + EVENT_KEY$6, - MOUSEENTER: "mouseenter" + EVENT_KEY$6, - MOUSELEAVE: "mouseleave" + EVENT_KEY$6 - }; - var ClassName$6 = { - FADE: 'fade', - SHOW: 'show' - }; - var Selector$6 = { - TOOLTIP: '.tooltip', - TOOLTIP_INNER: '.tooltip-inner', - ARROW: '.arrow' - }; - var Trigger = { - HOVER: 'hover', - FOCUS: 'focus', - CLICK: 'click', - MANUAL: 'manual' - }; + /** + * -------------------------------------------------------------------------- + * Bootstrap (v4.4.1): util.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ /** * ------------------------------------------------------------------------ - * Class Definition + * Private TransitionEnd Helpers * ------------------------------------------------------------------------ */ - var Tooltip = - /*#__PURE__*/ - function () { - function Tooltip(element, config) { - if (typeof Popper === 'undefined') { - throw new TypeError('Bootstrap\'s tooltips require Popper.js (https://popper.js.org/)'); - } // private - - - this._isEnabled = true; - this._timeout = 0; - this._hoverState = ''; - this._activeTrigger = {}; - this._popper = null; // Protected - - this.element = element; - this.config = this._getConfig(config); - this.tip = null; - - this._setListeners(); - } // Getters - + var TRANSITION_END = 'transitionend'; + var MAX_UID = 1000000; + var MILLISECONDS_MULTIPLIER = 1000; // Shoutout AngusCroll (https://goo.gl/pxwQGp) - var _proto = Tooltip.prototype; + function toType(obj) { + return {}.toString.call(obj).match(/\s([a-z]+)/i)[1].toLowerCase(); + } - // Public - _proto.enable = function enable() { - this._isEnabled = true; - }; + function getSpecialTransitionEndEvent() { + return { + bindType: TRANSITION_END, + delegateType: TRANSITION_END, + handle: function handle(event) { + if ($(event.target).is(this)) { + return event.handleObj.handler.apply(this, arguments); // eslint-disable-line prefer-rest-params + } - _proto.disable = function disable() { - this._isEnabled = false; + return undefined; // eslint-disable-line no-undefined + } }; + } - _proto.toggleEnabled = function toggleEnabled() { - this._isEnabled = !this._isEnabled; - }; + function transitionEndEmulator(duration) { + var _this = this; - _proto.toggle = function toggle(event) { - if (!this._isEnabled) { - return; + var called = false; + $(this).one(Util.TRANSITION_END, function () { + called = true; + }); + setTimeout(function () { + if (!called) { + Util.triggerTransitionEnd(_this); } + }, duration); + return this; + } - if (event) { - var dataKey = this.constructor.DATA_KEY; - var context = $(event.currentTarget).data(dataKey); - - if (!context) { - context = new this.constructor(event.currentTarget, this._getDelegateConfig()); - $(event.currentTarget).data(dataKey, context); - } + function setTransitionEndSupport() { + $.fn.emulateTransitionEnd = transitionEndEmulator; + $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent(); + } + /** + * -------------------------------------------------------------------------- + * Public Util Api + * -------------------------------------------------------------------------- + */ - context._activeTrigger.click = !context._activeTrigger.click; - if (context._isWithActiveTrigger()) { - context._enter(null, context); - } else { - context._leave(null, context); - } - } else { - if ($(this.getTipElement()).hasClass(ClassName$6.SHOW)) { - this._leave(null, this); + var Util = { + TRANSITION_END: 'bsTransitionEnd', + getUID: function getUID(prefix) { + do { + // eslint-disable-next-line no-bitwise + prefix += ~~(Math.random() * MAX_UID); // "~~" acts like a faster Math.floor() here + } while (document.getElementById(prefix)); - return; - } + return prefix; + }, + getSelectorFromElement: function getSelectorFromElement(element) { + var selector = element.getAttribute('data-target'); - this._enter(null, this); + if (!selector || selector === '#') { + var hrefAttr = element.getAttribute('href'); + selector = hrefAttr && hrefAttr !== '#' ? hrefAttr.trim() : ''; } - }; - - _proto.dispose = function dispose() { - clearTimeout(this._timeout); - $.removeData(this.element, this.constructor.DATA_KEY); - $(this.element).off(this.constructor.EVENT_KEY); - $(this.element).closest('.modal').off('hide.bs.modal', this._hideModalHandler); - if (this.tip) { - $(this.tip).remove(); + try { + return document.querySelector(selector) ? selector : null; + } catch (err) { + return null; } + }, + getTransitionDurationFromElement: function getTransitionDurationFromElement(element) { + if (!element) { + return 0; + } // Get transition-duration of the element - this._isEnabled = null; - this._timeout = null; - this._hoverState = null; - this._activeTrigger = null; - if (this._popper) { - this._popper.destroy(); - } + var transitionDuration = $(element).css('transition-duration'); + var transitionDelay = $(element).css('transition-delay'); + var floatTransitionDuration = parseFloat(transitionDuration); + var floatTransitionDelay = parseFloat(transitionDelay); // Return 0 if element or transition duration is not found - this._popper = null; - this.element = null; - this.config = null; - this.tip = null; - }; + if (!floatTransitionDuration && !floatTransitionDelay) { + return 0; + } // If multiple durations are defined, take the first - _proto.show = function show() { - var _this = this; - if ($(this.element).css('display') === 'none') { - throw new Error('Please use show on visible elements'); + transitionDuration = transitionDuration.split(',')[0]; + transitionDelay = transitionDelay.split(',')[0]; + return (parseFloat(transitionDuration) + parseFloat(transitionDelay)) * MILLISECONDS_MULTIPLIER; + }, + reflow: function reflow(element) { + return element.offsetHeight; + }, + triggerTransitionEnd: function triggerTransitionEnd(element) { + $(element).trigger(TRANSITION_END); + }, + // TODO: Remove in v5 + supportsTransitionEnd: function supportsTransitionEnd() { + return Boolean(TRANSITION_END); + }, + isElement: function isElement(obj) { + return (obj[0] || obj).nodeType; + }, + typeCheckConfig: function typeCheckConfig(componentName, config, configTypes) { + for (var property in configTypes) { + if (Object.prototype.hasOwnProperty.call(configTypes, property)) { + var expectedTypes = configTypes[property]; + var value = config[property]; + var valueType = value && Util.isElement(value) ? 'element' : toType(value); + + if (!new RegExp(expectedTypes).test(valueType)) { + throw new Error(componentName.toUpperCase() + ": " + ("Option \"" + property + "\" provided type \"" + valueType + "\" ") + ("but expected type \"" + expectedTypes + "\".")); + } + } } + }, + findShadowRoot: function findShadowRoot(element) { + if (!document.documentElement.attachShadow) { + return null; + } // Can find the shadow root otherwise it'll return the document - var showEvent = $.Event(this.constructor.Event.SHOW); - if (this.isWithContent() && this._isEnabled) { - $(this.element).trigger(showEvent); - var shadowRoot = Util.findShadowRoot(this.element); - var isInTheDom = $.contains(shadowRoot !== null ? shadowRoot : this.element.ownerDocument.documentElement, this.element); + if (typeof element.getRootNode === 'function') { + var root = element.getRootNode(); + return root instanceof ShadowRoot ? root : null; + } - if (showEvent.isDefaultPrevented() || !isInTheDom) { - return; - } + if (element instanceof ShadowRoot) { + return element; + } // when we don't find a shadow root - var tip = this.getTipElement(); - var tipId = Util.getUID(this.constructor.NAME); - tip.setAttribute('id', tipId); - this.element.setAttribute('aria-describedby', tipId); - this.setContent(); - if (this.config.animation) { - $(tip).addClass(ClassName$6.FADE); - } + if (!element.parentNode) { + return null; + } - var placement = typeof this.config.placement === 'function' ? this.config.placement.call(this, tip, this.element) : this.config.placement; + return Util.findShadowRoot(element.parentNode); + }, + jQueryDetection: function jQueryDetection() { + if (typeof $ === 'undefined') { + throw new TypeError('Bootstrap\'s JavaScript requires jQuery. jQuery must be included before Bootstrap\'s JavaScript.'); + } - var attachment = this._getAttachment(placement); + var version = $.fn.jquery.split(' ')[0].split('.'); + var minMajor = 1; + var ltMajor = 2; + var minMinor = 9; + var minPatch = 1; + var maxMajor = 4; - this.addAttachmentClass(attachment); + if (version[0] < ltMajor && version[1] < minMinor || version[0] === minMajor && version[1] === minMinor && version[2] < minPatch || version[0] >= maxMajor) { + throw new Error('Bootstrap\'s JavaScript requires at least jQuery v1.9.1 but less than v4.0.0'); + } + } + }; + Util.jQueryDetection(); + setTransitionEndSupport(); - var container = this._getContainer(); + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ - $(tip).data(this.constructor.DATA_KEY, this); + var NAME = 'alert'; + var VERSION = '4.4.1'; + var DATA_KEY = 'bs.alert'; + var EVENT_KEY = "." + DATA_KEY; + var DATA_API_KEY = '.data-api'; + var JQUERY_NO_CONFLICT = $.fn[NAME]; + var Selector = { + DISMISS: '[data-dismiss="alert"]' + }; + var Event = { + CLOSE: "close" + EVENT_KEY, + CLOSED: "closed" + EVENT_KEY, + CLICK_DATA_API: "click" + EVENT_KEY + DATA_API_KEY + }; + var ClassName = { + ALERT: 'alert', + FADE: 'fade', + SHOW: 'show' + }; + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ - if (!$.contains(this.element.ownerDocument.documentElement, this.tip)) { - $(tip).appendTo(container); - } + var Alert = + /*#__PURE__*/ + function () { + function Alert(element) { + this._element = element; + } // Getters - $(this.element).trigger(this.constructor.Event.INSERTED); - this._popper = new Popper(this.element, tip, this._getPopperConfig(attachment)); - $(tip).addClass(ClassName$6.SHOW); // If this is a touch-enabled device we add extra - // empty mouseover listeners to the body's immediate children; - // only needed because of broken event delegation on iOS - // https://www.quirksmode.org/blog/archives/2014/02/mouse_event_bub.html - if ('ontouchstart' in document.documentElement) { - $(document.body).children().on('mouseover', null, $.noop); - } + var _proto = Alert.prototype; - var complete = function complete() { - if (_this.config.animation) { - _this._fixTransition(); - } + // Public + _proto.close = function close(element) { + var rootElement = this._element; - var prevHoverState = _this._hoverState; - _this._hoverState = null; - $(_this.element).trigger(_this.constructor.Event.SHOWN); + if (element) { + rootElement = this._getRootElement(element); + } - if (prevHoverState === HoverState.OUT) { - _this._leave(null, _this); - } - }; + var customEvent = this._triggerCloseEvent(rootElement); - if ($(this.tip).hasClass(ClassName$6.FADE)) { - var transitionDuration = Util.getTransitionDurationFromElement(this.tip); - $(this.tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); - } else { - complete(); - } + if (customEvent.isDefaultPrevented()) { + return; } + + this._removeElement(rootElement); }; - _proto.hide = function hide(callback) { - var _this2 = this; + _proto.dispose = function dispose() { + $.removeData(this._element, DATA_KEY); + this._element = null; + } // Private + ; - var tip = this.getTipElement(); - var hideEvent = $.Event(this.constructor.Event.HIDE); + _proto._getRootElement = function _getRootElement(element) { + var selector = Util.getSelectorFromElement(element); + var parent = false; - var complete = function complete() { - if (_this2._hoverState !== HoverState.SHOW && tip.parentNode) { - tip.parentNode.removeChild(tip); - } + if (selector) { + parent = document.querySelector(selector); + } - _this2._cleanTipClass(); + if (!parent) { + parent = $(element).closest("." + ClassName.ALERT)[0]; + } - _this2.element.removeAttribute('aria-describedby'); + return parent; + }; - $(_this2.element).trigger(_this2.constructor.Event.HIDDEN); + _proto._triggerCloseEvent = function _triggerCloseEvent(element) { + var closeEvent = $.Event(Event.CLOSE); + $(element).trigger(closeEvent); + return closeEvent; + }; - if (_this2._popper !== null) { - _this2._popper.destroy(); - } + _proto._removeElement = function _removeElement(element) { + var _this = this; - if (callback) { - callback(); - } - }; + $(element).removeClass(ClassName.SHOW); - $(this.element).trigger(hideEvent); + if (!$(element).hasClass(ClassName.FADE)) { + this._destroyElement(element); - if (hideEvent.isDefaultPrevented()) { return; } - $(tip).removeClass(ClassName$6.SHOW); // If this is a touch-enabled device we remove the extra - // empty mouseover listeners we added for iOS support + var transitionDuration = Util.getTransitionDurationFromElement(element); + $(element).one(Util.TRANSITION_END, function (event) { + return _this._destroyElement(element, event); + }).emulateTransitionEnd(transitionDuration); + }; - if ('ontouchstart' in document.documentElement) { - $(document.body).children().off('mouseover', null, $.noop); - } + _proto._destroyElement = function _destroyElement(element) { + $(element).detach().trigger(Event.CLOSED).remove(); + } // Static + ; - this._activeTrigger[Trigger.CLICK] = false; - this._activeTrigger[Trigger.FOCUS] = false; - this._activeTrigger[Trigger.HOVER] = false; + Alert._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var $element = $(this); + var data = $element.data(DATA_KEY); - if ($(this.tip).hasClass(ClassName$6.FADE)) { - var transitionDuration = Util.getTransitionDurationFromElement(tip); - $(tip).one(Util.TRANSITION_END, complete).emulateTransitionEnd(transitionDuration); - } else { - complete(); - } + if (!data) { + data = new Alert(this); + $element.data(DATA_KEY, data); + } - this._hoverState = ''; + if (config === 'close') { + data[config](this); + } + }); }; - _proto.update = function update() { - if (this._popper !== null) { - this._popper.scheduleUpdate(); - } - } // Protected - ; - - _proto.isWithContent = function isWithContent() { - return Boolean(this.getTitle()); - }; + Alert._handleDismiss = function _handleDismiss(alertInstance) { + return function (event) { + if (event) { + event.preventDefault(); + } - _proto.addAttachmentClass = function addAttachmentClass(attachment) { - $(this.getTipElement()).addClass(CLASS_PREFIX + "-" + attachment); + alertInstance.close(this); + }; }; - _proto.getTipElement = function getTipElement() { - this.tip = this.tip || $(this.config.template)[0]; - return this.tip; - }; - - _proto.setContent = function setContent() { - var tip = this.getTipElement(); - this.setElementContent($(tip.querySelectorAll(Selector$6.TOOLTIP_INNER)), this.getTitle()); - $(tip).removeClass(ClassName$6.FADE + " " + ClassName$6.SHOW); - }; - - _proto.setElementContent = function setElementContent($element, content) { - if (typeof content === 'object' && (content.nodeType || content.jquery)) { - // Content is a DOM node or a jQuery - if (this.config.html) { - if (!$(content).parent().is($element)) { - $element.empty().append(content); - } - } else { - $element.text($(content).text()); - } - - return; - } - - if (this.config.html) { - if (this.config.sanitize) { - content = sanitizeHtml(content, this.config.whiteList, this.config.sanitizeFn); - } - - $element.html(content); - } else { - $element.text(content); + _createClass(Alert, null, [{ + key: "VERSION", + get: function get() { + return VERSION; } - }; + }]); - _proto.getTitle = function getTitle() { - var title = this.element.getAttribute('data-original-title'); + return Alert; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ - if (!title) { - title = typeof this.config.title === 'function' ? this.config.title.call(this.element) : this.config.title; - } - return title; - } // Private - ; + $(document).on(Event.CLICK_DATA_API, Selector.DISMISS, Alert._handleDismiss(new Alert())); + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ - _proto._getPopperConfig = function _getPopperConfig(attachment) { - var _this3 = this; + $.fn[NAME] = Alert._jQueryInterface; + $.fn[NAME].Constructor = Alert; - var defaultBsConfig = { - placement: attachment, - modifiers: { - offset: this._getOffset(), - flip: { - behavior: this.config.fallbackPlacement - }, - arrow: { - element: Selector$6.ARROW - }, - preventOverflow: { - boundariesElement: this.config.boundary - } - }, - onCreate: function onCreate(data) { - if (data.originalPlacement !== data.placement) { - _this3._handlePopperPlacementChange(data); - } - }, - onUpdate: function onUpdate(data) { - return _this3._handlePopperPlacementChange(data); - } - }; - return _objectSpread2({}, defaultBsConfig, {}, this.config.popperConfig); - }; + $.fn[NAME].noConflict = function () { + $.fn[NAME] = JQUERY_NO_CONFLICT; + return Alert._jQueryInterface; + }; - _proto._getOffset = function _getOffset() { - var _this4 = this; + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ - var offset = {}; + var NAME$1 = 'button'; + var VERSION$1 = '4.4.1'; + var DATA_KEY$1 = 'bs.button'; + var EVENT_KEY$1 = "." + DATA_KEY$1; + var DATA_API_KEY$1 = '.data-api'; + var JQUERY_NO_CONFLICT$1 = $.fn[NAME$1]; + var ClassName$1 = { + ACTIVE: 'active', + BUTTON: 'btn', + FOCUS: 'focus' + }; + var Selector$1 = { + DATA_TOGGLE_CARROT: '[data-toggle^="button"]', + DATA_TOGGLES: '[data-toggle="buttons"]', + DATA_TOGGLE: '[data-toggle="button"]', + DATA_TOGGLES_BUTTONS: '[data-toggle="buttons"] .btn', + INPUT: 'input:not([type="hidden"])', + ACTIVE: '.active', + BUTTON: '.btn' + }; + var Event$1 = { + CLICK_DATA_API: "click" + EVENT_KEY$1 + DATA_API_KEY$1, + FOCUS_BLUR_DATA_API: "focus" + EVENT_KEY$1 + DATA_API_KEY$1 + " " + ("blur" + EVENT_KEY$1 + DATA_API_KEY$1), + LOAD_DATA_API: "load" + EVENT_KEY$1 + DATA_API_KEY$1 + }; + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ - if (typeof this.config.offset === 'function') { - offset.fn = function (data) { - data.offsets = _objectSpread2({}, data.offsets, {}, _this4.config.offset(data.offsets, _this4.element) || {}); - return data; - }; - } else { - offset.offset = this.config.offset; - } + var Button = + /*#__PURE__*/ + function () { + function Button(element) { + this._element = element; + } // Getters - return offset; - }; - _proto._getContainer = function _getContainer() { - if (this.config.container === false) { - return document.body; - } + var _proto = Button.prototype; - if (Util.isElement(this.config.container)) { - return $(this.config.container); - } + // Public + _proto.toggle = function toggle() { + var triggerChangeEvent = true; + var addAriaPressed = true; + var rootElement = $(this._element).closest(Selector$1.DATA_TOGGLES)[0]; - return $(document).find(this.config.container); - }; + if (rootElement) { + var input = this._element.querySelector(Selector$1.INPUT); - _proto._getAttachment = function _getAttachment(placement) { - return AttachmentMap$1[placement.toUpperCase()]; - }; + if (input) { + if (input.type === 'radio') { + if (input.checked && this._element.classList.contains(ClassName$1.ACTIVE)) { + triggerChangeEvent = false; + } else { + var activeElement = rootElement.querySelector(Selector$1.ACTIVE); - _proto._setListeners = function _setListeners() { - var _this5 = this; + if (activeElement) { + $(activeElement).removeClass(ClassName$1.ACTIVE); + } + } + } else if (input.type === 'checkbox') { + if (this._element.tagName === 'LABEL' && input.checked === this._element.classList.contains(ClassName$1.ACTIVE)) { + triggerChangeEvent = false; + } + } else { + // if it's not a radio button or checkbox don't add a pointless/invalid checked property to the input + triggerChangeEvent = false; + } - var triggers = this.config.trigger.split(' '); - triggers.forEach(function (trigger) { - if (trigger === 'click') { - $(_this5.element).on(_this5.constructor.Event.CLICK, _this5.config.selector, function (event) { - return _this5.toggle(event); - }); - } else if (trigger !== Trigger.MANUAL) { - var eventIn = trigger === Trigger.HOVER ? _this5.constructor.Event.MOUSEENTER : _this5.constructor.Event.FOCUSIN; - var eventOut = trigger === Trigger.HOVER ? _this5.constructor.Event.MOUSELEAVE : _this5.constructor.Event.FOCUSOUT; - $(_this5.element).on(eventIn, _this5.config.selector, function (event) { - return _this5._enter(event); - }).on(eventOut, _this5.config.selector, function (event) { - return _this5._leave(event); - }); - } - }); + if (triggerChangeEvent) { + input.checked = !this._element.classList.contains(ClassName$1.ACTIVE); + $(input).trigger('change'); + } - this._hideModalHandler = function () { - if (_this5.element) { - _this5.hide(); + input.focus(); + addAriaPressed = false; } - }; - - $(this.element).closest('.modal').on('hide.bs.modal', this._hideModalHandler); - - if (this.config.selector) { - this.config = _objectSpread2({}, this.config, { - trigger: 'manual', - selector: '' - }); - } else { - this._fixTitle(); - } - }; - - _proto._fixTitle = function _fixTitle() { - var titleType = typeof this.element.getAttribute('data-original-title'); - - if (this.element.getAttribute('title') || titleType !== 'string') { - this.element.setAttribute('data-original-title', this.element.getAttribute('title') || ''); - this.element.setAttribute('title', ''); - } - }; - - _proto._enter = function _enter(event, context) { - var dataKey = this.constructor.DATA_KEY; - context = context || $(event.currentTarget).data(dataKey); - - if (!context) { - context = new this.constructor(event.currentTarget, this._getDelegateConfig()); - $(event.currentTarget).data(dataKey, context); - } - - if (event) { - context._activeTrigger[event.type === 'focusin' ? Trigger.FOCUS : Trigger.HOVER] = true; - } - - if ($(context.getTipElement()).hasClass(ClassName$6.SHOW) || context._hoverState === HoverState.SHOW) { - context._hoverState = HoverState.SHOW; - return; - } - - clearTimeout(context._timeout); - context._hoverState = HoverState.SHOW; - - if (!context.config.delay || !context.config.delay.show) { - context.show(); - return; } - context._timeout = setTimeout(function () { - if (context._hoverState === HoverState.SHOW) { - context.show(); + if (!(this._element.hasAttribute('disabled') || this._element.classList.contains('disabled'))) { + if (addAriaPressed) { + this._element.setAttribute('aria-pressed', !this._element.classList.contains(ClassName$1.ACTIVE)); } - }, context.config.delay.show); - }; - - _proto._leave = function _leave(event, context) { - var dataKey = this.constructor.DATA_KEY; - context = context || $(event.currentTarget).data(dataKey); - - if (!context) { - context = new this.constructor(event.currentTarget, this._getDelegateConfig()); - $(event.currentTarget).data(dataKey, context); - } - - if (event) { - context._activeTrigger[event.type === 'focusout' ? Trigger.FOCUS : Trigger.HOVER] = false; - } - if (context._isWithActiveTrigger()) { - return; + if (triggerChangeEvent) { + $(this._element).toggleClass(ClassName$1.ACTIVE); + } } + }; - clearTimeout(context._timeout); - context._hoverState = HoverState.OUT; - - if (!context.config.delay || !context.config.delay.hide) { - context.hide(); - return; - } + _proto.dispose = function dispose() { + $.removeData(this._element, DATA_KEY$1); + this._element = null; + } // Static + ; - context._timeout = setTimeout(function () { - if (context._hoverState === HoverState.OUT) { - context.hide(); - } - }, context.config.delay.hide); - }; + Button._jQueryInterface = function _jQueryInterface(config) { + return this.each(function () { + var data = $(this).data(DATA_KEY$1); - _proto._isWithActiveTrigger = function _isWithActiveTrigger() { - for (var trigger in this._activeTrigger) { - if (this._activeTrigger[trigger]) { - return true; + if (!data) { + data = new Button(this); + $(this).data(DATA_KEY$1, data); } - } - - return false; - }; - _proto._getConfig = function _getConfig(config) { - var dataAttributes = $(this.element).data(); - Object.keys(dataAttributes).forEach(function (dataAttr) { - if (DISALLOWED_ATTRIBUTES.indexOf(dataAttr) !== -1) { - delete dataAttributes[dataAttr]; + if (config === 'toggle') { + data[config](); } }); - config = _objectSpread2({}, this.constructor.Default, {}, dataAttributes, {}, typeof config === 'object' && config ? config : {}); - - if (typeof config.delay === 'number') { - config.delay = { - show: config.delay, - hide: config.delay - }; - } - - if (typeof config.title === 'number') { - config.title = config.title.toString(); - } - - if (typeof config.content === 'number') { - config.content = config.content.toString(); - } - - Util.typeCheckConfig(NAME$6, config, this.constructor.DefaultType); - - if (config.sanitize) { - config.template = sanitizeHtml(config.template, config.whiteList, config.sanitizeFn); - } - - return config; }; - _proto._getDelegateConfig = function _getDelegateConfig() { - var config = {}; - - if (this.config) { - for (var key in this.config) { - if (this.constructor.Default[key] !== this.config[key]) { - config[key] = this.config[key]; - } - } + _createClass(Button, null, [{ + key: "VERSION", + get: function get() { + return VERSION$1; } + }]); - return config; - }; - - _proto._cleanTipClass = function _cleanTipClass() { - var $tip = $(this.getTipElement()); - var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX); + return Button; + }(); + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ - if (tabClass !== null && tabClass.length) { - $tip.removeClass(tabClass.join('')); - } - }; - _proto._handlePopperPlacementChange = function _handlePopperPlacementChange(popperData) { - var popperInstance = popperData.instance; - this.tip = popperInstance.popper; + $(document).on(Event$1.CLICK_DATA_API, Selector$1.DATA_TOGGLE_CARROT, function (event) { + var button = event.target; - this._cleanTipClass(); + if (!$(button).hasClass(ClassName$1.BUTTON)) { + button = $(button).closest(Selector$1.BUTTON)[0]; + } - this.addAttachmentClass(this._getAttachment(popperData.placement)); - }; + if (!button || button.hasAttribute('disabled') || button.classList.contains('disabled')) { + event.preventDefault(); // work around Firefox bug #1540995 + } else { + var inputBtn = button.querySelector(Selector$1.INPUT); - _proto._fixTransition = function _fixTransition() { - var tip = this.getTipElement(); - var initConfigAnimation = this.config.animation; + if (inputBtn && (inputBtn.hasAttribute('disabled') || inputBtn.classList.contains('disabled'))) { + event.preventDefault(); // work around Firefox bug #1540995 - if (tip.getAttribute('x-placement') !== null) { return; } - $(tip).removeClass(ClassName$6.FADE); - this.config.animation = false; - this.hide(); - this.show(); - this.config.animation = initConfigAnimation; - } // Static - ; - - Tooltip._jQueryInterface = function _jQueryInterface(config) { - return this.each(function () { - var data = $(this).data(DATA_KEY$6); + Button._jQueryInterface.call($(button), 'toggle'); + } + }).on(Event$1.FOCUS_BLUR_DATA_API, Selector$1.DATA_TOGGLE_CARROT, function (event) { + var button = $(event.target).closest(Selector$1.BUTTON)[0]; + $(button).toggleClass(ClassName$1.FOCUS, /^focus(in)?$/.test(event.type)); + }); + $(window).on(Event$1.LOAD_DATA_API, function () { + // ensure correct active class is set to match the controls' actual values/states + // find all checkboxes/readio buttons inside data-toggle groups + var buttons = [].slice.call(document.querySelectorAll(Selector$1.DATA_TOGGLES_BUTTONS)); - var _config = typeof config === 'object' && config; + for (var i = 0, len = buttons.length; i < len; i++) { + var button = buttons[i]; + var input = button.querySelector(Selector$1.INPUT); - if (!data && /dispose|hide/.test(config)) { - return; - } + if (input.checked || input.hasAttribute('checked')) { + button.classList.add(ClassName$1.ACTIVE); + } else { + button.classList.remove(ClassName$1.ACTIVE); + } + } // find all button toggles - if (!data) { - data = new Tooltip(this, _config); - $(this).data(DATA_KEY$6, data); - } - if (typeof config === 'string') { - if (typeof data[config] === 'undefined') { - throw new TypeError("No method named \"" + config + "\""); - } + buttons = [].slice.call(document.querySelectorAll(Selector$1.DATA_TOGGLE)); - data[config](); - } - }); - }; + for (var _i = 0, _len = buttons.length; _i < _len; _i++) { + var _button = buttons[_i]; - _createClass(Tooltip, null, [{ - key: "VERSION", - get: function get() { - return VERSION$6; - } - }, { - key: "Default", - get: function get() { - return Default$4; - } - }, { - key: "NAME", - get: function get() { - return NAME$6; - } - }, { - key: "DATA_KEY", - get: function get() { - return DATA_KEY$6; - } - }, { - key: "Event", - get: function get() { - return Event$6; - } - }, { - key: "EVENT_KEY", - get: function get() { - return EVENT_KEY$6; - } - }, { - key: "DefaultType", - get: function get() { - return DefaultType$4; + if (_button.getAttribute('aria-pressed') === 'true') { + _button.classList.add(ClassName$1.ACTIVE); + } else { + _button.classList.remove(ClassName$1.ACTIVE); } - }]); - - return Tooltip; - }(); + } + }); /** * ------------------------------------------------------------------------ * jQuery * ------------------------------------------------------------------------ */ + $.fn[NAME$1] = Button._jQueryInterface; + $.fn[NAME$1].Constructor = Button; - $.fn[NAME$6] = Tooltip._jQueryInterface; - $.fn[NAME$6].Constructor = Tooltip; - - $.fn[NAME$6].noConflict = function () { - $.fn[NAME$6] = JQUERY_NO_CONFLICT$6; - return Tooltip._jQueryInterface; + $.fn[NAME$1].noConflict = function () { + $.fn[NAME$1] = JQUERY_NO_CONFLICT$1; + return Button._jQueryInterface; }; /** @@ -6592,44 +8981,80 @@ function fromByteArray (uint8) { * ------------------------------------------------------------------------ */ - var NAME$7 = 'popover'; - var VERSION$7 = '4.4.1'; - var DATA_KEY$7 = 'bs.popover'; - var EVENT_KEY$7 = "." + DATA_KEY$7; - var JQUERY_NO_CONFLICT$7 = $.fn[NAME$7]; - var CLASS_PREFIX$1 = 'bs-popover'; - var BSCLS_PREFIX_REGEX$1 = new RegExp("(^|\\s)" + CLASS_PREFIX$1 + "\\S+", 'g'); + var NAME$2 = 'carousel'; + var VERSION$2 = '4.4.1'; + var DATA_KEY$2 = 'bs.carousel'; + var EVENT_KEY$2 = "." + DATA_KEY$2; + var DATA_API_KEY$2 = '.data-api'; + var JQUERY_NO_CONFLICT$2 = $.fn[NAME$2]; + var ARROW_LEFT_KEYCODE = 37; // KeyboardEvent.which value for left arrow key - var Default$5 = _objectSpread2({}, Tooltip.Default, { - placement: 'right', - trigger: 'click', - content: '', - template: '' - }); + var ARROW_RIGHT_KEYCODE = 39; // KeyboardEvent.which value for right arrow key - var DefaultType$5 = _objectSpread2({}, Tooltip.DefaultType, { - content: '(string|element|function)' - }); + var TOUCHEVENT_COMPAT_WAIT = 500; // Time for mouse compat events to fire after touch - var ClassName$7 = { - FADE: 'fade', - SHOW: 'show' + var SWIPE_THRESHOLD = 40; + var Default = { + interval: 5000, + keyboard: true, + slide: false, + pause: 'hover', + wrap: true, + touch: true }; - var Selector$7 = { - TITLE: '.popover-header', - CONTENT: '.popover-body' + var DefaultType = { + interval: '(number|boolean)', + keyboard: 'boolean', + slide: '(boolean|string)', + pause: '(string|boolean)', + wrap: 'boolean', + touch: 'boolean' }; - var Event$7 = { - HIDE: "hide" + EVENT_KEY$7, - HIDDEN: "hidden" + EVENT_KEY$7, - SHOW: "show" + EVENT_KEY$7, - SHOWN: "shown" + EVENT_KEY$7, - INSERTED: "inserted" + EVENT_KEY$7, - CLICK: "click" + EVENT_KEY$7, - FOCUSIN: "focusin" + EVENT_KEY$7, - FOCUSOUT: "focusout" + EVENT_KEY$7, - MOUSEENTER: "mouseenter" + EVENT_KEY$7, - MOUSELEAVE: "mouseleave" + EVENT_KEY$7 + var Direction = { + NEXT: 'next', + PREV: 'prev', + LEFT: 'left', + RIGHT: 'right' + }; + var Event$2 = { + SLIDE: "slide" + EVENT_KEY$2, + SLID: "slid" + EVENT_KEY$2, + KEYDOWN: "keydown" + EVENT_KEY$2, + MOUSEENTER: "mouseenter" + EVENT_KEY$2, + MOUSELEAVE: "mouseleave" + EVENT_KEY$2, + TOUCHSTART: "touchstart" + EVENT_KEY$2, + TOUCHMOVE: "touchmove" + EVENT_KEY$2, + TOUCHEND: "touchend" + EVENT_KEY$2, + POINTERDOWN: "pointerdown" + EVENT_KEY$2, + POINTERUP: "pointerup" + EVENT_KEY$2, + DRAG_START: "dragstart" + EVENT_KEY$2, + LOAD_DATA_API: "load" + EVENT_KEY$2 + DATA_API_KEY$2, + CLICK_DATA_API: "click" + EVENT_KEY$2 + DATA_API_KEY$2 + }; + var ClassName$2 = { + CAROUSEL: 'carousel', + ACTIVE: 'active', + SLIDE: 'slide', + RIGHT: 'carousel-item-right', + LEFT: 'carousel-item-left', + NEXT: 'carousel-item-next', + PREV: 'carousel-item-prev', + ITEM: 'carousel-item', + POINTER_EVENT: 'pointer-event' + }; + var Selector$2 = { + ACTIVE: '.active', + ACTIVE_ITEM: '.active.carousel-item', + ITEM: '.carousel-item', + ITEM_IMG: '.carousel-item img', + NEXT_PREV: '.carousel-item-next, .carousel-item-prev', + INDICATORS: '.carousel-indicators', + DATA_SLIDE: '[data-slide], [data-slide-to]', + DATA_RIDE: '[data-ride="carousel"]' + }; + var PointerType = { + TOUCH: 'touch', + PEN: 'pen' }; /** * ------------------------------------------------------------------------ @@ -6637,415 +9062,485 @@ function fromByteArray (uint8) { * ------------------------------------------------------------------------ */ - var Popover = + var Carousel = /*#__PURE__*/ - function (_Tooltip) { - _inheritsLoose(Popover, _Tooltip); + function () { + function Carousel(element, config) { + this._items = null; + this._interval = null; + this._activeElement = null; + this._isPaused = false; + this._isSliding = false; + this.touchTimeout = null; + this.touchStartX = 0; + this.touchDeltaX = 0; + this._config = this._getConfig(config); + this._element = element; + this._indicatorsElement = this._element.querySelector(Selector$2.INDICATORS); + this._touchSupported = 'ontouchstart' in document.documentElement || navigator.maxTouchPoints > 0; + this._pointerEvent = Boolean(window.PointerEvent || window.MSPointerEvent); - function Popover() { - return _Tooltip.apply(this, arguments) || this; - } + this._addEventListeners(); + } // Getters - var _proto = Popover.prototype; - // Overrides - _proto.isWithContent = function isWithContent() { - return this.getTitle() || this._getContent(); - }; + var _proto = Carousel.prototype; - _proto.addAttachmentClass = function addAttachmentClass(attachment) { - $(this.getTipElement()).addClass(CLASS_PREFIX$1 + "-" + attachment); + // Public + _proto.next = function next() { + if (!this._isSliding) { + this._slide(Direction.NEXT); + } }; - _proto.getTipElement = function getTipElement() { - this.tip = this.tip || $(this.config.template)[0]; - return this.tip; + _proto.nextWhenVisible = function nextWhenVisible() { + // Don't call next when the page isn't visible + // or the carousel or its parent isn't visible + if (!document.hidden && $(this._element).is(':visible') && $(this._element).css('visibility') !== 'hidden') { + this.next(); + } }; - _proto.setContent = function setContent() { - var $tip = $(this.getTipElement()); // We use append for html objects to maintain js events - - this.setElementContent($tip.find(Selector$7.TITLE), this.getTitle()); - - var content = this._getContent(); - - if (typeof content === 'function') { - content = content.call(this.element); + _proto.prev = function prev() { + if (!this._isSliding) { + this._slide(Direction.PREV); } - - this.setElementContent($tip.find(Selector$7.CONTENT), content); - $tip.removeClass(ClassName$7.FADE + " " + ClassName$7.SHOW); - } // Private - ; - - _proto._getContent = function _getContent() { - return this.element.getAttribute('data-content') || this.config.content; }; - _proto._cleanTipClass = function _cleanTipClass() { - var $tip = $(this.getTipElement()); - var tabClass = $tip.attr('class').match(BSCLS_PREFIX_REGEX$1); - - if (tabClass !== null && tabClass.length > 0) { - $tip.removeClass(tabClass.join('')); + _proto.pause = function pause(event) { + if (!event) { + this._isPaused = true; } - } // Static - ; - - Popover._jQueryInterface = function _jQueryInterface(config) { - return this.each(function () { - var data = $(this).data(DATA_KEY$7); - var _config = typeof config === 'object' ? config : null; - - if (!data && /dispose|hide/.test(config)) { - return; - } - - if (!data) { - data = new Popover(this, _config); - $(this).data(DATA_KEY$7, data); - } - - if (typeof config === 'string') { - if (typeof data[config] === 'undefined') { - throw new TypeError("No method named \"" + config + "\""); - } + if (this._element.querySelector(Selector$2.NEXT_PREV)) { + Util.triggerTransitionEnd(this._element); + this.cycle(true); + } - data[config](); - } - }); + clearInterval(this._interval); + this._interval = null; }; - _createClass(Popover, null, [{ - key: "VERSION", - // Getters - get: function get() { - return VERSION$7; - } - }, { - key: "Default", - get: function get() { - return Default$5; - } - }, { - key: "NAME", - get: function get() { - return NAME$7; - } - }, { - key: "DATA_KEY", - get: function get() { - return DATA_KEY$7; - } - }, { - key: "Event", - get: function get() { - return Event$7; - } - }, { - key: "EVENT_KEY", - get: function get() { - return EVENT_KEY$7; - } - }, { - key: "DefaultType", - get: function get() { - return DefaultType$5; + _proto.cycle = function cycle(event) { + if (!event) { + this._isPaused = false; } - }]); - - return Popover; - }(Tooltip); - /** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - */ - - - $.fn[NAME$7] = Popover._jQueryInterface; - $.fn[NAME$7].Constructor = Popover; - - $.fn[NAME$7].noConflict = function () { - $.fn[NAME$7] = JQUERY_NO_CONFLICT$7; - return Popover._jQueryInterface; - }; - /** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ + if (this._interval) { + clearInterval(this._interval); + this._interval = null; + } - var NAME$8 = 'scrollspy'; - var VERSION$8 = '4.4.1'; - var DATA_KEY$8 = 'bs.scrollspy'; - var EVENT_KEY$8 = "." + DATA_KEY$8; - var DATA_API_KEY$6 = '.data-api'; - var JQUERY_NO_CONFLICT$8 = $.fn[NAME$8]; - var Default$6 = { - offset: 10, - method: 'auto', - target: '' - }; - var DefaultType$6 = { - offset: 'number', - method: 'string', - target: '(string|element)' - }; - var Event$8 = { - ACTIVATE: "activate" + EVENT_KEY$8, - SCROLL: "scroll" + EVENT_KEY$8, - LOAD_DATA_API: "load" + EVENT_KEY$8 + DATA_API_KEY$6 - }; - var ClassName$8 = { - DROPDOWN_ITEM: 'dropdown-item', - DROPDOWN_MENU: 'dropdown-menu', - ACTIVE: 'active' - }; - var Selector$8 = { - DATA_SPY: '[data-spy="scroll"]', - ACTIVE: '.active', - NAV_LIST_GROUP: '.nav, .list-group', - NAV_LINKS: '.nav-link', - NAV_ITEMS: '.nav-item', - LIST_ITEMS: '.list-group-item', - DROPDOWN: '.dropdown', - DROPDOWN_ITEMS: '.dropdown-item', - DROPDOWN_TOGGLE: '.dropdown-toggle' - }; - var OffsetMethod = { - OFFSET: 'offset', - POSITION: 'position' - }; - /** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ + if (this._config.interval && !this._isPaused) { + this._interval = setInterval((document.visibilityState ? this.nextWhenVisible : this.next).bind(this), this._config.interval); + } + }; - var ScrollSpy = - /*#__PURE__*/ - function () { - function ScrollSpy(element, config) { + _proto.to = function to(index) { var _this = this; - this._element = element; - this._scrollElement = element.tagName === 'BODY' ? window : element; - this._config = this._getConfig(config); - this._selector = this._config.target + " " + Selector$8.NAV_LINKS + "," + (this._config.target + " " + Selector$8.LIST_ITEMS + ",") + (this._config.target + " " + Selector$8.DROPDOWN_ITEMS); - this._offsets = []; - this._targets = []; - this._activeTarget = null; - this._scrollHeight = 0; - $(this._scrollElement).on(Event$8.SCROLL, function (event) { - return _this._process(event); - }); - this.refresh(); - - this._process(); - } // Getters - - - var _proto = ScrollSpy.prototype; - - // Public - _proto.refresh = function refresh() { - var _this2 = this; + this._activeElement = this._element.querySelector(Selector$2.ACTIVE_ITEM); - var autoMethod = this._scrollElement === this._scrollElement.window ? OffsetMethod.OFFSET : OffsetMethod.POSITION; - var offsetMethod = this._config.method === 'auto' ? autoMethod : this._config.method; - var offsetBase = offsetMethod === OffsetMethod.POSITION ? this._getScrollTop() : 0; - this._offsets = []; - this._targets = []; - this._scrollHeight = this._getScrollHeight(); - var targets = [].slice.call(document.querySelectorAll(this._selector)); - targets.map(function (element) { - var target; - var targetSelector = Util.getSelectorFromElement(element); + var activeIndex = this._getItemIndex(this._activeElement); - if (targetSelector) { - target = document.querySelector(targetSelector); - } + if (index > this._items.length - 1 || index < 0) { + return; + } - if (target) { - var targetBCR = target.getBoundingClientRect(); + if (this._isSliding) { + $(this._element).one(Event$2.SLID, function () { + return _this.to(index); + }); + return; + } - if (targetBCR.width || targetBCR.height) { - // TODO (fat): remove sketch reliance on jQuery position/offset - return [$(target)[offsetMethod]().top + offsetBase, targetSelector]; - } - } + if (activeIndex === index) { + this.pause(); + this.cycle(); + return; + } - return null; - }).filter(function (item) { - return item; - }).sort(function (a, b) { - return a[0] - b[0]; - }).forEach(function (item) { - _this2._offsets.push(item[0]); + var direction = index > activeIndex ? Direction.NEXT : Direction.PREV; - _this2._targets.push(item[1]); - }); + this._slide(direction, this._items[index]); }; _proto.dispose = function dispose() { - $.removeData(this._element, DATA_KEY$8); - $(this._scrollElement).off(EVENT_KEY$8); - this._element = null; - this._scrollElement = null; + $(this._element).off(EVENT_KEY$2); + $.removeData(this._element, DATA_KEY$2); + this._items = null; this._config = null; - this._selector = null; - this._offsets = null; - this._targets = null; - this._activeTarget = null; - this._scrollHeight = null; + this._element = null; + this._interval = null; + this._isPaused = null; + this._isSliding = null; + this._activeElement = null; + this._indicatorsElement = null; } // Private ; _proto._getConfig = function _getConfig(config) { - config = _objectSpread2({}, Default$6, {}, typeof config === 'object' && config ? config : {}); - - if (typeof config.target !== 'string') { - var id = $(config.target).attr('id'); - - if (!id) { - id = Util.getUID(NAME$8); - $(config.target).attr('id', id); - } - - config.target = "#" + id; - } - - Util.typeCheckConfig(NAME$8, config, DefaultType$6); + config = _objectSpread2({}, Default, {}, config); + Util.typeCheckConfig(NAME$2, config, DefaultType); return config; }; - _proto._getScrollTop = function _getScrollTop() { - return this._scrollElement === window ? this._scrollElement.pageYOffset : this._scrollElement.scrollTop; - }; - - _proto._getScrollHeight = function _getScrollHeight() { - return this._scrollElement.scrollHeight || Math.max(document.body.scrollHeight, document.documentElement.scrollHeight); - }; + _proto._handleSwipe = function _handleSwipe() { + var absDeltax = Math.abs(this.touchDeltaX); - _proto._getOffsetHeight = function _getOffsetHeight() { - return this._scrollElement === window ? window.innerHeight : this._scrollElement.getBoundingClientRect().height; - }; + if (absDeltax <= SWIPE_THRESHOLD) { + return; + } - _proto._process = function _process() { - var scrollTop = this._getScrollTop() + this._config.offset; + var direction = absDeltax / this.touchDeltaX; + this.touchDeltaX = 0; // swipe left - var scrollHeight = this._getScrollHeight(); + if (direction > 0) { + this.prev(); + } // swipe right - var maxScroll = this._config.offset + scrollHeight - this._getOffsetHeight(); - if (this._scrollHeight !== scrollHeight) { - this.refresh(); + if (direction < 0) { + this.next(); } + }; - if (scrollTop >= maxScroll) { - var target = this._targets[this._targets.length - 1]; + _proto._addEventListeners = function _addEventListeners() { + var _this2 = this; - if (this._activeTarget !== target) { - this._activate(target); - } + if (this._config.keyboard) { + $(this._element).on(Event$2.KEYDOWN, function (event) { + return _this2._keydown(event); + }); + } - return; + if (this._config.pause === 'hover') { + $(this._element).on(Event$2.MOUSEENTER, function (event) { + return _this2.pause(event); + }).on(Event$2.MOUSELEAVE, function (event) { + return _this2.cycle(event); + }); } - if (this._activeTarget && scrollTop < this._offsets[0] && this._offsets[0] > 0) { - this._activeTarget = null; + if (this._config.touch) { + this._addTouchEventListeners(); + } + }; - this._clear(); + _proto._addTouchEventListeners = function _addTouchEventListeners() { + var _this3 = this; + if (!this._touchSupported) { return; } - var offsetLength = this._offsets.length; - - for (var i = offsetLength; i--;) { - var isActiveTarget = this._activeTarget !== this._targets[i] && scrollTop >= this._offsets[i] && (typeof this._offsets[i + 1] === 'undefined' || scrollTop < this._offsets[i + 1]); + var start = function start(event) { + if (_this3._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) { + _this3.touchStartX = event.originalEvent.clientX; + } else if (!_this3._pointerEvent) { + _this3.touchStartX = event.originalEvent.touches[0].clientX; + } + }; - if (isActiveTarget) { - this._activate(this._targets[i]); + var move = function move(event) { + // ensure swiping with one touch and not pinching + if (event.originalEvent.touches && event.originalEvent.touches.length > 1) { + _this3.touchDeltaX = 0; + } else { + _this3.touchDeltaX = event.originalEvent.touches[0].clientX - _this3.touchStartX; } - } - }; + }; - _proto._activate = function _activate(target) { - this._activeTarget = target; + var end = function end(event) { + if (_this3._pointerEvent && PointerType[event.originalEvent.pointerType.toUpperCase()]) { + _this3.touchDeltaX = event.originalEvent.clientX - _this3.touchStartX; + } - this._clear(); + _this3._handleSwipe(); - var queries = this._selector.split(',').map(function (selector) { - return selector + "[data-target=\"" + target + "\"]," + selector + "[href=\"" + target + "\"]"; + if (_this3._config.pause === 'hover') { + // If it's a touch-enabled device, mouseenter/leave are fired as + // part of the mouse compatibility events on first tap - the carousel + // would stop cycling until user tapped out of it; + // here, we listen for touchend, explicitly pause the carousel + // (as if it's the second time we tap on it, mouseenter compat event + // is NOT fired) and after a timeout (to allow for mouse compatibility + // events to fire) we explicitly restart cycling + _this3.pause(); + + if (_this3.touchTimeout) { + clearTimeout(_this3.touchTimeout); + } + + _this3.touchTimeout = setTimeout(function (event) { + return _this3.cycle(event); + }, TOUCHEVENT_COMPAT_WAIT + _this3._config.interval); + } + }; + + $(this._element.querySelectorAll(Selector$2.ITEM_IMG)).on(Event$2.DRAG_START, function (e) { + return e.preventDefault(); }); - var $link = $([].slice.call(document.querySelectorAll(queries.join(',')))); + if (this._pointerEvent) { + $(this._element).on(Event$2.POINTERDOWN, function (event) { + return start(event); + }); + $(this._element).on(Event$2.POINTERUP, function (event) { + return end(event); + }); - if ($link.hasClass(ClassName$8.DROPDOWN_ITEM)) { - $link.closest(Selector$8.DROPDOWN).find(Selector$8.DROPDOWN_TOGGLE).addClass(ClassName$8.ACTIVE); - $link.addClass(ClassName$8.ACTIVE); + this._element.classList.add(ClassName$2.POINTER_EVENT); } else { - // Set triggered link as active - $link.addClass(ClassName$8.ACTIVE); // Set triggered links parents as active - // With both