From 46a555a038609b57b0cf405942fcf6f0a5bae675 Mon Sep 17 00:00:00 2001 From: Simon Vieille Date: Sun, 17 Apr 2022 16:38:18 +0200 Subject: [PATCH] add calendar in dashboard --- assets/js/admin.js | 110 +-------------- assets/js/components/Calendar.vue | 150 +++++++++++++++++++++ assets/js/components/Week.vue | 95 +++++++++++++ assets/js/modules/address.js | 84 ++++++++++++ assets/js/modules/calendar.js | 17 +++ assets/js/modules/collection-sorter.js | 26 ++++ package.json | 4 +- src/Controller/CalendarAdminController.php | 123 +++++++++++++++++ src/Controller/ProjectAdminController.php | 2 +- src/Controller/SpeakerAdminController.php | 2 +- src/Entity/Event.php | 48 ++++--- src/Entity/Project.php | 19 +-- src/Entity/Speaker.php | 17 +++ src/Form/SpeakerType.php | 12 ++ src/Repository/EventRepositoryQuery.php | 52 ++++++- src/Repository/ProjectRepositoryQuery.php | 12 ++ src/Repository/SpeakerRepositoryQuery.php | 12 ++ templates/core/dashboard/index.html.twig | 10 +- yarn.lock | 46 ++----- 19 files changed, 659 insertions(+), 182 deletions(-) create mode 100644 assets/js/components/Calendar.vue create mode 100644 assets/js/components/Week.vue create mode 100644 assets/js/modules/address.js create mode 100644 assets/js/modules/calendar.js create mode 100644 assets/js/modules/collection-sorter.js create mode 100644 src/Controller/CalendarAdminController.php diff --git a/assets/js/admin.js b/assets/js/admin.js index 4b2fbca..1ae07eb 100644 --- a/assets/js/admin.js +++ b/assets/js/admin.js @@ -1,111 +1,9 @@ import '../../vendor/murph/murph-core/src/core/Resources/assets/js/admin.js' -const Sortable = require('sortablejs').Sortable -const Routing = require('../../vendor/friendsofsymfony/jsrouting-bundle/Resources/public/js/router.min.js') -const routes = require('../../public/js/fos_js_routes.json') - -Routing.setRoutingData(routes) - -class AddressAutocomplete { - constructor () { - this.fields = { - address: document.querySelector('#establishment_address'), - zipCode: document.querySelector('#establishment_zipCode'), - city: document.querySelector('#establishment_city') - } - - this.results = [] - this.timer = null - - if (!this.fields.address) { - return - } - - const that = this - - this.fields.address.addEventListener('keyup', () => { - if (that.timer) { - clearTimeout(that.timer) - } - - that.timer = setTimeout(() => { - const query = that.fields.address.value - - fetch(Routing.generate('admin_establishment_address', { - q: query - })) - .then(response => response.json()) - .then((data) => { - that.results = data.features - that.renderResults() - }) - }, 500) - }) - } - - renderResults () { - const address = this.fields.address - const that = this - - let wrapper = address.nextSibling - - if (wrapper) { - wrapper.remove() - } - - if (this.results.length === 0) { - return - } - - wrapper = document.createElement('div') - wrapper.classList.add('list-group', 'mt-1', 'mb-1') - - for (const address of this.results) { - const item = document.createElement('div') - item.classList.add('list-group-item', 'btn', 'text-left') - item.textContent = address.properties.label - - item.setAttribute('data-name', address.properties.name) - item.setAttribute('data-zipCode', address.properties.postcode) - item.setAttribute('data-city', address.properties.city) - - item.addEventListener('click', (e) => { - that.fields.address.value = e.target.getAttribute('data-name') - that.fields.zipCode.value = e.target.getAttribute('data-zipCode') - that.fields.city.value = e.target.getAttribute('data-city') - - wrapper.remove() - }) - - wrapper.appendChild(item) - } - - address.parentNode.appendChild(wrapper) - } -} - -class FilesCollectionSorter { - constructor () { - const collections = document.querySelectorAll('div[data-collection^="collection-files"]') - - for (const collection of collections) { - return new Sortable(collection, { - handle: '*[data-collection-item]', - sort: true, - animation: 150, - fallbackTolerance: 3, - onEnd: (e) => { - const positions = collection.querySelectorAll('*[data-collection-item] input[type=hidden]') - console.log(positions); - - for (let u = 0; u < positions.length; u++) { - positions[u].value = u - } - } - }) - } - } -} +const AddressAutocomplete = require('./modules/address.js') +const FilesCollectionSorter = require('./modules/collection-sorter.js') +const Calendar = require('./modules/calendar.js') new AddressAutocomplete() new FilesCollectionSorter() +new Calendar() diff --git a/assets/js/components/Calendar.vue b/assets/js/components/Calendar.vue new file mode 100644 index 0000000..32160eb --- /dev/null +++ b/assets/js/components/Calendar.vue @@ -0,0 +1,150 @@ + + + + + diff --git a/assets/js/components/Week.vue b/assets/js/components/Week.vue new file mode 100644 index 0000000..56c3d16 --- /dev/null +++ b/assets/js/components/Week.vue @@ -0,0 +1,95 @@ + + + + + diff --git a/assets/js/modules/address.js b/assets/js/modules/address.js new file mode 100644 index 0000000..9c8e9bd --- /dev/null +++ b/assets/js/modules/address.js @@ -0,0 +1,84 @@ +const Routing = require('../../../vendor/friendsofsymfony/jsrouting-bundle/Resources/public/js/router.min.js') +const routes = require('../../../public/js/fos_js_routes.json') + +Routing.setRoutingData(routes) + +class AddressAutocomplete { + constructor () { + this.fields = { + address: document.querySelector('#establishment_address'), + zipCode: document.querySelector('#establishment_zipCode'), + city: document.querySelector('#establishment_city') + } + + this.results = [] + this.timer = null + + if (!this.fields.address) { + return + } + + const that = this + + this.fields.address.addEventListener('keyup', () => { + if (that.timer) { + clearTimeout(that.timer) + } + + that.timer = setTimeout(() => { + const query = that.fields.address.value + + fetch(Routing.generate('admin_establishment_address', { + q: query + })) + .then(response => response.json()) + .then((data) => { + that.results = data.features + that.renderResults() + }) + }, 500) + }) + } + + renderResults () { + const address = this.fields.address + const that = this + + let wrapper = address.nextSibling + + if (wrapper) { + wrapper.remove() + } + + if (this.results.length === 0) { + return + } + + wrapper = document.createElement('div') + wrapper.classList.add('list-group', 'mt-1', 'mb-1') + + for (const address of this.results) { + const item = document.createElement('div') + item.classList.add('list-group-item', 'btn', 'text-left') + item.textContent = address.properties.label + + item.setAttribute('data-name', address.properties.name) + item.setAttribute('data-zipCode', address.properties.postcode) + item.setAttribute('data-city', address.properties.city) + + item.addEventListener('click', (e) => { + that.fields.address.value = e.target.getAttribute('data-name') + that.fields.zipCode.value = e.target.getAttribute('data-zipCode') + that.fields.city.value = e.target.getAttribute('data-city') + + wrapper.remove() + }) + + wrapper.appendChild(item) + } + + address.parentNode.appendChild(wrapper) + } +} + +module.exports = AddressAutocomplete diff --git a/assets/js/modules/calendar.js b/assets/js/modules/calendar.js new file mode 100644 index 0000000..7922d86 --- /dev/null +++ b/assets/js/modules/calendar.js @@ -0,0 +1,17 @@ +const Vue = require('vue').default + +const Calendar = require('../components/Calendar').default + +module.exports = () => { + if (!document.getElementById('calendar')) { + return + } + + return new Vue({ + el: '#calendar', + template: '', + components: { + Calendar + } + }) +} diff --git a/assets/js/modules/collection-sorter.js b/assets/js/modules/collection-sorter.js new file mode 100644 index 0000000..13a74bb --- /dev/null +++ b/assets/js/modules/collection-sorter.js @@ -0,0 +1,26 @@ +const Sortable = require('sortablejs').Sortable + +class FilesCollectionSorter { + constructor () { + const collections = document.querySelectorAll('div[data-collection^="collection-files"]') + + for (const collection of collections) { + return new Sortable(collection, { + handle: '*[data-collection-item]', + sort: true, + animation: 150, + fallbackTolerance: 3, + onEnd: (e) => { + const positions = collection.querySelectorAll('*[data-collection-item] input[type=hidden]') + console.log(positions) + + for (let u = 0; u < positions.length; u++) { + positions[u].value = u + } + } + }) + } + } +} + +module.exports = FilesCollectionSorter diff --git a/package.json b/package.json index 7802611..806bc53 100644 --- a/package.json +++ b/package.json @@ -8,6 +8,8 @@ "build": "encore production --progress" }, "dependencies": { - "murph-project": "^1" + "chunk": "^0.0.3", + "murph-project": "^1", + "vue-fragment": "^1.5.2" } } diff --git a/src/Controller/CalendarAdminController.php b/src/Controller/CalendarAdminController.php new file mode 100644 index 0000000..422357d --- /dev/null +++ b/src/Controller/CalendarAdminController.php @@ -0,0 +1,123 @@ + true])] + public function month( + Request $request, + SpeakerRepositoryQuery $speakerQuery, + ProjectRepositoryQuery $projectQuery, + EventRepositoryQuery $eventQuery + ): Response { + $projects = $projectQuery->create()->withIds($request->query->get('projects'))->find(); + $speakers = $speakerQuery->create()->withIds($request->query->get('speakers'))->find(); + + $month = $request->query->get('month', date('m')); + $year = $request->query->get('year', date('Y')); + + $dateFrom = new \DateTime(sprintf('%d-%d-1', $year, $month)); + + $currentMonthFirstDayOfWeek = $dateFrom->format('N'); + $nextMonthFirstDayOfWeek = date('N', $dateFrom->getTimestamp() + 3600 * 24 * $dateFrom->format('t')); + $currentMonthDays = $dateFrom->format('t'); + $prevMonthDays = date('t', $dateFrom->getTimestamp() - 3600); + + $days = []; + + if ($currentMonthFirstDayOfWeek > 1) { + for ($day = $prevMonthDays - $currentMonthFirstDayOfWeek + 2; $day <= $prevMonthDays; ++$day) { + $days[] = [ + 'day' => $day, + 'currentMonth' => false, + 'events' => [], + ]; + } + } + + for ($day = 1; $day <= $currentMonthDays; ++$day) { + $events = $eventQuery->create() + ->ofProjects($projects) + ->ofSpeakers($speakers) + ->ofMonth($month) + ->ofYear($year) + ->ofDay($day) + ->find() + ; + + $events = array_map(function ($event) { + return [ + 'uid' => $event->getUid(), + 'summary' => $event->getSummary(), + 'description' => $event->getCleanedDescription(), + 'startAt' => $event->getStartAt() ? $event->getStartAt()->format('H:i') : null, + 'finishAt' => $event->getFinishAt() ? $event->getFinishAt()->format('H:i') : null, + 'projects' => array_map(fn ($i) => [ + 'id' => $i->getId(), + 'label' => $i->getLabel() + ], $event->getProjects()->toArray()), + 'speakers' => array_map(fn ($i) => [ + 'id' => $i->getId(), + 'name' => $i->getName(), + 'color' => $i->getColor(), + ], $event->getSpeakers()->toArray()), + ]; + }, $events); + + $days[] = [ + 'day' => $day, + 'currentMonth' => true, + 'events' => $events, + ]; + } + + if ($nextMonthFirstDayOfWeek > 1) { + $day = 0; + + for ($u = $nextMonthFirstDayOfWeek; $u <= 7; ++$u) { + $days[] = [ + 'day' => ++$day, + 'currentMonth' => false, + 'events' => [], + ]; + } + } + + return $this->json($days); + } + + #[Route('/admin/calendar/projects', name: 'admin_calendar_projects', options: ['expose' => true])] + public function projects(ProjectRepositoryQuery $query): Response + { + $entities = array_map(function ($entity) { + return [ + 'id' => $entity->getId(), + 'label' => $entity->getLabel(), + ]; + }, $query->create()->orderBy('.label')->find()); + + return $this->json($entities); + } + + #[Route('/admin/calendar/speakers', name: 'admin_calendar_speakers', options: ['expose' => true])] + public function speakers(SpeakerRepositoryQuery $query): Response + { + $entities = array_map(function ($entity) { + return [ + 'id' => $entity->getId(), + 'name' => $entity->getName(), + ]; + }, $query->create()->orderBy('.name')->find()); + + return $this->json($entities); + } +} diff --git a/src/Controller/ProjectAdminController.php b/src/Controller/ProjectAdminController.php index 3abd95a..50719dd 100644 --- a/src/Controller/ProjectAdminController.php +++ b/src/Controller/ProjectAdminController.php @@ -35,7 +35,7 @@ class ProjectAdminController extends CrudController } /** - * @Route("/admin/project/show/{entity}", name="admin_project_show", methods={"GET"}) + * @Route("/admin/project/show/{entity}", name="admin_project_show", methods={"GET"}, options={"expose":true}) */ public function show(Entity $entity): Response { diff --git a/src/Controller/SpeakerAdminController.php b/src/Controller/SpeakerAdminController.php index 195a874..ae502d9 100644 --- a/src/Controller/SpeakerAdminController.php +++ b/src/Controller/SpeakerAdminController.php @@ -38,7 +38,7 @@ class SpeakerAdminController extends CrudController } /** - * @Route("/admin/speaker/show/{entity}", name="admin_speaker_show", methods={"GET"}) + * @Route("/admin/speaker/show/{entity}", name="admin_speaker_show", methods={"GET"}, options={"expose":true}) */ public function show(Entity $entity): Response { diff --git a/src/Entity/Event.php b/src/Entity/Event.php index 00290df..6af172e 100644 --- a/src/Entity/Event.php +++ b/src/Entity/Event.php @@ -45,20 +45,20 @@ class Event implements EntityInterface */ protected $finishAt; - /** - * @ORM\ManyToOne(targetEntity=Project::class, inversedBy="events", cascade={"persist", "remove"}) - * @ORM\JoinColumn(nullable=false) - */ - protected $projects; - /** * @ORM\ManyToMany(targetEntity=Speaker::class, inversedBy="events") */ private $speakers; + /** + * @ORM\ManyToMany(targetEntity=Project::class, inversedBy="events") + */ + private $projects; + public function __construct() { $this->speakers = new ArrayCollection(); + $this->projects = new ArrayCollection(); } public function getId(): ?int @@ -131,18 +131,6 @@ class Event implements EntityInterface return $this; } - public function getProjects(): ?Project - { - return $this->projects; - } - - public function setProjects(?Project $projects): self - { - $this->projects = $projects; - - return $this; - } - /** * @return Collection */ @@ -166,4 +154,28 @@ class Event implements EntityInterface return $this; } + + /** + * @return Collection + */ + public function getProjects(): Collection + { + return $this->projects; + } + + public function addProject(Project $project): self + { + if (!$this->projects->contains($project)) { + $this->projects[] = $project; + } + + return $this; + } + + public function removeProject(Project $project): self + { + $this->projects->removeElement($project); + + return $this; + } } diff --git a/src/Entity/Project.php b/src/Entity/Project.php index f4e265c..c0edf7e 100644 --- a/src/Entity/Project.php +++ b/src/Entity/Project.php @@ -51,9 +51,9 @@ class Project implements EntityInterface protected $debriefings; /** - * @ORM\OneToMany(targetEntity=Event::class, mappedBy="projects", cascade={"persist", "remove"}) + * @ORM\ManyToMany(targetEntity=Event::class, mappedBy="projects") */ - protected $events; + private $events; public function __construct() { @@ -185,20 +185,14 @@ class Project implements EntityInterface */ public function getEvents(): Collection { - $events = $this->events->toArray(); - - usort($events, function($a, $b) { - return $a->getStartAt() <=> $a->getFinishAt(); - }); - - return new ArrayCollection($events); + return $this->events; } public function addEvent(Event $event): self { if (!$this->events->contains($event)) { $this->events[] = $event; - $event->setProjects($this); + $event->addProject($this); } return $this; @@ -207,10 +201,7 @@ class Project implements EntityInterface public function removeEvent(Event $event): self { if ($this->events->removeElement($event)) { - // set the owning side to null (unless already changed) - if ($event->getProjects() === $this) { - $event->setProjects(null); - } + $event->removeProject($this); } return $this; diff --git a/src/Entity/Speaker.php b/src/Entity/Speaker.php index 3301b9e..5b6e52c 100644 --- a/src/Entity/Speaker.php +++ b/src/Entity/Speaker.php @@ -56,6 +56,11 @@ class Speaker implements EntityInterface, EncryptedEntityInterface */ private $events; + /** + * @ORM\Column(type="string", length=30, nullable=true) + */ + private $color; + public function __construct() { $this->interventions = new ArrayCollection(); @@ -192,4 +197,16 @@ class Speaker implements EntityInterface, EncryptedEntityInterface return $this; } + + public function getColor(): ?string + { + return $this->color; + } + + public function setColor(?string $color): self + { + $this->color = $color; + + return $this; + } } diff --git a/src/Form/SpeakerType.php b/src/Form/SpeakerType.php index 1f44901..47e24cd 100644 --- a/src/Form/SpeakerType.php +++ b/src/Form/SpeakerType.php @@ -7,6 +7,7 @@ use Symfony\Component\Form\AbstractType; use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; use Symfony\Component\Form\Extension\Core\Type\PasswordType; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; class SpeakerType extends AbstractType { @@ -14,6 +15,17 @@ class SpeakerType extends AbstractType { $builder ->add('name') + ->add('color', ChoiceType::class, [ + 'required' => true, + 'choices' => [ + 'Bleu' => 'primary', + 'Gris' => 'secondary', + 'Vert' => 'success', + 'Rouge' => 'danger', + 'Jaune' => 'warning', + 'Turquoise' => 'info', + ], + ]) ; if ($options['edit_caldav']) { diff --git a/src/Repository/EventRepositoryQuery.php b/src/Repository/EventRepositoryQuery.php index 97d7c97..fcdca7f 100644 --- a/src/Repository/EventRepositoryQuery.php +++ b/src/Repository/EventRepositoryQuery.php @@ -3,8 +3,8 @@ namespace App\Repository; use App\Core\Repository\RepositoryQuery; -use Knp\Component\Pager\PaginatorInterface; use App\Repository\EventRepository as Repository; +use Knp\Component\Pager\PaginatorInterface; class EventRepositoryQuery extends RepositoryQuery { @@ -12,4 +12,54 @@ class EventRepositoryQuery extends RepositoryQuery { parent::__construct($repository, 'e', $paginator); } + + public function ofProjects(array $projects): self + { + if (empty($projects)) { + return $this; + } + + return $this + ->innerJoin('.projects', 'p') + ->andWhere('p.id IN (:projectIds)') + ->setParameter('projectIds', array_map(fn ($i) => $i->getId(), $projects)) + ; + } + + public function ofSpeakers(array $speakers): self + { + if (empty($speakers)) { + return $this; + } + + return $this + ->innerJoin('.speakers', 's') + ->andWhere('s.id IN (:speakerIds)') + ->setParameter('speakerIds', array_map(fn ($i) => $i->getId(), $speakers)) + ; + } + + public function ofMonth(int $month): self + { + return $this + ->andWhere('.startAt LIKE :month') + ->setParameter('month', '%-'.sprintf('%02d', $month).'-% %') + ; + } + + public function ofYear(int $year): self + { + return $this + ->andWhere('.startAt LIKE :year') + ->setParameter('year', $year.'-%-% %') + ; + } + + public function ofDay(int $day): self + { + return $this + ->andWhere('.startAt LIKE :day') + ->setParameter('day', '%-%-'.sprintf('%02d', $day).' %') + ; + } } diff --git a/src/Repository/ProjectRepositoryQuery.php b/src/Repository/ProjectRepositoryQuery.php index d660755..821621b 100644 --- a/src/Repository/ProjectRepositoryQuery.php +++ b/src/Repository/ProjectRepositoryQuery.php @@ -12,4 +12,16 @@ class ProjectRepositoryQuery extends RepositoryQuery { parent::__construct($repository, 'p', $paginator); } + + public function withIds(?array $ids) + { + if (null === $ids) { + return $this; + } + + return $this + ->andWhere('.id IN (:ids)') + ->setParameter('ids', $ids) + ; + } } diff --git a/src/Repository/SpeakerRepositoryQuery.php b/src/Repository/SpeakerRepositoryQuery.php index 3c948d5..6409c53 100644 --- a/src/Repository/SpeakerRepositoryQuery.php +++ b/src/Repository/SpeakerRepositoryQuery.php @@ -13,6 +13,18 @@ class SpeakerRepositoryQuery extends RepositoryQuery parent::__construct($repository, 's', $paginator); } + public function withIds(?array $ids) + { + if (null === $ids) { + return $this; + } + + return $this + ->andWhere('.id IN (:ids)') + ->setParameter('ids', $ids) + ; + } + public function withCalendar() { return $this diff --git a/templates/core/dashboard/index.html.twig b/templates/core/dashboard/index.html.twig index 0b3d2b4..831ae52 100644 --- a/templates/core/dashboard/index.html.twig +++ b/templates/core/dashboard/index.html.twig @@ -1,12 +1,10 @@ {% extends '@Core/admin/layout.html.twig' %} {% block body %} -
-
-
-

