Selaa lähdekoodia

Adds a feedback button and dialog.

j8
yanas 9 vuotta sitten
vanhempi
commit
73b1d3c7c2

+ 2
- 2
Makefile Näytä tiedosto

@@ -3,12 +3,12 @@ BROWSERIFY = ./node_modules/.bin/browserify
3 3
 UGLIFYJS = ./node_modules/.bin/uglifyjs
4 4
 EXORCIST = ./node_modules/.bin/exorcist
5 5
 CLEANCSS = ./node_modules/.bin/cleancss
6
-CSS_FILES = font.css toastr.css main.css videolayout_default.css font-awesome.css jquery-impromptu.css modaldialog.css notice.css popup_menu.css login_menu.css popover.css jitsi_popover.css contact_list.css chat.css welcome_page.css settingsmenu.css
6
+CSS_FILES = font.css toastr.css main.css videolayout_default.css font-awesome.css jquery-impromptu.css modaldialog.css notice.css popup_menu.css login_menu.css popover.css jitsi_popover.css contact_list.css chat.css welcome_page.css settingsmenu.css feedback.css
7 7
 DEPLOY_DIR = libs
8 8
 BROWSERIFY_FLAGS = -d
9 9
 OUTPUT_DIR = .
10 10
 
11
-all: compile uglify deploy clean 
11
+all: compile uglify deploy clean
12 12
 
13 13
 compile:
14 14
 	$(NPM) update && $(BROWSERIFY) $(BROWSERIFY_FLAGS) -e app.js -s APP | $(EXORCIST) $(OUTPUT_DIR)/app.bundle.js.map > $(OUTPUT_DIR)/app.bundle.js

+ 48
- 0
css/feedback.css Näytä tiedosto

@@ -0,0 +1,48 @@
1
+/**
2
+ * The feedback window inner div css.
3
+ */
4
+.feedback {
5
+    width: 450px;
6
+    display: block;
7
+    margin-left: auto;
8
+    margin-right: auto;
9
+    text-align: center;
10
+    font-size: 22px;
11
+}
12
+
13
+/**
14
+ * Style of the thank you text inside the feedback window.
15
+ */
16
+.feedbackTitle {
17
+    font-size: 22px;
18
+    color: #087dba;
19
+}
20
+
21
+/**
22
+ * Stars div css.
23
+ */
24
+#stars {
25
+    font-size: 30px;
26
+}
27
+
28
+/**
29
+ * Star css.
30
+ */
31
+#stars>a {
32
+    padding-right: 4px;
33
+}
34
+
35
+/**
36
+ * Mouse over a star.
37
+ */
38
+.starHover {
39
+    color: #087dba;
40
+}
41
+
42
+/**
43
+ * Detailed feedback section text area style.
44
+ */
45
+.feedbackDetails textarea {
46
+    resize: vertical;
47
+    min-height: 100px;
48
+}

+ 26
- 2
css/main.css Näytä tiedosto

@@ -10,7 +10,7 @@ html, body{
10 10
     font-family:'Helvetica Neue', Helvetica, sans-serif;
11 11
     font-weight: 400;
12 12
     background: #000000;
13
-    overflow-x: hidden;
13
+    overflow: hidden;
14 14
 }
15 15
 
16 16
 .right-panel {
@@ -236,10 +236,34 @@ form {
236 236
     bottom: 5;
237 237
     left: 5;
238 238
     overflow: visible;
239
-    z-index: 100;
240 239
     color: rgba(255,255,255,.50);
241 240
 }
242 241
 
242
+#feedbackButton {
243
+    position: absolute;
244
+    bottom: 60;
245
+    left: 60;
246
+    overflow: visible;
247
+    color: rgba(255,255,255,.50);
248
+}
249
+
250
+div.feedbackButton {
251
+    position: absolute;
252
+    background-color: rgba(0,0,0,.50);
253
+    border-radius: 50%;
254
+    width: 100px;
255
+    height: 100px;
256
+    bottom: -50px;
257
+    left: -50px;
258
+    z-index: 100;
259
+    overflow: hidden;
260
+    transition: all .2s ease-in-out;
261
+}
262
+
263
+div.feedbackButton:hover {
264
+    transform: scale(1.3);
265
+}
266
+
243 267
 #bottomToolbar {
