refactor(workspace): restore yaml exports and align docker builds
- return scenario export payloads as yaml to match existing workflows - harden step reordering flow for drag-and-drop and one-based ui labels - switch server container to workspace-lockfile installs and root ignore rules
This commit is contained in:
@@ -94,19 +94,39 @@ export class ScenarioService {
|
||||
|
||||
// ── Steps ─────────────────────────────────────────────────────────────────
|
||||
|
||||
private async normalizeStepOrder(scenarioId: string): Promise<void> {
|
||||
const ordered = await this.stepRepo.find({
|
||||
where: { scenarioId },
|
||||
order: { order: "ASC", createdAt: "ASC", id: "ASC" },
|
||||
});
|
||||
for (let i = 0; i < ordered.length; i += 1) {
|
||||
const step = ordered[i];
|
||||
if (step.order !== i) {
|
||||
step.order = i;
|
||||
await this.stepRepo.save(step);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async createStep(
|
||||
scenarioId: string,
|
||||
dto: CreateScenarioStepDto,
|
||||
): Promise<ScenarioStepEntity> {
|
||||
await this.findOne(scenarioId);
|
||||
return this.stepRepo.save(
|
||||
const currentCount = await this.stepRepo.count({ where: { scenarioId } });
|
||||
const created = await this.stepRepo.save(
|
||||
this.stepRepo.create({
|
||||
...dto,
|
||||
order: currentCount,
|
||||
scenarioId,
|
||||
title: dto.title ?? null,
|
||||
sessionName: dto.sessionName ?? null,
|
||||
execCode: dto.execCode ?? null,
|
||||
validateCode: dto.validateCode ?? null,
|
||||
}),
|
||||
);
|
||||
await this.normalizeStepOrder(scenarioId);
|
||||
return this.findStep(scenarioId, created.id);
|
||||
}
|
||||
|
||||
async findStep(
|
||||
@@ -127,13 +147,52 @@ export class ScenarioService {
|
||||
dto: UpdateScenarioStepDto,
|
||||
): Promise<ScenarioStepEntity> {
|
||||
const step = await this.findStep(scenarioId, stepId);
|
||||
Object.assign(step, dto);
|
||||
return this.stepRepo.save(step);
|
||||
|
||||
const nextOrder = dto.order;
|
||||
Object.assign(step, {
|
||||
...dto,
|
||||
order: step.order,
|
||||
title: dto.title ?? step.title,
|
||||
sessionName: dto.sessionName ?? step.sessionName,
|
||||
execCode: dto.execCode ?? step.execCode,
|
||||
validateCode: dto.validateCode ?? step.validateCode,
|
||||
});
|
||||
await this.stepRepo.save(step);
|
||||
|
||||
if (nextOrder !== undefined) {
|
||||
const ordered = await this.stepRepo.find({
|
||||
where: { scenarioId },
|
||||
order: { order: "ASC", createdAt: "ASC", id: "ASC" },
|
||||
});
|
||||
const currentIndex = ordered.findIndex((s) => s.id === stepId);
|
||||
if (currentIndex >= 0) {
|
||||
const boundedTarget = Math.max(
|
||||
0,
|
||||
Math.min(nextOrder, ordered.length - 1),
|
||||
);
|
||||
if (currentIndex !== boundedTarget) {
|
||||
const [moved] = ordered.splice(currentIndex, 1);
|
||||
ordered.splice(boundedTarget, 0, moved);
|
||||
}
|
||||
for (let i = 0; i < ordered.length; i += 1) {
|
||||
const item = ordered[i];
|
||||
if (item.order !== i) {
|
||||
item.order = i;
|
||||
await this.stepRepo.save(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
await this.normalizeStepOrder(scenarioId);
|
||||
}
|
||||
|
||||
return this.findStep(scenarioId, stepId);
|
||||
}
|
||||
|
||||
async removeStep(scenarioId: string, stepId: string): Promise<void> {
|
||||
await this.findStep(scenarioId, stepId);
|
||||
await this.stepRepo.delete(stepId);
|
||||
await this.normalizeStepOrder(scenarioId);
|
||||
}
|
||||
|
||||
// ── Scenario Credentials ──────────────────────────────────────────────────
|
||||
@@ -333,7 +392,6 @@ export class ScenarioService {
|
||||
id: scenario.id,
|
||||
name: scenario.name,
|
||||
steps: scenario.steps.map((s) => ({
|
||||
order: s.order,
|
||||
title: s.title,
|
||||
execCode: s.execCode,
|
||||
validateCode: s.validateCode,
|
||||
@@ -362,16 +420,17 @@ export class ScenarioService {
|
||||
);
|
||||
}
|
||||
if (dto.steps.length > 0) {
|
||||
const steps = dto.steps.map((s) =>
|
||||
const steps = dto.steps.map((s, index) =>
|
||||
this.stepRepo.create({
|
||||
scenarioId: scenario.id,
|
||||
order: s.order,
|
||||
order: index,
|
||||
title: s.title ?? null,
|
||||
execCode: s.execCode ?? null,
|
||||
validateCode: s.validateCode ?? null,
|
||||
}),
|
||||
);
|
||||
await this.stepRepo.save(steps);
|
||||
await this.normalizeStepOrder(scenario.id);
|
||||
}
|
||||
return this.findOne(scenario.id);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user