Merge lp:~ic90/openlp/animated-alerts into lp:~openlp-dev/openlp/webengine-migrate

Proposed by Nico Opiyo
Status: Superseded
Proposed branch: lp:~ic90/openlp/animated-alerts
Merge into: lp:~openlp-dev/openlp/webengine-migrate
Diff against target: 426 lines (+339/-7)
4 files modified
openlp/core/display/html/display.html (+75/-0)
openlp/core/display/html/display.js (+150/-5)
openlp/core/display/window.py (+1/-1)
tests/js/test_display.js (+113/-1)
To merge this branch: bzr merge lp:~ic90/openlp/animated-alerts
Reviewer Review Type Date Requested Status
Nico Opiyo Needs Resubmitting
Raoul Snyman Needs Fixing
Review via email: mp+362833@code.launchpad.net

This proposal has been superseded by a proposal from 2019-02-12.

Commit message

Added transitions and animations to the alerts.

Description of the change

I have fixed the tests to test the various components added to the UI and also made some slight adjustments to the entrance transition and fixed a glitch when an alert is first displayed on opening the program.

JS Test Output is as below:
PhantomJS 2.1.1 (Windows 8.0.0) Display.setTextSlides should correctly set outline width FAILED
        TypeError: undefined is not an object (evaluating 'dom.wrapper.querySelectorAll') in openlp/core/display/html/reveal.js (line 2304)
        slide@openlp/core/display/html/reveal.js:2304:37
        goToSlide@openlp/core/display/html/display.js:694:19
        setTextSlides@openlp/core/display/html/display.js:551:22
        tests/js/test_display.js:404:26
PhantomJS 2.1.1 (Windows 8.0.0): Executed 78 of 78 (1 FAILED) (0 secs / 0.087 secs)
PhantomJS 2.1.1 (Windows 8.0.0): Executed 78 of 78 (1 FAILED) (0.108 secs / 0.087 secs)
TOTAL: 1 FAILED, 77 SUCCESS

To post a comment you must log in.
Revision history for this message
Raoul Snyman (raoul-snyman) wrote :

See the inline comments.

Also, in your tests you seem to be testing a single style every time, you should be able to combine those into a single test. For example:

   it("should set the correct styles when the location is the top of the page", function(){
       Display.doEntranceTransition("0");
       expect(alertBackground.style.top).toEqual('0px');
       expect(alertBackground.style.transition).toEqual("2s linear");
       expect(alertBackground.style.height).toEqual("25%");
   });

review: Needs Fixing
lp:~ic90/openlp/animated-alerts updated
2865. By Nico Opiyo

Refactored alert tests and optimized alert code plus fixed spacing

2866. By Nico Opiyo

Fixed the location enumeration for the alerts

Revision history for this message
Nico Opiyo (ic90) wrote :

Javascript Test Output:

PhantomJS 2.1.1 (Windows 8.0.0) Display.setTextSlides should correctly set outline width FAILED
        TypeError: undefined is not an object (evaluating 'dom.wrapper.querySelectorAll') in openlp/core/display/html/reveal.js (line 2304)
        slide@openlp/core/display/html/reveal.js:2304:37
        goToSlide@openlp/core/display/html/display.js:712:19
        setTextSlides@openlp/core/display/html/display.js:569:22
        tests/js/test_display.js:365:26
PhantomJS 2.1.1 (Windows 8.0.0): Executed 68 of 68 (1 FAILED) (0 secs / 0.063 secs)
PhantomJS 2.1.1 (Windows 8.0.0): Executed 68 of 68 (1 FAILED) (0.073 secs / 0.063 secs)
TOTAL: 1 FAILED, 67 SUCCESS

lp:~ic90/openlp/animated-alerts updated
2867. By Nico Opiyo

Refactored transition code and added settings from alert settings configuration

2868. By Nico Opiyo

Refactored the tests for the alerts to mkae them DRY

2869. By Nico Opiyo

Refactored the hex_to_rgb method in the alerts manager class

2870. By Nico Opiyo

Added queuing functionality to the alerts

2871. By Nico Opiyo

Added a few tests and fixed failing JS tests

2872. By Nico Opiyo

Fixed exit transition bug

2873. By Nico Opiyo

Added scrolling option to alerts