244 268
     display:block;
245 269
     position: absolute;

+ 5
- 2
index.html Näytä tiedosto

@@ -14,7 +14,7 @@
14 14
     <script src="https://api.callstats.io/static/callstats.min.js"></script>
15 15
     <script src="config.js?v=15"></script><!-- adapt to your needs, i.e. set hosts and bosh path -->
16 16
     <script src="interface_config.js?v=6"></script>
17
-    <script src="libs/app.bundle.min.js?v=138"></script>
17
+    <script src="libs/app.bundle.min.js?v=139"></script>
18 18
     <script src="analytics.js?v=1"></script><!-- google analytics plugin -->
19 19
     <!--
20 20
         Link used for inline installation of chrome desktop streaming extension,
@@ -218,8 +218,11 @@
218 218
                 </label>
219 219
             </div>
220 220
             <button id="updateSettings" data-i18n="settings.update"></button>
221
+            <a id="downloadlog" data-container="body" data-toggle="popover" data-placement="right" data-i18n="[data-content]downloadlogs" ><i class="fa fa-cloud-download"></i></a>
222
+        </div>
223
+        <div class="feedbackButton">
224
+            <a id="feedbackButton" data-container="body" data-toggle="popover" data-placement="right" data-i18n="[data-content]feedback"><i class="fa fa-heart"></i></a>
221 225
         </div>
222
-        <a id="downloadlog" data-container="body" data-toggle="popover" data-placement="right" data-i18n="[data-content]downloadlogs" ><i class="fa fa-cloud-download"></i></a>
223 226
     </div>
224 227
   </body>
225 228
 </html>

+ 5
- 1
lang/main.json Näytä tiedosto

@@ -3,6 +3,7 @@
3 3
     "connectionsettings": "Connection Settings",
4 4
     "poweredby": "powered by",
5 5
     "downloadlogs": "Download logs",
6
+    "feedback": "Give us your feedback",
6 7
     "roomUrlDefaultMsg": "Your conference is currently being created...",
7 8
     "participant": "Participant",
8 9
     "me": "me",
@@ -197,7 +198,10 @@
197 198
         "tokenAuthFailed": "Failed to authenticate with XMPP server: invalid token",
198 199
         "displayNameRequired": "Please enter your display name:",
199 200
         "extensionRequired": "Extension required:",
200
-        "firefoxExtensionPrompt": "You need to install a Firefox extension in order to use screen sharing. Please try again after you <a href='__url__'>get it from here</a>!"
201
+        "firefoxExtensionPrompt": "You need to install a Firefox extension in order to use screen sharing. Please try again after you <a href='__url__'>get it from here</a>!",
202
+        "feedbackQuestion": "How was your call?",
203
+        "thankYou": "Thank you for using __appName__!",
204
+        "sorryFeedback": "We're sorry to hear that. Would you like to tell us more?"
201 205
     },
202 206
     "email":
