@sequent-org/moodboard 1.2.50 → 1.2.52
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/core/ApiClient.js +7 -2
- package/src/core/index.js +46 -1
- package/src/moodboard/DataManager.js +31 -1
- package/src/services/BoardService.js +3 -19
package/package.json
CHANGED
package/src/core/ApiClient.js
CHANGED
|
@@ -42,8 +42,12 @@ export class ApiClient {
|
|
|
42
42
|
|
|
43
43
|
async saveBoard(boardId, boardData) {
|
|
44
44
|
try {
|
|
45
|
+
// Поддержка нового формата: { boardData: {...}, settings: {...} }
|
|
46
|
+
let payloadBoardData = boardData && boardData.boardData ? boardData.boardData : boardData;
|
|
47
|
+
let payloadSettings = boardData && boardData.settings ? boardData.settings : undefined;
|
|
48
|
+
|
|
45
49
|
// Фильтруем объекты изображений и файлов - убираем избыточные данные
|
|
46
|
-
const cleanedData = this._cleanObjectData(
|
|
50
|
+
const cleanedData = this._cleanObjectData(payloadBoardData);
|
|
47
51
|
|
|
48
52
|
const csrfToken = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
|
|
49
53
|
|
|
@@ -58,7 +62,8 @@ export class ApiClient {
|
|
|
58
62
|
credentials: 'same-origin',
|
|
59
63
|
body: JSON.stringify({
|
|
60
64
|
boardId: boardId,
|
|
61
|
-
boardData: cleanedData
|
|
65
|
+
boardData: cleanedData,
|
|
66
|
+
settings: payloadSettings
|
|
62
67
|
})
|
|
63
68
|
});
|
|
64
69
|
|
package/src/core/index.js
CHANGED
|
@@ -2151,7 +2151,52 @@ export class CoreMoodBoard {
|
|
|
2151
2151
|
* Получение данных доски для сохранения
|
|
2152
2152
|
*/
|
|
2153
2153
|
getBoardData() {
|
|
2154
|
-
|
|
2154
|
+
// Базовые данные доски (объекты и метаданные из state)
|
|
2155
|
+
const s = this.state.serialize();
|
|
2156
|
+
const boardData = {
|
|
2157
|
+
objects: Array.isArray(s.objects) ? s.objects : [],
|
|
2158
|
+
name: s.name || s.title || 'Untitled Board',
|
|
2159
|
+
description: s.description || null
|
|
2160
|
+
};
|
|
2161
|
+
|
|
2162
|
+
// Настройки (settings): фон, сетка, зум, размеры канваса
|
|
2163
|
+
const app = this.pixi?.app;
|
|
2164
|
+
const rendererBg = app?.renderer?.background?.color ?? app?.renderer?.backgroundColor;
|
|
2165
|
+
const toHex = (num) => {
|
|
2166
|
+
try { return '#' + Number(num >>> 0).toString(16).padStart(6, '0'); } catch (_) { return '#F5F5F5'; }
|
|
2167
|
+
};
|
|
2168
|
+
const world = this.pixi?.worldLayer || app?.stage;
|
|
2169
|
+
const currentZoom = Math.max(0.1, Math.min(5, world?.scale?.x || 1));
|
|
2170
|
+
const canvasW = app?.view?.clientWidth || app?.view?.width || 0;
|
|
2171
|
+
const canvasH = app?.view?.clientHeight || app?.view?.height || 0;
|
|
2172
|
+
|
|
2173
|
+
// Сетка: берём то, что накапливается в state.board.grid через BoardService
|
|
2174
|
+
const gridState = (this.state?.state?.board && this.state.state.board.grid) ? this.state.state.board.grid : null;
|
|
2175
|
+
const gridSettings = (() => {
|
|
2176
|
+
if (gridState && gridState.type) {
|
|
2177
|
+
// Если храним полные options от serialize(), извлекаем ключевые
|
|
2178
|
+
const opts = gridState.options || {};
|
|
2179
|
+
// Унификация ключей под формат из задачи
|
|
2180
|
+
return {
|
|
2181
|
+
type: gridState.type,
|
|
2182
|
+
size: opts.size || 20,
|
|
2183
|
+
visible: opts.enabled !== false,
|
|
2184
|
+
color: toHex(opts.color ?? 0xE0E0E0)
|
|
2185
|
+
};
|
|
2186
|
+
}
|
|
2187
|
+
return null;
|
|
2188
|
+
})();
|
|
2189
|
+
|
|
2190
|
+
const settings = {
|
|
2191
|
+
backgroundColor: toHex(rendererBg ?? 0xF5F5F5),
|
|
2192
|
+
grid: gridSettings || undefined,
|
|
2193
|
+
zoom: { min: 0.1, max: 5.0, default: 1.0, current: currentZoom },
|
|
2194
|
+
canvas: { width: canvasW, height: canvasH }
|
|
2195
|
+
};
|
|
2196
|
+
|
|
2197
|
+
const boardId = (this.state?.state?.board && this.state.state.board.id) || this.options?.boardId || null;
|
|
2198
|
+
|
|
2199
|
+
return { id: boardId, boardData, settings };
|
|
2155
2200
|
}
|
|
2156
2201
|
|
|
2157
2202
|
/**
|
|
@@ -19,7 +19,7 @@ export class DataManager {
|
|
|
19
19
|
|
|
20
20
|
// Восстанавливаем тип сетки и её параметры до загрузки объектов
|
|
21
21
|
try {
|
|
22
|
-
const grid = data.grid || (data.board && data.board.grid);
|
|
22
|
+
const grid = (data.settings && data.settings.grid) || data.grid || (data.board && data.board.grid);
|
|
23
23
|
if (grid && grid.type) {
|
|
24
24
|
const payload = { type: grid.type };
|
|
25
25
|
const opts = grid.options || null;
|
|
@@ -29,6 +29,36 @@ export class DataManager {
|
|
|
29
29
|
this.coreMoodboard.eventBus.emit(this.coreMoodboard.Events?.UI?.GridChange || 'ui:grid:change', payload);
|
|
30
30
|
}
|
|
31
31
|
} catch (_) {}
|
|
32
|
+
|
|
33
|
+
// Восстановим фон и зум из settings, если есть
|
|
34
|
+
try {
|
|
35
|
+
const settings = data.settings || {};
|
|
36
|
+
// Фон
|
|
37
|
+
const bg = settings.backgroundColor;
|
|
38
|
+
if (bg && this.coreMoodboard?.pixi?.app?.renderer) {
|
|
39
|
+
const parseHex = (v) => {
|
|
40
|
+
if (typeof v === 'number') return v;
|
|
41
|
+
if (typeof v === 'string') {
|
|
42
|
+
const s = v.startsWith('#') ? v.slice(1) : v;
|
|
43
|
+
const n = parseInt(s, 16);
|
|
44
|
+
if (Number.isFinite(n)) return n;
|
|
45
|
+
}
|
|
46
|
+
return null;
|
|
47
|
+
};
|
|
48
|
+
const bgInt = parseHex(bg);
|
|
49
|
+
if (bgInt != null) this.coreMoodboard.pixi.app.renderer.backgroundColor = bgInt;
|
|
50
|
+
}
|
|
51
|
+
// Зум
|
|
52
|
+
const z = settings.zoom && (settings.zoom.current || settings.zoom.default);
|
|
53
|
+
const world = this.coreMoodboard?.pixi?.worldLayer || this.coreMoodboard?.pixi?.app?.stage;
|
|
54
|
+
if (world && Number.isFinite(z) && z > 0) {
|
|
55
|
+
world.scale.set(z);
|
|
56
|
+
const percent = Math.round(z * 100);
|
|
57
|
+
try {
|
|
58
|
+
this.coreMoodboard.eventBus.emit('ui:zoom:percent', { percentage: percent });
|
|
59
|
+
} catch (_) {}
|
|
60
|
+
}
|
|
61
|
+
} catch (_) {}
|
|
32
62
|
|
|
33
63
|
// Загружаем объекты
|
|
34
64
|
if (data.objects && Array.isArray(data.objects)) {
|
|
@@ -11,25 +11,9 @@ export class BoardService {
|
|
|
11
11
|
|
|
12
12
|
async init(getCanvasSize) {
|
|
13
13
|
this._getCanvasSize = getCanvasSize;
|
|
14
|
-
//
|
|
15
|
-
|
|
16
|
-
this.grid =
|
|
17
|
-
enabled: true,
|
|
18
|
-
size: 32,
|
|
19
|
-
width: canvasSize.width || 800,
|
|
20
|
-
height: canvasSize.height || 600,
|
|
21
|
-
color: 0x6a6aff,
|
|
22
|
-
opacity: 0.4
|
|
23
|
-
});
|
|
24
|
-
this.grid.updateVisual();
|
|
25
|
-
this.pixi.setGrid(this.grid);
|
|
26
|
-
this.eventBus.emit(Events.UI.GridCurrent, { type: 'line' });
|
|
27
|
-
// Сообщаем о текущих данных сетки для сохранения в boardData
|
|
28
|
-
try {
|
|
29
|
-
this.eventBus.emit(Events.Grid.BoardDataChanged, {
|
|
30
|
-
grid: { type: 'line', options: this.grid.serialize ? this.grid.serialize() : {} }
|
|
31
|
-
});
|
|
32
|
-
} catch (_) {}
|
|
14
|
+
// Не создаём сетку по умолчанию, чтобы избежать визуального переключения.
|
|
15
|
+
// Сетка будет установлена из сохранённых настроек через Events.UI.GridChange.
|
|
16
|
+
this.grid = null;
|
|
33
17
|
|
|
34
18
|
this._attachEvents();
|
|
35
19
|
}
|