@rocketshow/designer 1.63.0 → 1.65.0
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/assets/i18n/de.json +3 -1
- package/assets/i18n/en.json +3 -1
- package/fesm2022/rocketshow-designer.mjs +136 -58
- package/fesm2022/rocketshow-designer.mjs.map +1 -1
- package/index.d.ts +37 -17
- package/package.json +1 -1
- package/rocketshow-designer-1.65.0.tgz +0 -0
- package/rocketshow-designer-1.63.0.tgz +0 -0
package/assets/i18n/de.json
CHANGED
|
@@ -158,7 +158,9 @@
|
|
|
158
158
|
"create-fixture-from-profile-file": "Von Profil-Datei erstellen",
|
|
159
159
|
"create-from-local-profile": "Von Profil-Datei erstellen",
|
|
160
160
|
"create-fixture-from-profile-file-dialog-title": "OFL Profil-Datei auswählen",
|
|
161
|
-
"invalid-fixture-profile-file": "Das ist keine gültige OFL Profil-Datei. Bitte wähle eine gültige OFL Profil-Datei."
|
|
161
|
+
"invalid-fixture-profile-file": "Das ist keine gültige OFL Profil-Datei. Bitte wähle eine gültige OFL Profil-Datei.",
|
|
162
|
+
"edit-universes": "Universen bearbeiten",
|
|
163
|
+
"edit-universes-title": "Universen bearbeiten"
|
|
162
164
|
},
|
|
163
165
|
"effect": {
|
|
164
166
|
"add-new": "Neuen Effekt hinzufügen",
|
package/assets/i18n/en.json
CHANGED
|
@@ -157,7 +157,9 @@
|
|
|
157
157
|
"profiles-update-error-title": "Update error",
|
|
158
158
|
"create-fixture-from-profile-file": "Create from profile file",
|
|
159
159
|
"create-fixture-from-profile-file-dialog-title": "Select an OFL profile file",
|
|
160
|
-
"invalid-fixture-profile-file": "This is not a valid OFL fixture profile file. Please select a valid profile file."
|
|
160
|
+
"invalid-fixture-profile-file": "This is not a valid OFL fixture profile file. Please select a valid profile file.",
|
|
161
|
+
"edit-universes": "Edit universes",
|
|
162
|
+
"edit-universes-title": "Edit universes"
|
|
161
163
|
},
|
|
162
164
|
"effect": {
|
|
163
165
|
"add-new": "Add new Effect",
|
|
@@ -24,9 +24,9 @@ import * as i5 from 'ngx-dropzone-wrapper';
|
|
|
24
24
|
import { DropzoneModule } from 'ngx-dropzone-wrapper';
|
|
25
25
|
import * as i3$2 from '@angular/forms';
|
|
26
26
|
import { FormsModule } from '@angular/forms';
|
|
27
|
+
import Sortable from 'sortablejs';
|
|
27
28
|
import * as i12 from 'ngx-bootstrap/popover';
|
|
28
29
|
import { PopoverModule } from 'ngx-bootstrap/popover';
|
|
29
|
-
import Sortable from 'sortablejs';
|
|
30
30
|
import * as i10 from 'ngx-bootstrap/typeahead';
|
|
31
31
|
import { TypeaheadModule } from 'ngx-bootstrap/typeahead';
|
|
32
32
|
import * as i4 from 'ngx-bootstrap-slider';
|
|
@@ -1900,7 +1900,7 @@ class FixtureService {
|
|
|
1900
1900
|
// no free space left for the needed channels
|
|
1901
1901
|
return -1;
|
|
1902
1902
|
}
|
|
1903
|
-
addFixture(profile, fixturePool) {
|
|
1903
|
+
addFixture(profile, fixturePool, channelPool) {
|
|
1904
1904
|
const fixture = new Fixture();
|
|
1905
1905
|
fixture.uuid = this.uuidService.getUuid();
|
|
1906
1906
|
fixture.profileUuid = profile.uuid;
|
|
@@ -1925,7 +1925,7 @@ class FixtureService {
|
|
|
1925
1925
|
}
|
|
1926
1926
|
const mode = this.getModeByFixture(profile, fixture);
|
|
1927
1927
|
const channelCount = this.getModeChannelCount(profile, mode);
|
|
1928
|
-
const firstChannel = this.getNextFreeDmxChannel(fixturePool, channelCount);
|
|
1928
|
+
const firstChannel = this.getNextFreeDmxChannel(channelPool ?? fixturePool, channelCount);
|
|
1929
1929
|
if (firstChannel >= 0) {
|
|
1930
1930
|
fixture.dmxFirstChannel = firstChannel;
|
|
1931
1931
|
fixturePool.push(fixture);
|
|
@@ -2207,6 +2207,7 @@ class PresetService {
|
|
|
2207
2207
|
for (let i = this.selectedPreset.fixtures.length - 1; i >= 0; i--) {
|
|
2208
2208
|
const projectFixture = this.fixtureService.getFixtureByUuid(this.selectedPreset.fixtures[i].fixtureUuid);
|
|
2209
2209
|
if (projectFixture.dmxFirstChannel === fixture.dmxFirstChannel &&
|
|
2210
|
+
projectFixture.dmxUniverseUuid === fixture.dmxUniverseUuid &&
|
|
2210
2211
|
((!this.selectedPreset.fixtures[i].pixelKey && !pixelKey) || this.selectedPreset.fixtures[i].pixelKey === pixelKey)) {
|
|
2211
2212
|
this.selectedPreset.fixtures.splice(i, 1);
|
|
2212
2213
|
}
|
|
@@ -2216,7 +2217,7 @@ class PresetService {
|
|
|
2216
2217
|
for (const projectPresetFixture of this.projectService.project.presetFixtures) {
|
|
2217
2218
|
if ((!projectPresetFixture.pixelKey && !pixelKey) || projectPresetFixture.pixelKey === pixelKey) {
|
|
2218
2219
|
const projectFixture = this.fixtureService.getFixtureByUuid(projectPresetFixture.fixtureUuid);
|
|
2219
|
-
if (projectFixture.dmxFirstChannel === fixture.dmxFirstChannel) {
|
|
2220
|
+
if (projectFixture.dmxFirstChannel === fixture.dmxFirstChannel && projectFixture.dmxUniverseUuid === fixture.dmxUniverseUuid) {
|
|
2220
2221
|
const presetFixture = new PresetFixture();
|
|
2221
2222
|
presetFixture.fixtureUuid = projectPresetFixture.fixtureUuid;
|
|
2222
2223
|
presetFixture.pixelKey = pixelKey;
|
|
@@ -2286,6 +2287,7 @@ class PresetService {
|
|
|
2286
2287
|
const fixture = this.fixtureService.getFixtureByUuid(presetFixture.fixtureUuid);
|
|
2287
2288
|
for (const projectFixture of this.projectService.project.fixtures) {
|
|
2288
2289
|
if (projectFixture.dmxFirstChannel === fixture.dmxFirstChannel &&
|
|
2290
|
+
projectFixture.dmxUniverseUuid === fixture.dmxUniverseUuid &&
|
|
2289
2291
|
!this.fixtureIsSelected(projectFixture, presetFixture.pixelKey, preset)) {
|
|
2290
2292
|
const newPresetFixture = new PresetFixture();
|
|
2291
2293
|
newPresetFixture.fixtureUuid = projectFixture.uuid;
|
|
@@ -5386,6 +5388,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
5386
5388
|
type: Output
|
|
5387
5389
|
}] } });
|
|
5388
5390
|
|
|
5391
|
+
class FixturePoolEditUniversesComponent {
|
|
5392
|
+
constructor(bsModalRef, uuidService) {
|
|
5393
|
+
this.bsModalRef = bsModalRef;
|
|
5394
|
+
this.uuidService = uuidService;
|
|
5395
|
+
this.universes = [];
|
|
5396
|
+
this.newUniverseName = '';
|
|
5397
|
+
this.onClose = new Subject();
|
|
5398
|
+
}
|
|
5399
|
+
addUniverse() {
|
|
5400
|
+
const name = (this.newUniverseName || '').trim();
|
|
5401
|
+
if (!name)
|
|
5402
|
+
return;
|
|
5403
|
+
this.universes.push({ uuid: this.uuidService.getUuid(), name });
|
|
5404
|
+
this.newUniverseName = '';
|
|
5405
|
+
}
|
|
5406
|
+
removeUniverse(universe) {
|
|
5407
|
+
const index = this.universes.findIndex((u) => u.uuid === universe.uuid);
|
|
5408
|
+
if (index >= 0) {
|
|
5409
|
+
this.universes.splice(index, 1);
|
|
5410
|
+
}
|
|
5411
|
+
}
|
|
5412
|
+
ok() {
|
|
5413
|
+
this.onClose.next(this.universes);
|
|
5414
|
+
this.bsModalRef.hide();
|
|
5415
|
+
}
|
|
5416
|
+
cancel() {
|
|
5417
|
+
this.onClose.next(undefined);
|
|
5418
|
+
this.bsModalRef.hide();
|
|
5419
|
+
}
|
|
5420
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FixturePoolEditUniversesComponent, deps: [{ token: i1$1.BsModalRef }, { token: UuidService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5421
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: FixturePoolEditUniversesComponent, isStandalone: false, selector: "lib-fixture-pool-edit-universes", ngImport: i0, template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.fixture-pool.edit-universes-title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"cancel()\">\n <span aria-hidden=\"true\">×</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <!-- Add universe -->\n <div class=\"input-group mb-3\">\n <input\n type=\"text\"\n class=\"form-control\"\n maxlength=\"200\"\n [(ngModel)]=\"newUniverseName\"\n (keydown.enter)=\"addUniverse(); $event.stopPropagation(); $event.preventDefault()\"\n placeholder=\"{{ 'designer.fixture-pool.universe-name' | translate }}\"\n />\n <div class=\"input-group-append\">\n <button type=\"button\" class=\"btn btn-secondary\" [disabled]=\"!newUniverseName || !newUniverseName.trim()\" (click)=\"addUniverse()\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n <!-- Sortable universe list -->\n <ul class=\"list-group\" [sortablejs]=\"universes\">\n @for (universe of universes; track universe.uuid) {\n <li class=\"list-group-item d-flex align-items-center py-1\">\n <div class=\"list-sort-handle mr-2\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <span class=\"flex-grow-1\">{{ universe.name }}</span>\n <button class=\"btn btn-primary btn-sm\" type=\"button\" (click)=\"removeUniverse(universe)\">\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n </button>\n </li>\n }\n </ul>\n</div>\n<div class=\"modal-footer\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n", styles: [""], dependencies: [{ kind: "directive", type: i3$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i3$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: SortablejsDirective, selector: "[sortablejs]", inputs: ["sortablejs", "sortablejsContainer", "sortablejsOptions"], outputs: ["sortablejsInit"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }] }); }
|
|
5422
|
+
}
|
|
5423
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FixturePoolEditUniversesComponent, decorators: [{
|
|
5424
|
+
type: Component,
|
|
5425
|
+
args: [{ selector: 'lib-fixture-pool-edit-universes', standalone: false, template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.fixture-pool.edit-universes-title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"cancel()\">\n <span aria-hidden=\"true\">×</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <!-- Add universe -->\n <div class=\"input-group mb-3\">\n <input\n type=\"text\"\n class=\"form-control\"\n maxlength=\"200\"\n [(ngModel)]=\"newUniverseName\"\n (keydown.enter)=\"addUniverse(); $event.stopPropagation(); $event.preventDefault()\"\n placeholder=\"{{ 'designer.fixture-pool.universe-name' | translate }}\"\n />\n <div class=\"input-group-append\">\n <button type=\"button\" class=\"btn btn-secondary\" [disabled]=\"!newUniverseName || !newUniverseName.trim()\" (click)=\"addUniverse()\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n\n <!-- Sortable universe list -->\n <ul class=\"list-group\" [sortablejs]=\"universes\">\n @for (universe of universes; track universe.uuid) {\n <li class=\"list-group-item d-flex align-items-center py-1\">\n <div class=\"list-sort-handle mr-2\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <span class=\"flex-grow-1\">{{ universe.name }}</span>\n <button class=\"btn btn-primary btn-sm\" type=\"button\" (click)=\"removeUniverse(universe)\">\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n </button>\n </li>\n }\n </ul>\n</div>\n<div class=\"modal-footer\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n" }]
|
|
5426
|
+
}], ctorParameters: () => [{ type: i1$1.BsModalRef }, { type: UuidService }] });
|
|
5427
|
+
|
|
5389
5428
|
class FixturePoolComponent {
|
|
5390
5429
|
constructor(bsModalRef, fixtureService, uuidService, projectService, previewService, translateService, toastrService, presetService, configService, modalService, livePreviewService) {
|
|
5391
5430
|
this.bsModalRef = bsModalRef;
|
|
@@ -5407,48 +5446,41 @@ class FixturePoolComponent {
|
|
|
5407
5446
|
// extend this list at runtime; otherwise it is provided by the host
|
|
5408
5447
|
// application through the ConfigService.
|
|
5409
5448
|
this.universes = [];
|
|
5410
|
-
// Name buffer for the "add universe" input shown when freeUniverseEdit is true.
|
|
5411
|
-
this.newUniverseName = '';
|
|
5412
5449
|
this.fixturePool = structuredClone(this.projectService.project.fixtures);
|
|
5413
5450
|
// Initialise the universe list from the config. We keep a local copy so
|
|
5414
5451
|
// edits done in free-edit mode don't bleed into the config until the user
|
|
5415
5452
|
// confirms with OK (see `ok()` below).
|
|
5416
5453
|
this.universes = structuredClone(this.configService.universes || []);
|
|
5417
|
-
if (this.
|
|
5418
|
-
this.
|
|
5454
|
+
if (this.universes.length === 0 && this.configService.freeUniverseEdit) {
|
|
5455
|
+
this.universes.push({ uuid: this.uuidService.getUuid(), name: 'Universe 1' });
|
|
5456
|
+
}
|
|
5457
|
+
if (this.universes.length > 0) {
|
|
5458
|
+
this.selectedUniverse = this.universes[0];
|
|
5459
|
+
}
|
|
5460
|
+
const firstVisible = this.currentUniverseFixtures[0] ?? this.fixturePool[0];
|
|
5461
|
+
if (firstVisible) {
|
|
5462
|
+
this.selectFixture(firstVisible);
|
|
5419
5463
|
}
|
|
5420
5464
|
}
|
|
5421
5465
|
get freeUniverseEdit() {
|
|
5422
5466
|
return this.configService.freeUniverseEdit;
|
|
5423
5467
|
}
|
|
5424
|
-
|
|
5425
|
-
|
|
5426
|
-
if (!
|
|
5427
|
-
return;
|
|
5428
|
-
}
|
|
5429
|
-
const universe = {
|
|
5430
|
-
uuid: this.uuidService.getUuid(),
|
|
5431
|
-
name: trimmed,
|
|
5432
|
-
};
|
|
5433
|
-
this.universes.push(universe);
|
|
5434
|
-
this.newUniverseName = '';
|
|
5435
|
-
// If the currently selected fixture has no universe yet, auto-assign
|
|
5436
|
-
// the freshly created one for convenience.
|
|
5437
|
-
if (this.selectedFixture && !this.selectedFixture.dmxUniverseUuid) {
|
|
5438
|
-
this.selectedFixture.dmxUniverseUuid = universe.uuid;
|
|
5468
|
+
/** Fixtures belonging to the currently selected universe. */
|
|
5469
|
+
get currentUniverseFixtures() {
|
|
5470
|
+
if (!this.selectedUniverse) {
|
|
5471
|
+
return this.fixturePool;
|
|
5439
5472
|
}
|
|
5473
|
+
return this.fixturePool.filter((f) => f.dmxUniverseUuid === this.selectedUniverse.uuid);
|
|
5440
5474
|
}
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
this.
|
|
5447
|
-
//
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
fixture.dmxUniverseUuid = undefined;
|
|
5451
|
-
}
|
|
5475
|
+
/** Fixtures used for channel-map calculations (same as currentUniverseFixtures). */
|
|
5476
|
+
get channelFixtures() {
|
|
5477
|
+
return this.currentUniverseFixtures;
|
|
5478
|
+
}
|
|
5479
|
+
selectUniverse(universe) {
|
|
5480
|
+
this.selectedUniverse = universe;
|
|
5481
|
+
// Deselect the current fixture if it doesn't belong to the new universe.
|
|
5482
|
+
if (this.selectedFixture && this.selectedFixture.dmxUniverseUuid !== universe?.uuid) {
|
|
5483
|
+
this.selectFixture(this.currentUniverseFixtures[0] ?? undefined);
|
|
5452
5484
|
}
|
|
5453
5485
|
}
|
|
5454
5486
|
ngOnInit() {
|
|
@@ -5498,8 +5530,9 @@ class FixturePoolComponent {
|
|
|
5498
5530
|
// minimal profile passed from the search.
|
|
5499
5531
|
this.fixtureService.loadProfileByUuid(searchProfile.uuid).subscribe(() => {
|
|
5500
5532
|
const profile = this.fixtureService.getProfileByUuid(searchProfile.uuid);
|
|
5501
|
-
const newFixture = this.fixtureService.addFixture(profile, this.fixturePool);
|
|
5533
|
+
const newFixture = this.fixtureService.addFixture(profile, this.fixturePool, this.currentUniverseFixtures);
|
|
5502
5534
|
if (newFixture) {
|
|
5535
|
+
newFixture.dmxUniverseUuid = this.selectedUniverse?.uuid;
|
|
5503
5536
|
this.selectFixture(newFixture);
|
|
5504
5537
|
}
|
|
5505
5538
|
});
|
|
@@ -5511,7 +5544,7 @@ class FixturePoolComponent {
|
|
|
5511
5544
|
fixture.name = originalFixture.name;
|
|
5512
5545
|
fixture.modeShortName = originalFixture.modeShortName;
|
|
5513
5546
|
fixture.dmxFirstChannel = originalFixture.dmxFirstChannel;
|
|
5514
|
-
fixture.dmxUniverseUuid =
|
|
5547
|
+
fixture.dmxUniverseUuid = this.selectedUniverse?.uuid;
|
|
5515
5548
|
this.fixturePool.push(fixture);
|
|
5516
5549
|
this.selectFixture(fixture);
|
|
5517
5550
|
}
|
|
@@ -5525,8 +5558,8 @@ class FixturePoolComponent {
|
|
|
5525
5558
|
break;
|
|
5526
5559
|
}
|
|
5527
5560
|
}
|
|
5528
|
-
if (!this.selectedFixture
|
|
5529
|
-
this.selectFixture(
|
|
5561
|
+
if (!this.selectedFixture) {
|
|
5562
|
+
this.selectFixture(this.currentUniverseFixtures[0] ?? undefined);
|
|
5530
5563
|
}
|
|
5531
5564
|
// remove unused profiles
|
|
5532
5565
|
for (let i = 0; i < this.projectService.project.fixtureProfiles.length; i++) {
|
|
@@ -5543,7 +5576,7 @@ class FixturePoolComponent {
|
|
|
5543
5576
|
}
|
|
5544
5577
|
}
|
|
5545
5578
|
channelOccupied(index) {
|
|
5546
|
-
for (const fixture of this.
|
|
5579
|
+
for (const fixture of this.channelFixtures) {
|
|
5547
5580
|
const profile = this.fixtureService.getProfileByUuid(fixture.profileUuid);
|
|
5548
5581
|
const mode = this.fixtureService.getModeByFixture(profile, fixture);
|
|
5549
5582
|
const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
|
|
@@ -5554,7 +5587,7 @@ class FixturePoolComponent {
|
|
|
5554
5587
|
return false;
|
|
5555
5588
|
}
|
|
5556
5589
|
channelOccupiedStart(index) {
|
|
5557
|
-
for (const fixture of this.
|
|
5590
|
+
for (const fixture of this.channelFixtures) {
|
|
5558
5591
|
if (index === fixture.dmxFirstChannel) {
|
|
5559
5592
|
return true;
|
|
5560
5593
|
}
|
|
@@ -5562,7 +5595,7 @@ class FixturePoolComponent {
|
|
|
5562
5595
|
return false;
|
|
5563
5596
|
}
|
|
5564
5597
|
channelOccupiedEnd(index) {
|
|
5565
|
-
for (const fixture of this.
|
|
5598
|
+
for (const fixture of this.channelFixtures) {
|
|
5566
5599
|
const profile = this.fixtureService.getProfileByUuid(fixture.profileUuid);
|
|
5567
5600
|
const mode = this.fixtureService.getModeByFixture(profile, fixture);
|
|
5568
5601
|
const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
|
|
@@ -5573,16 +5606,21 @@ class FixturePoolComponent {
|
|
|
5573
5606
|
return false;
|
|
5574
5607
|
}
|
|
5575
5608
|
channelOverlapped(index) {
|
|
5609
|
+
return this.channelOverlappedInFixtures(index, this.channelFixtures);
|
|
5610
|
+
}
|
|
5611
|
+
channelOverlappedInFixtures(index, fixtures) {
|
|
5576
5612
|
let occupiedFixture;
|
|
5577
|
-
for (const fixture of
|
|
5613
|
+
for (const fixture of fixtures) {
|
|
5578
5614
|
const profile = this.fixtureService.getProfileByUuid(fixture.profileUuid);
|
|
5579
5615
|
const mode = this.fixtureService.getModeByFixture(profile, fixture);
|
|
5580
5616
|
const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
|
|
5581
5617
|
if (index >= fixture.dmxFirstChannel && index < fixture.dmxFirstChannel + channelCount) {
|
|
5582
5618
|
if (occupiedFixture) {
|
|
5583
|
-
if (occupiedFixture.dmxFirstChannel !== fixture.dmxFirstChannel ||
|
|
5584
|
-
|
|
5585
|
-
|
|
5619
|
+
if (occupiedFixture.dmxFirstChannel !== fixture.dmxFirstChannel ||
|
|
5620
|
+
occupiedFixture.modeShortName !== fixture.modeShortName ||
|
|
5621
|
+
occupiedFixture.dmxUniverseUuid !== fixture.dmxUniverseUuid) {
|
|
5622
|
+
// fixtures are allowed to overlap, if they start at the same channel,
|
|
5623
|
+
// use the same mode and belong to the same universe. otherwise it's not allowed.
|
|
5586
5624
|
return true;
|
|
5587
5625
|
}
|
|
5588
5626
|
}
|
|
@@ -5599,7 +5637,7 @@ class FixturePoolComponent {
|
|
|
5599
5637
|
let newSelectedFixture;
|
|
5600
5638
|
// find a dragging fixture and select it, but don't change the selection, if the
|
|
5601
5639
|
// currently selected fixture might also be selected (on overlapped fixtures)
|
|
5602
|
-
for (const fixture of this.
|
|
5640
|
+
for (const fixture of this.channelFixtures) {
|
|
5603
5641
|
const profile = this.fixtureService.getProfileByUuid(fixture.profileUuid);
|
|
5604
5642
|
const mode = this.fixtureService.getModeByFixture(profile, fixture);
|
|
5605
5643
|
const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
|
|
@@ -5655,15 +5693,18 @@ class FixturePoolComponent {
|
|
|
5655
5693
|
}
|
|
5656
5694
|
}
|
|
5657
5695
|
ok() {
|
|
5658
|
-
// don't allow OK if overlapping fixtures exist
|
|
5659
|
-
for (
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5696
|
+
// don't allow OK if overlapping fixtures exist within any universe
|
|
5697
|
+
for (const universe of this.universes) {
|
|
5698
|
+
const universeFixtures = this.fixturePool.filter((f) => f.dmxUniverseUuid === universe.uuid);
|
|
5699
|
+
for (let i = 0; i < this.dmxChannels.length; i++) {
|
|
5700
|
+
if (this.channelOverlappedInFixtures(i, universeFixtures)) {
|
|
5701
|
+
const msg = 'designer.fixture-pool.channel-occupied';
|
|
5702
|
+
const title = 'designer.fixture-pool.channel-occupied-title';
|
|
5703
|
+
this.translateService.get([msg, title]).subscribe((result) => {
|
|
5704
|
+
this.toastrService.error(result[msg], result[title]);
|
|
5705
|
+
});
|
|
5706
|
+
return;
|
|
5707
|
+
}
|
|
5667
5708
|
}
|
|
5668
5709
|
}
|
|
5669
5710
|
// remove deleted fixtures/pixel keys from preset fixtures
|
|
@@ -5762,10 +5803,45 @@ class FixturePoolComponent {
|
|
|
5762
5803
|
});
|
|
5763
5804
|
});
|
|
5764
5805
|
}
|
|
5806
|
+
openEditUniverses() {
|
|
5807
|
+
const ref = this.modalService.show(FixturePoolEditUniversesComponent, {
|
|
5808
|
+
keyboard: true,
|
|
5809
|
+
ignoreBackdropClick: false,
|
|
5810
|
+
initialState: { universes: structuredClone(this.universes) },
|
|
5811
|
+
});
|
|
5812
|
+
ref.content.onClose.subscribe((result) => {
|
|
5813
|
+
if (!result)
|
|
5814
|
+
return;
|
|
5815
|
+
// Clear fixture universe assignments for any removed universe
|
|
5816
|
+
for (const universe of this.universes) {
|
|
5817
|
+
if (!result.find((u) => u.uuid === universe.uuid)) {
|
|
5818
|
+
for (const fixture of this.fixturePool) {
|
|
5819
|
+
if (fixture.dmxUniverseUuid === universe.uuid) {
|
|
5820
|
+
fixture.dmxUniverseUuid = undefined;
|
|
5821
|
+
}
|
|
5822
|
+
}
|
|
5823
|
+
}
|
|
5824
|
+
}
|
|
5825
|
+
this.universes = result;
|
|
5826
|
+
// Re-anchor selectedUniverse to the new object reference from result.
|
|
5827
|
+
// The modal works on a structuredClone, so all objects have new references.
|
|
5828
|
+
const stillSelected = this.universes.find((u) => u.uuid === this.selectedUniverse?.uuid);
|
|
5829
|
+
if (stillSelected) {
|
|
5830
|
+
this.selectedUniverse = stillSelected;
|
|
5831
|
+
}
|
|
5832
|
+
else {
|
|
5833
|
+
this.selectedUniverse = this.universes[0] ?? undefined;
|
|
5834
|
+
this.selectFixture(this.currentUniverseFixtures[0] ?? undefined);
|
|
5835
|
+
}
|
|
5836
|
+
});
|
|
5837
|
+
}
|
|
5765
5838
|
createFixtureFromProfileFile() {
|
|
5766
5839
|
const bsModalRef = this.modalService.show(FixturePoolCreateFromFileComponent, { keyboard: true, ignoreBackdropClick: false });
|
|
5767
5840
|
bsModalRef.content.onClose.subscribe((profile) => {
|
|
5768
|
-
const newFixture = this.fixtureService.addFixture(profile, this.fixturePool);
|
|
5841
|
+
const newFixture = this.fixtureService.addFixture(profile, this.fixturePool, this.currentUniverseFixtures);
|
|
5842
|
+
if (newFixture) {
|
|
5843
|
+
newFixture.dmxUniverseUuid = this.selectedUniverse?.uuid;
|
|
5844
|
+
}
|
|
5769
5845
|
this.selectFixture(newFixture);
|
|
5770
5846
|
});
|
|
5771
5847
|
}
|
|
@@ -5773,11 +5849,11 @@ class FixturePoolComponent {
|
|
|
5773
5849
|
this.ok();
|
|
5774
5850
|
}
|
|
5775
5851
|
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FixturePoolComponent, deps: [{ token: i1$1.BsModalRef }, { token: FixtureService }, { token: UuidService }, { token: ProjectService }, { token: PreviewService }, { token: i2.TranslateService }, { token: i3$1.ToastrService }, { token: PresetService }, { token: ConfigService }, { token: i1$1.BsModalService }, { token: LivePreviewService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
5776
|
-
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: FixturePoolComponent, isStandalone: false, selector: "lib-app-fixture-pool", host: { listeners: { "window:mouseup": "mouseUp($event)", "document:keydown.enter": "handleKeyboardEvent($event)" } }, ngImport: i0, template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.fixture-pool.title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"cancel(); (false)\">\n <span aria-hidden=\"true\">×</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <div class=\"row\">\n <div class=\"col-6\">\n <!-- Search for profiles -->\n <input\n type=\"text\"\n class=\"form-control input-block mb-3\"\n id=\"searchSet\"\n placeholder=\"{{ 'designer.fixture-pool.search-profiles' | translate }}\"\n (input)=\"searchExpression = $event.target.value; filterProfiles()\"\n />\n\n <!-- Profiles -->\n <div class=\"card border-secondary w-100\" style=\"height: 200px\">\n <div class=\"card-body p-0 w-100\">\n <div class=\"list-group list-group-flush w-100\">\n @if (loadingProfiles) {\n <a class=\"list-group-item flex-column align-items-start d-flex\">\n <p class=\"mb-0 mx-auto\">\n <i class=\"fa fa-spinner fa-pulse fa-fw\"></i>\n </p>\n </a>\n } @for (profile of filteredProfiles | sort : 'uuid'; track profile) {\n <div class=\"list-group-item\">\n <div class=\"row\">\n <div class=\"col-10 col-auto my-auto pl-2\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(profile) }} mr-1\"></span> {{ profile.manufacturerName }} -\n {{ profile.name }}\n </p>\n </div>\n <div class=\"col-2 my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"addFixture(profile); (false)\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n <div>\n <p class=\"d-inline-block mb-0 mt-2\">\n Powered by the <a href=\"https://open-fixture-library.org/\" target=\"_blank\">Open Fixture Library</a>\n </p>\n <a\n class=\"mt-2 btn btn-secondary btn-sm float-right\"\n href=\"https://open-fixture-library.org/fixture-editor\"\n target=\"_blank\"\n role=\"button\"\n >\n <i class=\"fa fa-file-o\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.add-profile' | translate }}\n </a>\n @if (configService.localProfiles) {\n <button\n type=\"button\"\n class=\"mr-2 mt-2 btn btn-secondary btn-sm float-right\"\n (click)=\"updateProfiles(); (false)\"\n [disabled]=\"updatingProfiles\"\n role=\"button\"\n >\n @if (updatingProfiles) {\n <i class=\"fa fa-spinner fa-pulse fa-fw\" aria-hidden=\"true\"></i>\n } @if (!updatingProfiles) {\n <i class=\"fa fa-download fa-fw\" aria-hidden=\"true\"></i>\n }\n {{ 'designer.fixture-pool.update-profiles' | translate }}\n </button>\n }\n </div>\n </div>\n <div class=\"col-6\">\n <div class=\"row\">\n <!-- Add fixture from local profile -->\n <div class=\"col-6\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"createFixtureFromProfileFile()\" role=\"button\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.create-fixture-from-profile-file' | translate }}\n </button>\n </div>\n\n <!-- Universe -->\n <div class=\"col-6\">\n <div class=\"form-group row\">\n <label class=\"col-lg-4 col-form-label\">{{ 'designer.fixture-pool.universe' | translate }}</label>\n <div class=\"col-lg-8\">\n <select\n class=\"custom-select\"\n [disabled]=\"!selectedFixture || universes.length === 0\"\n [ngModel]=\"selectedFixture?.dmxUniverseUuid\"\n (ngModelChange)=\"selectedFixture && (selectedFixture.dmxUniverseUuid = $event)\"\n >\n @for (universe of universes; track universe.uuid) {\n <option [ngValue]=\"universe.uuid\">{{ universe.name }}</option>\n }\n </select>\n </div>\n </div>\n\n <!-- Free universe edit: let the user add/remove their own universes -->\n @if (freeUniverseEdit) {\n <div class=\"form-group row\">\n <label class=\"col-lg-4 col-form-label\">{{ 'designer.fixture-pool.add-universe' | translate }}</label>\n <div class=\"col-lg-8\">\n <div class=\"input-group\">\n <input\n type=\"text\"\n class=\"form-control\"\n maxlength=\"200\"\n [(ngModel)]=\"newUniverseName\"\n (keydown.enter)=\"addUniverse(newUniverseName); $event.stopPropagation(); $event.preventDefault()\"\n placeholder=\"{{ 'designer.fixture-pool.universe-name' | translate }}\"\n />\n <div class=\"input-group-append\">\n <button\n type=\"button\"\n class=\"btn btn-secondary\"\n [disabled]=\"!newUniverseName || !newUniverseName.trim()\"\n (click)=\"addUniverse(newUniverseName)\"\n >\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n </div>\n </div>\n @if (universes.length > 0) {\n <div class=\"form-group row\">\n <div class=\"col-lg-12\">\n <ul class=\"list-group\">\n @for (universe of universes; track universe.uuid) {\n <li class=\"list-group-item d-flex justify-content-between align-items-center py-1\">\n <span>{{ universe.name }}</span>\n <a class=\"btn btn-primary btn-sm\" href=\"#\" role=\"button\" (click)=\"removeUniverse(universe); (false)\">\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n </a>\n </li>\n }\n </ul>\n </div>\n </div>\n } }\n </div>\n </div>\n\n <!-- Fixtures -->\n <div class=\"card border-secondary\" style=\"height: 235px\">\n <div class=\"card-body p-0\">\n <div class=\"list-group list-group-flush\" [sortablejs]=\"fixturePool\">\n @for (fixture of fixturePool; track fixture) {\n <div\n class=\"list-group-item\"\n [class.active]=\"fixture == selectedFixture\"\n (click)=\"selectFixture(fixture)\"\n style=\"cursor: pointer\"\n >\n <div class=\"row\">\n <div class=\"col-auto list-sort-handle my-auto\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"col-auto flex-grow pl-0 my-auto\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(fixtureService.getProfileByUuid(fixture.profileUuid)) }} mr-1\">\n </span\n >{{ fixture.name }}\n </p>\n </div>\n <div class=\"col-auto my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"removeFixture(fixture); (false)\">\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"row mt-3\">\n <div class=\"col\">\n <!-- Tab navigation -->\n <ul class=\"nav nav-tabs mb-4\" id=\"myTab\" role=\"tablist\">\n <li class=\"nav-item\">\n <a class=\"nav-link active\" id=\"sets-tab\" data-toggle=\"tab\" href=\"#dmx\" role=\"tab\">\n <i class=\"icon-ola\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.dmx' | translate }}\n </a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link\" id=\"compositions-tab\" data-toggle=\"tab\" href=\"#settings\" role=\"tab\">\n <i class=\"fa fa-cog\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.settings' | translate }}\n </a>\n </li>\n </ul>\n\n <!-- Tab content -->\n <div class=\"tab-content\" id=\"myTabContent\">\n <!-- DMX universe overview-->\n <div class=\"tab-pane show active\" id=\"dmx\" role=\"tabpanel\">\n <!-- Show all channel numbers -->\n <!-- <div class=\"form-group row\">\n <div class=\"col-auto flex-grow\"></div>\n <div class=\"col-lg-3 d-flex\">\n <div class=\"form-check my-auto ml-auto\">\n <input type=\"checkbox\" class=\"form-check-input\" id=\"showChannelNumbers\" [ngModel]=\"showChannelNumbers\"\n (ngModelChange)=\"showChannelNumbers = $event\">\n <label class=\"form-check-label\" for=\"showChannelNumbers\">Show channels</label>\n </div>\n </div>\n </div> -->\n\n <!-- List of DMX channels -->\n <div>\n @for (channel of dmxChannels; track $index; let i = $index) {\n <div\n class=\"dmx-channel\"\n [class.dmx-channel-occupied]=\"channelOccupied(i)\"\n [class.dmx-channel-occupied-start]=\"channelOccupiedStart(i)\"\n [class.dmx-channel-occupied-end]=\"channelOccupiedEnd(i)\"\n [class.dmx-channel-selected]=\"channelSelected(i)\"\n [class.dmx-channel-overlapped]=\"channelOverlapped(i)\"\n (mousedown)=\"channelMouseDown($event)\"\n (mouseover)=\"channelMouseOver($event)\"\n [attr.data-index]=\"i\"\n popover=\"{{ i + 1 }}\"\n placement=\"top\"\n triggers=\"mouseenter:mouseleave\"\n >\n <div class=\"d-flex w-100 dmx-channel-text\" [attr.data-index]=\"i\" [class.dmx-channel-text-visible]=\"showChannelNumbers\">\n <div class=\"m-auto\" style=\"font-size: 11px\" [attr.data-index]=\"i\"><small [attr.data-index]=\"i\"> </small></div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Fixture settings -->\n <div class=\"tab-pane\" id=\"settings\" role=\"tabpanel\">\n @if (selectedFixture && selectedFixtureProfile) {\n <div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\" for=\"fixtureName\">{{ 'designer.fixture-pool.fixture-name' | translate }}</label>\n <div class=\"col-lg-9\">\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"selectedFixture.name\" maxlength=\"200\" id=\"fixtureName\" />\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.mode' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.modeShortName\"\n (ngModelChange)=\"selectedFixture.modeShortName = $event\"\n >\n @for (mode of selectedFixtureProfile.modes; track mode) {\n <option [ngValue]=\"mode.shortName || mode.name\">\n {{ mode.name }}\n - {{ fixtureService.getModeChannelCount(selectedFixtureProfile, mode) }}\n {{ 'designer.fixture-pool.channels' | translate }}\n </option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.first-channel' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.dmxFirstChannel\"\n (ngModelChange)=\"selectedFixture.dmxFirstChannel = $event\"\n >\n @for (channel of dmxChannels; track $index; let i = $index) {\n <option [ngValue]=\"i\">\n {{ i + 1 }}\n </option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\"></label>\n <div class=\"col-lg-9\">\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"addCopy(selectedFixture)\">\n {{ 'designer.fixture.add-copy' | translate }}\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n</div>\n<div class=\"modal-footer\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n", styles: [".list-group-item{padding:.3rem 1.25rem}.dmx-channel{display:flex;float:left;width:28px;border:1px solid white;margin-left:-1px;margin-bottom:-1px;padding-bottom:2px}.dmx-channel-occupied{background-color:#63462e;border-left:none;border-right:none;cursor:move}.dmx-channel-occupied-start{border-left:1px solid white;border-top-left-radius:8px;border-bottom-left-radius:8px}.dmx-channel-occupied-end{border-right:1px solid white;border-top-right-radius:8px;border-bottom-right-radius:8px}.dmx-channel-selected{background-color:#fd7e14}.dmx-channel-overlapped{background-color:red;border:1px solid red;cursor:move}.card{overflow:auto}\n"], dependencies: [{ kind: "directive", type: i3$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i3$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i3$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i3$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i3$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i12.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "directive", type: SortablejsDirective, selector: "[sortablejs]", inputs: ["sortablejs", "sortablejsContainer", "sortablejsOptions"], outputs: ["sortablejsInit"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "pipe", type: ArraySortPipe, name: "sort" }] }); }
|
|
5852
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.16", type: FixturePoolComponent, isStandalone: false, selector: "lib-app-fixture-pool", host: { listeners: { "window:mouseup": "mouseUp($event)", "document:keydown.enter": "handleKeyboardEvent($event)" } }, ngImport: i0, template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.fixture-pool.title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"cancel(); (false)\">\n <span aria-hidden=\"true\">×</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <div class=\"row\">\n <div class=\"col-6\">\n <!-- Search for profiles -->\n <input\n type=\"text\"\n class=\"form-control input-block mb-3\"\n id=\"searchSet\"\n placeholder=\"{{ 'designer.fixture-pool.search-profiles' | translate }}\"\n (input)=\"searchExpression = $event.target.value; filterProfiles()\"\n />\n\n <!-- Profiles -->\n <div class=\"card border-secondary w-100\" style=\"height: 200px\">\n <div class=\"card-body p-0 w-100\">\n <div class=\"list-group list-group-flush w-100\">\n @if (loadingProfiles) {\n <a class=\"list-group-item flex-column align-items-start d-flex\">\n <p class=\"mb-0 mx-auto\">\n <i class=\"fa fa-spinner fa-pulse fa-fw\"></i>\n </p>\n </a>\n } @for (profile of filteredProfiles | sort : 'uuid'; track profile) {\n <div class=\"list-group-item\">\n <div class=\"row\">\n <div class=\"col-10 col-auto my-auto pl-2\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(profile) }} mr-1\"></span> {{ profile.manufacturerName }} -\n {{ profile.name }}\n </p>\n </div>\n <div class=\"col-2 my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"addFixture(profile); (false)\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n <div>\n <p class=\"d-inline-block mb-0 mt-2\">\n Powered by the <a href=\"https://open-fixture-library.org/\" target=\"_blank\">Open Fixture Library</a>\n </p>\n <a\n class=\"mt-2 btn btn-secondary btn-sm float-right\"\n href=\"https://open-fixture-library.org/fixture-editor\"\n target=\"_blank\"\n role=\"button\"\n >\n <i class=\"fa fa-file-o\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.add-profile' | translate }}\n </a>\n @if (configService.localProfiles) {\n <button\n type=\"button\"\n class=\"mr-2 mt-2 btn btn-secondary btn-sm float-right\"\n (click)=\"updateProfiles(); (false)\"\n [disabled]=\"updatingProfiles\"\n role=\"button\"\n >\n @if (updatingProfiles) {\n <i class=\"fa fa-spinner fa-pulse fa-fw\" aria-hidden=\"true\"></i>\n } @if (!updatingProfiles) {\n <i class=\"fa fa-download fa-fw\" aria-hidden=\"true\"></i>\n }\n {{ 'designer.fixture-pool.update-profiles' | translate }}\n </button>\n }\n </div>\n </div>\n <div class=\"col-6\">\n <div class=\"row\">\n <!-- Add fixture from local profile -->\n <div class=\"col-6\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"createFixtureFromProfileFile()\" role=\"button\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.create-fixture-from-profile-file' | translate }}\n </button>\n </div>\n\n <!-- Universe -->\n <div class=\"col-6\">\n <div class=\"form-group row\">\n <label class=\"col-lg-4 col-form-label\">{{ 'designer.fixture-pool.universe' | translate }}</label>\n <div class=\"col-lg-8\">\n <div class=\"input-group\">\n <select\n class=\"custom-select\"\n [disabled]=\"universes.length === 0\"\n [ngModel]=\"selectedUniverse\"\n (ngModelChange)=\"selectUniverse($event)\"\n >\n @for (universe of universes; track universe.uuid) {\n <option [ngValue]=\"universe\">{{ universe.name }}</option>\n }\n </select>\n @if (freeUniverseEdit) {\n <div class=\"input-group-append\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"openEditUniverses()\">\n <i class=\"fa fa-pencil\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Fixtures -->\n <div class=\"card border-secondary\" style=\"height: 235px\">\n <div class=\"card-body p-0\">\n <div class=\"list-group list-group-flush\" [sortablejs]=\"fixturePool\">\n @for (fixture of currentUniverseFixtures; track fixture) {\n <div\n class=\"list-group-item\"\n [class.active]=\"fixture == selectedFixture\"\n (click)=\"selectFixture(fixture)\"\n style=\"cursor: pointer\"\n >\n <div class=\"row\">\n <div class=\"col-auto list-sort-handle my-auto\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"col-auto flex-grow pl-0 my-auto\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(fixtureService.getProfileByUuid(fixture.profileUuid)) }} mr-1\">\n </span\n >{{ fixture.name }}\n </p>\n </div>\n <div class=\"col-auto my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"removeFixture(fixture); (false)\">\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"row mt-3\">\n <div class=\"col\">\n <!-- Tab navigation -->\n <ul class=\"nav nav-tabs mb-4\" id=\"myTab\" role=\"tablist\">\n <li class=\"nav-item\">\n <a class=\"nav-link active\" id=\"sets-tab\" data-toggle=\"tab\" href=\"#dmx\" role=\"tab\">\n <i class=\"icon-ola\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.dmx' | translate }}\n </a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link\" id=\"compositions-tab\" data-toggle=\"tab\" href=\"#settings\" role=\"tab\">\n <i class=\"fa fa-cog\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.settings' | translate }}\n </a>\n </li>\n </ul>\n\n <!-- Tab content -->\n <div class=\"tab-content\" id=\"myTabContent\">\n <!-- DMX universe overview-->\n <div class=\"tab-pane show active\" id=\"dmx\" role=\"tabpanel\">\n <!-- Show all channel numbers -->\n <!-- <div class=\"form-group row\">\n <div class=\"col-auto flex-grow\"></div>\n <div class=\"col-lg-3 d-flex\">\n <div class=\"form-check my-auto ml-auto\">\n <input type=\"checkbox\" class=\"form-check-input\" id=\"showChannelNumbers\" [ngModel]=\"showChannelNumbers\"\n (ngModelChange)=\"showChannelNumbers = $event\">\n <label class=\"form-check-label\" for=\"showChannelNumbers\">Show channels</label>\n </div>\n </div>\n </div> -->\n\n <!-- List of DMX channels -->\n <div>\n @for (channel of dmxChannels; track $index; let i = $index) {\n <div\n class=\"dmx-channel\"\n [class.dmx-channel-occupied]=\"channelOccupied(i)\"\n [class.dmx-channel-occupied-start]=\"channelOccupiedStart(i)\"\n [class.dmx-channel-occupied-end]=\"channelOccupiedEnd(i)\"\n [class.dmx-channel-selected]=\"channelSelected(i)\"\n [class.dmx-channel-overlapped]=\"channelOverlapped(i)\"\n (mousedown)=\"channelMouseDown($event)\"\n (mouseover)=\"channelMouseOver($event)\"\n [attr.data-index]=\"i\"\n popover=\"{{ i + 1 }}\"\n placement=\"top\"\n triggers=\"mouseenter:mouseleave\"\n >\n <div class=\"d-flex w-100 dmx-channel-text\" [attr.data-index]=\"i\" [class.dmx-channel-text-visible]=\"showChannelNumbers\">\n <div class=\"m-auto\" style=\"font-size: 11px\" [attr.data-index]=\"i\"><small [attr.data-index]=\"i\"> </small></div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Fixture settings -->\n <div class=\"tab-pane\" id=\"settings\" role=\"tabpanel\">\n @if (selectedFixture && selectedFixtureProfile) {\n <div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\" for=\"fixtureName\">{{ 'designer.fixture-pool.fixture-name' | translate }}</label>\n <div class=\"col-lg-9\">\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"selectedFixture.name\" maxlength=\"200\" id=\"fixtureName\" />\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.mode' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.modeShortName\"\n (ngModelChange)=\"selectedFixture.modeShortName = $event\"\n >\n @for (mode of selectedFixtureProfile.modes; track mode) {\n <option [ngValue]=\"mode.shortName || mode.name\">\n {{ mode.name }}\n - {{ fixtureService.getModeChannelCount(selectedFixtureProfile, mode) }}\n {{ 'designer.fixture-pool.channels' | translate }}\n </option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.universe' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [disabled]=\"universes.length === 0\"\n [ngModel]=\"selectedFixture.dmxUniverseUuid\"\n (ngModelChange)=\"selectedFixture.dmxUniverseUuid = $event\"\n >\n @for (universe of universes; track universe.uuid) {\n <option [ngValue]=\"universe.uuid\">{{ universe.name }}</option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.first-channel' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.dmxFirstChannel\"\n (ngModelChange)=\"selectedFixture.dmxFirstChannel = $event\"\n >\n @for (channel of dmxChannels; track $index; let i = $index) {\n <option [ngValue]=\"i\">\n {{ i + 1 }}\n </option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\"></label>\n <div class=\"col-lg-9\">\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"addCopy(selectedFixture)\">\n {{ 'designer.fixture.add-copy' | translate }}\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n</div>\n<div class=\"modal-footer\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n", styles: [".list-group-item{padding:.3rem 1.25rem}.dmx-channel{display:flex;float:left;width:28px;border:1px solid white;margin-left:-1px;margin-bottom:-1px;padding-bottom:2px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.dmx-channel-occupied{background-color:#63462e;border-left:none;border-right:none;cursor:move}.dmx-channel-occupied-start{border-left:1px solid white;border-top-left-radius:8px;border-bottom-left-radius:8px}.dmx-channel-occupied-end{border-right:1px solid white;border-top-right-radius:8px;border-bottom-right-radius:8px}.dmx-channel-selected{background-color:#fd7e14}.dmx-channel-overlapped{background-color:red;border:1px solid red;cursor:move}.card{overflow:auto}\n"], dependencies: [{ kind: "directive", type: i3$2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i3$2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i3$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i3$2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i3$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i3$2.MaxLengthValidator, selector: "[maxlength][formControlName],[maxlength][formControl],[maxlength][ngModel]", inputs: ["maxlength"] }, { kind: "directive", type: i3$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "directive", type: i12.PopoverDirective, selector: "[popover]", inputs: ["adaptivePosition", "boundariesElement", "popover", "popoverContext", "popoverTitle", "placement", "outsideClick", "triggers", "container", "containerClass", "isOpen", "delay"], outputs: ["onShown", "onHidden"], exportAs: ["bs-popover"] }, { kind: "directive", type: SortablejsDirective, selector: "[sortablejs]", inputs: ["sortablejs", "sortablejsContainer", "sortablejsOptions"], outputs: ["sortablejsInit"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }, { kind: "pipe", type: ArraySortPipe, name: "sort" }] }); }
|
|
5777
5853
|
}
|
|
5778
5854
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FixturePoolComponent, decorators: [{
|
|
5779
5855
|
type: Component,
|
|
5780
|
-
args: [{ selector: 'lib-app-fixture-pool', standalone: false, template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.fixture-pool.title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"cancel(); (false)\">\n <span aria-hidden=\"true\">×</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <div class=\"row\">\n <div class=\"col-6\">\n <!-- Search for profiles -->\n <input\n type=\"text\"\n class=\"form-control input-block mb-3\"\n id=\"searchSet\"\n placeholder=\"{{ 'designer.fixture-pool.search-profiles' | translate }}\"\n (input)=\"searchExpression = $event.target.value; filterProfiles()\"\n />\n\n <!-- Profiles -->\n <div class=\"card border-secondary w-100\" style=\"height: 200px\">\n <div class=\"card-body p-0 w-100\">\n <div class=\"list-group list-group-flush w-100\">\n @if (loadingProfiles) {\n <a class=\"list-group-item flex-column align-items-start d-flex\">\n <p class=\"mb-0 mx-auto\">\n <i class=\"fa fa-spinner fa-pulse fa-fw\"></i>\n </p>\n </a>\n } @for (profile of filteredProfiles | sort : 'uuid'; track profile) {\n <div class=\"list-group-item\">\n <div class=\"row\">\n <div class=\"col-10 col-auto my-auto pl-2\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(profile) }} mr-1\"></span> {{ profile.manufacturerName }} -\n {{ profile.name }}\n </p>\n </div>\n <div class=\"col-2 my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"addFixture(profile); (false)\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n <div>\n <p class=\"d-inline-block mb-0 mt-2\">\n Powered by the <a href=\"https://open-fixture-library.org/\" target=\"_blank\">Open Fixture Library</a>\n </p>\n <a\n class=\"mt-2 btn btn-secondary btn-sm float-right\"\n href=\"https://open-fixture-library.org/fixture-editor\"\n target=\"_blank\"\n role=\"button\"\n >\n <i class=\"fa fa-file-o\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.add-profile' | translate }}\n </a>\n @if (configService.localProfiles) {\n <button\n type=\"button\"\n class=\"mr-2 mt-2 btn btn-secondary btn-sm float-right\"\n (click)=\"updateProfiles(); (false)\"\n [disabled]=\"updatingProfiles\"\n role=\"button\"\n >\n @if (updatingProfiles) {\n <i class=\"fa fa-spinner fa-pulse fa-fw\" aria-hidden=\"true\"></i>\n } @if (!updatingProfiles) {\n <i class=\"fa fa-download fa-fw\" aria-hidden=\"true\"></i>\n }\n {{ 'designer.fixture-pool.update-profiles' | translate }}\n </button>\n }\n </div>\n </div>\n <div class=\"col-6\">\n <div class=\"row\">\n <!-- Add fixture from local profile -->\n <div class=\"col-6\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"createFixtureFromProfileFile()\" role=\"button\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.create-fixture-from-profile-file' | translate }}\n </button>\n </div>\n\n <!-- Universe -->\n <div class=\"col-6\">\n <div class=\"form-group row\">\n <label class=\"col-lg-4 col-form-label\">{{ 'designer.fixture-pool.universe' | translate }}</label>\n <div class=\"col-lg-8\">\n <select\n class=\"custom-select\"\n [disabled]=\"!selectedFixture || universes.length === 0\"\n [ngModel]=\"selectedFixture?.dmxUniverseUuid\"\n (ngModelChange)=\"selectedFixture && (selectedFixture.dmxUniverseUuid = $event)\"\n >\n @for (universe of universes; track universe.uuid) {\n <option [ngValue]=\"universe.uuid\">{{ universe.name }}</option>\n }\n </select>\n </div>\n </div>\n\n <!-- Free universe edit: let the user add/remove their own universes -->\n @if (freeUniverseEdit) {\n <div class=\"form-group row\">\n <label class=\"col-lg-4 col-form-label\">{{ 'designer.fixture-pool.add-universe' | translate }}</label>\n <div class=\"col-lg-8\">\n <div class=\"input-group\">\n <input\n type=\"text\"\n class=\"form-control\"\n maxlength=\"200\"\n [(ngModel)]=\"newUniverseName\"\n (keydown.enter)=\"addUniverse(newUniverseName); $event.stopPropagation(); $event.preventDefault()\"\n placeholder=\"{{ 'designer.fixture-pool.universe-name' | translate }}\"\n />\n <div class=\"input-group-append\">\n <button\n type=\"button\"\n class=\"btn btn-secondary\"\n [disabled]=\"!newUniverseName || !newUniverseName.trim()\"\n (click)=\"addUniverse(newUniverseName)\"\n >\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </button>\n </div>\n </div>\n </div>\n </div>\n @if (universes.length > 0) {\n <div class=\"form-group row\">\n <div class=\"col-lg-12\">\n <ul class=\"list-group\">\n @for (universe of universes; track universe.uuid) {\n <li class=\"list-group-item d-flex justify-content-between align-items-center py-1\">\n <span>{{ universe.name }}</span>\n <a class=\"btn btn-primary btn-sm\" href=\"#\" role=\"button\" (click)=\"removeUniverse(universe); (false)\">\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n </a>\n </li>\n }\n </ul>\n </div>\n </div>\n } }\n </div>\n </div>\n\n <!-- Fixtures -->\n <div class=\"card border-secondary\" style=\"height: 235px\">\n <div class=\"card-body p-0\">\n <div class=\"list-group list-group-flush\" [sortablejs]=\"fixturePool\">\n @for (fixture of fixturePool; track fixture) {\n <div\n class=\"list-group-item\"\n [class.active]=\"fixture == selectedFixture\"\n (click)=\"selectFixture(fixture)\"\n style=\"cursor: pointer\"\n >\n <div class=\"row\">\n <div class=\"col-auto list-sort-handle my-auto\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"col-auto flex-grow pl-0 my-auto\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(fixtureService.getProfileByUuid(fixture.profileUuid)) }} mr-1\">\n </span\n >{{ fixture.name }}\n </p>\n </div>\n <div class=\"col-auto my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"removeFixture(fixture); (false)\">\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"row mt-3\">\n <div class=\"col\">\n <!-- Tab navigation -->\n <ul class=\"nav nav-tabs mb-4\" id=\"myTab\" role=\"tablist\">\n <li class=\"nav-item\">\n <a class=\"nav-link active\" id=\"sets-tab\" data-toggle=\"tab\" href=\"#dmx\" role=\"tab\">\n <i class=\"icon-ola\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.dmx' | translate }}\n </a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link\" id=\"compositions-tab\" data-toggle=\"tab\" href=\"#settings\" role=\"tab\">\n <i class=\"fa fa-cog\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.settings' | translate }}\n </a>\n </li>\n </ul>\n\n <!-- Tab content -->\n <div class=\"tab-content\" id=\"myTabContent\">\n <!-- DMX universe overview-->\n <div class=\"tab-pane show active\" id=\"dmx\" role=\"tabpanel\">\n <!-- Show all channel numbers -->\n <!-- <div class=\"form-group row\">\n <div class=\"col-auto flex-grow\"></div>\n <div class=\"col-lg-3 d-flex\">\n <div class=\"form-check my-auto ml-auto\">\n <input type=\"checkbox\" class=\"form-check-input\" id=\"showChannelNumbers\" [ngModel]=\"showChannelNumbers\"\n (ngModelChange)=\"showChannelNumbers = $event\">\n <label class=\"form-check-label\" for=\"showChannelNumbers\">Show channels</label>\n </div>\n </div>\n </div> -->\n\n <!-- List of DMX channels -->\n <div>\n @for (channel of dmxChannels; track $index; let i = $index) {\n <div\n class=\"dmx-channel\"\n [class.dmx-channel-occupied]=\"channelOccupied(i)\"\n [class.dmx-channel-occupied-start]=\"channelOccupiedStart(i)\"\n [class.dmx-channel-occupied-end]=\"channelOccupiedEnd(i)\"\n [class.dmx-channel-selected]=\"channelSelected(i)\"\n [class.dmx-channel-overlapped]=\"channelOverlapped(i)\"\n (mousedown)=\"channelMouseDown($event)\"\n (mouseover)=\"channelMouseOver($event)\"\n [attr.data-index]=\"i\"\n popover=\"{{ i + 1 }}\"\n placement=\"top\"\n triggers=\"mouseenter:mouseleave\"\n >\n <div class=\"d-flex w-100 dmx-channel-text\" [attr.data-index]=\"i\" [class.dmx-channel-text-visible]=\"showChannelNumbers\">\n <div class=\"m-auto\" style=\"font-size: 11px\" [attr.data-index]=\"i\"><small [attr.data-index]=\"i\"> </small></div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Fixture settings -->\n <div class=\"tab-pane\" id=\"settings\" role=\"tabpanel\">\n @if (selectedFixture && selectedFixtureProfile) {\n <div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\" for=\"fixtureName\">{{ 'designer.fixture-pool.fixture-name' | translate }}</label>\n <div class=\"col-lg-9\">\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"selectedFixture.name\" maxlength=\"200\" id=\"fixtureName\" />\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.mode' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.modeShortName\"\n (ngModelChange)=\"selectedFixture.modeShortName = $event\"\n >\n @for (mode of selectedFixtureProfile.modes; track mode) {\n <option [ngValue]=\"mode.shortName || mode.name\">\n {{ mode.name }}\n - {{ fixtureService.getModeChannelCount(selectedFixtureProfile, mode) }}\n {{ 'designer.fixture-pool.channels' | translate }}\n </option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.first-channel' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.dmxFirstChannel\"\n (ngModelChange)=\"selectedFixture.dmxFirstChannel = $event\"\n >\n @for (channel of dmxChannels; track $index; let i = $index) {\n <option [ngValue]=\"i\">\n {{ i + 1 }}\n </option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\"></label>\n <div class=\"col-lg-9\">\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"addCopy(selectedFixture)\">\n {{ 'designer.fixture.add-copy' | translate }}\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n</div>\n<div class=\"modal-footer\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n", styles: [".list-group-item{padding:.3rem 1.25rem}.dmx-channel{display:flex;float:left;width:28px;border:1px solid white;margin-left:-1px;margin-bottom:-1px;padding-bottom:2px}.dmx-channel-occupied{background-color:#63462e;border-left:none;border-right:none;cursor:move}.dmx-channel-occupied-start{border-left:1px solid white;border-top-left-radius:8px;border-bottom-left-radius:8px}.dmx-channel-occupied-end{border-right:1px solid white;border-top-right-radius:8px;border-bottom-right-radius:8px}.dmx-channel-selected{background-color:#fd7e14}.dmx-channel-overlapped{background-color:red;border:1px solid red;cursor:move}.card{overflow:auto}\n"] }]
|
|
5856
|
+
args: [{ selector: 'lib-app-fixture-pool', standalone: false, template: "<div class=\"modal-header\">\n <h4 class=\"modal-title pull-left\">{{ 'designer.fixture-pool.title' | translate }}</h4>\n <button type=\"button\" class=\"close pull-right\" aria-label=\"Close\" (click)=\"cancel(); (false)\">\n <span aria-hidden=\"true\">×</span>\n </button>\n</div>\n<div class=\"modal-body\">\n <div class=\"row\">\n <div class=\"col-6\">\n <!-- Search for profiles -->\n <input\n type=\"text\"\n class=\"form-control input-block mb-3\"\n id=\"searchSet\"\n placeholder=\"{{ 'designer.fixture-pool.search-profiles' | translate }}\"\n (input)=\"searchExpression = $event.target.value; filterProfiles()\"\n />\n\n <!-- Profiles -->\n <div class=\"card border-secondary w-100\" style=\"height: 200px\">\n <div class=\"card-body p-0 w-100\">\n <div class=\"list-group list-group-flush w-100\">\n @if (loadingProfiles) {\n <a class=\"list-group-item flex-column align-items-start d-flex\">\n <p class=\"mb-0 mx-auto\">\n <i class=\"fa fa-spinner fa-pulse fa-fw\"></i>\n </p>\n </a>\n } @for (profile of filteredProfiles | sort : 'uuid'; track profile) {\n <div class=\"list-group-item\">\n <div class=\"row\">\n <div class=\"col-10 col-auto my-auto pl-2\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(profile) }} mr-1\"></span> {{ profile.manufacturerName }} -\n {{ profile.name }}\n </p>\n </div>\n <div class=\"col-2 my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"addFixture(profile); (false)\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n <div>\n <p class=\"d-inline-block mb-0 mt-2\">\n Powered by the <a href=\"https://open-fixture-library.org/\" target=\"_blank\">Open Fixture Library</a>\n </p>\n <a\n class=\"mt-2 btn btn-secondary btn-sm float-right\"\n href=\"https://open-fixture-library.org/fixture-editor\"\n target=\"_blank\"\n role=\"button\"\n >\n <i class=\"fa fa-file-o\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.add-profile' | translate }}\n </a>\n @if (configService.localProfiles) {\n <button\n type=\"button\"\n class=\"mr-2 mt-2 btn btn-secondary btn-sm float-right\"\n (click)=\"updateProfiles(); (false)\"\n [disabled]=\"updatingProfiles\"\n role=\"button\"\n >\n @if (updatingProfiles) {\n <i class=\"fa fa-spinner fa-pulse fa-fw\" aria-hidden=\"true\"></i>\n } @if (!updatingProfiles) {\n <i class=\"fa fa-download fa-fw\" aria-hidden=\"true\"></i>\n }\n {{ 'designer.fixture-pool.update-profiles' | translate }}\n </button>\n }\n </div>\n </div>\n <div class=\"col-6\">\n <div class=\"row\">\n <!-- Add fixture from local profile -->\n <div class=\"col-6\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"createFixtureFromProfileFile()\" role=\"button\">\n <i class=\"fa fa-plus\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.create-fixture-from-profile-file' | translate }}\n </button>\n </div>\n\n <!-- Universe -->\n <div class=\"col-6\">\n <div class=\"form-group row\">\n <label class=\"col-lg-4 col-form-label\">{{ 'designer.fixture-pool.universe' | translate }}</label>\n <div class=\"col-lg-8\">\n <div class=\"input-group\">\n <select\n class=\"custom-select\"\n [disabled]=\"universes.length === 0\"\n [ngModel]=\"selectedUniverse\"\n (ngModelChange)=\"selectUniverse($event)\"\n >\n @for (universe of universes; track universe.uuid) {\n <option [ngValue]=\"universe\">{{ universe.name }}</option>\n }\n </select>\n @if (freeUniverseEdit) {\n <div class=\"input-group-append\">\n <button type=\"button\" class=\"btn btn-secondary\" (click)=\"openEditUniverses()\">\n <i class=\"fa fa-pencil\" aria-hidden=\"true\"></i>\n </button>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n\n <!-- Fixtures -->\n <div class=\"card border-secondary\" style=\"height: 235px\">\n <div class=\"card-body p-0\">\n <div class=\"list-group list-group-flush\" [sortablejs]=\"fixturePool\">\n @for (fixture of currentUniverseFixtures; track fixture) {\n <div\n class=\"list-group-item\"\n [class.active]=\"fixture == selectedFixture\"\n (click)=\"selectFixture(fixture)\"\n style=\"cursor: pointer\"\n >\n <div class=\"row\">\n <div class=\"col-auto list-sort-handle my-auto\" style=\"cursor: move; cursor: -webkit-grabbing\">\n <i class=\"fa fa-bars\" aria-hidden=\"true\"></i>\n </div>\n <div class=\"col-auto flex-grow pl-0 my-auto\">\n <p class=\"mb-0\">\n <span class=\"icon-{{ fixtureService.getFixtureIconClass(fixtureService.getProfileByUuid(fixture.profileUuid)) }} mr-1\">\n </span\n >{{ fixture.name }}\n </p>\n </div>\n <div class=\"col-auto my-auto\">\n <a class=\"btn btn-primary btn-sm float-right\" href=\"#\" role=\"button\" (click)=\"removeFixture(fixture); (false)\">\n <i class=\"fa fa-minus\" aria-hidden=\"true\"></i>\n </a>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n </div>\n <div class=\"row mt-3\">\n <div class=\"col\">\n <!-- Tab navigation -->\n <ul class=\"nav nav-tabs mb-4\" id=\"myTab\" role=\"tablist\">\n <li class=\"nav-item\">\n <a class=\"nav-link active\" id=\"sets-tab\" data-toggle=\"tab\" href=\"#dmx\" role=\"tab\">\n <i class=\"icon-ola\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.dmx' | translate }}\n </a>\n </li>\n <li class=\"nav-item\">\n <a class=\"nav-link\" id=\"compositions-tab\" data-toggle=\"tab\" href=\"#settings\" role=\"tab\">\n <i class=\"fa fa-cog\" aria-hidden=\"true\"></i> {{ 'designer.fixture-pool.settings' | translate }}\n </a>\n </li>\n </ul>\n\n <!-- Tab content -->\n <div class=\"tab-content\" id=\"myTabContent\">\n <!-- DMX universe overview-->\n <div class=\"tab-pane show active\" id=\"dmx\" role=\"tabpanel\">\n <!-- Show all channel numbers -->\n <!-- <div class=\"form-group row\">\n <div class=\"col-auto flex-grow\"></div>\n <div class=\"col-lg-3 d-flex\">\n <div class=\"form-check my-auto ml-auto\">\n <input type=\"checkbox\" class=\"form-check-input\" id=\"showChannelNumbers\" [ngModel]=\"showChannelNumbers\"\n (ngModelChange)=\"showChannelNumbers = $event\">\n <label class=\"form-check-label\" for=\"showChannelNumbers\">Show channels</label>\n </div>\n </div>\n </div> -->\n\n <!-- List of DMX channels -->\n <div>\n @for (channel of dmxChannels; track $index; let i = $index) {\n <div\n class=\"dmx-channel\"\n [class.dmx-channel-occupied]=\"channelOccupied(i)\"\n [class.dmx-channel-occupied-start]=\"channelOccupiedStart(i)\"\n [class.dmx-channel-occupied-end]=\"channelOccupiedEnd(i)\"\n [class.dmx-channel-selected]=\"channelSelected(i)\"\n [class.dmx-channel-overlapped]=\"channelOverlapped(i)\"\n (mousedown)=\"channelMouseDown($event)\"\n (mouseover)=\"channelMouseOver($event)\"\n [attr.data-index]=\"i\"\n popover=\"{{ i + 1 }}\"\n placement=\"top\"\n triggers=\"mouseenter:mouseleave\"\n >\n <div class=\"d-flex w-100 dmx-channel-text\" [attr.data-index]=\"i\" [class.dmx-channel-text-visible]=\"showChannelNumbers\">\n <div class=\"m-auto\" style=\"font-size: 11px\" [attr.data-index]=\"i\"><small [attr.data-index]=\"i\"> </small></div>\n </div>\n </div>\n }\n </div>\n </div>\n\n <!-- Fixture settings -->\n <div class=\"tab-pane\" id=\"settings\" role=\"tabpanel\">\n @if (selectedFixture && selectedFixtureProfile) {\n <div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\" for=\"fixtureName\">{{ 'designer.fixture-pool.fixture-name' | translate }}</label>\n <div class=\"col-lg-9\">\n <input type=\"text\" class=\"form-control\" [(ngModel)]=\"selectedFixture.name\" maxlength=\"200\" id=\"fixtureName\" />\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.mode' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.modeShortName\"\n (ngModelChange)=\"selectedFixture.modeShortName = $event\"\n >\n @for (mode of selectedFixtureProfile.modes; track mode) {\n <option [ngValue]=\"mode.shortName || mode.name\">\n {{ mode.name }}\n - {{ fixtureService.getModeChannelCount(selectedFixtureProfile, mode) }}\n {{ 'designer.fixture-pool.channels' | translate }}\n </option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.universe' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [disabled]=\"universes.length === 0\"\n [ngModel]=\"selectedFixture.dmxUniverseUuid\"\n (ngModelChange)=\"selectedFixture.dmxUniverseUuid = $event\"\n >\n @for (universe of universes; track universe.uuid) {\n <option [ngValue]=\"universe.uuid\">{{ universe.name }}</option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\">{{ 'designer.fixture-pool.first-channel' | translate }}</label>\n <div class=\"col-lg-9\">\n <select\n class=\"custom-select\"\n [ngModel]=\"selectedFixture.dmxFirstChannel\"\n (ngModelChange)=\"selectedFixture.dmxFirstChannel = $event\"\n >\n @for (channel of dmxChannels; track $index; let i = $index) {\n <option [ngValue]=\"i\">\n {{ i + 1 }}\n </option>\n }\n </select>\n </div>\n </div>\n <div class=\"form-group row\">\n <label class=\"col-lg-3 col-form-label\"></label>\n <div class=\"col-lg-9\">\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"addCopy(selectedFixture)\">\n {{ 'designer.fixture.add-copy' | translate }}\n </button>\n </div>\n </div>\n </div>\n }\n </div>\n </div>\n </div>\n </div>\n</div>\n<div class=\"modal-footer\">\n <a class=\"mr-3 my-auto\" href=\"#\" role=\"button\" (click)=\"cancel(); (false)\">\n {{ 'designer.misc.cancel' | translate }}\n </a>\n <button type=\"button\" class=\"btn btn-primary\" (click)=\"ok()\">{{ 'designer.misc.ok' | translate }}</button>\n</div>\n", styles: [".list-group-item{padding:.3rem 1.25rem}.dmx-channel{display:flex;float:left;width:28px;border:1px solid white;margin-left:-1px;margin-bottom:-1px;padding-bottom:2px;-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}.dmx-channel-occupied{background-color:#63462e;border-left:none;border-right:none;cursor:move}.dmx-channel-occupied-start{border-left:1px solid white;border-top-left-radius:8px;border-bottom-left-radius:8px}.dmx-channel-occupied-end{border-right:1px solid white;border-top-right-radius:8px;border-bottom-right-radius:8px}.dmx-channel-selected{background-color:#fd7e14}.dmx-channel-overlapped{background-color:red;border:1px solid red;cursor:move}.card{overflow:auto}\n"] }]
|
|
5781
5857
|
}], ctorParameters: () => [{ type: i1$1.BsModalRef }, { type: FixtureService }, { type: UuidService }, { type: ProjectService }, { type: PreviewService }, { type: i2.TranslateService }, { type: i3$1.ToastrService }, { type: PresetService }, { type: ConfigService }, { type: i1$1.BsModalService }, { type: LivePreviewService }], propDecorators: { mouseUp: [{
|
|
5782
5858
|
type: HostListener,
|
|
5783
5859
|
args: ['window:mouseup', ['$event']]
|
|
@@ -8691,6 +8767,7 @@ class DesignerModule {
|
|
|
8691
8767
|
SceneSettingsComponent,
|
|
8692
8768
|
ProjectSaveComponent,
|
|
8693
8769
|
FixturePoolCreateFromFileComponent,
|
|
8770
|
+
FixturePoolEditUniversesComponent,
|
|
8694
8771
|
DropzoneComponent,
|
|
8695
8772
|
SortablejsDirective], imports: [i3.RouterModule, BrowserModule,
|
|
8696
8773
|
BrowserAnimationsModule,
|
|
@@ -8757,6 +8834,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
8757
8834
|
SceneSettingsComponent,
|
|
8758
8835
|
ProjectSaveComponent,
|
|
8759
8836
|
FixturePoolCreateFromFileComponent,
|
|
8837
|
+
FixturePoolEditUniversesComponent,
|
|
8760
8838
|
DropzoneComponent,
|
|
8761
8839
|
SortablejsDirective,
|
|
8762
8840
|
],
|