- Tableau de bord -

+
+
+
+
diff --git a/yarn.lock b/yarn.lock index 3d8c17b..eff7db4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2246,6 +2246,11 @@ chrome-trace-event@^1.0.2: resolved "https://registry.yarnpkg.com/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz#1015eced4741e15d06664a957dbbf50d041e26ac" integrity sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg== +chunk@^0.0.3: + version "0.0.3" + resolved "https://registry.yarnpkg.com/chunk/-/chunk-0.0.3.tgz#d4f7473e35439c543d1d209464c27839e2b51d7a" + integrity sha512-oGfwvhjGRW3Ks4GTdGoJhZWKEO1eomjOC26001R+5H0TIlP7vBCO+/XcNcPCA6ayYC7RQSq1/NsN4679Odcm5A== + ci-info@^1.5.0: version "1.6.0" resolved "https://registry.yarnpkg.com/ci-info/-/ci-info-1.6.0.tgz#2ca20dbb9ceb32d4524a683303313f0304b1e497" @@ -2800,7 +2805,7 @@ debug@^4.0.1, debug@^4.1.0, debug@^4.1.1: dependencies: ms "2.1.2" -debuglog@*, debuglog@^1.0.1: +debuglog@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/debuglog/-/debuglog-1.0.1.tgz#aa24ffb9ac3df9a2351837cfb2d279360cd78492" integrity sha1-qiT/uaw9+aI1GDfPstJ5NgzXhJI= @@ -4250,7 +4255,7 @@ import-local@^3.0.2: pkg-dir "^4.2.0" resolve-cwd "^3.0.0" -imurmurhash@*, imurmurhash@^0.1.4: +imurmurhash@^0.1.4: version "0.1.4" resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" integrity sha1-khi5srkoojixPcT7a21XbyMUU+o= @@ -4966,11 +4971,6 @@ lockfile@^1.0.4: dependencies: signal-exit "^3.0.2" -lodash._baseindexof@*: - version "3.1.0" - resolved "https://registry.yarnpkg.com/lodash._baseindexof/-/lodash._baseindexof-3.1.0.tgz#fe52b53a1c6761e42618d654e4a25789ed61822c" - integrity sha1-/lK1OhxnYeQmGNZU5KJXie1hgiw= - lodash._baseuniq@~4.6.0: version "4.6.0" resolved "https://registry.yarnpkg.com/lodash._baseuniq/-/lodash._baseuniq-4.6.0.tgz#0ebb44e456814af7905c6212fa2c9b2d51b841e8" @@ -4979,33 +4979,11 @@ lodash._baseuniq@~4.6.0: lodash._createset "~4.0.0" lodash._root "~3.0.0" -lodash._bindcallback@*: - version "3.0.1" - resolved "https://registry.yarnpkg.com/lodash._bindcallback/-/lodash._bindcallback-3.0.1.tgz#e531c27644cf8b57a99e17ed95b35c748789392e" - integrity sha1-5THCdkTPi1epnhftlbNcdIeJOS4= - -lodash._cacheindexof@*: - version "3.0.2" - resolved "https://registry.yarnpkg.com/lodash._cacheindexof/-/lodash._cacheindexof-3.0.2.tgz#3dc69ac82498d2ee5e3ce56091bafd2adc7bde92" - integrity sha1-PcaayCSY0u5ePOVgkbr9Ktx73pI= - -lodash._createcache@*: - version "3.1.2" - resolved "https://registry.yarnpkg.com/lodash._createcache/-/lodash._createcache-3.1.2.tgz#56d6a064017625e79ebca6b8018e17440bdcf093" - integrity sha1-VtagZAF2JeeevKa4AY4XRAvc8JM= - dependencies: - lodash._getnative "^3.0.0" - lodash._createset@~4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/lodash._createset/-/lodash._createset-4.0.3.tgz#0f4659fbb09d75194fa9e2b88a6644d363c9fe26" integrity sha1-D0ZZ+7CddRlPqeK4imZE02PJ/iY= -lodash._getnative@*, lodash._getnative@^3.0.0: - version "3.9.1" - resolved "https://registry.yarnpkg.com/lodash._getnative/-/lodash._getnative-3.9.1.tgz#570bc7dede46d61cdcde687d65d3eecbaa3aaff5" - integrity sha1-VwvH3t5G1hzc3mh9ZdPuy6o6r/U= - lodash._root@~3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/lodash._root/-/lodash._root-3.0.1.tgz#fba1c4524c19ee9a5f8136b4609f017cf4ded692" @@ -5036,11 +5014,6 @@ lodash.merge@^4.6.2: resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== -lodash.restparam@*: - version "3.6.1" - resolved "https://registry.yarnpkg.com/lodash.restparam/-/lodash.restparam-3.6.1.tgz#936a4e309ef330a7645ed4145986c85ae5b20805" - integrity sha1-k2pOMJ7zMKdkXtQUWYbIWuWyCAU= - lodash.truncate@^4.4.2: version "4.4.2" resolved "https://registry.yarnpkg.com/lodash.truncate/-/lodash.truncate-4.4.2.tgz#5a350da0b1113b837ecfffd5812cbe58d6eae193" @@ -8024,6 +7997,11 @@ vue-eslint-parser@^7.10.0: lodash "^4.17.21" semver "^6.3.0" +vue-fragment@^1.5.2: + version "1.5.2" + resolved "https://registry.yarnpkg.com/vue-fragment/-/vue-fragment-1.5.2.tgz#310017170c564c4aad95da14c185c92c6784fd3c" + integrity sha512-KEW0gkeNOLJjtXN4jqJhTazez5jtrwimHkE5Few/VxblH4F9EcvJiEsahrV5kg5uKd5U8du4ORKS6QjGE0piYA== + vue-hot-reload-api@^2.3.0: version "2.3.4" resolved "https://registry.yarnpkg.com/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz#532955cc1eb208a3d990b3a9f9a70574657e08f2"