Compare commits
No commits in common. "main" and "v0.1" have entirely different histories.
1
.gitignore
vendored
1
.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
.idea/
|
|
||||||
43
README.md
43
README.md
@ -35,11 +35,10 @@
|
|||||||
|
|
||||||
## Основные концепции
|
## Основные концепции
|
||||||
|
|
||||||
Библиотека работает с тремя основными режимами открытия диалога:
|
Библиотека работает с двумя основными режимами открытия диалога:
|
||||||
|
|
||||||
- **create** — создание нового элемента (пустая форма)
|
- **create** — создание нового элемента (пустая форма)
|
||||||
- **update** — редактирование существующего элемента (форма с подгруженными данными)
|
- **update** — редактирование существующего элемента (форма с подгруженными данными)
|
||||||
- **create from** — создание нового элемента из существующего (форма с подгруженными данными)
|
|
||||||
|
|
||||||
Каждый диалог имеет:
|
Каждый диалог имеет:
|
||||||
- Уникальный строковый идентификатор (dialogId)
|
- Уникальный строковый идентификатор (dialogId)
|
||||||
@ -144,19 +143,6 @@ dialog.openUpdate(42, 'Редактирование пользователя')
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
#### openCreateFrom(itemId, title)
|
|
||||||
Открывает диалог в режиме создания с загруженными данными через GET endpoint.
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
dialog.openUpdate(42, 'Создание копии пользователя')
|
|
||||||
.onSuccess(function(result) {
|
|
||||||
console.log('Создана копия:', result);
|
|
||||||
})
|
|
||||||
.onError(function(error) {
|
|
||||||
console.error('Ошибка:', error);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### getConfig()
|
#### getConfig()
|
||||||
Возвращает текущую конфигурацию диалога.
|
Возвращает текущую конфигурацию диалога.
|
||||||
|
|
||||||
@ -210,16 +196,6 @@ api.onDelete(function(itemId) {
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
#### onOpen(callback)
|
|
||||||
Устанавливает обработчик успешного открытия. Если диалог открыт
|
|
||||||
в режиме редактирования, функция будет вызвана после загрузки всех данных.
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
api.onOpen(function() {
|
|
||||||
console.log('Диалог открыт и загружен');
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### setValues(values)
|
#### setValues(values)
|
||||||
Устанавливает значения полей формы.
|
Устанавливает значения полей формы.
|
||||||
|
|
||||||
@ -294,14 +270,6 @@ crud_d.openUpdate('user_form', 42, 'Редактирование')
|
|||||||
});
|
});
|
||||||
```
|
```
|
||||||
|
|
||||||
#### openCreateFrom(dialogId, itemId, title)
|
|
||||||
```javascript
|
|
||||||
crud_d.openUpdate('user_form', 42, 'Копирование')
|
|
||||||
.onSuccess(function(result) {
|
|
||||||
console.log('Создан из объекта:', result);
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
#### closeDialog(dialogId)
|
#### closeDialog(dialogId)
|
||||||
```javascript
|
```javascript
|
||||||
crud_d.closeDialog('user_form');
|
crud_d.closeDialog('user_form');
|
||||||
@ -680,15 +648,6 @@ dialog.openCreate('Новый заказ')
|
|||||||
- При удалении: подтверждение → DELETE запрос → `onDelete`/`onError`
|
- При удалении: подтверждение → DELETE запрос → `onDelete`/`onError`
|
||||||
- Автоматическое закрытие диалога при успехе
|
- Автоматическое закрытие диалога при успехе
|
||||||
|
|
||||||
3. **Создание из существующего элемента (create from):**
|
|
||||||
- GET запрос на get endpoint для загрузки данных
|
|
||||||
- Заполнение формы полученными данными
|
|
||||||
- Валидация формы
|
|
||||||
- POST запрос на create endpoint
|
|
||||||
- `onSuccess` при успехе
|
|
||||||
- `onError` при ошибке
|
|
||||||
- Автоматическое закрытие диалога при успехе
|
|
||||||
|
|
||||||
### Цепочка методов
|
### Цепочка методов
|
||||||
|
|
||||||
Все методы настройки возвращают `this`, что позволяет использовать цепочку вызовов:
|
Все методы настройки возвращают `this`, что позволяет использовать цепочку вызовов:
|
||||||
|
|||||||
48
crud_d.js
48
crud_d.js
@ -1,3 +1,4 @@
|
|||||||
|
(function() {
|
||||||
'use strict';
|
'use strict';
|
||||||
|
|
||||||
// Хранилище зарегистрированных диалогов
|
// Хранилище зарегистрированных диалогов
|
||||||
@ -322,7 +323,6 @@ async function apiRequest(method, url, data = null) {
|
|||||||
const options = {
|
const options = {
|
||||||
method,
|
method,
|
||||||
headers: {
|
headers: {
|
||||||
'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content ?? '',
|
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@ -365,7 +365,7 @@ function createModal(dialogId, title, fields, options = {}, mode = 'create', ite
|
|||||||
|
|
||||||
// Заголовок
|
// Заголовок
|
||||||
const header = dom.div().cls('modal-header');
|
const header = dom.div().cls('modal-header');
|
||||||
const titleText = mode === 'create' ? title : mode === 'create_from' ? `Скопировать из: ${title}` : `Редактирование: ${title}`;
|
const titleText = mode === 'create' ? title : `Редактирование: ${title}`;
|
||||||
const titleEl = dom.h5().cls('modal-title').text(titleText);
|
const titleEl = dom.h5().cls('modal-title').text(titleText);
|
||||||
const closeBtn = dom.button().cls('btn-close').atr('data-bs-dismiss', 'modal').atr('aria-label', 'Close');
|
const closeBtn = dom.button().cls('btn-close').atr('data-bs-dismiss', 'modal').atr('aria-label', 'Close');
|
||||||
header.child(titleEl);
|
header.child(titleEl);
|
||||||
@ -413,7 +413,7 @@ function createModal(dialogId, title, fields, options = {}, mode = 'create', ite
|
|||||||
const categoryNames = Object.keys(finalCategories);
|
const categoryNames = Object.keys(finalCategories);
|
||||||
|
|
||||||
const tabNav = dom.ul().cls('nav nav-tabs').atr('role', 'tablist');
|
const tabNav = dom.ul().cls('nav nav-tabs').atr('role', 'tablist');
|
||||||
const tabContent = dom.div().cls('tab-content').cls('mt-3');
|
const tabContent = dom.div().cls('tab-content');
|
||||||
|
|
||||||
categoryNames.forEach((catName, index) => {
|
categoryNames.forEach((catName, index) => {
|
||||||
const tabId = `tab_${dialogId}_${catName.replace(/[^a-zA-Z0-9]/g, '_')}`;
|
const tabId = `tab_${dialogId}_${catName.replace(/[^a-zA-Z0-9]/g, '_')}`;
|
||||||
@ -475,7 +475,7 @@ function createModal(dialogId, title, fields, options = {}, mode = 'create', ite
|
|||||||
const submitSpinner = dom.span().cls('spinner-border spinner-border-sm').atr('role', 'status')
|
const submitSpinner = dom.span().cls('spinner-border spinner-border-sm').atr('role', 'status')
|
||||||
.atr('aria-hidden', 'true').css('display: none');
|
.atr('aria-hidden', 'true').css('display: none');
|
||||||
|
|
||||||
if (mode === 'create' || mode === 'create_from') {
|
if (mode === 'create') {
|
||||||
submitBtn.text('Создать');
|
submitBtn.text('Создать');
|
||||||
submitBtn.child(submitSpinner);
|
submitBtn.child(submitSpinner);
|
||||||
footer.child(cancelBtn);
|
footer.child(cancelBtn);
|
||||||
@ -630,10 +630,6 @@ window.crud_d = {
|
|||||||
return this._open(title, 'create');
|
return this._open(title, 'create');
|
||||||
},
|
},
|
||||||
|
|
||||||
openCreateFrom: function(itemId, title = 'Скопировать из') {
|
|
||||||
return this._open(title, 'create_from', itemId);
|
|
||||||
},
|
|
||||||
|
|
||||||
// Открытие в режиме обновления
|
// Открытие в режиме обновления
|
||||||
openUpdate: function(itemId, title = 'Редактирование') {
|
openUpdate: function(itemId, title = 'Редактирование') {
|
||||||
return this._open(title, 'update', itemId);
|
return this._open(title, 'update', itemId);
|
||||||
@ -652,10 +648,6 @@ window.crud_d = {
|
|||||||
activeDialogs.set(dialogId, modal);
|
activeDialogs.set(dialogId, modal);
|
||||||
|
|
||||||
const api = {
|
const api = {
|
||||||
onOpen: function(callback) {
|
|
||||||
modal.onOpen = callback;
|
|
||||||
return this;
|
|
||||||
},
|
|
||||||
onSuccess: function(callback) {
|
onSuccess: function(callback) {
|
||||||
modal.onSuccess = callback;
|
modal.onSuccess = callback;
|
||||||
return this;
|
return this;
|
||||||
@ -689,7 +681,7 @@ window.crud_d = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Загрузка данных для режима update
|
// Загрузка данных для режима update
|
||||||
if ((mode === 'update' || mode === 'create_from') && itemId) {
|
if (mode === 'update' && itemId) {
|
||||||
modal.showLoadingOverlay();
|
modal.showLoadingOverlay();
|
||||||
|
|
||||||
const getEndpoint = config.endpoints.get;
|
const getEndpoint = config.endpoints.get;
|
||||||
@ -706,9 +698,6 @@ window.crud_d = {
|
|||||||
.then(data => {
|
.then(data => {
|
||||||
modal.setValues(data);
|
modal.setValues(data);
|
||||||
modal.hideLoadingOverlay();
|
modal.hideLoadingOverlay();
|
||||||
if (typeof modal.onOpen === 'function') {
|
|
||||||
modal.onOpen(modal);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch(error => {
|
.catch(error => {
|
||||||
modal.hideLoadingOverlay();
|
modal.hideLoadingOverlay();
|
||||||
@ -716,14 +705,6 @@ window.crud_d = {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mode === 'create') {
|
|
||||||
setTimeout(() => {
|
|
||||||
if (typeof modal.onOpen === 'function') {
|
|
||||||
modal.onOpen(modal);
|
|
||||||
}
|
|
||||||
}, 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Обработчик сохранения/создания
|
// Обработчик сохранения/создания
|
||||||
modal.submitBtn.addEventListener('click', async () => {
|
modal.submitBtn.addEventListener('click', async () => {
|
||||||
const errors = modal.validate();
|
const errors = modal.validate();
|
||||||
@ -739,7 +720,7 @@ window.crud_d = {
|
|||||||
const formData = modal.getFormData();
|
const formData = modal.getFormData();
|
||||||
let result;
|
let result;
|
||||||
|
|
||||||
if (mode === 'create' || mode === 'create_from') {
|
if (mode === 'create') {
|
||||||
const createEndpoint = config.endpoints.create;
|
const createEndpoint = config.endpoints.create;
|
||||||
if (!createEndpoint) {
|
if (!createEndpoint) {
|
||||||
throw new Error('Create endpoint не установлен');
|
throw new Error('Create endpoint не установлен');
|
||||||
@ -842,6 +823,8 @@ window.crud_d = {
|
|||||||
return dialogApi;
|
return dialogApi;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
// Глобальные методы для работы по имени диалога
|
||||||
|
|
||||||
// Установка эндпоинтов по имени диалога
|
// Установка эндпоинтов по имени диалога
|
||||||
setCreateEndpoint: function(dialogId, endpoint) {
|
setCreateEndpoint: function(dialogId, endpoint) {
|
||||||
const dialog = dialogs.get(dialogId);
|
const dialog = dialogs.get(dialogId);
|
||||||
@ -893,19 +876,6 @@ window.crud_d = {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
openCreateFrom: function(dialogId, itemId, title = 'Скопировать из') {
|
|
||||||
const dialog = dialogs.get(dialogId);
|
|
||||||
if (dialog) {
|
|
||||||
const api = this.makeDialog(dialogId, dialog.fields, dialog.options);
|
|
||||||
// Копируем эндпоинты
|
|
||||||
api.getConfig().endpoints = dialog.endpoints;
|
|
||||||
return api.openCreateFrom(itemId, title);
|
|
||||||
} else {
|
|
||||||
console.error(`Диалог "${dialogId}" не найден`);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
|
|
||||||
openUpdate: function(dialogId, itemId, title = 'Редактирование') {
|
openUpdate: function(dialogId, itemId, title = 'Редактирование') {
|
||||||
const dialog = dialogs.get(dialogId);
|
const dialog = dialogs.get(dialogId);
|
||||||
if (dialog) {
|
if (dialog) {
|
||||||
@ -937,3 +907,5 @@ window.crud_d = {
|
|||||||
activeDialogs.clear();
|
activeDialogs.clear();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
})();
|
||||||
Loading…
x
Reference in New Issue
Block a user