From 6c4f1ad6249203013176086d977852b68b7ccf0c Mon Sep 17 00:00:00 2001 From: Fabian Breitling <83815772+msfb3@users.noreply.github.com> Date: Thu, 30 Jan 2025 11:09:59 +0100 Subject: [PATCH 1/5] feat(ZMS-3503): added logic to end emergency with checkbox --- zmsadmin/js/block/emergency/index.js | 2 + zmsadmin/js/block/scope/emergencyend.js | 163 ++++++++++++++++++ zmsadmin/js/index.js | 6 + zmsadmin/templates/block/scope/form.twig | 8 +- zmsentities/src/Zmsentities/Schema/Entity.php | 4 +- 5 files changed, 181 insertions(+), 2 deletions(-) create mode 100644 zmsadmin/js/block/scope/emergencyend.js diff --git a/zmsadmin/js/block/emergency/index.js b/zmsadmin/js/block/emergency/index.js index 1751ac346..4e6cb719f 100644 --- a/zmsadmin/js/block/emergency/index.js +++ b/zmsadmin/js/block/emergency/index.js @@ -9,10 +9,12 @@ class View extends BaseView { constructor (element, options) { super(element) + console.log("Options received:", options); this.includeUrl = options.includeurl this.returnTarget = options.returnTarget this.workstationName = ""+options.workstationname this.scope = options.scope + console.log("Scope received:", this.scope); this.data = Object.assign({}, deepGet(this, ['scope', 'status', 'emergency'])) this.minimized = false this.refreshTimer = null diff --git a/zmsadmin/js/block/scope/emergencyend.js b/zmsadmin/js/block/scope/emergencyend.js new file mode 100644 index 000000000..9f685b659 --- /dev/null +++ b/zmsadmin/js/block/scope/emergencyend.js @@ -0,0 +1,163 @@ +import BaseView from '../../lib/baseview' +import $ from 'jquery' +import { deepGet, tryJson, noOp } from '../../lib/utils' +// import { playSound } from '../../lib/audio' + +const DEFAULT_REFRESH_INTERVAL = 15 + +class View extends BaseView { + + constructor (element, options) { + super(element) + console.log("Emergency Options received:", options); + this.includeUrl = options.includeurl + this.returnTarget = options.returnTarget + this.workstationName = ""+options.workstationname + this.scope = options.scope + console.log("Emergency Scope received:", this.scope); + this.data = Object.assign({}, deepGet(this, ['scope', 'status', 'emergency'])) + this.minimized = false + this.refreshTimer = null + this.refreshId = 0 + + this.bindPublicMethods( 'endEmergency') + this.$.find('.emergency__button-end').on('click', this.endEmergency) + this.$.on('keydown', function exitKeyEventListener (ev){ + var key = ev.key; + switch(key) { + case 'Escape': // ESC + console.log('ESC'); + this.minimize; // ToDo: Don't work yet + break; + } + }) + + + // ) + //console.log('Component: Emergency', this) + } + + invalidateRefreshId() { + this.refreshId = this.refreshId + 1 + } + + + loadData () { + const url = `${this.includeUrl}/workstation/status/` + + return new Promise((resolve, reject) => { + $.ajax(url, { + method: 'GET' + }).done(data => { + const emergencyData = deepGet(tryJson(data), ['workstation', 'scope', 'status', 'emergency']) + resolve(emergencyData) + }).fail(err => { + console.log('XHR error', url, err) + reject(err) + }) + }) + } + + + + sendEmergencyCancel() { + this.invalidateRefreshId() + const url = `${this.includeUrl}/scope/${this.scope.id}/emergency/` + + return new Promise((resolve, reject) => { + $.ajax(url, { + method: 'GET' + }).done(() => { + resolve() + }).fail(err => { + console.log('XHR error', url, err) + reject(err) + }) + }) + } + + update (newData) { + this.data = Object.assign({}, this.data, newData) + this.render() + } + + + render () { + const data = this.data + + const activated = parseInt(data.activated, 10) + const acceptedByWorkstation = parseInt(data.acceptedByWorkstation, 10) + const source = data.calledByWorkstation === this.workstationName ? 'self' : 'other' + + let state = 'clear' + if (activated > 0) { + state = 'triggered' + + if (acceptedByWorkstation > -1) { + state = 'help-coming' + } + } + + if (this.minimized) { + this.$.attr('data-minimized', true) + } else { + this.$.removeAttr('data-minimized') + } + // Barrierefreiheit + if (state == 'clear') { + this.$.find('.emergency__overlay').attr('hidden', 'hidden') + } else { + this.$.find('.emergency__overlay').removeAttr('hidden') + } + + this.$.attr('data-source', source) + this.$.attr('data-state', state) + this.$.find('.emergency__source').text((data.calledByWorkstation === '0') ? 'Tresen' : `Platz ${data.calledByWorkstation}`) + this.$.find('.emergency__help-from').text((data.acceptedByWorkstation === '0' ? 'Tresen' : `Platz ${data.acceptedByWorkstation}`)) + } + + endEmergency() { + this.update({activated: "0", calledByWorkstation: "-1", acceptedByWorkstation: "-1"}) + this.sendEmergencyCancel() + console.log('end emergency'); + this.removeFocusTrap(this.$.find('.emergency__overlay-layout')); + } + + removeFocusTrap(elem) { + var tabbable = elem.find('select, input, textarea, button, a, *[role="button"]'); + tabbable.unbind('keydown'); + } + + addFocusTrap(elem) { + // Get all focusable elements inside our trap container + var tabbable = elem.find('select, input, textarea, button, a, *[role="button"]'); + // Focus the first element + if (tabbable.length ) { + tabbable.filter(':visible').first().focus(); + //console.log(tabbable.filter(':visible').first()); + } + tabbable.bind('keydown', function (e) { + if (e.keyCode === 9) { // TAB pressed + // we need to update the visible last and first focusable elements everytime tab is pressed, + // because elements can change their visibility + var firstVisible = tabbable.filter(':visible').first(); + var lastVisible = tabbable.filter(':visible').last(); + if (firstVisible && lastVisible) { + if (e.shiftKey && ( $(firstVisible)[0] === $(this)[0] ) ) { + // TAB + SHIFT pressed on first visible element + e.preventDefault(); + lastVisible.focus(); + } + else if (!e.shiftKey && ( $(lastVisible)[0] === $(this)[0] ) ) { + // TAB pressed pressed on last visible element + e.preventDefault(); + firstVisible.focus(); + } + } + } + }); + } + +} + +export default View; diff --git a/zmsadmin/js/index.js b/zmsadmin/js/index.js index 6b1ec817f..92e2c2dec 100644 --- a/zmsadmin/js/index.js +++ b/zmsadmin/js/index.js @@ -26,6 +26,7 @@ import PickupKeyboardHandheldView from "./page/pickup/keyboard-handheld" import StatisticView from './page/statistic' import LoginScopeSelectView from './block/scope/loginselectform' +import EmergencyEnd from './block/scope/emergencyend' //import AvailabilityDayPage from './page/availabilityDay' import WeekCalendarPage from './page/weekCalendar' import printScopeAppointmentsByDay from './page/scopeAppointmentsByDay/print' @@ -108,6 +109,10 @@ $('[data-scope-select-form]').each(function () { new LoginScopeSelectView(this, getDataAttributes(this)); }) +$('.emergency-end').each(function () { + new EmergencyEnd(this, getDataAttributes(this)); +}) + $('.pickup-view').each(function () { new PickupView(this, getDataAttributes(this)); }) @@ -139,6 +144,7 @@ DialogHandler.hideMessages(); // Say hello console.log("Welcome to the ZMS admin interface..."); +console.log("Hello") // hook up react components diff --git a/zmsadmin/templates/block/scope/form.twig b/zmsadmin/templates/block/scope/form.twig index 568b5dcf8..d527fef83 100644 --- a/zmsadmin/templates/block/scope/form.twig +++ b/zmsadmin/templates/block/scope/form.twig @@ -627,7 +627,12 @@
Notruf -
+
{{ formgroup( { "label": null @@ -639,6 +644,7 @@ "name": "preferences[workstation][emergencyEnabled]", "value": 1, "checked": scope.preferences.workstation.emergencyEnabled|default(0), + "class": "emergency__button-end" } }] ) }} diff --git a/zmsentities/src/Zmsentities/Schema/Entity.php b/zmsentities/src/Zmsentities/Schema/Entity.php index 4afbbf8af..2c9afedab 100644 --- a/zmsentities/src/Zmsentities/Schema/Entity.php +++ b/zmsentities/src/Zmsentities/Schema/Entity.php @@ -308,7 +308,9 @@ public function withLessData() public function withCleanedUpFormData() { $entity = clone $this; - unset($entity['save']); + if (isset($entity['save'])) { + unset($entity['save']); + } if (isset($entity['removeImage'])) { unset($entity['removeImage']); } From 2c41030b87fee41a8f076c6616e385290874433e Mon Sep 17 00:00:00 2001 From: Fabian Breitling <83815772+msfb3@users.noreply.github.com> Date: Thu, 30 Jan 2025 13:10:44 +0100 Subject: [PATCH 2/5] feat(ZMS-3503): removed console.log and unesscessy function --- zmsadmin/js/block/scope/emergencyend.js | 9 --------- zmsadmin/js/index.js | 1 - 2 files changed, 10 deletions(-) diff --git a/zmsadmin/js/block/scope/emergencyend.js b/zmsadmin/js/block/scope/emergencyend.js index 9f685b659..adf19e2bc 100644 --- a/zmsadmin/js/block/scope/emergencyend.js +++ b/zmsadmin/js/block/scope/emergencyend.js @@ -22,15 +22,6 @@ class View extends BaseView { this.bindPublicMethods( 'endEmergency') this.$.find('.emergency__button-end').on('click', this.endEmergency) - this.$.on('keydown', function exitKeyEventListener (ev){ - var key = ev.key; - switch(key) { - case 'Escape': // ESC - console.log('ESC'); - this.minimize; // ToDo: Don't work yet - break; - } - }) // ) diff --git a/zmsadmin/js/index.js b/zmsadmin/js/index.js index 92e2c2dec..2a85edea2 100644 --- a/zmsadmin/js/index.js +++ b/zmsadmin/js/index.js @@ -144,7 +144,6 @@ DialogHandler.hideMessages(); // Say hello console.log("Welcome to the ZMS admin interface..."); -console.log("Hello") // hook up react components From 0db8598711a3304accbe59c2e7075e3a4f2a9694 Mon Sep 17 00:00:00 2001 From: Fabian Breitling <83815772+msfb3@users.noreply.github.com> Date: Thu, 30 Jan 2025 13:17:53 +0100 Subject: [PATCH 3/5] feat(ZMS-3503): removed console.log and unesscessy function --- zmsadmin/js/block/emergency/index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/zmsadmin/js/block/emergency/index.js b/zmsadmin/js/block/emergency/index.js index 4e6cb719f..1751ac346 100644 --- a/zmsadmin/js/block/emergency/index.js +++ b/zmsadmin/js/block/emergency/index.js @@ -9,12 +9,10 @@ class View extends BaseView { constructor (element, options) { super(element) - console.log("Options received:", options); this.includeUrl = options.includeurl this.returnTarget = options.returnTarget this.workstationName = ""+options.workstationname this.scope = options.scope - console.log("Scope received:", this.scope); this.data = Object.assign({}, deepGet(this, ['scope', 'status', 'emergency'])) this.minimized = false this.refreshTimer = null From e642fb00624437a933764d1a7354c66c40546151 Mon Sep 17 00:00:00 2001 From: Fabian Breitling <83815772+msfb3@users.noreply.github.com> Date: Fri, 31 Jan 2025 11:18:51 +0100 Subject: [PATCH 4/5] feat(ZMS-3503): removed console.log and unnecessary functions --- zmsadmin/js/block/scope/emergencyend.js | 138 +++--------------------- 1 file changed, 12 insertions(+), 126 deletions(-) diff --git a/zmsadmin/js/block/scope/emergencyend.js b/zmsadmin/js/block/scope/emergencyend.js index adf19e2bc..0667cd603 100644 --- a/zmsadmin/js/block/scope/emergencyend.js +++ b/zmsadmin/js/block/scope/emergencyend.js @@ -1,58 +1,27 @@ -import BaseView from '../../lib/baseview' import $ from 'jquery' -import { deepGet, tryJson, noOp } from '../../lib/utils' -// import { playSound } from '../../lib/audio' -const DEFAULT_REFRESH_INTERVAL = 15 +class EndEmergencyView { -class View extends BaseView { - - constructor (element, options) { - super(element) - console.log("Emergency Options received:", options); + constructor(element, options) { this.includeUrl = options.includeurl - this.returnTarget = options.returnTarget - this.workstationName = ""+options.workstationname this.scope = options.scope - console.log("Emergency Scope received:", this.scope); - this.data = Object.assign({}, deepGet(this, ['scope', 'status', 'emergency'])) - this.minimized = false - this.refreshTimer = null - this.refreshId = 0 - - this.bindPublicMethods( 'endEmergency') - this.$.find('.emergency__button-end').on('click', this.endEmergency) - + this.workstationName = "" + options.workstationname + this.data = {} + this.$ = $(element) - // ) - //console.log('Component: Emergency', this) + this.$.find('.emergency__button-end').on('click', this.endEmergency.bind(this)) } - invalidateRefreshId() { - this.refreshId = this.refreshId + 1 + endEmergency() { + this.update({ activated: "0", calledByWorkstation: "-1", acceptedByWorkstation: "-1" }) + this.sendEmergencyCancel() } - - loadData () { - const url = `${this.includeUrl}/workstation/status/` - - return new Promise((resolve, reject) => { - $.ajax(url, { - method: 'GET' - }).done(data => { - const emergencyData = deepGet(tryJson(data), ['workstation', 'scope', 'status', 'emergency']) - resolve(emergencyData) - }).fail(err => { - console.log('XHR error', url, err) - reject(err) - }) - }) + update(newData) { + this.data = Object.assign({}, this.data, newData) } - - sendEmergencyCancel() { - this.invalidateRefreshId() const url = `${this.includeUrl}/scope/${this.scope.id}/emergency/` return new Promise((resolve, reject) => { @@ -66,89 +35,6 @@ class View extends BaseView { }) }) } - - update (newData) { - this.data = Object.assign({}, this.data, newData) - this.render() - } - - - render () { - const data = this.data - - const activated = parseInt(data.activated, 10) - const acceptedByWorkstation = parseInt(data.acceptedByWorkstation, 10) - const source = data.calledByWorkstation === this.workstationName ? 'self' : 'other' - - let state = 'clear' - if (activated > 0) { - state = 'triggered' - - if (acceptedByWorkstation > -1) { - state = 'help-coming' - } - } - - if (this.minimized) { - this.$.attr('data-minimized', true) - } else { - this.$.removeAttr('data-minimized') - } - // Barrierefreiheit - if (state == 'clear') { - this.$.find('.emergency__overlay').attr('hidden', 'hidden') - } else { - this.$.find('.emergency__overlay').removeAttr('hidden') - } - - this.$.attr('data-source', source) - this.$.attr('data-state', state) - this.$.find('.emergency__source').text((data.calledByWorkstation === '0') ? 'Tresen' : `Platz ${data.calledByWorkstation}`) - this.$.find('.emergency__help-from').text((data.acceptedByWorkstation === '0' ? 'Tresen' : `Platz ${data.acceptedByWorkstation}`)) - } - - endEmergency() { - this.update({activated: "0", calledByWorkstation: "-1", acceptedByWorkstation: "-1"}) - this.sendEmergencyCancel() - console.log('end emergency'); - this.removeFocusTrap(this.$.find('.emergency__overlay-layout')); - } - - removeFocusTrap(elem) { - var tabbable = elem.find('select, input, textarea, button, a, *[role="button"]'); - tabbable.unbind('keydown'); - } - - addFocusTrap(elem) { - // Get all focusable elements inside our trap container - var tabbable = elem.find('select, input, textarea, button, a, *[role="button"]'); - // Focus the first element - if (tabbable.length ) { - tabbable.filter(':visible').first().focus(); - //console.log(tabbable.filter(':visible').first()); - } - tabbable.bind('keydown', function (e) { - if (e.keyCode === 9) { // TAB pressed - // we need to update the visible last and first focusable elements everytime tab is pressed, - // because elements can change their visibility - var firstVisible = tabbable.filter(':visible').first(); - var lastVisible = tabbable.filter(':visible').last(); - if (firstVisible && lastVisible) { - if (e.shiftKey && ( $(firstVisible)[0] === $(this)[0] ) ) { - // TAB + SHIFT pressed on first visible element - e.preventDefault(); - lastVisible.focus(); - } - else if (!e.shiftKey && ( $(lastVisible)[0] === $(this)[0] ) ) { - // TAB pressed pressed on last visible element - e.preventDefault(); - firstVisible.focus(); - } - } - } - }); - } - } -export default View; +export default EndEmergencyView; \ No newline at end of file From 3aa65ca56b39ce37d1c26ecc19f0f51acdf551f6 Mon Sep 17 00:00:00 2001 From: Fabian Breitling <83815772+msfb3@users.noreply.github.com> Date: Tue, 4 Feb 2025 08:45:21 +0100 Subject: [PATCH 5/5] feat(ZMS-3503): added explanation to the function --- zmsadmin/templates/block/scope/form.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zmsadmin/templates/block/scope/form.twig b/zmsadmin/templates/block/scope/form.twig index d527fef83..6f9c4d439 100644 --- a/zmsadmin/templates/block/scope/form.twig +++ b/zmsadmin/templates/block/scope/form.twig @@ -640,7 +640,7 @@ [{ "type":"checkbox", "parameter": { - "label": "Notruffunktion im Backend", + "label": "Notruffunktion im Backend (Durch das Deaktivieren der Funktion wird auch ein aktuell bestehender Notruf am Standort beendet.)", "name": "preferences[workstation][emergencyEnabled]", "value": 1, "checked": scope.preferences.workstation.emergencyEnabled|default(0),