Merge pull request #3412 from yurikuzn/i/category
Category drag and drop
This commit is contained in:
@@ -29,15 +29,20 @@
|
||||
|
||||
namespace Espo\Core\Controllers;
|
||||
|
||||
use Espo\Core\Acl\Table;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\BadRequest;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
|
||||
use Espo\Core\Exceptions\NotFound;
|
||||
use Espo\Core\ORM\Entity;
|
||||
use Espo\Core\Templates\Entities\CategoryTree;
|
||||
use Espo\Services\RecordTree as Service;
|
||||
use Espo\Core\Api\Request;
|
||||
|
||||
use Espo\Tools\CategoryTree\Move\MoveParams;
|
||||
use Espo\Tools\CategoryTree\MoveService;
|
||||
use RuntimeException;
|
||||
use stdClass;
|
||||
|
||||
class RecordTree extends Record
|
||||
@@ -58,11 +63,6 @@ class RecordTree extends Record
|
||||
*/
|
||||
public function getActionListTree(Request $request): stdClass
|
||||
{
|
||||
if (method_exists($this, 'actionListTree')) {
|
||||
// For backward compatibility.
|
||||
return (object) $this->actionListTree($request->getRouteParams(), $request->getParsedBody(), $request);
|
||||
}
|
||||
|
||||
$selectParams = $this->fetchSearchParamsFromRequest($request);
|
||||
|
||||
$parentId = $request->getQueryParam('parentId');
|
||||
@@ -101,7 +101,7 @@ class RecordTree extends Record
|
||||
*/
|
||||
public function getActionLastChildrenIdList(Request $request): array
|
||||
{
|
||||
if (!$this->acl->check($this->name, 'read')) {
|
||||
if (!$this->acl->check($this->name, Table::ACTION_READ)) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
@@ -110,6 +110,68 @@ class RecordTree extends Record
|
||||
return $this->getRecordTreeService()->getLastChildrenIdList($parentId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Forbidden
|
||||
* @throws BadRequest
|
||||
* @throws NotFound
|
||||
* @throws Error
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
public function postActionMove(Request $request): bool
|
||||
{
|
||||
if (!$this->acl->check($this->name, Table::ACTION_EDIT)) {
|
||||
throw new Forbidden();
|
||||
}
|
||||
|
||||
$id = $request->getParsedBody()->id ?? null;
|
||||
$referenceId = $request->getParsedBody()->referenceId ?? null;
|
||||
$type = $request->getParsedBody()->type ?? null;
|
||||
|
||||
if (!is_string($id)) {
|
||||
throw new BadRequest("Bad id.");
|
||||
}
|
||||
|
||||
if (!is_string($referenceId)) {
|
||||
throw new BadRequest("Bad referenceId.");
|
||||
}
|
||||
|
||||
$typeInternal = match ($type) {
|
||||
'into' => MoveParams::TYPE_INTO,
|
||||
'before' => MoveParams::TYPE_BEFORE,
|
||||
'after' => MoveParams::TYPE_AFTER,
|
||||
default => null,
|
||||
};
|
||||
|
||||
if ($typeInternal === null) {
|
||||
throw new BadRequest("Bad type.");
|
||||
}
|
||||
|
||||
$entity = $this->getRecordService()->getEntity($id);
|
||||
|
||||
if (!$entity) {
|
||||
throw new NotFound("Record not found.");
|
||||
}
|
||||
|
||||
if (!$entity instanceof CategoryTree) {
|
||||
throw new RuntimeException("Non-tree entity.");
|
||||
}
|
||||
|
||||
if (!$this->acl->checkEntityEdit($entity)) {
|
||||
throw new Forbidden("No edit access.");
|
||||
}
|
||||
|
||||
$params = new MoveParams(
|
||||
type: $typeInternal,
|
||||
referenceId: $referenceId,
|
||||
);
|
||||
|
||||
$service = $this->injectableFactory->create(MoveService::class);
|
||||
|
||||
$service->move($entity, $params);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Service<Entity>
|
||||
*/
|
||||
@@ -117,7 +179,9 @@ class RecordTree extends Record
|
||||
{
|
||||
$service = $this->getRecordService();
|
||||
|
||||
assert($service instanceof Service);
|
||||
if (!$service instanceof Service) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
return $service;
|
||||
}
|
||||
|
||||
@@ -86,7 +86,14 @@ class DevModeJsFileListProvider
|
||||
$amdId = $item->amdId ?? null;
|
||||
|
||||
if ($amdId) {
|
||||
return 'client/lib/original/' . $amdId . '.js';
|
||||
$file = $amdId;
|
||||
|
||||
if (str_starts_with($amdId, '@')) {
|
||||
$file = substr($amdId, 1);
|
||||
$file = str_replace('/', '-', $file);
|
||||
}
|
||||
|
||||
return 'client/lib/original/' . $file . '.js';
|
||||
}
|
||||
|
||||
$src = $item->src ?? null;
|
||||
|
||||
@@ -78,7 +78,7 @@
|
||||
}
|
||||
},
|
||||
"collection": {
|
||||
"orderBy": "parent",
|
||||
"orderBy": "name",
|
||||
"order": "asc"
|
||||
},
|
||||
"additionalTables": {
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
"order": {
|
||||
"type": "int",
|
||||
"minValue": 1,
|
||||
"readOnly": true,
|
||||
"disableFormatting": true,
|
||||
"textFilterDisabled": true
|
||||
},
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"order": {
|
||||
"type": "int",
|
||||
"minValue": 1,
|
||||
"readOnly": true,
|
||||
"textFilterDisabled": true
|
||||
},
|
||||
"description": {
|
||||
|
||||
@@ -77,6 +77,9 @@
|
||||
"exportsTo": "window",
|
||||
"exportsAs": "Selectize"
|
||||
},
|
||||
"@shopify/draggable": {
|
||||
"devPath": "client/lib/original/shopify-draggable.js"
|
||||
},
|
||||
"autonumeric": {},
|
||||
"intl-tel-input": {
|
||||
"exportsTo": "window",
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
"order": {
|
||||
"type": "int",
|
||||
"minValue": 1,
|
||||
"readOnly": true,
|
||||
"textFilterDisabled": true
|
||||
},
|
||||
"description": {
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Tools\CategoryTree\Move;
|
||||
|
||||
readonly class MoveParams
|
||||
{
|
||||
public const TYPE_INTO = 0;
|
||||
public const TYPE_BEFORE = 1;
|
||||
public const TYPE_AFTER = 2;
|
||||
|
||||
public function __construct(
|
||||
public int $type,
|
||||
public ?string $referenceId = null,
|
||||
) {}
|
||||
}
|
||||
@@ -0,0 +1,234 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2025 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
|
||||
* Website: https://www.espocrm.com
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Affero General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Affero General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Affero General Public License
|
||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
*
|
||||
* The interactive user interfaces in modified source and object code versions
|
||||
* of this program must display Appropriate Legal Notices, as required under
|
||||
* Section 5 of the GNU Affero General Public License version 3.
|
||||
*
|
||||
* In accordance with Section 7(b) of the GNU Affero General Public License version 3,
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
namespace Espo\Tools\CategoryTree;
|
||||
|
||||
use Espo\Core\Acl;
|
||||
use Espo\Core\Exceptions\Error;
|
||||
use Espo\Core\Exceptions\Forbidden;
|
||||
use Espo\Core\Exceptions\NotFound;
|
||||
use Espo\Core\Templates\Entities\CategoryTree;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
use Espo\ORM\Query\Part\Expression as Expr;
|
||||
use Espo\ORM\Query\UpdateBuilder;
|
||||
use Espo\ORM\Repository\Option\SaveOption;
|
||||
use Espo\Tools\CategoryTree\Move\MoveParams;
|
||||
|
||||
class MoveService
|
||||
{
|
||||
private const ATTR_PARENT_ID = 'parentId';
|
||||
private const ATTR_ORDER = 'order';
|
||||
|
||||
public function __construct(
|
||||
private EntityManager $entityManager,
|
||||
private Acl $acl,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* @throws NotFound
|
||||
* @throws Forbidden
|
||||
* @throws Error
|
||||
*/
|
||||
public function move(CategoryTree $entity, MoveParams $params): void
|
||||
{
|
||||
$hasOrder = $entity->hasAttribute(self::ATTR_ORDER);
|
||||
|
||||
if (!$hasOrder && $params->type !== MoveParams::TYPE_INTO) {
|
||||
throw new Error("Order not supported.");
|
||||
}
|
||||
|
||||
$entityType = $entity->getEntityType();
|
||||
|
||||
$reference = null;
|
||||
|
||||
if ($params->referenceId) {
|
||||
$reference = $this->entityManager->getEntityById($entityType, $params->referenceId);
|
||||
|
||||
if (!$reference) {
|
||||
throw new NotFound("No reference record found.");
|
||||
}
|
||||
}
|
||||
|
||||
if ($params->type === MoveParams::TYPE_INTO) {
|
||||
$this->processInto($reference, $entity, $params);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$reference) {
|
||||
throw new Error("No reference.");
|
||||
}
|
||||
|
||||
$parentId = $reference->get(self::ATTR_PARENT_ID);
|
||||
|
||||
if ($parentId !== $entity->get(self::ATTR_PARENT_ID) && $parentId) {
|
||||
$parent = $this->entityManager->getEntityById($entityType, $parentId);
|
||||
|
||||
if ($parent && !$this->acl->checkEntityEdit($parent)) {
|
||||
throw new Forbidden("No edit access to target category.");
|
||||
}
|
||||
|
||||
if ($parent) {
|
||||
$this->checkReferenceNoLoop($parent, $entity);
|
||||
}
|
||||
}
|
||||
|
||||
if ($params->type === MoveParams::TYPE_AFTER) {
|
||||
$this->processAfter($reference, $entity);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->processBefore($reference, $entity);
|
||||
}
|
||||
|
||||
private function incrementAfter(Entity $reference): void
|
||||
{
|
||||
$update = UpdateBuilder::create()
|
||||
->in($reference->getEntityType())
|
||||
->where([
|
||||
self::ATTR_PARENT_ID => $reference->get(self::ATTR_PARENT_ID),
|
||||
self::ATTR_ORDER . '>' => $reference->get(self::ATTR_ORDER),
|
||||
])
|
||||
->set([
|
||||
self::ATTR_ORDER => Expr::add(Expr::column(self::ATTR_ORDER), 2)
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($update);
|
||||
}
|
||||
|
||||
private function decrementBefore(Entity $reference): void
|
||||
{
|
||||
$update = UpdateBuilder::create()
|
||||
->in($reference->getEntityType())
|
||||
->where([
|
||||
self::ATTR_PARENT_ID => $reference->get(self::ATTR_PARENT_ID),
|
||||
self::ATTR_ORDER . '<' => $reference->get(self::ATTR_ORDER),
|
||||
])
|
||||
->set([
|
||||
self::ATTR_ORDER => Expr::subtract(Expr::column(self::ATTR_ORDER), 2)
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($update);
|
||||
}
|
||||
|
||||
private function rearrange(Entity $reference): void
|
||||
{
|
||||
$entities = $this->entityManager
|
||||
->getRDBRepository($reference->getEntityType())
|
||||
->where([
|
||||
self::ATTR_PARENT_ID => $reference->get(self::ATTR_PARENT_ID),
|
||||
])
|
||||
->order(self::ATTR_ORDER)
|
||||
->find();
|
||||
|
||||
foreach ($entities as $i => $entity) {
|
||||
$entity->set(self::ATTR_ORDER, $i + 1);
|
||||
|
||||
$this->entityManager->saveEntity($entity, [SaveOption::SKIP_ALL => true]);
|
||||
}
|
||||
}
|
||||
|
||||
private function processAfter(Entity $reference, CategoryTree $entity): void
|
||||
{
|
||||
$this->incrementAfter($reference);
|
||||
$this->rearrange($reference);
|
||||
|
||||
$order = ($reference->get(self::ATTR_ORDER) ?? 0) + 1;
|
||||
|
||||
$entity->set(self::ATTR_ORDER, $order);
|
||||
$entity->set(self::ATTR_PARENT_ID, $reference->get(self::ATTR_PARENT_ID));
|
||||
|
||||
$this->entityManager->saveEntity($entity);
|
||||
|
||||
$this->rearrange($reference);
|
||||
}
|
||||
|
||||
private function processBefore(Entity $reference, CategoryTree $entity): void
|
||||
{
|
||||
$this->decrementBefore($reference);
|
||||
|
||||
$order = ($reference->get(self::ATTR_ORDER) ?? 0) - 1;
|
||||
|
||||
$entity->set(self::ATTR_ORDER, $order);
|
||||
$entity->set(self::ATTR_PARENT_ID, $reference->get(self::ATTR_PARENT_ID));
|
||||
|
||||
$this->entityManager->saveEntity($entity);
|
||||
|
||||
$this->rearrange($reference);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Forbidden
|
||||
*/
|
||||
private function processInto(?Entity $reference, CategoryTree $entity, MoveParams $params): void
|
||||
{
|
||||
if ($reference && !$this->acl->checkEntityEdit($reference)) {
|
||||
throw new Forbidden("No edit access to target category.");
|
||||
}
|
||||
|
||||
if ($reference) {
|
||||
$this->checkReferenceNoLoop($reference, $entity);
|
||||
}
|
||||
|
||||
$entity->setMultiple([
|
||||
self::ATTR_PARENT_ID => $params->referenceId,
|
||||
self::ATTR_ORDER => null,
|
||||
]);
|
||||
|
||||
$this->entityManager->saveEntity($entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Forbidden
|
||||
*/
|
||||
private function checkReferenceNoLoop(Entity $reference, CategoryTree $entity): void
|
||||
{
|
||||
$parentId = $reference->get(self::ATTR_PARENT_ID);
|
||||
|
||||
if (!$parentId) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ($parentId === $entity->getId()) {
|
||||
throw new Forbidden("Cannot move. Circle reference.");
|
||||
}
|
||||
|
||||
$parent = $this->entityManager->getEntityById($entity->getEntityType(), $parentId);
|
||||
|
||||
if (!$parent) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->checkReferenceNoLoop($parent, $entity);
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,10 @@
|
||||
<div class="no-data">{{translate 'No Data'}}</div>
|
||||
{{/if}}
|
||||
|
||||
<div class="list list-expanded list-tree{{#if noData}} hidden{{/if}}">
|
||||
<div
|
||||
class="list list-expanded list-tree {{#if noData}} hidden {{/if}}"
|
||||
{{#if isEditable}} data-editable="true" {{/if}}
|
||||
>
|
||||
{{#if showRoot}}
|
||||
<div class="root-item">
|
||||
<a
|
||||
|
||||
@@ -38,6 +38,12 @@ class ListTreeRecordItemView extends View {
|
||||
level = 0
|
||||
listViewName = 'views/record/list-tree'
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {import('views/record/list-tree').default}
|
||||
*/
|
||||
rootView
|
||||
|
||||
data() {
|
||||
return {
|
||||
name: this.model.get('name'),
|
||||
@@ -282,11 +288,14 @@ class ListTreeRecordItemView extends View {
|
||||
if (!this.readOnly) {
|
||||
const $remove = this.$el.find('> .cell [data-action="remove"]');
|
||||
|
||||
this.$el.find('> .cell').on('mouseenter', function () {
|
||||
this.$el.find('> .cell').on('mouseenter', () => {
|
||||
if (this.rootView.movedId) {
|
||||
return;
|
||||
}
|
||||
$remove.removeClass('hidden');
|
||||
});
|
||||
|
||||
this.$el.find('> .cell').on('mouseleave', function () {
|
||||
this.$el.find('> .cell').on('mouseleave', () => {
|
||||
$remove.addClass('hidden');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
|
||||
import ListRecordView from 'views/record/list';
|
||||
import RecordModal from 'helpers/record-modal';
|
||||
import {Draggable} from '@shopify/draggable';
|
||||
|
||||
class ListTreeRecordView extends ListRecordView {
|
||||
|
||||
@@ -51,8 +52,43 @@ class ListTreeRecordView extends ListRecordView {
|
||||
level = 0
|
||||
itemViewName = 'views/record/list-tree-item'
|
||||
|
||||
/**
|
||||
* @protected
|
||||
* @type {boolean}
|
||||
*/
|
||||
readOnly
|
||||
|
||||
expandToggleInactive = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {ListTreeRecordView}
|
||||
*/
|
||||
rootView
|
||||
|
||||
/**
|
||||
* @type {string|null}
|
||||
*/
|
||||
movedId = null
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
blockDraggable = false
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
moveSupported
|
||||
|
||||
/**
|
||||
* @private
|
||||
* {Draggable}
|
||||
*/
|
||||
draggable
|
||||
|
||||
// noinspection JSCheckFunctionSignatures
|
||||
data() {
|
||||
const data = super.data();
|
||||
@@ -77,6 +113,8 @@ class ListTreeRecordView extends ListRecordView {
|
||||
data.expandToggleInactive = this.expandToggleInactive;
|
||||
data.hasExpandToggle = !this.getUser().isPortal();
|
||||
|
||||
data.isEditable = this.level === 0 && !this.readOnly;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
@@ -137,6 +175,16 @@ class ListTreeRecordView extends ListRecordView {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.moveSupported = !!this.getMetadata().get(`entityDefs.${this.entityType}.fields.order`);
|
||||
}
|
||||
|
||||
afterRender() {
|
||||
super.afterRender();
|
||||
|
||||
if (this.level === 0 && !this.readOnly && this.moveSupported) {
|
||||
this.initDraggableRoot();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -145,8 +193,7 @@ class ListTreeRecordView extends ListRecordView {
|
||||
setSelected(id) {
|
||||
if (id === null) {
|
||||
this.selectedData.id = null;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
this.selectedData.id = id;
|
||||
}
|
||||
|
||||
@@ -166,6 +213,13 @@ class ListTreeRecordView extends ListRecordView {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {import('views/record/list-tree-item').default[]}
|
||||
*/
|
||||
getItemViews() {
|
||||
return this.rowList.map(key => this.getView(key));
|
||||
}
|
||||
|
||||
buildRows(callback) {
|
||||
this.checkedList = [];
|
||||
this.rowList = [];
|
||||
@@ -251,12 +305,10 @@ class ListTreeRecordView extends ListRecordView {
|
||||
attributes.parentName = this.model.attributes.name;
|
||||
}
|
||||
|
||||
const scope = this.collection.entityType;
|
||||
|
||||
const helper = new RecordModal();
|
||||
|
||||
helper.showCreate(this, {
|
||||
entityType: scope,
|
||||
entityType: this.entityType,
|
||||
attributes: attributes,
|
||||
afterSave: model => {
|
||||
const collection = /** @type {import('collections/tree').default} collection */
|
||||
@@ -296,6 +348,261 @@ class ListTreeRecordView extends ListRecordView {
|
||||
this.setSelected(null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
initDraggableRoot() {
|
||||
if (this.draggable) {
|
||||
this.draggable.destroy();
|
||||
}
|
||||
|
||||
const draggable = this.draggable = new Draggable(this.element, {
|
||||
distance: 8,
|
||||
draggable: '.list-group-item > .cell > .link',
|
||||
mirror: {
|
||||
cursorOffsetX: 5,
|
||||
cursorOffsetY: 5,
|
||||
appendTo: 'body',
|
||||
},
|
||||
});
|
||||
|
||||
/** @type {HTMLElement[]} */
|
||||
let rows;
|
||||
/** @type {Map<HTMLElement, number>} */
|
||||
let levelMap;
|
||||
/** @type {HTMLElement|null} */
|
||||
let movedLink = null;
|
||||
/** @type {HTMLElement|null} */
|
||||
let movedFromLi = null;
|
||||
|
||||
draggable.on('mirror:created', event => {
|
||||
const mirror = event.mirror;
|
||||
const source = event.source;
|
||||
const originalSource = event.originalSource;
|
||||
|
||||
originalSource.style.display = '';
|
||||
source.style.display = 'none';
|
||||
|
||||
mirror.style.display = 'block';
|
||||
mirror.style.cursor = 'grabbing';
|
||||
mirror.classList.add('draggable-helper', 'draggable-helper-transparent', 'text-info');
|
||||
mirror.classList.remove('link');
|
||||
mirror.style.pointerEvents = 'auto';
|
||||
mirror.removeAttribute('href');
|
||||
mirror.style.textDecoration = 'none';
|
||||
});
|
||||
|
||||
draggable.on('mirror:move', event => {
|
||||
event.mirror.style.pointerEvents = 'auto';
|
||||
});
|
||||
|
||||
draggable.on('drag:start', event => {
|
||||
if (this.blockDraggable) {
|
||||
event.cancel();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
rows = Array.from(this.element.querySelectorAll('.list-group-tree > .list-group-item'));
|
||||
|
||||
levelMap = new Map();
|
||||
|
||||
rows.forEach(row => {
|
||||
let depth = 0;
|
||||
let current = row;
|
||||
|
||||
while (current && current !== this.element) {
|
||||
current = current.parentElement;
|
||||
|
||||
depth ++;
|
||||
}
|
||||
|
||||
levelMap.set(row, depth);
|
||||
});
|
||||
|
||||
rows.sort((a, b) => levelMap.get(b) - levelMap.get(a));
|
||||
|
||||
this.movedId = event.source.dataset.id;
|
||||
movedLink = event.originalSource;
|
||||
movedFromLi = movedLink.parentElement.parentElement;
|
||||
|
||||
movedLink.classList.add('text-info');
|
||||
});
|
||||
|
||||
let overId = null;
|
||||
let overParentId = null;
|
||||
let isAfter = false;
|
||||
let wasOutOfSelf = false;
|
||||
|
||||
draggable.on('drag:move', event => {
|
||||
isAfter = false;
|
||||
overId = null;
|
||||
|
||||
let rowFound = null;
|
||||
|
||||
for (const row of rows) {
|
||||
const rect = row.getBoundingClientRect();
|
||||
|
||||
const isIn =
|
||||
rect.left < event.sensorEvent.clientX &&
|
||||
rect.right > event.sensorEvent.clientX &&
|
||||
rect.top < event.sensorEvent.clientY &&
|
||||
rect.bottom >= event.sensorEvent.clientY;
|
||||
|
||||
if (!isIn) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const itemId = row.dataset.id ?? null;
|
||||
let itemParentId = null;
|
||||
|
||||
if (!itemId) {
|
||||
const parent = row.closest(`.list-group-item[data-id]`);
|
||||
|
||||
if (parent instanceof HTMLElement) {
|
||||
// Over a plus row.
|
||||
itemParentId = parent.dataset.id;
|
||||
}
|
||||
}
|
||||
|
||||
const itemIsAfter = event.sensorEvent.clientY - rect.top >= rect.bottom - event.sensorEvent.clientY;
|
||||
|
||||
if (itemParentId && itemIsAfter) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (itemId === this.movedId) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (movedFromLi.contains(row)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (!itemId && !itemParentId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
isAfter = itemIsAfter;
|
||||
overParentId = itemParentId;
|
||||
overId = itemId;
|
||||
rowFound = row;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
for (const row of rows) {
|
||||
row.classList.remove('border-top-highlighted');
|
||||
row.classList.remove('border-bottom-highlighted');
|
||||
}
|
||||
|
||||
if (!rowFound) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isAfter) {
|
||||
rowFound.classList.add('border-bottom-highlighted');
|
||||
rowFound.classList.remove('border-top-highlighted');
|
||||
} else {
|
||||
rowFound.classList.add('border-top-highlighted');
|
||||
rowFound.classList.remove('border-bottom-highlighted');
|
||||
}
|
||||
});
|
||||
|
||||
draggable.on('drag:stop', async () => {
|
||||
if (movedLink) {
|
||||
movedLink.classList.remove('text-info');
|
||||
}
|
||||
|
||||
rows.forEach(row => {
|
||||
row.classList.remove('border-bottom-highlighted');
|
||||
row.classList.remove('border-top-highlighted');
|
||||
});
|
||||
|
||||
rows = undefined;
|
||||
|
||||
let moveType;
|
||||
let referenceId = overId;
|
||||
|
||||
if (overParentId || overId) {
|
||||
if (overParentId) {
|
||||
moveType = 'into';
|
||||
referenceId = overParentId;
|
||||
} else if (isAfter) {
|
||||
moveType = 'after';
|
||||
} else {
|
||||
moveType = 'before';
|
||||
}
|
||||
}
|
||||
|
||||
if (moveType) {
|
||||
this.blockDraggable = true;
|
||||
|
||||
const movedId = this.movedId;
|
||||
const affectedId = referenceId;
|
||||
|
||||
Espo.Ui.notifyWait();
|
||||
|
||||
Espo.Ajax
|
||||
.postRequest(`${this.entityType}/action/move`, {
|
||||
id: this.movedId,
|
||||
referenceId: referenceId,
|
||||
type: moveType,
|
||||
})
|
||||
.then(async () => {
|
||||
/**
|
||||
*
|
||||
* @param {ListTreeRecordView} view
|
||||
* @param {string} movedId
|
||||
* @return {Promise}
|
||||
*/
|
||||
const update = async (view, movedId) => {
|
||||
if (view.collection.has(movedId)) {
|
||||
await view.collection.fetch();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
for (const subView of view.getItemViews()) {
|
||||
if (!subView.getChildrenView()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
await update(subView.getChildrenView(), movedId);
|
||||
}
|
||||
};
|
||||
|
||||
const promises = [];
|
||||
|
||||
if (movedId) {
|
||||
promises.push(update(this, movedId));
|
||||
}
|
||||
|
||||
if (affectedId) {
|
||||
promises.push(update(this, affectedId));
|
||||
}
|
||||
|
||||
await Promise.all(promises);
|
||||
|
||||
Espo.Ui.success(this.translate('Done'));
|
||||
})
|
||||
.finally(() => {
|
||||
this.blockDraggable = false;
|
||||
});
|
||||
}
|
||||
|
||||
this.movedId = null;
|
||||
|
||||
movedLink = null;
|
||||
movedFromLi = null;
|
||||
levelMap = undefined;
|
||||
overParentId = null;
|
||||
overId = null;
|
||||
isAfter = false;
|
||||
wasOutOfSelf = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default ListTreeRecordView;
|
||||
|
||||
@@ -2928,18 +2928,69 @@ table.table td.cell .html-container {
|
||||
|
||||
.list-group-tree {
|
||||
border: 0;
|
||||
}
|
||||
.list-group-tree > li {
|
||||
border: 0;
|
||||
padding: 0 0 0 var(--panel-padding);
|
||||
|
||||
> li {
|
||||
border: 0;
|
||||
padding: 0 0 0 var(--panel-padding);
|
||||
|
||||
.cell {
|
||||
padding: var(--3px) 0;
|
||||
|
||||
.remove-link {
|
||||
margin-left: var(--4px);
|
||||
margin-right: var(--4px);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.list-group-tree > li .cell {
|
||||
padding: var(--3px) 0;
|
||||
.list-tree {
|
||||
&[data-editable="true"] {
|
||||
.list-group-tree {
|
||||
> li {
|
||||
position: relative;
|
||||
|
||||
.remove-link {
|
||||
margin-left: var(--4px);
|
||||
margin-right: var(--4px);
|
||||
&.border-bottom-highlighted,
|
||||
&.border-top-highlighted {
|
||||
&::after {
|
||||
display: block;
|
||||
content: " ";
|
||||
height: var(--2px);
|
||||
width: var(--20px);
|
||||
background-color: var(--gray-soft);
|
||||
left: var(--30px);
|
||||
position: absolute;
|
||||
border-radius: var(--1px);
|
||||
}
|
||||
}
|
||||
|
||||
&.border-bottom-highlighted {
|
||||
&::after {
|
||||
bottom: var(--minus-1px);
|
||||
}
|
||||
}
|
||||
|
||||
&.border-top-highlighted {
|
||||
&::after {
|
||||
top: var(--minus-1px);
|
||||
}
|
||||
}
|
||||
|
||||
> .cell {
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
a[data-action="fold"],
|
||||
a[data-action="unfold"],
|
||||
a[data-action="remove"],
|
||||
a[data-action="create"] {
|
||||
&,
|
||||
&:hover {
|
||||
color: var(--btn-text-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3978,6 +4029,10 @@ body:has(.modal-backdrop) {
|
||||
opacity: 1;
|
||||
position: absolute;
|
||||
z-index: 10002;
|
||||
|
||||
&.draggable-helper-transparent {
|
||||
opacity: 0.5;
|
||||
}
|
||||
}
|
||||
|
||||
.reminders-container {
|
||||
|
||||
@@ -129,6 +129,12 @@
|
||||
"bundle": true,
|
||||
"amdId": "intl-tel-input-globals"
|
||||
},
|
||||
{
|
||||
"src": "client/lib/original/shopify-draggable.js",
|
||||
"bundle": true,
|
||||
"amdId": "@shopify/draggable",
|
||||
"prepareCommand": "npx rollup node_modules/@shopify/draggable/build/esm/index.mjs --format amd --file client/lib/original/shopify-draggable.js --amd.id @shopify/draggable"
|
||||
},
|
||||
{
|
||||
"src": "node_modules/summernote/dist/summernote.js",
|
||||
"amdId": "summernote",
|
||||
|
||||
+32
-4
@@ -28,14 +28,37 @@
|
||||
|
||||
const BuildUtils = {
|
||||
/**
|
||||
* @param {Array} libs
|
||||
* @param {{
|
||||
* src?: string,
|
||||
* dest?: string,
|
||||
* bundle?: boolean,
|
||||
* amdId?: string,
|
||||
* suppressAmd?: boolean,
|
||||
* minify?: boolean,
|
||||
* prepareCommand?: string,
|
||||
* name?: string,
|
||||
* files?: {
|
||||
* src: string,
|
||||
* dest: string,
|
||||
* }[],
|
||||
* }[]} libs
|
||||
* @param {boolean} [skipPreparable]
|
||||
* @return {{src: string, file: string}[]}
|
||||
*/
|
||||
getBundleLibList: function(libs) {
|
||||
getBundleLibList: function(libs, skipPreparable = false) {
|
||||
const list = [];
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {{amdId?: string, src: string}} item
|
||||
* @return {*|string}
|
||||
*/
|
||||
const getFile = item => {
|
||||
if (item.amdId) {
|
||||
if (item.amdId.startsWith('@')) {
|
||||
return item.amdId.slice(1).replace('/', '-') + '.js';
|
||||
}
|
||||
|
||||
return item.amdId + '.js';
|
||||
}
|
||||
|
||||
@@ -44,6 +67,10 @@ const BuildUtils = {
|
||||
|
||||
libs.filter(item => item.bundle)
|
||||
.forEach(item => {
|
||||
if (item.prepareCommand && skipPreparable) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (item.files) {
|
||||
item.files.forEach(item => list.push({
|
||||
src: item.src,
|
||||
@@ -67,8 +94,9 @@ const BuildUtils = {
|
||||
},
|
||||
|
||||
getPreparedBundleLibList: function (libs) {
|
||||
return BuildUtils.getBundleLibList(libs)
|
||||
.map(item => 'client/lib/original/' + item.file);
|
||||
const items = BuildUtils.getBundleLibList(libs);
|
||||
|
||||
return items.map(item => 'client/lib/original/' + item.file);
|
||||
},
|
||||
|
||||
destToOriginalDest: function (dest) {
|
||||
|
||||
@@ -27,9 +27,28 @@
|
||||
************************************************************************/
|
||||
|
||||
const fs = require('fs');
|
||||
const cp = require('child_process');
|
||||
const buildUtils = require('../build-utils');
|
||||
|
||||
// @todo Introduce libs-provider.
|
||||
/**
|
||||
* @type {{
|
||||
* src?: string,
|
||||
* dest?: string,
|
||||
* bundle?: boolean,
|
||||
* amdId?: string,
|
||||
* suppressAmd?: boolean,
|
||||
* minify?: boolean,
|
||||
* prepareCommand?: string,
|
||||
* name?: string,
|
||||
* files?: {
|
||||
* src: string,
|
||||
* dest: string,
|
||||
* }[],
|
||||
* }[]}
|
||||
*/
|
||||
const libs = require('./../../frontend/libs.json');
|
||||
|
||||
const bundleConfig = require('../../frontend/bundle-config.json');
|
||||
|
||||
const libDir = './client/lib';
|
||||
@@ -55,6 +74,11 @@ fs.readdirSync(originalLibDir)
|
||||
fs.readdirSync(originalLibCrmDir)
|
||||
.forEach(file => fs.unlinkSync(originalLibCrmDir + '/' + file));
|
||||
|
||||
libs.filter(it => it.prepareCommand)
|
||||
.forEach(it => {
|
||||
cp.execSync(it.prepareCommand, {stdio: ['ignore', 'ignore', 'pipe']});
|
||||
});
|
||||
|
||||
const stripSourceMappingUrl = path => {
|
||||
/** @var {string} */
|
||||
const originalContents = fs.readFileSync(path, {encoding: 'utf-8'});
|
||||
@@ -94,8 +118,6 @@ const addSuppressAmd = path => {
|
||||
fs.writeFileSync(path, contents, {encoding: 'utf-8'});
|
||||
}
|
||||
|
||||
const bundleLibDataList = buildUtils.getBundleLibList(libs);
|
||||
|
||||
const amdIdMap = {};
|
||||
const suppressAmdMap = {};
|
||||
|
||||
@@ -113,7 +135,7 @@ libs.forEach(item => {
|
||||
amdIdMap[item.src] = 'lib!' + item.amdId;
|
||||
});
|
||||
|
||||
bundleLibDataList.forEach(item => {
|
||||
buildUtils.getBundleLibList(libs, true).forEach(item => {
|
||||
const src = item.src;
|
||||
|
||||
const dest = originalLibDir + '/' + item.file;
|
||||
|
||||
@@ -29,6 +29,22 @@
|
||||
const fs = require('fs');
|
||||
const buildUtils = require('../build-utils');
|
||||
|
||||
/**
|
||||
* @type {{
|
||||
* src?: string,
|
||||
* dest?: string,
|
||||
* bundle?: boolean,
|
||||
* amdId?: string,
|
||||
* suppressAmd?: boolean,
|
||||
* minify?: boolean,
|
||||
* prepareCommand?: string,
|
||||
* name?: string,
|
||||
* files?: {
|
||||
* src: string,
|
||||
* dest: string,
|
||||
* }[],
|
||||
* }[]}
|
||||
*/
|
||||
const libs = require('./../../frontend/libs.json');
|
||||
|
||||
const stripSourceMappingUrl = path => {
|
||||
|
||||
Generated
+493
@@ -12,6 +12,7 @@
|
||||
"dependencies": {
|
||||
"@fullcalendar/moment": "^6.1.8",
|
||||
"@fullcalendar/moment-timezone": "^6.1.8",
|
||||
"@shopify/draggable": "^1.1.4",
|
||||
"ace-builds": "^1.4.12",
|
||||
"autobahn-espo": "github:yurikuzn/autobahn-espo#0.1.0",
|
||||
"autonumeric": "^4.6.0",
|
||||
@@ -71,6 +72,7 @@
|
||||
"jasmine-core": "^5.2.0",
|
||||
"js-yaml": "^3.13.1",
|
||||
"pofile": "^1.1.3",
|
||||
"rollup": "^4.43.0",
|
||||
"tar": "^6.1.11"
|
||||
},
|
||||
"engines": {
|
||||
@@ -1914,6 +1916,266 @@
|
||||
"node": ">=14"
|
||||
}
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.43.0.tgz",
|
||||
"integrity": "sha512-Krjy9awJl6rKbruhQDgivNbD1WuLb8xAclM4IR4cN5pHGAs2oIMMQJEiC3IC/9TZJ+QZkmZhlMO/6MBGxPidpw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-android-arm64": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.43.0.tgz",
|
||||
"integrity": "sha512-ss4YJwRt5I63454Rpj+mXCXicakdFmKnUNxr1dLK+5rv5FJgAxnN7s31a5VchRYxCFWdmnDWKd0wbAdTr0J5EA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"android"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.43.0.tgz",
|
||||
"integrity": "sha512-eKoL8ykZ7zz8MjgBenEF2OoTNFAPFz1/lyJ5UmmFSz5jW+7XbH1+MAgCVHy72aG59rbuQLcJeiMrP8qP5d/N0A==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-darwin-x64": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.43.0.tgz",
|
||||
"integrity": "sha512-SYwXJgaBYW33Wi/q4ubN+ldWC4DzQY62S4Ll2dgfr/dbPoF50dlQwEaEHSKrQdSjC6oIe1WgzosoaNoHCdNuMg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"darwin"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-arm64": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.43.0.tgz",
|
||||
"integrity": "sha512-SV+U5sSo0yujrjzBF7/YidieK2iF6E7MdF6EbYxNz94lA+R0wKl3SiixGyG/9Klab6uNBIqsN7j4Y/Fya7wAjQ==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-freebsd-x64": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.43.0.tgz",
|
||||
"integrity": "sha512-J7uCsiV13L/VOeHJBo5SjasKiGxJ0g+nQTrBkAsmQBIdil3KhPnSE9GnRon4ejX1XDdsmK/l30IYLiAaQEO0Cg==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"freebsd"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.43.0.tgz",
|
||||
"integrity": "sha512-gTJ/JnnjCMc15uwB10TTATBEhK9meBIY+gXP4s0sHD1zHOaIh4Dmy1X9wup18IiY9tTNk5gJc4yx9ctj/fjrIw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.43.0.tgz",
|
||||
"integrity": "sha512-ZJ3gZynL1LDSIvRfz0qXtTNs56n5DI2Mq+WACWZ7yGHFUEirHBRt7fyIk0NsCKhmRhn7WAcjgSkSVVxKlPNFFw==",
|
||||
"cpu": [
|
||||
"arm"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.43.0.tgz",
|
||||
"integrity": "sha512-8FnkipasmOOSSlfucGYEu58U8cxEdhziKjPD2FIa0ONVMxvl/hmONtX/7y4vGjdUhjcTHlKlDhw3H9t98fPvyA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.43.0.tgz",
|
||||
"integrity": "sha512-KPPyAdlcIZ6S9C3S2cndXDkV0Bb1OSMsX0Eelr2Bay4EsF9yi9u9uzc9RniK3mcUGCLhWY9oLr6er80P5DE6XA==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-loongarch64-gnu": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.43.0.tgz",
|
||||
"integrity": "sha512-HPGDIH0/ZzAZjvtlXj6g+KDQ9ZMHfSP553za7o2Odegb/BEfwJcR0Sw0RLNpQ9nC6Gy8s+3mSS9xjZ0n3rhcYg==",
|
||||
"cpu": [
|
||||
"loong64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.43.0.tgz",
|
||||
"integrity": "sha512-gEmwbOws4U4GLAJDhhtSPWPXUzDfMRedT3hFMyRAvM9Mrnj+dJIFIeL7otsv2WF3D7GrV0GIewW0y28dOYWkmw==",
|
||||
"cpu": [
|
||||
"ppc64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.43.0.tgz",
|
||||
"integrity": "sha512-XXKvo2e+wFtXZF/9xoWohHg+MuRnvO29TI5Hqe9xwN5uN8NKUYy7tXUG3EZAlfchufNCTHNGjEx7uN78KsBo0g==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-riscv64-musl": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.43.0.tgz",
|
||||
"integrity": "sha512-ruf3hPWhjw6uDFsOAzmbNIvlXFXlBQ4nk57Sec8E8rUxs/AI4HD6xmiiasOOx/3QxS2f5eQMKTAwk7KHwpzr/Q==",
|
||||
"cpu": [
|
||||
"riscv64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.43.0.tgz",
|
||||
"integrity": "sha512-QmNIAqDiEMEvFV15rsSnjoSmO0+eJLoKRD9EAa9rrYNwO/XRCtOGM3A5A0X+wmG+XRrw9Fxdsw+LnyYiZWWcVw==",
|
||||
"cpu": [
|
||||
"s390x"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.43.0.tgz",
|
||||
"integrity": "sha512-jAHr/S0iiBtFyzjhOkAics/2SrXE092qyqEg96e90L3t9Op8OTzS6+IX0Fy5wCt2+KqeHAkti+eitV0wvblEoQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.43.0.tgz",
|
||||
"integrity": "sha512-3yATWgdeXyuHtBhrLt98w+5fKurdqvs8B53LaoKD7P7H7FKOONLsBVMNl9ghPQZQuYcceV5CDyPfyfGpMWD9mQ==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"linux"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.43.0.tgz",
|
||||
"integrity": "sha512-wVzXp2qDSCOpcBCT5WRWLmpJRIzv23valvcTwMHEobkjippNf+C3ys/+wf07poPkeNix0paTNemB2XrHr2TnGw==",
|
||||
"cpu": [
|
||||
"arm64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.43.0.tgz",
|
||||
"integrity": "sha512-fYCTEyzf8d+7diCw8b+asvWDCLMjsCEA8alvtAutqJOJp/wL5hs1rWSqJ1vkjgW0L2NB4bsYJrpKkiIPRR9dvw==",
|
||||
"cpu": [
|
||||
"ia32"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.43.0.tgz",
|
||||
"integrity": "sha512-SnGhLiE5rlK0ofq8kzuDkM0g7FN1s5VYY+YSMTibP7CqShxCQvqtNxTARS4xX4PFJfHjG0ZQYX9iGzI3FQh5Aw==",
|
||||
"cpu": [
|
||||
"x64"
|
||||
],
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"os": [
|
||||
"win32"
|
||||
]
|
||||
},
|
||||
"node_modules/@selectize/sifter": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@selectize/sifter/-/sifter-0.6.2.tgz",
|
||||
@@ -1929,6 +2191,11 @@
|
||||
"sifter": "bin/sifter.js"
|
||||
}
|
||||
},
|
||||
"node_modules/@shopify/draggable": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@shopify/draggable/-/draggable-1.1.4.tgz",
|
||||
"integrity": "sha512-EkXxBtQH119pGpLWhhhIPEdaeirGcVwkh6Nft1nqbMdM4N6b4r4v9wCmR1/r2gjTwu888I6qGI0VSlhoYivbYw=="
|
||||
},
|
||||
"node_modules/@testim/chrome-version": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.4.tgz",
|
||||
@@ -1941,6 +2208,12 @@
|
||||
"integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/estree": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz",
|
||||
"integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
|
||||
"dev": true
|
||||
},
|
||||
"node_modules/@types/hammerjs": {
|
||||
"version": "2.0.41",
|
||||
"resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.41.tgz",
|
||||
@@ -6393,6 +6666,45 @@
|
||||
"node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/rollup": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.43.0.tgz",
|
||||
"integrity": "sha512-wdN2Kd3Twh8MAEOEJZsuxuLKCsBEo4PVNLK6tQWAn10VhsVewQLzcucMgLolRlhFybGxfclbPeEYBaP6RvUFGg==",
|
||||
"dev": true,
|
||||
"dependencies": {
|
||||
"@types/estree": "1.0.7"
|
||||
},
|
||||
"bin": {
|
||||
"rollup": "dist/bin/rollup"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=18.0.0",
|
||||
"npm": ">=8.0.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.43.0",
|
||||
"@rollup/rollup-android-arm64": "4.43.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.43.0",
|
||||
"@rollup/rollup-darwin-x64": "4.43.0",
|
||||
"@rollup/rollup-freebsd-arm64": "4.43.0",
|
||||
"@rollup/rollup-freebsd-x64": "4.43.0",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.43.0",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.43.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.43.0",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.43.0",
|
||||
"@rollup/rollup-linux-loongarch64-gnu": "4.43.0",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.43.0",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.43.0",
|
||||
"@rollup/rollup-linux-riscv64-musl": "4.43.0",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.43.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.43.0",
|
||||
"@rollup/rollup-linux-x64-musl": "4.43.0",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.43.0",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.43.0",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.43.0",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
@@ -8750,6 +9062,146 @@
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-android-arm-eabi": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.43.0.tgz",
|
||||
"integrity": "sha512-Krjy9awJl6rKbruhQDgivNbD1WuLb8xAclM4IR4cN5pHGAs2oIMMQJEiC3IC/9TZJ+QZkmZhlMO/6MBGxPidpw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-android-arm64": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.43.0.tgz",
|
||||
"integrity": "sha512-ss4YJwRt5I63454Rpj+mXCXicakdFmKnUNxr1dLK+5rv5FJgAxnN7s31a5VchRYxCFWdmnDWKd0wbAdTr0J5EA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-darwin-arm64": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.43.0.tgz",
|
||||
"integrity": "sha512-eKoL8ykZ7zz8MjgBenEF2OoTNFAPFz1/lyJ5UmmFSz5jW+7XbH1+MAgCVHy72aG59rbuQLcJeiMrP8qP5d/N0A==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-darwin-x64": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.43.0.tgz",
|
||||
"integrity": "sha512-SYwXJgaBYW33Wi/q4ubN+ldWC4DzQY62S4Ll2dgfr/dbPoF50dlQwEaEHSKrQdSjC6oIe1WgzosoaNoHCdNuMg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-freebsd-arm64": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.43.0.tgz",
|
||||
"integrity": "sha512-SV+U5sSo0yujrjzBF7/YidieK2iF6E7MdF6EbYxNz94lA+R0wKl3SiixGyG/9Klab6uNBIqsN7j4Y/Fya7wAjQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-freebsd-x64": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.43.0.tgz",
|
||||
"integrity": "sha512-J7uCsiV13L/VOeHJBo5SjasKiGxJ0g+nQTrBkAsmQBIdil3KhPnSE9GnRon4ejX1XDdsmK/l30IYLiAaQEO0Cg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-linux-arm-gnueabihf": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.43.0.tgz",
|
||||
"integrity": "sha512-gTJ/JnnjCMc15uwB10TTATBEhK9meBIY+gXP4s0sHD1zHOaIh4Dmy1X9wup18IiY9tTNk5gJc4yx9ctj/fjrIw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-linux-arm-musleabihf": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.43.0.tgz",
|
||||
"integrity": "sha512-ZJ3gZynL1LDSIvRfz0qXtTNs56n5DI2Mq+WACWZ7yGHFUEirHBRt7fyIk0NsCKhmRhn7WAcjgSkSVVxKlPNFFw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-linux-arm64-gnu": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.43.0.tgz",
|
||||
"integrity": "sha512-8FnkipasmOOSSlfucGYEu58U8cxEdhziKjPD2FIa0ONVMxvl/hmONtX/7y4vGjdUhjcTHlKlDhw3H9t98fPvyA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-linux-arm64-musl": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.43.0.tgz",
|
||||
"integrity": "sha512-KPPyAdlcIZ6S9C3S2cndXDkV0Bb1OSMsX0Eelr2Bay4EsF9yi9u9uzc9RniK3mcUGCLhWY9oLr6er80P5DE6XA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-linux-loongarch64-gnu": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.43.0.tgz",
|
||||
"integrity": "sha512-HPGDIH0/ZzAZjvtlXj6g+KDQ9ZMHfSP553za7o2Odegb/BEfwJcR0Sw0RLNpQ9nC6Gy8s+3mSS9xjZ0n3rhcYg==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.43.0.tgz",
|
||||
"integrity": "sha512-gEmwbOws4U4GLAJDhhtSPWPXUzDfMRedT3hFMyRAvM9Mrnj+dJIFIeL7otsv2WF3D7GrV0GIewW0y28dOYWkmw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-linux-riscv64-gnu": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.43.0.tgz",
|
||||
"integrity": "sha512-XXKvo2e+wFtXZF/9xoWohHg+MuRnvO29TI5Hqe9xwN5uN8NKUYy7tXUG3EZAlfchufNCTHNGjEx7uN78KsBo0g==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-linux-riscv64-musl": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.43.0.tgz",
|
||||
"integrity": "sha512-ruf3hPWhjw6uDFsOAzmbNIvlXFXlBQ4nk57Sec8E8rUxs/AI4HD6xmiiasOOx/3QxS2f5eQMKTAwk7KHwpzr/Q==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-linux-s390x-gnu": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.43.0.tgz",
|
||||
"integrity": "sha512-QmNIAqDiEMEvFV15rsSnjoSmO0+eJLoKRD9EAa9rrYNwO/XRCtOGM3A5A0X+wmG+XRrw9Fxdsw+LnyYiZWWcVw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-linux-x64-gnu": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.43.0.tgz",
|
||||
"integrity": "sha512-jAHr/S0iiBtFyzjhOkAics/2SrXE092qyqEg96e90L3t9Op8OTzS6+IX0Fy5wCt2+KqeHAkti+eitV0wvblEoQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-linux-x64-musl": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.43.0.tgz",
|
||||
"integrity": "sha512-3yATWgdeXyuHtBhrLt98w+5fKurdqvs8B53LaoKD7P7H7FKOONLsBVMNl9ghPQZQuYcceV5CDyPfyfGpMWD9mQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-win32-arm64-msvc": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.43.0.tgz",
|
||||
"integrity": "sha512-wVzXp2qDSCOpcBCT5WRWLmpJRIzv23valvcTwMHEobkjippNf+C3ys/+wf07poPkeNix0paTNemB2XrHr2TnGw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-win32-ia32-msvc": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.43.0.tgz",
|
||||
"integrity": "sha512-fYCTEyzf8d+7diCw8b+asvWDCLMjsCEA8alvtAutqJOJp/wL5hs1rWSqJ1vkjgW0L2NB4bsYJrpKkiIPRR9dvw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@rollup/rollup-win32-x64-msvc": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.43.0.tgz",
|
||||
"integrity": "sha512-SnGhLiE5rlK0ofq8kzuDkM0g7FN1s5VYY+YSMTibP7CqShxCQvqtNxTARS4xX4PFJfHjG0ZQYX9iGzI3FQh5Aw==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"@selectize/sifter": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/@selectize/sifter/-/sifter-0.6.2.tgz",
|
||||
@@ -8762,6 +9214,11 @@
|
||||
"optimist": "^0.5.2"
|
||||
}
|
||||
},
|
||||
"@shopify/draggable": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@shopify/draggable/-/draggable-1.1.4.tgz",
|
||||
"integrity": "sha512-EkXxBtQH119pGpLWhhhIPEdaeirGcVwkh6Nft1nqbMdM4N6b4r4v9wCmR1/r2gjTwu888I6qGI0VSlhoYivbYw=="
|
||||
},
|
||||
"@testim/chrome-version": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/@testim/chrome-version/-/chrome-version-1.1.4.tgz",
|
||||
@@ -8774,6 +9231,12 @@
|
||||
"integrity": "sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/estree": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz",
|
||||
"integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==",
|
||||
"dev": true
|
||||
},
|
||||
"@types/hammerjs": {
|
||||
"version": "2.0.41",
|
||||
"resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.41.tgz",
|
||||
@@ -12092,6 +12555,36 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"rollup": {
|
||||
"version": "4.43.0",
|
||||
"resolved": "https://registry.npmjs.org/rollup/-/rollup-4.43.0.tgz",
|
||||
"integrity": "sha512-wdN2Kd3Twh8MAEOEJZsuxuLKCsBEo4PVNLK6tQWAn10VhsVewQLzcucMgLolRlhFybGxfclbPeEYBaP6RvUFGg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@rollup/rollup-android-arm-eabi": "4.43.0",
|
||||
"@rollup/rollup-android-arm64": "4.43.0",
|
||||
"@rollup/rollup-darwin-arm64": "4.43.0",
|
||||
"@rollup/rollup-darwin-x64": "4.43.0",
|
||||
"@rollup/rollup-freebsd-arm64": "4.43.0",
|
||||
"@rollup/rollup-freebsd-x64": "4.43.0",
|
||||
"@rollup/rollup-linux-arm-gnueabihf": "4.43.0",
|
||||
"@rollup/rollup-linux-arm-musleabihf": "4.43.0",
|
||||
"@rollup/rollup-linux-arm64-gnu": "4.43.0",
|
||||
"@rollup/rollup-linux-arm64-musl": "4.43.0",
|
||||
"@rollup/rollup-linux-loongarch64-gnu": "4.43.0",
|
||||
"@rollup/rollup-linux-powerpc64le-gnu": "4.43.0",
|
||||
"@rollup/rollup-linux-riscv64-gnu": "4.43.0",
|
||||
"@rollup/rollup-linux-riscv64-musl": "4.43.0",
|
||||
"@rollup/rollup-linux-s390x-gnu": "4.43.0",
|
||||
"@rollup/rollup-linux-x64-gnu": "4.43.0",
|
||||
"@rollup/rollup-linux-x64-musl": "4.43.0",
|
||||
"@rollup/rollup-win32-arm64-msvc": "4.43.0",
|
||||
"@rollup/rollup-win32-ia32-msvc": "4.43.0",
|
||||
"@rollup/rollup-win32-x64-msvc": "4.43.0",
|
||||
"@types/estree": "1.0.7",
|
||||
"fsevents": "~2.3.2"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
|
||||
@@ -37,11 +37,13 @@
|
||||
"jasmine-core": "^5.2.0",
|
||||
"js-yaml": "^3.13.1",
|
||||
"pofile": "^1.1.3",
|
||||
"rollup": "^4.43.0",
|
||||
"tar": "^6.1.11"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fullcalendar/moment": "^6.1.8",
|
||||
"@fullcalendar/moment-timezone": "^6.1.8",
|
||||
"@shopify/draggable": "^1.1.4",
|
||||
"ace-builds": "^1.4.12",
|
||||
"autobahn-espo": "github:yurikuzn/autobahn-espo#0.1.0",
|
||||
"autonumeric": "^4.6.0",
|
||||
|
||||
Reference in New Issue
Block a user