2874. By Nico Opiyo

Fixed tests and refactored event listeners for effective testing

2875. By Nico Opiyo

Fixed buggy alerts and refactored CSS

2876. By Nico Opiyo

Cleaned up Javascript and refactored the functions and tests plus optimized animation of text

2877. By Nico Opiyo

Fixed all tests and changed entrance transition to class based toggling

2878. By Nico Opiyo

Fixed queue bug when showing alerts from the queue

2879. By Nico Opiyo

Fixed alert positioning with CSS flexbox and also fixed non-scrolling alert display

2880. By Nico Opiyo

Pulled in changes from trunk

2881. By Nico Opiyo

Fixed scrolling bug display

2882. By Nico Opiyo

Fixed unit tests for alerts branch

2883. By Nico Opiyo

Pulled in latest changes from trunk

2884. By Nico Opiyo

Changed variable names to camelCase and added parameter for Jenkins JS tests

Unmerged revisions

2884. By Nico Opiyo

Changed variable names to camelCase and added parameter for Jenkins JS tests

2883. By Nico Opiyo

Pulled in latest changes from trunk

2882. By Nico Opiyo

Fixed unit tests for alerts branch

2881. By Nico Opiyo

Fixed scrolling bug display

2880. By Nico Opiyo

Pulled in changes from trunk

2879. By Nico Opiyo

Fixed alert positioning with CSS flexbox and also fixed non-scrolling alert display

2878. By Nico Opiyo

Fixed queue bug when showing alerts from the queue

2877. By Nico Opiyo

Fixed all tests and changed entrance transition to class based toggling

2876. By Nico Opiyo

Cleaned up Javascript and refactored the functions and tests plus optimized animation of text

2875. By Nico Opiyo

