@rocketshow/designer 1.63.0 → 1.64.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 +128 -54
- package/fesm2022/rocketshow-designer.mjs.map +1 -1
- package/index.d.ts +37 -17
- package/package.json +1 -1
- package/rocketshow-designer-1.64.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);
|
|
@@ -5386,6 +5386,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
5386
5386
|
type: Output
|
|
5387
5387
|
}] } });
|
|
5388
5388
|
|
|
5389
|
+
class FixturePoolEditUniversesComponent {
|
|
5390
|
+
constructor(bsModalRef, uuidService) {
|
|
5391
|
+
this.bsModalRef = bsModalRef;
|
|
5392
|
+
this.uuidService = uuidService;
|
|
5393
|
+
this.universes = [];
|
|
5394
|
+
this.newUniverseName = '';
|
|
5395
|
+
this.onClose = new Subject();
|
|
5396
|
+
}
|
|
5397
|
+
addUniverse() {
|
|
5398
|
+
const name = (this.newUniverseName || '').trim();
|
|
5399
|
+
if (!name)
|
|
5400
|
+
return;
|
|
5401
|
+
this.universes.push({ uuid: this.uuidService.getUuid(), name });
|
|
5402
|
+
this.newUniverseName = '';
|
|
5403
|
+
}
|
|
5404
|
+
removeUniverse(universe) {
|
|
5405
|
+
const index = this.universes.findIndex((u) => u.uuid === universe.uuid);
|
|
5406
|
+
if (index >= 0) {
|
|
5407
|
+
this.universes.splice(index, 1);
|
|
5408
|
+
}
|
|
5409
|
+
}
|
|
5410
|
+
ok() {
|
|
5411
|
+
this.onClose.next(this.universes);
|
|
5412
|
+
this.bsModalRef.hide();
|
|
5413
|
+
}
|
|
5414
|
+
cancel() {
|
|
5415
|
+
this.onClose.next(undefined);
|
|
5416
|
+
this.bsModalRef.hide();
|
|
5417
|
+
}
|
|
5418
|
+
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 }); }
|
|
5419
|
+
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\n type=\"button\"\n class=\"btn btn-secondary\"\n [disabled]=\"!newUniverseName || !newUniverseName.trim()\"\n (click)=\"addUniverse()\"\n >\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" }] }); }
|
|
5420
|
+
}
|
|
5421
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FixturePoolEditUniversesComponent, decorators: [{
|
|
5422
|
+
type: Component,
|
|
5423
|
+
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\n type=\"button\"\n class=\"btn btn-secondary\"\n [disabled]=\"!newUniverseName || !newUniverseName.trim()\"\n (click)=\"addUniverse()\"\n >\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" }]
|
|
5424
|
+
}], ctorParameters: () => [{ type: i1$1.BsModalRef }, { type: UuidService }] });
|
|
5425
|
+
|
|
5389
5426
|
class FixturePoolComponent {
|
|
5390
5427
|
constructor(bsModalRef, fixtureService, uuidService, projectService, previewService, translateService, toastrService, presetService, configService, modalService, livePreviewService) {
|
|
5391
5428
|
this.bsModalRef = bsModalRef;
|
|
@@ -5407,48 +5444,41 @@ class FixturePoolComponent {
|
|
|
5407
5444
|
// extend this list at runtime; otherwise it is provided by the host
|
|
5408
5445
|
// application through the ConfigService.
|
|
5409
5446
|
this.universes = [];
|
|
5410
|
-
// Name buffer for the "add universe" input shown when freeUniverseEdit is true.
|
|
5411
|
-
this.newUniverseName = '';
|
|
5412
5447
|
this.fixturePool = structuredClone(this.projectService.project.fixtures);
|
|
5413
5448
|
// Initialise the universe list from the config. We keep a local copy so
|
|
5414
5449
|
// edits done in free-edit mode don't bleed into the config until the user
|
|
5415
5450
|
// confirms with OK (see `ok()` below).
|
|
5416
5451
|
this.universes = structuredClone(this.configService.universes || []);
|
|
5417
|
-
if (this.
|
|
5418
|
-
this.
|
|
5452
|
+
if (this.universes.length === 0 && this.configService.freeUniverseEdit) {
|
|
5453
|
+
this.universes.push({ uuid: this.uuidService.getUuid(), name: 'Universe 1' });
|
|
5454
|
+
}
|
|
5455
|
+
if (this.universes.length > 0) {
|
|
5456
|
+
this.selectedUniverse = this.universes[0];
|
|
5457
|
+
}
|
|
5458
|
+
const firstVisible = this.currentUniverseFixtures[0] ?? this.fixturePool[0];
|
|
5459
|
+
if (firstVisible) {
|
|
5460
|
+
this.selectFixture(firstVisible);
|
|
5419
5461
|
}
|
|
5420
5462
|
}
|
|
5421
5463
|
get freeUniverseEdit() {
|
|
5422
5464
|
return this.configService.freeUniverseEdit;
|
|
5423
5465
|
}
|
|
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;
|
|
5466
|
+
/** Fixtures belonging to the currently selected universe. */
|
|
5467
|
+
get currentUniverseFixtures() {
|
|
5468
|
+
if (!this.selectedUniverse) {
|
|
5469
|
+
return this.fixturePool;
|
|
5439
5470
|
}
|
|
5471
|
+
return this.fixturePool.filter((f) => f.dmxUniverseUuid === this.selectedUniverse.uuid);
|
|
5440
5472
|
}
|
|
5441
|
-
|
|
5442
|
-
|
|
5443
|
-
|
|
5444
|
-
|
|
5445
|
-
|
|
5446
|
-
this.
|
|
5447
|
-
//
|
|
5448
|
-
|
|
5449
|
-
|
|
5450
|
-
fixture.dmxUniverseUuid = undefined;
|
|
5451
|
-
}
|
|
5473
|
+
/** Fixtures used for channel-map calculations (same as currentUniverseFixtures). */
|
|
5474
|
+
get channelFixtures() {
|
|
5475
|
+
return this.currentUniverseFixtures;
|
|
5476
|
+
}
|
|
5477
|
+
selectUniverse(universe) {
|
|
5478
|
+
this.selectedUniverse = universe;
|
|
5479
|
+
// Deselect the current fixture if it doesn't belong to the new universe.
|
|
5480
|
+
if (this.selectedFixture && this.selectedFixture.dmxUniverseUuid !== universe?.uuid) {
|
|
5481
|
+
this.selectFixture(this.currentUniverseFixtures[0] ?? undefined);
|
|
5452
5482
|
}
|
|
5453
5483
|
}
|
|
5454
5484
|
ngOnInit() {
|
|
@@ -5498,8 +5528,9 @@ class FixturePoolComponent {
|
|
|
5498
5528
|
// minimal profile passed from the search.
|
|
5499
5529
|
this.fixtureService.loadProfileByUuid(searchProfile.uuid).subscribe(() => {
|
|
5500
5530
|
const profile = this.fixtureService.getProfileByUuid(searchProfile.uuid);
|
|
5501
|
-
const newFixture = this.fixtureService.addFixture(profile, this.fixturePool);
|
|
5531
|
+
const newFixture = this.fixtureService.addFixture(profile, this.fixturePool, this.currentUniverseFixtures);
|
|
5502
5532
|
if (newFixture) {
|
|
5533
|
+
newFixture.dmxUniverseUuid = this.selectedUniverse?.uuid;
|
|
5503
5534
|
this.selectFixture(newFixture);
|
|
5504
5535
|
}
|
|
5505
5536
|
});
|
|
@@ -5511,7 +5542,7 @@ class FixturePoolComponent {
|
|
|
5511
5542
|
fixture.name = originalFixture.name;
|
|
5512
5543
|
fixture.modeShortName = originalFixture.modeShortName;
|
|
5513
5544
|
fixture.dmxFirstChannel = originalFixture.dmxFirstChannel;
|
|
5514
|
-
fixture.dmxUniverseUuid =
|
|
5545
|
+
fixture.dmxUniverseUuid = this.selectedUniverse?.uuid;
|
|
5515
5546
|
this.fixturePool.push(fixture);
|
|
5516
5547
|
this.selectFixture(fixture);
|
|
5517
5548
|
}
|
|
@@ -5525,8 +5556,8 @@ class FixturePoolComponent {
|
|
|
5525
5556
|
break;
|
|
5526
5557
|
}
|
|
5527
5558
|
}
|
|
5528
|
-
if (!this.selectedFixture
|
|
5529
|
-
this.selectFixture(
|
|
5559
|
+
if (!this.selectedFixture) {
|
|
5560
|
+
this.selectFixture(this.currentUniverseFixtures[0] ?? undefined);
|
|
5530
5561
|
}
|
|
5531
5562
|
// remove unused profiles
|
|
5532
5563
|
for (let i = 0; i < this.projectService.project.fixtureProfiles.length; i++) {
|
|
@@ -5543,7 +5574,7 @@ class FixturePoolComponent {
|
|
|
5543
5574
|
}
|
|
5544
5575
|
}
|
|
5545
5576
|
channelOccupied(index) {
|
|
5546
|
-
for (const fixture of this.
|
|
5577
|
+
for (const fixture of this.channelFixtures) {
|
|
5547
5578
|
const profile = this.fixtureService.getProfileByUuid(fixture.profileUuid);
|
|
5548
5579
|
const mode = this.fixtureService.getModeByFixture(profile, fixture);
|
|
5549
5580
|
const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
|
|
@@ -5554,7 +5585,7 @@ class FixturePoolComponent {
|
|
|
5554
5585
|
return false;
|
|
5555
5586
|
}
|
|
5556
5587
|
channelOccupiedStart(index) {
|
|
5557
|
-
for (const fixture of this.
|
|
5588
|
+
for (const fixture of this.channelFixtures) {
|
|
5558
5589
|
if (index === fixture.dmxFirstChannel) {
|
|
5559
5590
|
return true;
|
|
5560
5591
|
}
|
|
@@ -5562,7 +5593,7 @@ class FixturePoolComponent {
|
|
|
5562
5593
|
return false;
|
|
5563
5594
|
}
|
|
5564
5595
|
channelOccupiedEnd(index) {
|
|
5565
|
-
for (const fixture of this.
|
|
5596
|
+
for (const fixture of this.channelFixtures) {
|
|
5566
5597
|
const profile = this.fixtureService.getProfileByUuid(fixture.profileUuid);
|
|
5567
5598
|
const mode = this.fixtureService.getModeByFixture(profile, fixture);
|
|
5568
5599
|
const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
|
|
@@ -5573,8 +5604,11 @@ class FixturePoolComponent {
|
|
|
5573
5604
|
return false;
|
|
5574
5605
|
}
|
|
5575
5606
|
channelOverlapped(index) {
|
|
5607
|
+
return this.channelOverlappedInFixtures(index, this.channelFixtures);
|
|
5608
|
+
}
|
|
5609
|
+
channelOverlappedInFixtures(index, fixtures) {
|
|
5576
5610
|
let occupiedFixture;
|
|
5577
|
-
for (const fixture of
|
|
5611
|
+
for (const fixture of fixtures) {
|
|
5578
5612
|
const profile = this.fixtureService.getProfileByUuid(fixture.profileUuid);
|
|
5579
5613
|
const mode = this.fixtureService.getModeByFixture(profile, fixture);
|
|
5580
5614
|
const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
|
|
@@ -5599,7 +5633,7 @@ class FixturePoolComponent {
|
|
|
5599
5633
|
let newSelectedFixture;
|
|
5600
5634
|
// find a dragging fixture and select it, but don't change the selection, if the
|
|
5601
5635
|
// currently selected fixture might also be selected (on overlapped fixtures)
|
|
5602
|
-
for (const fixture of this.
|
|
5636
|
+
for (const fixture of this.channelFixtures) {
|
|
5603
5637
|
const profile = this.fixtureService.getProfileByUuid(fixture.profileUuid);
|
|
5604
5638
|
const mode = this.fixtureService.getModeByFixture(profile, fixture);
|
|
5605
5639
|
const channelCount = this.fixtureService.getModeChannelCount(profile, mode);
|
|
@@ -5655,15 +5689,18 @@ class FixturePoolComponent {
|
|
|
5655
5689
|
}
|
|
5656
5690
|
}
|
|
5657
5691
|
ok() {
|
|
5658
|
-
// don't allow OK if overlapping fixtures exist
|
|
5659
|
-
for (
|
|
5660
|
-
|
|
5661
|
-
|
|
5662
|
-
|
|
5663
|
-
|
|
5664
|
-
|
|
5665
|
-
|
|
5666
|
-
|
|
5692
|
+
// don't allow OK if overlapping fixtures exist within any universe
|
|
5693
|
+
for (const universe of this.universes) {
|
|
5694
|
+
const universeFixtures = this.fixturePool.filter((f) => f.dmxUniverseUuid === universe.uuid);
|
|
5695
|
+
for (let i = 0; i < this.dmxChannels.length; i++) {
|
|
5696
|
+
if (this.channelOverlappedInFixtures(i, universeFixtures)) {
|
|
5697
|
+
const msg = 'designer.fixture-pool.channel-occupied';
|
|
5698
|
+
const title = 'designer.fixture-pool.channel-occupied-title';
|
|
5699
|
+
this.translateService.get([msg, title]).subscribe((result) => {
|
|
5700
|
+
this.toastrService.error(result[msg], result[title]);
|
|
5701
|
+
});
|
|
5702
|
+
return;
|
|
5703
|
+
}
|
|
5667
5704
|
}
|
|
5668
5705
|
}
|
|
5669
5706
|
// remove deleted fixtures/pixel keys from preset fixtures
|
|
@@ -5762,10 +5799,45 @@ class FixturePoolComponent {
|
|
|
5762
5799
|
});
|
|
5763
5800
|
});
|
|
5764
5801
|
}
|
|
5802
|
+
openEditUniverses() {
|
|
5803
|
+
const ref = this.modalService.show(FixturePoolEditUniversesComponent, {
|
|
5804
|
+
keyboard: true,
|
|
5805
|
+
ignoreBackdropClick: false,
|
|
5806
|
+
initialState: { universes: structuredClone(this.universes) },
|
|
5807
|
+
});
|
|
5808
|
+
ref.content.onClose.subscribe((result) => {
|
|
5809
|
+
if (!result)
|
|
5810
|
+
return;
|
|
5811
|
+
// Clear fixture universe assignments for any removed universe
|
|
5812
|
+
for (const universe of this.universes) {
|
|
5813
|
+
if (!result.find((u) => u.uuid === universe.uuid)) {
|
|
5814
|
+
for (const fixture of this.fixturePool) {
|
|
5815
|
+
if (fixture.dmxUniverseUuid === universe.uuid) {
|
|
5816
|
+
fixture.dmxUniverseUuid = undefined;
|
|
5817
|
+
}
|
|
5818
|
+
}
|
|
5819
|
+
}
|
|
5820
|
+
}
|
|
5821
|
+
this.universes = result;
|
|
5822
|
+
// Re-anchor selectedUniverse to the new object reference from result.
|
|
5823
|
+
// The modal works on a structuredClone, so all objects have new references.
|
|
5824
|
+
const stillSelected = this.universes.find((u) => u.uuid === this.selectedUniverse?.uuid);
|
|
5825
|
+
if (stillSelected) {
|
|
5826
|
+
this.selectedUniverse = stillSelected;
|
|
5827
|
+
}
|
|
5828
|
+
else {
|
|
5829
|
+
this.selectedUniverse = this.universes[0] ?? undefined;
|
|
5830
|
+
this.selectFixture(this.currentUniverseFixtures[0] ?? undefined);
|
|
5831
|
+
}
|
|
5832
|
+
});
|
|
5833
|
+
}
|
|
5765
5834
|
createFixtureFromProfileFile() {
|
|
5766
5835
|
const bsModalRef = this.modalService.show(FixturePoolCreateFromFileComponent, { keyboard: true, ignoreBackdropClick: false });
|
|
5767
5836
|
bsModalRef.content.onClose.subscribe((profile) => {
|
|
5768
|
-
const newFixture = this.fixtureService.addFixture(profile, this.fixturePool);
|
|
5837
|
+
const newFixture = this.fixtureService.addFixture(profile, this.fixturePool, this.currentUniverseFixtures);
|
|
5838
|
+
if (newFixture) {
|
|
5839
|
+
newFixture.dmxUniverseUuid = this.selectedUniverse?.uuid;
|
|
5840
|
+
}
|
|
5769
5841
|
this.selectFixture(newFixture);
|
|
5770
5842
|
});
|
|
5771
5843
|
}
|
|
@@ -5773,11 +5845,11 @@ class FixturePoolComponent {
|
|
|
5773
5845
|
this.ok();
|
|
5774
5846
|
}
|
|
5775
5847
|
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" }] }); }
|
|
5848
|
+
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.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
5849
|
}
|
|
5778
5850
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImport: i0, type: FixturePoolComponent, decorators: [{
|
|
5779
5851
|
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"] }]
|
|
5852
|
+
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.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
5853
|
}], 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
5854
|
type: HostListener,
|
|
5783
5855
|
args: ['window:mouseup', ['$event']]
|
|
@@ -8691,6 +8763,7 @@ class DesignerModule {
|
|
|
8691
8763
|
SceneSettingsComponent,
|
|
8692
8764
|
ProjectSaveComponent,
|
|
8693
8765
|
FixturePoolCreateFromFileComponent,
|
|
8766
|
+
FixturePoolEditUniversesComponent,
|
|
8694
8767
|
DropzoneComponent,
|
|
8695
8768
|
SortablejsDirective], imports: [i3.RouterModule, BrowserModule,
|
|
8696
8769
|
BrowserAnimationsModule,
|
|
@@ -8757,6 +8830,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.16", ngImpo
|
|
|
8757
8830
|
SceneSettingsComponent,
|
|
8758
8831
|
ProjectSaveComponent,
|
|
8759
8832
|
FixturePoolCreateFromFileComponent,
|
|
8833
|
+
FixturePoolEditUniversesComponent,
|
|
8760
8834
|
DropzoneComponent,
|
|
8761
8835
|
SortablejsDirective,
|
|
8762
8836
|
],
|