203 207
     {

+ 214
- 0
modules/UI/Feedback.js Näytä tiedosto

@@ -0,0 +1,214 @@
1
+/**
2
+ * Created by ystamcheva on 2/10/15.
3
+ */
4
+/* jshint -W101 */
5
+var messageHandler = require("./util/MessageHandler");
6
+var callStats = require("../statistics/CallStats");
7
+var APP = require("../../app");
8
+
9
+/**
10
+ * Constructs the html for the overall feedback window.
11
+ *
12
+ * @returns {string} the constructed html string
13
+ */
14
+var constructOverallFeedbackHtml = function() {
15
+    var feedbackQuestion = (Feedback.feedbackScore < 0)
16
+        ? '<br/><br/>' + APP.translation
17
+        .translateString("dialog.feedbackQuestion")
18
+        : '';
19
+
20
+    var message = '<div class="feedback"><div>' +
21
+        '<div class="feedbackTitle">' +
22
+        APP.translation.translateString("dialog.thankYou",
23
+                                        {appName:interfaceConfig.APP_NAME}) +
24
+        '</div>' +
25
+        feedbackQuestion +
26
+        '</div><br/><br/>' +
27
+        '<div id="stars">' +
28
+        '<a><i class="fa fa-star-o fa fa-star"></i></a>' +
29
+        '<a><i class="fa fa-star-o fa fa-star"></i></a>' +
30
+        '<a><i class="fa fa-star-o fa fa-star"></i></a>' +
31
+        '<a><i class="fa fa-star-o fa fa-star"></i></a>' +
32
+        '<a><i class="fa fa-star-o fa fa-star"></i></a>' +
33
+        '</div></div>';
34
+
35
+    return message;
36
+};
37
+
38
+/**
39
+ * Constructs the html for the detailed feedback window.
40
+ *
41
+ * @returns {string} the contructed html string
42
+ */
43
+var constructDetailedFeedbackHtml = function() {
44
+    // Construct the html, which will be served as a dialog message.
45
+    var message = '<div class="feedback">' +
46
+        '<div class="feedbackTitle">' +
47
+        APP.translation.translateString("dialog.sorryFeedback") +
48
+        '</div><br/><br/>' +
49
+        '<div class="feedbackDetails">' +
50
+        '<textarea id="feedbackTextArea" rows="10" cols="50" autofocus>' +
51
+        '</textarea>' +
52
+        '</div></div>';
53
+
54
+    return message;
55
+};
56
+
57
+/**
58
+ * The callback function corresponding to the openFeedbackWindow parameter.
59
+ *
60
+ * @type {function}
61
+ */
62
+var feedbackWindowCallback = null;
63
+
64
+/**
65
+ * Defines all methods in connection to the Feedback window.
66
+ *
67
+ * @type {{feedbackScore: number, openFeedbackWindow: Function,
68
+ * toggleStars: Function, hoverStars: Function, unhoverStars: Function}}
69
+ */
70
+var Feedback = {
71
+    /**
72
+     * The feedback score. -1 indicates no score has been given for now.
73
+     */
74
+    feedbackScore: -1,
75
+    /**
76
+     * Opens the feedback window.
77
+     */
78
+    openFeedbackWindow: function (callback) {
79
+        feedbackWindowCallback = callback;
80
+        // Add all mouse and click listeners.
81
+        var onLoadFunction = function (event) {
82
+            $('#stars >a').each(function(index) {
83
+                // On star mouse over.
84
+                $(this).get(0).onmouseover = function(){
85
+                    Feedback.hoverStars(index);
86
+                };
87
+                // On star mouse leave.
88
+                $(this).get(0).onmouseleave = function(){
89
+                    Feedback.unhoverStars(index);
90
+                };
91
+                // On star click.
92
+                $(this).get(0).onclick = function(){
93
+                    Feedback.toggleStars(index);
94
+                    Feedback.feedbackScore = index+1;
95
+
96
+                    // If the feedback is less than 3 stars we're going to
97
+                    // ask the user for more information.
98
+                    if (Feedback.feedbackScore > 3) {
99
+                        callStats.sendFeedback(Feedback.feedbackScore, "");
100
+                        if (feedbackWindowCallback)
101
+                            feedbackWindowCallback();
102
+                        else
103
+                            APP.UI.messageHandler.closeDialog();
104
+                    }
105
+                    else {
106
+                        feedbackDialog.goToState('detailed_feedback');
107
+                    }
108
+                };
109
+                // Initialise stars to correspond to previously entered feedback.
110
+                if (Feedback.feedbackScore > 0
111
+                    && index < Feedback.feedbackScore) {
112
+                    Feedback.hoverStars(index);
113
+                    Feedback.toggleStars(index);
114
+                }
115
+            });
116
+        };
117
+
118
+        // Defines the different states of the feedback window.
119
+        var states = {
120
+            overall_feedback: {
121
+                html: constructOverallFeedbackHtml(),
122
+                persistent: true,
123
+                buttons: {},
124
+                closeText: '',
125
+                focus: "div[id='stars']",
126
+                position: {width: 500}
127
+            },
128
+            detailed_feedback: {
129
+                html: constructDetailedFeedbackHtml(),
130
+                buttons: {"Submit": true, "Cancel": false},
131
+                closeText: '',
132
+                focus: "textarea[id='feedbackTextArea']",
133
+                position: {width: 500},
134
+                submit: function(e,v,m,f) {
135
+                    e.preventDefault();
136
+                    if (v) {
137
+                        var feedbackDetails
138
+                            = document.getElementById("feedbackTextArea").value;
139
+
140
+                        if (feedbackDetails && feedbackDetails.length > 0)
141
+                            callStats.sendFeedback( Feedback.feedbackScore,
142
+                                                    feedbackDetails);
143
+
144
+                        if (feedbackWindowCallback)
145
+                            feedbackWindowCallback();
146
+                        else
147
+                            APP.UI.messageHandler.closeDialog();
148
+                    } else {
149
+                        // User cancelled
150
+                        if (feedbackWindowCallback)
151
+                            feedbackWindowCallback();
152
+                        else
153
+                            APP.UI.messageHandler.closeDialog();
154
+                    }
155
+                }
156
+            }
157
+        };
158
+
159
+        // Create the feedback dialog.
160
+        var feedbackDialog
161
+            = APP.UI.messageHandler.openDialogWithStates(
162
+                states,
163
+                {   persistent: true,
164
+                    buttons: {},
165
+                    closeText: '',
166
+                    loaded: onLoadFunction,
167
+                    position: {width: 500}}, null);
168
+    },
169
+    /**
170
+     * Toggles the appropriate css class for the given number of stars, to
171
+     * indicate that those stars have been clicked/selected.
172
+     *
173
+     * @param starCount the number of stars, for which to toggle the css class
174
+     */
175
+    toggleStars: function (starCount)
176
+    {
177
+        $('#stars >a >i').each(function(index) {
178
+            if (index <= starCount) {
179
+                $(this).removeClass("fa-star-o");
180
+            }
181
+            else
182
+                $(this).addClass("fa-star-o");
183
+        });
184
+    },
185
+    /**
186
+     * Toggles the appropriate css class for the given number of stars, to
187
+     * indicate that those stars have been hovered.
188
+     *
189
+     * @param starCount the number of stars, for which to toggle the css class
190
+     */
191
+    hoverStars: function (starCount)
192
+    {
193
+        $('#stars >a >i').each(function(index) {
194
+            if (index <= starCount)
195
+                $(this).addClass("starHover");
196
+        });
197
+    },
198
+    /**
199
+     * Toggles the appropriate css class for the given number of stars, to
200
+     * indicate that those stars have been un-hovered.
201
+     *
202
+     * @param starCount the number of stars, for which to toggle the css class
203
+     */
204
+    unhoverStars: function (starCount)
205
+    {
206
+        $('#stars >a >i').each(function(index) {
207
+            if (index <= starCount && $(this).hasClass("fa-star-o"))
208
+                $(this).removeClass("starHover");
209
+        });
210
+    }
211
+};
212
+
213
+// Exports the Feedback class.
214
+module.exports = Feedback;

+ 5
- 0
modules/UI/UI.js Näytä tiedosto

@@ -33,6 +33,7 @@ var XMPPEvents = require("../../service/xmpp/XMPPEvents");
33 33
 var StatisticsEvents = require("../../service/statistics/Events");
34 34
 var UIEvents = require("../../service/UI/UIEvents");
35 35
 var MemberEvents = require("../../service/members/Events");
36
+var Feedback = require("./Feedback");
36 37
 
37 38
 var eventEmitter = new EventEmitter();
38 39
 var roomNode = null;
@@ -423,11 +424,15 @@ UI.start = function (init) {
423 424
         $("#downloadlog").click(function (event) {
424 425
             dump(event.target);
425 426
         });
427
+        $("#feedbackButton").click(function (event) {
428
+            Feedback.openFeedbackWindow();
429
+        });
426 430
     }
427 431
     else
428 432
     {
429 433
         $("#header").css("display", "none");
430 434
         $("#bottomToolbar").css("display", "none");
435
+        $("#feedbackButton").css("display", "none");
431 436
         $("#downloadlog").css("display", "none");
432 437
         $("#remoteVideos").css("padding", "0px 0px 18px 0px");
433 438
         $("#remoteVideos").css("right", "0px");

+ 19
- 27
modules/UI/toolbars/Toolbar.js Näytä tiedosto

@@ -11,6 +11,7 @@ var UIUtil = require("../util/UIUtil");
11 11
 var AuthenticationEvents
12 12
     = require("../../../service/authentication/AuthenticationEvents");
13 13
 var AnalyticsAdapter = require("../../statistics/AnalyticsAdapter");
14
+var Feedback = require("../Feedback");
14 15
 
15 16
 var roomUrl = null;
16 17
 var sharedKey = '';
@@ -135,41 +136,32 @@ var defaultToolbarButtons = {
135 136
     'hangup': '#toolbar_button_hangup'
136 137
 };
137 138
 
139
+/**
140
+ * Hangs up this call.
141
+ */
138 142
 function hangup() {
139
-    APP.xmpp.disposeConference();
140
-    if(config.enableWelcomePage) {
141
-        setTimeout(function() {
142
-            window.localStorage.welcomePageDisabled = false;
143
-            window.location.pathname = "/";
144
-        }, 10000);
145
-
143
+    var conferenceDispose = function () {
144
+        APP.xmpp.disposeConference();
145
+
146
+        if (config.enableWelcomePage) {
147
+            setTimeout(function() {
148
+                window.localStorage.welcomePageDisabled = false;
149
+                window.location.pathname = "/";
150
+            }, 3000);
151
+        }
146 152
     }
147 153
 
148
-    var title = APP.translation.generateTranslationHTML(
149
-        "dialog.sessTerminated");
150
-    var msg = APP.translation.generateTranslationHTML(
151
-        "dialog.hungUp");
152
-    var button = APP.translation.generateTranslationHTML(
153
-        "dialog.joinAgain");
154
-    var buttons = [];
155
-    buttons.push({title: button, value: true});
156
-
157
-    UI.messageHandler.openDialog(
158
-        title,
159
-        msg,
160
-        true,
161
-        buttons,
162
-        function(event, value, message, formVals) {
163
-            window.location.reload();
164
-            return false;
165
-        }
166
-    );
154
+    if (Feedback.feedbackScore > 0) {
155
+        Feedback.openFeedbackWindow();
156
+        conferenceDispose();
157
+    }
158
+    else
159
+        Feedback.openFeedbackWindow(conferenceDispose);
167 160
 }
168 161
 
169 162
 /**
170 163
  * Starts or stops the recording for the conference.
171 164
  */
172
-
173 165
 function toggleRecording(predefinedToken) {
174 166
     APP.xmpp.toggleRecording(function (callback) {
175 167
         if (predefinedToken) {

+ 2
- 1
modules/UI/util/MessageHandler.js Näytä tiedosto

@@ -84,7 +84,8 @@ var messageHandler = (function(my) {
84 84
     };
85 85
 
86 86
     /**
87
-     * Shows a message to the user with two buttons: first is given as a parameter and the second is Cancel.
87
+     * Shows a message to the user with two buttons: first is given as a
88
+     * parameter and the second is Cancel.
88 89
      *
89 90
      * @param titleString the title of the message
90 91
      * @param msgString the text of the message

+ 20
- 1
modules/statistics/CallStats.js Näytä tiedosto

@@ -77,7 +77,26 @@ var CallStats = {
77 77
         }
78 78
         callStats.sendFabricEvent(this.peerconnection,
79 79
             callStats.fabricEvent.fabricSetupFailed, this.confID);
80
-    }
80
+    },
81
+    /**
82
+     * Sends the given feedback through CallStats.
83
+     *
84
+     * @param overallFeedback an integer between 1 and 5 indicating the
85
+     * user feedback
86
+     * @param detailedFeedback detailed feedback from the user. Not yet used
87
+     */
88
+    sendFeedback: function(overallFeedback, detailedFeedback) {
89
+        if(!callStats) {
90
+            return;
91
+        }
92
+        var feedbackString =    '{"userID":"' + this.userID + '"' +
93
+                                ', "overall":' + overallFeedback +
94
+                                ', "comment": "' + detailedFeedback + '"}';
81 95
 
96
+        var feedbackJSON = JSON.parse(feedbackString);
97
+        
98
+        callStats.sendUserFeedback(
99
+            this.confID, feedbackJSON);
100
+    }
82 101
 };
83 102
 module.exports = CallStats;

Loading…
Peruuta
Tallenna