Fixed buggy alerts and refactored CSS

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'openlp/core/display/html/display.html'
2--- openlp/core/display/html/display.html 2018-10-12 19:51:51 +0000
3+++ openlp/core/display/html/display.html 2019-02-12 10:25:19 +0000
4@@ -24,14 +24,89 @@
5 visibility: visible;
6 z-index: -1;
7 }
8+
9+ /* Animation key frames for horizontal scrolling of alert */
10+ @keyframes alert-scrolling-text {
11+ from { margin-left: 100%; }
12+ to { margin-left: -300% }
13+ }
14+ /* Middle fade-in alert animation */
15+ @keyframes middle-fade-in {
16+ from { opacity: 0;}
17+ to { opacity: 1;}
18+ }
19+
20+ /* Middle fade-out alert animation */
21+ @keyframes middle-fade-out {
22+ from { opacity: 1;}
23+ to { opacity: 0;}
24+ }
25+
26+ /* Fade in when alert location is in the middle */
27+ .middle-entrance-animation {
28+ animation-duration: 2s;
29+ animation-timing-function: linear;
30+ animation-name: middle-fade-in;
31+ }
32+
33+ /* Fade out when alert location is in the middle */
34+ .middle-exit-animation {
35+ animation-duration: 2s;
36+ animation-timing-function: linear;
37+ animation-name: middle-fade-out;
38+ }
39+
40+ .horizontal-scroll-animation {
41+ animation-duration: 10s;
42+ animation-iteration-count: 1;
43+ animation-timing-function: linear;
44+ animation-name: alert-scrolling-text;
45+ }
46+
47+ /* ALERT STYLING */
48+ #alert-background {
49+ position: absolute;
50+ margin: 0;
51+ padding: 0;
52+ left: 0px;
53+ right: 0px;
54+ z-index: 10;
55+ width: 100%;
56+ height: 0%;
57+ vertical-align: middle;
58+ color: #ffffff;
59+ background-color: #660000;
60+ overflow: hidden;
61+ visibility:hidden;
62+ }
63+
64+ #alert {
65+ position: relative;
66+ top: 50%;
67+ transform: translateY(-50%);
68+ margin-top: 0%;
69+ margin-right: 0%;
70+ margin-left: 100%;
71+ margin-bottom: 0%;
72+ z-index: 11;
73+ overflow: visible;
74+ white-space: nowrap;
75+ font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
76+ font-size: 100pt;
77+ color: #ffffff;
78+ visibility: hidden;
79+ }
80+
81 </style>
82 <script type="text/javascript" src="qrc:///qtwebchannel/qwebchannel.js"></script>
83 <script type="text/javascript" src="reveal.js"></script>
84 <script type="text/javascript" src="display.js"></script>
85 </head>
86+
87 <body>
88 <div class="reveal">
89 <div id="global-background" class="slide-background present" data-loaded="true"></div>
90+ <div id="alert-background"><p id="alert">Testing alerts</p></div>
91 <div class="slides"></div>
92 <div class="footer"></div>
93 </div>
94
95=== modified file 'openlp/core/display/html/display.js'
96--- openlp/core/display/html/display.js 2019-02-05 21:26:30 +0000
97+++ openlp/core/display/html/display.js 2019-02-12 10:25:19 +0000
98@@ -53,6 +53,39 @@
99 };
100
101 /**
102+ * Transition state enumeration
103+ */
104+
105+var TransitionState = {
106+ EntranceTransition: "entranceTransition",
107+ NoTransition: "noTransition",
108+ ExitTransition: "exitTransition"
109+};
110+
111+/**
112+ * Animation state enumeration
113+ */
114+var AnimationState = {
115+ NoAnimation: "noAnimation",
116+ ScrollingAnimation: "scrollingAnimation",
117+ FadeInAnimation: "fadeInAnimation",
118+ FadeOutAnimation: "fadeOutAnimation"
119+};
120+/**
121+ * Alert location enumeration
122+ */
123+var AlertLocation = {
124+ Top: "0",
125+ Middle: "1",
126+ Bottom: "2"
127+};
128+
129+/**
130+ *
131+ * @param {Location} selector
132+ */
133+
134+/**
135 * Return an array of elements based on the selector query
136 * @param {string} selector - The selector to find elements
137 * @returns {array} An array of matching elements
138@@ -132,6 +165,10 @@
139 }
140
141 /**
142+ *
143+ */
144+
145+/**
146 * An audio player with a play list
147 */
148 var AudioPlayer = function (audioElement) {
149@@ -249,6 +286,8 @@
150 */
151 var Display = {
152 _slides: {},
153+ _transitionState: TransitionState.NoTransition,
154+ _animationState: AnimationState.NoAnimation,
155 _revealConfig: {
156 margin: 0.0,
157 minScale: 1.0,
158@@ -372,15 +411,121 @@
159 * @param {string} text - The alert text
160 * @param {int} location - The location of the text (top, middle or bottom)
161 */
162- alert: function (text, location) {
163- console.debug(" alert text: " + text, ", location: " + location);
164+ alert: function (text, location) {
165+ console.debug(" alert text: " + text + ", location: " + location);
166+
167+ if (text == "") {
168+ return null;
169+ }
170+
171+ var alertBackground = $("#alert-background")[0];
172+ var alertText = $("#alert")[0];
173+
174+ alertText.innerHTML = text;
175+
176+ /* Bring in the transition background */
177+ Display._transitionState = Display.doEntranceTransition(location);
178+
179+ alertBackground.addEventListener('transitionend', function (e) {
180+ e.stopPropagation();
181+ if (Display._transitionState == TransitionState.EntranceTransition) {
182+ alertText.style.visibility = "visible";
183+ alertText.classList.add("horizontal-scroll-animation");
184+ }
185+ else if (Display._transitionState == TransitionState.ExitTransition) {
186+ Display._transitionState = TransitionState.NoTransition;
187+ alertBackground.style.visibility = "hidden";
188+ alertText.style.visibility = "hidden";
189+ alertBackground.style.top = "";
190+ alertBackground.style.bottom = "";
191+ alertBackground.style.height = "";
192+ alertBackground.style.transition = "";
193+ alertBackground.classList.remove("middle-exit-animation");
194+ }
195+ });
196+
197+ alertBackground.addEventListener('animationend', function () {
198+
199+ if (Display._animationState == AnimationState.FadeInAnimation) {
200+ alertText.style.visibility = "visible";
201+ alertText.classList.add("horizontal-scroll-animation");
202+ alertText.classList.remove("middle-entrance-animation");
203+ Display._animationState = AnimationState.ScrollingAnimation;
204+ }
205+ else if (Display._animationState == AnimationState.FadeOutAnimation) {
206+ alertBackground.style.visibility = "hidden";
207+ alertBackground.classList.remove("middle-exit-animation");
208+ Display._animationState = AnimationState.NoAnimation;
209+ }
210+ else if (alertText.classList.contains("horizontal-scroll-animation")) {
211+ alertText.classList.remove("horizontal-scroll-animation");
212+ alertText.style.visibility = "hidden";
213+ Display._animationState = AnimationState.NoAnimation;
214+ Display._transitionState = Display.doExitTransition(location);
215+ }
216+
217+ });
218+
219 /*
220 * The implementation should show an alert.
221 * It should be able to handle receiving a new alert before a previous one is "finished", basically queueing it.
222 */
223- return;
224-},
225-
226+ return location;
227+ },
228+
229+ /**
230+ * Start background entrance transition for display of alert
231+ * @param {string} location - String showing the location of the alert on screen
232+ */
233+ doEntranceTransition: function (location) {
234+ var alertBackground = $("#alert-background")[0];
235+
236+ switch (location) {
237+ case AlertLocation.Top:
238+ alertBackground.style.bottom = '';
239+ alertBackground.style.top = '0px';
240+ alertBackground.style.height = "25%";
241+ alertBackground.style.transition = "2s linear";
242+ break;
243+ case AlertLocation.Middle:
244+ alertBackground.style.top = ((window.innerHeight - alertBackground.clientHeight) / 2) + 'px';
245+ alertBackground.style.height = "25%";
246+ alertBackground.classList.add("middle-entrance-animation");
247+ Display._animationState = AnimationState.FadeInAnimation;
248+ break;
249+ case AlertLocation.Bottom:
250+ default:
251+ alertBackground.style.top = '';
252+ alertBackground.style.bottom = '0px';
253+ alertBackground.style.height = "25%";
254+ alertBackground.style.transition= "2s linear";
255+ break;
256+ }
257+ alertBackground.style.visibility = "visible";
258+ return TransitionState.EntranceTransition;
259+
260+ },
261+
262+ /**
263+ * Start background exit transition once alert has been displayed
264+ * @param {string} location - Integer showing the location of the alert on screen
265+ */
266+ doExitTransition: function (location) {
267+
268+ var alertBackground = $("#alert-background")[0];
269+
270+ if (location == AlertLocation.Top || location == AlertLocation.Bottom) {
271+ alertBackground.style.height = "0%";
272+ alertBackground.style.transition = '2s linear';
273+ }
274+ else if (location == AlertLocation.Middle) {
275+ alertBackground.classList.add("middle-exit-animation");
276+ alertBackground.style.height = "0%";
277+ Display._animationState = AnimationState.FadeOutAnimation;
278+ }
279+
280+ return TransitionState.ExitTransition;
281+ },
282 /**
283 * Add a slides. If the slide exists but the HTML is different, update the slide.
284 * @param {string} verse - The verse number, e.g. "v1"
285
286=== modified file 'openlp/core/display/window.py'
287--- openlp/core/display/window.py 2018-12-06 20:26:35 +0000
288+++ openlp/core/display/window.py 2019-02-12 10:25:19 +0000
289@@ -401,4 +401,4 @@
290 """
291 Set an alert
292 """
293- self.run_javascript('Display.alert({text}, {location});'.format(text=text, location=location))
294+ self.run_javascript('Display.alert("{text}", "{location}");'.format(text=text, location=location))
295
296=== modified file 'tests/js/test_display.js'
297--- tests/js/test_display.js 2019-01-16 06:15:21 +0000
298+++ tests/js/test_display.js 2019-02-12 10:25:19 +0000
299@@ -18,6 +18,14 @@
300 it("AudioState should exist", function () {
301 expect(AudioState).toBeDefined();
302 });
303+
304+ it("TransitionState should exist", function(){
305+ expect(TransitionState).toBeDefined();
306+ });
307+
308+ it("AnimationState should exist", function(){
309+ expect(AnimationState).toBeDefined();
310+ });
311 });
312
313 describe("The function", function () {
314@@ -138,7 +146,111 @@
315 Display.goToSlide("v1");
316 expect(Reveal.slide).toHaveBeenCalledWith(0);
317 });
318-});
319+
320+ it("should have an alert() method", function () {
321+ expect(Display.alert).toBeDefined();
322+ });
323+
324+});
325+
326+describe("Display.alert", function () {
327+ var alertBackground, alert;
328+
329+ beforeEach(function () {
330+ document.body.innerHTML = "";
331+ alertBackground = document.createElement("div");
332+ alertBackground.setAttribute("id", "alert-background");
333+ document.body.appendChild(alertBackground);
334+ alert = document.createElement("p");
335+ alert.setAttribute("id","alert");
336+ alertBackground.appendChild(alert);
337+ });
338+
339+ it("should return null if called without any text", function () {
340+ expect(Display.alert("","2")).toBeNull();
341+ });
342+
343+ it("should set correct alert text", function () {
344+ Display.alert("OPEN-LP-3.0 Alert Test", "2");
345+ expect(alert.innerHTML).toEqual("OPEN-LP-3.0 Alert Test");
346+ });
347+
348+ it("should set the correct alert position", function () {
349+ expect(Display.alert("Alert Location Test","2")).toEqual("2");
350+ });
351+});
352+
353+describe("The doEntranceTransition", function () {
354+
355+ var alertBackground;
356+
357+ beforeEach(function() {
358+ document.body.innerHTML = "";
359+ alertBackground = document.createElement("div");
360+ alertBackground.setAttribute("id", "alert-background");
361+ document.body.appendChild(alertBackground);
362+ alertBackground.style.top = '0px';
363+ alertBackground.style.height = "0%";
364+ });
365+
366+ it("should set the correct styles for the alert when location is top of the page", function () {
367+ Display.doEntranceTransition("0");
368+ expect(alertBackground.style.bottom).toEqual('');
369+ expect(alertBackground.style.top).toEqual('0px');
370+ expect(alertBackground.style.transition).toEqual("2s linear");
371+ expect(alertBackground.style.height).toEqual("25%");
372+ expect(alertBackground.style.visibility).toEqual("visible");
373+ });
374+
375+ it("should set the correct styles for the alert when location is middle of the page", function () {
376+ Display.doEntranceTransition("1");
377+ var middlePosition = ((window.innerHeight - alertBackground.clientHeight) / 2) + 'px';
378+ expect(alertBackground.style.top).toEqual(middlePosition);
379+ expect(alertBackground.classList.contains("middle-entrance-animation"));
380+ expect(alertBackground.style.height).toEqual("25%");
381+ expect(alertBackground.style.visibility).toEqual("visible");
382+ });
383+
384+ it("should set the correct styles for the alert when location is bottom of the page", function () {
385+ Display.doEntranceTransition("2");
386+ expect(alertBackground.style.top).toEqual('');
387+ expect(alertBackground.style.bottom).toEqual('0px');
388+ expect(alertBackground.style.transition).toEqual("2s linear");
389+ expect(alertBackground.style.height).toEqual("25%");
390+ expect(alertBackground.style.visibility).toEqual("visible");
391+ });
392+});
393+
394+describe("The doExitTransition", function () {
395+ var alertBackground;
396+
397+ beforeEach(function () {
398+ document.body.innerHTML = "";
399+ alertBackground = document.createElement("div");
400+ alertBackground.setAttribute("id", "alert-background");
401+ document.body.appendChild(alertBackground);
402+ });
403+
404+ it("should remove the styles correctly when the location is the top of the page", function () {
405+ Display.doExitTransition("0");
406+ expect(alertBackground.style.height).toEqual('0%');
407+ expect(alertBackground.style.transition).toEqual("2s linear");
408+ });
409+
410+ it("should remove the styles correctly when the location is middle of the page", function () {
411+ Display.doExitTransition("1");
412+ expect(alertBackground.style.height).toEqual('0%');
413+ expect(alertBackground.classList.contains("middle-exit-animation"));
414+ });
415+
416+it("should remove the styles correctly when the location is the bottom of the page", function () {
417+ Display.doExitTransition("2");
418+ expect(alertBackground.style.height).toEqual('0%');
419+ expect(alertBackground.style.transition).toEqual("2s linear");
420+});
421+
422+});
423+
424
425 describe("Display.addTextSlide", function () {
426 beforeEach(function() {

Subscribers

People subscribed via source and target branches

to all changes: