Add full Ignition Perspective view.json generator with bindings, scripts, and controls
Extracts all CDW5_SCADA boilerplate (zoom controls, markdown tooltip, pan/wheel events, element color/state/priority tag bindings, display filters, Start/Stop special-case bindings) into a new ignition-view.ts module. deployToIgnition() now produces the complete view.json instead of a minimal skeleton. Also adds ignitionViewPath to the store/toolbar and routes it through the deploy endpoint so views land under the correct sub-folder (e.g. DetailedView/MCM09). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
3f122d9177
commit
0f50ab27ae
@ -207,7 +207,11 @@
|
|||||||
<div class="section-body">
|
<div class="section-body">
|
||||||
<div class="inline-row">
|
<div class="inline-row">
|
||||||
<label>Project</label>
|
<label>Project</label>
|
||||||
<input type="text" bind:value={layout.ignitionProject} placeholder="Testing_Project">
|
<input type="text" bind:value={layout.ignitionProject} placeholder="CDW5_SCADA">
|
||||||
|
</div>
|
||||||
|
<div class="inline-row">
|
||||||
|
<label>Path</label>
|
||||||
|
<input type="text" bind:value={layout.ignitionViewPath} placeholder="DetailedView">
|
||||||
</div>
|
</div>
|
||||||
<div class="inline-row">
|
<div class="inline-row">
|
||||||
<label>View</label>
|
<label>View</label>
|
||||||
|
|||||||
@ -2,6 +2,7 @@ import { layout } from './stores/layout.svelte.js';
|
|||||||
import { isEpcType, isInductionType, isSpurType, isCurvedType, isRectConveyanceType, isExtendoType, isPhotoeyeType, getSymbolGroup, EPC_CONFIG, INDUCTION_CONFIG, PHOTOEYE_CONFIG, EXTENDO_CONFIG, LABEL_CONFIG, CONVEYANCE_STYLE, getCurveGeometry } from './symbols.js';
|
import { isEpcType, isInductionType, isSpurType, isCurvedType, isRectConveyanceType, isExtendoType, isPhotoeyeType, getSymbolGroup, EPC_CONFIG, INDUCTION_CONFIG, PHOTOEYE_CONFIG, EXTENDO_CONFIG, LABEL_CONFIG, CONVEYANCE_STYLE, getCurveGeometry } from './symbols.js';
|
||||||
import { serializeSymbol, deserializeSymbol } from './serialization.js';
|
import { serializeSymbol, deserializeSymbol } from './serialization.js';
|
||||||
import { parseConveyanceLabel } from './label-utils.js';
|
import { parseConveyanceLabel } from './label-utils.js';
|
||||||
|
import { buildIgnitionViewJson } from './ignition-view.js';
|
||||||
import type { PlacedSymbol } from './types.js';
|
import type { PlacedSymbol } from './types.js';
|
||||||
|
|
||||||
/** Emit conveyance label text inside a <g> — inherits outer transform from group */
|
/** Emit conveyance label text inside a <g> — inherits outer transform from group */
|
||||||
@ -556,27 +557,12 @@ export async function exportIgnitionJSON() {
|
|||||||
/** Deploy directly to Ignition project directory */
|
/** Deploy directly to Ignition project directory */
|
||||||
export async function deployToIgnition() {
|
export async function deployToIgnition() {
|
||||||
const component = await buildIgnitionComponent();
|
const component = await buildIgnitionComponent();
|
||||||
const projectName = layout.ignitionProject || 'Testing_Project';
|
const projectName = layout.ignitionProject || 'CDW5_SCADA';
|
||||||
const viewName = layout.ignitionViewName || layout.currentMcm || 'MCM01';
|
const viewName = layout.ignitionViewName || layout.currentMcm || 'MCM01';
|
||||||
|
const viewPath = layout.ignitionViewPath || 'DetailedView';
|
||||||
|
|
||||||
const viewJson = JSON.stringify({
|
const viewData = buildIgnitionViewJson(viewName, component);
|
||||||
custom: {},
|
const viewJson = JSON.stringify(viewData, null, 2);
|
||||||
params: {},
|
|
||||||
props: {
|
|
||||||
defaultSize: { height: layout.canvasH, width: layout.canvasW },
|
|
||||||
},
|
|
||||||
root: {
|
|
||||||
children: [{
|
|
||||||
meta: { name: viewName },
|
|
||||||
position: { width: 1, height: 1 },
|
|
||||||
props: component.props,
|
|
||||||
type: 'ia.shapes.svg',
|
|
||||||
}],
|
|
||||||
meta: { name: 'root' },
|
|
||||||
props: { mode: 'percent' },
|
|
||||||
type: 'ia.container.coord',
|
|
||||||
},
|
|
||||||
}, null, 2);
|
|
||||||
|
|
||||||
// Compute SHA-256 signature of view.json for Ignition resource integrity
|
// Compute SHA-256 signature of view.json for Ignition resource integrity
|
||||||
const viewBytes = new TextEncoder().encode(viewJson);
|
const viewBytes = new TextEncoder().encode(viewJson);
|
||||||
@ -603,7 +589,7 @@ export async function deployToIgnition() {
|
|||||||
const resp = await fetch('/api/deploy-ignition', {
|
const resp = await fetch('/api/deploy-ignition', {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: { 'Content-Type': 'application/json' },
|
headers: { 'Content-Type': 'application/json' },
|
||||||
body: JSON.stringify({ projectName, viewName, viewJson, resourceJson }),
|
body: JSON.stringify({ projectName, viewName, viewPath, viewJson, resourceJson }),
|
||||||
});
|
});
|
||||||
const result = await resp.json();
|
const result = await resp.json();
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
|
|||||||
661
svelte-app/src/lib/ignition-view.ts
Normal file
661
svelte-app/src/lib/ignition-view.ts
Normal file
File diff suppressed because one or more lines are too long
@ -26,8 +26,9 @@ class LayoutStore {
|
|||||||
currentMcm = $state<string>('');
|
currentMcm = $state<string>('');
|
||||||
|
|
||||||
// Ignition export settings
|
// Ignition export settings
|
||||||
ignitionProject = $state<string>('Testing_Project');
|
ignitionProject = $state<string>('CDW5_SCADA');
|
||||||
ignitionViewName = $state<string>('');
|
ignitionViewName = $state<string>('');
|
||||||
|
ignitionViewPath = $state<string>('DetailedView');
|
||||||
|
|
||||||
// PDF state
|
// PDF state
|
||||||
pdfScale = $state(1.0);
|
pdfScale = $state(1.0);
|
||||||
|
|||||||
@ -263,9 +263,10 @@ export default defineConfig({
|
|||||||
req.on('data', (chunk: Buffer) => { body += chunk.toString(); });
|
req.on('data', (chunk: Buffer) => { body += chunk.toString(); });
|
||||||
req.on('end', () => {
|
req.on('end', () => {
|
||||||
try {
|
try {
|
||||||
const { projectName, viewName, viewJson, resourceJson } = JSON.parse(body);
|
const { projectName, viewName, viewPath, viewJson, resourceJson } = JSON.parse(body);
|
||||||
const ignitionBase = 'C:/Program Files/Inductive Automation/Ignition/data/projects';
|
const ignitionBase = 'C:/Program Files/Inductive Automation/Ignition/data/projects';
|
||||||
const viewDir = path.join(ignitionBase, projectName, 'com.inductiveautomation.perspective/views', viewName);
|
const viewSubPath = viewPath ? `${viewPath}/${viewName}` : viewName;
|
||||||
|
const viewDir = path.join(ignitionBase, projectName, 'com.inductiveautomation.perspective/views', viewSubPath);
|
||||||
fs.mkdirSync(viewDir, { recursive: true });
|
fs.mkdirSync(viewDir, { recursive: true });
|
||||||
fs.writeFileSync(path.join(viewDir, 'view.json'), viewJson);
|
fs.writeFileSync(path.join(viewDir, 'view.json'), viewJson);
|
||||||
fs.writeFileSync(path.join(viewDir, 'resource.json'), resourceJson);
|
fs.writeFileSync(path.join(viewDir, 'resource.json'), resourceJson);
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user