Difference between revisions of "IS480 Team wiki: 2016T1 Stark Final Wiki"
Cylee.2013 (talk | contribs) |
Cylee.2013 (talk | contribs) |
||
(17 intermediate revisions by the same user not shown) | |||
Line 53: | Line 53: | ||
<br><br> | <br><br> | ||
=<div style="background: #D80E0E; padding: 15px; font-weight: bold; line-height: 0.3em; text-indent: 15px; font-size: 22px"><font color=#FFFFF>Project Progress Summary</font></div>= | =<div style="background: #D80E0E; padding: 15px; font-weight: bold; line-height: 0.3em; text-indent: 15px; font-size: 22px"><font color=#FFFFF>Project Progress Summary</font></div>= | ||
− | <font size=4><b>Final Slides</b>:</font> [ Download Here] | + | <font size=4><b>Final Slides</b>:</font> [https://drive.google.com/open?id=0Bw61nolwJbl6MWszU0R6aDZTclk Download Here] |
<br><br> | <br><br> | ||
− | MaiMai is deployed for production at | + | MaiMai is deployed for production at http://www.app.maitwo.com<br> |
− | MaiMai is deployed for testing purpose at <br> | + | MaiMai is deployed for testing purpose at http://www.uat.maitwo.com<br> |
Learn more about us at http://www.maitwo.com<br><br> | Learn more about us at http://www.maitwo.com<br><br> | ||
− | <b>Current Iteration:</b> | + | <b>Current Iteration:</b> 15 <br/> |
<b>Total Iterations:</b> 16 <br/> | <b>Total Iterations:</b> 16 <br/> | ||
− | <b>Iteration Dates (Current):</b> | + | <b>Iteration Dates (Current):</b> 7 Nov 2016 - 20 Nov 2016<br/> |
− | <b>Iteration Dates (Final):</b> | + | <b>Iteration Dates (Final):</b> 21 Nov 2016 - 2 Dec 2016<br/> |
<h2>Project Highlights</h2> | <h2>Project Highlights</h2> | ||
+ | <b>The Truth of Self-Proposed Projects </b><br> | ||
+ | People have the misconception that a self-proposed project has no rules (i.e. the team will make up their own requirements as and when they like). However, the truth is that the users of the application are the ones that come out with specifications. In light of that, the team has faced several conflicting comments and suggestions. | ||
− | + | To solve these conflicting comments, the team has conducted several user and A/B testing. The team has also reached out to the users during real life transactions and gather pain and gain points for further discussions and improvements. | |
− | + | <br><br> | |
− | |||
− | |||
− | < | ||
+ | <font size=3><b>Project Challenges</b></font><br> | ||
+ | <b>Web Push Notifications </b><br> | ||
+ | Web Push Notification is currently an experimental technology. Documentation for implementation is extremely basic and not much help and support is available online. It took the team much time and effort to figure problems out ourselves as many issues were not faced by other people. These notifications are especially vital for good user experience as many users express the need for it. The team successfully implemented these notifications and they are exceptionally well-received by users. | ||
+ | [[File:stark_Notifi.png|400px|center]] | ||
+ | <b>Extensive and Feature-Rich Admin System </b><br> | ||
+ | MaiMai's business processes require administrative intervention (e.g. dispute handling, iBanking transactions etc.) In addition, this admin system has to be forward-looking in the sense that it needs to be easily usable and sufficiently functional. As such, this results in doubling the workload of the team. The team successfully implemented a robust and usable system for administrative functions with additional statistical capabilities. | ||
+ | <br><br> | ||
+ | <font size=3><b>Project Achievements</b></font><br> | ||
+ | * Facilitated real users' transactions that utilize MaiMai's online payment system. | ||
+ | * Fully reactive and real-time web application with high compatibility with modern browsers. Users express great satisfaction in terms of usability and functionality. | ||
+ | <br> | ||
=<div style="background: #D80E0E; padding: 15px; font-weight: bold; line-height: 0.3em; text-indent: 15px; font-size: 22px"><font color=#FFFFF>Project Management</font></div>= | =<div style="background: #D80E0E; padding: 15px; font-weight: bold; line-height: 0.3em; text-indent: 15px; font-size: 22px"><font color=#FFFFF>Project Management</font></div>= | ||
<h2>Project Scope</h2> | <h2>Project Scope</h2> | ||
Line 119: | Line 129: | ||
<h2>Project Metrics</h2> | <h2>Project Metrics</h2> | ||
<font size=3><h3>Schedule Metrics</h3></font> | <font size=3><h3>Schedule Metrics</h3></font> | ||
− | [[File: | + | [[File:Stark_SM_final2.png|600px|center|link=]]<br> |
{| class="wikitable" style="text-align:center; background: white; margin: 0px;" | {| class="wikitable" style="text-align:center; background: white; margin: 0px;" | ||
! style="background: #D80E0E; color: white; font-weight: bold; width: 10%" | Iteration | ! style="background: #D80E0E; color: white; font-weight: bold; width: 10%" | Iteration | ||
Line 134: | Line 144: | ||
|More time needed to fix bugs from UT1 and after the integration of Dispute Management. | |More time needed to fix bugs from UT1 and after the integration of Dispute Management. | ||
Follow up action: Informed supervisor and mentor about the delay. More hours put in for debugging. No major delay to overall schedule. | Follow up action: Informed supervisor and mentor about the delay. More hours put in for debugging. No major delay to overall schedule. | ||
+ | |Completed | ||
+ | |- | ||
+ | |13 | ||
+ | |14 | ||
+ | |16 | ||
+ | |0.88 | ||
+ | |Underestimated the complexity of 'Web Push Notification' | ||
+ | Follow up action: Informed supervisor and mentor about the delay. No major delay to overall schedule. | ||
|Completed | |Completed | ||
|} | |} | ||
Line 139: | Line 157: | ||
<font size=3><h3>Bug Metrics</h3></font> | <font size=3><h3>Bug Metrics</h3></font> | ||
− | [[File:|600px|center|link=]]<br> | + | [[File:Stark_Bm_final_wiki.png|600px|center|link=]]<br> |
{| class="wikitable" style="text-align:center; background: white; margin: 0px;" | {| class="wikitable" style="text-align:center; background: white; margin: 0px;" | ||
! style="background: #D80E0E; color: white; font-weight: bold; width: 10%" | Iteration | ! style="background: #D80E0E; color: white; font-weight: bold; width: 10%" | Iteration | ||
Line 705: | Line 723: | ||
<h2>Deployment</h2> | <h2>Deployment</h2> | ||
− | + | MaiMai is deployed for production at http://www.app.maitwo.com<br> | |
+ | MaiMai is deployed for testing purpose at http://www.uat.maitwo.com<br> | ||
+ | Learn more about us at http://www.maitwo.com<br><br> | ||
<h2>User Testing</h2> | <h2>User Testing</h2> | ||
Line 730: | Line 750: | ||
|- | |- | ||
|| User Testing 3 | || User Testing 3 | ||
− | || | + | || 31st October 2016 - 11th November 2016 |
− | || | + | || Off-Site (At respective members' discretion) |
− | || | + | || 32 |
|| [[IS480 Team wiki: 2016T1 Stark Documentation Testing User Testing 3 | User Testing 3]] | || [[IS480 Team wiki: 2016T1 Stark Documentation Testing User Testing 3 | User Testing 3]] | ||
|- | |- | ||
Line 740: | Line 760: | ||
<font size=3><b>Team Reflection</b></font> | <font size=3><b>Team Reflection</b></font> | ||
− | The journey so far has been tough but enjoyable learning experience for Team Stark. As a self-proposed IS480 project, we learnt how to make use of this opportunity to learn about running a start-up. For example, the importance of gathering feedbacks from actual users, validating ideas and features, followed by developing an application that caters to market needs. We have learnt about individual's strengths and weaknesses and worked towards complementing each other to produce quality work. Furthermore, given the guidance of our supervisor, mentor, and reviewers helps the team to overcome obstacles and stretch us to our maximum capability. | + | The journey so far has been tough but enjoyable learning experience for Team Stark. As a self-proposed IS480 project, we learnt how to make use of this opportunity to learn about running a start-up. For example, the importance of gathering feedbacks from actual users, validating ideas and features, followed by developing an application that caters to market needs. We have learnt about individual's strengths and weaknesses and worked towards complementing each other to produce quality work. Furthermore, given the guidance of our supervisor, mentor, and reviewers helps the team to overcome obstacles and stretch us to our maximum capability.<br> |
+ | [[Image:Stark_all.png|700px|center]] | ||
<br><font size=3><b>Individual Reflection</b></font> | <br><font size=3><b>Individual Reflection</b></font> |
Latest revision as of 14:54, 24 November 2016
Project Progress Summary
Final Slides: Download Here
MaiMai is deployed for production at http://www.app.maitwo.com
MaiMai is deployed for testing purpose at http://www.uat.maitwo.com
Learn more about us at http://www.maitwo.com
Current Iteration: 15
Total Iterations: 16
Iteration Dates (Current): 7 Nov 2016 - 20 Nov 2016
Iteration Dates (Final): 21 Nov 2016 - 2 Dec 2016
Project Highlights
The Truth of Self-Proposed Projects
People have the misconception that a self-proposed project has no rules (i.e. the team will make up their own requirements as and when they like). However, the truth is that the users of the application are the ones that come out with specifications. In light of that, the team has faced several conflicting comments and suggestions.
To solve these conflicting comments, the team has conducted several user and A/B testing. The team has also reached out to the users during real life transactions and gather pain and gain points for further discussions and improvements.
Project Challenges
Web Push Notifications
Web Push Notification is currently an experimental technology. Documentation for implementation is extremely basic and not much help and support is available online. It took the team much time and effort to figure problems out ourselves as many issues were not faced by other people. These notifications are especially vital for good user experience as many users express the need for it. The team successfully implemented these notifications and they are exceptionally well-received by users.
Extensive and Feature-Rich Admin System
MaiMai's business processes require administrative intervention (e.g. dispute handling, iBanking transactions etc.) In addition, this admin system has to be forward-looking in the sense that it needs to be easily usable and sufficiently functional. As such, this results in doubling the workload of the team. The team successfully implemented a robust and usable system for administrative functions with additional statistical capabilities.
Project Achievements
- Facilitated real users' transactions that utilize MaiMai's online payment system.
- Fully reactive and real-time web application with high compatibility with modern browsers. Users express great satisfaction in terms of usability and functionality.
Project Management
Project Scope
Planned |
---|
Actual |
---|
Scope Changes The following changes has been made to our project scope and reflected in our schedule.
- Altered "Location Check-In" to "Agreement fields (Location, Date and Time)" as check-In process requires much more planning and considerations. As there is limited time, the team has decided to focus on providing as much structured agreements as possible to show future plan of using such structured agreements as a mean to automate the dispute management process.
- Added "Web Push Notification" into "Good-To-Have" feature to integrate the user's experience with the notification function in MaiMai.
Project Timeline
Planned |
---|
Actual |
---|
Schedule Highlights
The following changes has been made to our project scope and reflected in our schedule.
- iBanking was shifted from iteration 12 to iteration 13 as we need to replan the business process as there is no way for savings account to be automated
- Added "Web Push Notification" into "Good-To-Have" feature in iteration 13 as to integrate the user's experience with the notification function in MaiMai
- Altered "Location Check-In" to "Agreement fields (Location, Date and Time)" as check-In process requires much more planning and considerations. As there is limited time, the team has decided to focus on providing as much structured agreements as possible to show future plan of using such structured agreements as a mean to automate the dispute management process.
- Shifted UT3 from 24 Oct to 31 Oct as additional features were being modified and added into scope, UT3 will focus on all additional features.
Refer to our Change Management for more!
Project Metrics
Schedule Metrics
Iteration | Planned Duration (Days) | Actual Duration (Days) | Schedule Metric Score | Action Taken | Status |
---|---|---|---|---|---|
8 | 14 | 16 | 0.88 | More time needed to fix bugs from UT1 and after the integration of Dispute Management.
Follow up action: Informed supervisor and mentor about the delay. More hours put in for debugging. No major delay to overall schedule. |
Completed |
13 | 14 | 16 | 0.88 | Underestimated the complexity of 'Web Push Notification'
Follow up action: Informed supervisor and mentor about the delay. No major delay to overall schedule. |
Completed |
View our Schedule Metrics Here!
Bug Metrics
Iteration | Bug Score | Bug Summary | Action Taken |
---|---|---|---|
6 | 43 3 low |
The spike in bug count is due to the integration of dispute management system together with previous completed features. | Resolve bugs immediately. No major delay was caused. |
8 | 179 44 low |
The spike in bug count is because of the integration of many new features together for UT1. | Resolve bugs immediately. Iteration 8 was scheduled for post UT1 debugging. PM scheduled the Lead Backend developer to focus on debugging while the rest of the developers focus on development. |
9 | 42 7 low |
The first critical bug was system crashed when a dispute for review is filed. The second critical bug was images is not updated when listing image name is being edited. | Resolve bugs immediately. No major delay was caused. Critical bug did not occur again. Similar action was performed but bug did not replicate. |
Project Risks
Risk Description | Likelihood | Impact | Mitigation Strategy |
---|---|---|---|
Mismatch of product against market. | High | High Developed product may not be what our target users or anyone in the market wants. |
1. Gather more feedbacks during testing to validate market needs against project idea. 2. Transact with more real user and conduct interview with them to understand the problems and needs of the market. |
Quick rise of direct competition | Low | Low Existing application like Caurosell can easily implement payment services that we are providing. |
We provide user with dispute management service which is something that is unique to us and we are investing our resources into defining a stringent and reliable process of micro management. As such we have the upper hand because that is our prime feature. However, it still remain as a risk. |
Technical Complexity
Complexities arise due to the following needs:
- User Experience
- Performance (Client and Server)
- Compatibility across devices and browsers
- Mobile vs Desktop
Processing of Users’ Uploaded Images
Problem: Beforehand we had a “limit” on the size of images to 1MB
- Server resources
- Faster loading for users
Causes: Poor user experience
- Users complain why other “apps” out there that can accept all images from their phones (main basis of benchmarking).
Benchmark max file size to accept:
- Two “best” phones (iPhone 7s and Samsung Galaxy 7 camera captured photos (12 MP 3-6 MB)
Keep file sizes after processing below 1MB
- Maintaining sufficient quality for the web
Processing to be done client side
- If image processing is to be at server side there is an additional two way transfer of the user uploading to the server and downloading the processed image
- Heavy on server resources
What we did:
- Used HTML’s Canvas for resizing
- Client-side library Pica for reducing image quality
Explaination:
1. Retrieve images from form
2. Create HTML Image object
3. Load uploaded image into Image object
//Goes through the images ( might have multiple images at one go) let images = this.state.image; for (let i = 0; i < images.length; i++) { let image = images[i]; let img = new Image(); img.src = window.URL.createObjectURL(image); img.onload = () => {
4. Create a HTML Canvas object
5. Draw Image object onto Canvas
img.onload = () => { let src = document.createElement('canvas'); src.width = img.width; src.height = img.height; let ctx = src.getContext('2d'); ctx.drawImage(img, 0, 0);
6. Determine processed Canvas size while maintaining ratio
let dest = document.createElement('canvas'); let longerLength = 1536; let shorterLength = 1180; let ratio; if ((src.width > src.height || src.width === src.height) && (src.width > longerLength || src.height > shorterLength)) { if (src.width / longerLength > 1) { ratio = longerLength / src.width; dest.width = Math.round(ratio * src.width); dest.height = Math.round(ratio * src.height); } else { ratio = src.width / longerLength; dest.height = Math.round(ratio * src.height); dest.width = Math.round(ratio * src.width); }
7. Use Pica to do image optimization from source Canvas to destination Canvas
pica.resizeCanvas(src, dest, (err) => { if (err) { console.log(err); return; } dest.toBlob(processImage, 'image/jpeg', 0.8); });
8. With processed Canvas ready, we convert it into a blob and then into a Buffer Object to transfer to backend later
const processImage = (blob) => { const data = (file) => { let reader = new FileReader(); let name = file.name; reader.onloadend = (e) => { let results = this.state.uploadData; let sha1 = this.state.sha1; let image = reader.result; let buffer = new Buffer(image.byteLength); let view = new Uint8Array(image); for (let i = 0; i < buffer.length; ++i) { buffer[i] = view[i]; }
9. We later realized that iOS browsers do not support the Canvas function “toBlob”
export const addToBlobFunction = function () { // add toBlob functionality for browsers that do not support it. if( !HTMLCanvasElement.prototype.toBlob ) { Object.defineProperty( HTMLCanvasElement.prototype, 'toBlob', { value: function( callback, type, quality ) { const bin = atob( this.toDataURL( type, quality ).split(',')[1] ), len = bin.length, len32 = len >> 2, a8 = new Uint8Array( len ), a32 = new Uint32Array( a8.buffer, 0, len32 ); for( var i=0, j=0; i < len32; i++ ) { a32[i] = bin.charCodeAt(j++) | bin.charCodeAt(j++) << 8 | bin.charCodeAt(j++) << 16 | bin.charCodeAt(j++) << 24; } let tailLength = len & 3; while( tailLength-- ) { a8[ j ] = bin.charCodeAt(j++); }
End Result: Image sizes reduced from (5.5MB to 0.4MB, 8% of original image size)
Reactive and Real-time Chat
The chat serves as the core foundation to the transaction process for buyers and sellers Its’ main purpose is to facilitate efficient and effective communication and transaction between users. It needed to be reactive and real-time:
- Needs to respond to changes by either user especially when building up the initial agreements
- Needs to reflect proper status and relevant information according to the stage in the transaction
Reactivity and Real-Time achieved with Meteor and React:
- Meteor provide the real time syncing
- React allows us to react to changes in data
Designing of the data “schemas” is especially important Required to allow for changes to be properly reflected Caters to a publish-subscribe methodology
let toInsert = { "_id": chatId, "listing": listingId, "listingOwner": listingOwner, "otherUser": otherUser, "status": "open", "price": listing.price, "agreements": agreements, "privateImages": {}, createdAt: new Date() }; Chats.insert(toInsert);
Messages.insert({ "chat": chatId, "owner": username, "type": "user", "message": message, "createdAt": new Date() })
case 'add': if (currentAgreement) throw new Meteor.Error('agreement already exists'); agreements[agreement] = { agreement: agreement, owner: username, status: 'add' };
Using Meteor for data subscription, data changes are continuously pushed to the React Component
export default createContainer(({params}) => { // … const chatHandle = Meteor.subscribe('getChat', chatId, { // … }); // … }, Conversation);
componentWillReceiveProps(nextProps) { let {user, chat, transaction, payment} = nextProps;
Using React’s lifecycle management (componentWillReceiveProps), we respond to changes whenever it receives new data
componentWillReceiveProps(nextProps) { let chat = nextProps.chat; let listing = nextProps.listing; if (Object.keys(chat).length > 0) { this.setDetails(chat); } else if (Object.keys(listing).length > 0) { this.setListingDetails(listing); }}
For example rendering the agreements and the available actions
agreements.forEach((val) => { let agreement = val.agreement; let owner = val.owner; let status = val.status; switch (status) { case 'confirmed': contentConfirmed.push(confirmedAgreement(agreement)); break; case 'edit': contentEdited.push(pendingAgreement(agreement, 'edit', owner === myUser)); break; case 'delete': contentEdited.push(pendingAgreement(agreement, 'delete', owner === myUser)); break;
Or showing new chat messages immediately
getMessage(messageArr) { let user = this.props.myUser; let messages = []; messageArr.map((message) => { let {_id: id, owner, type, message: content, createdAt: date} = message; switch (type) { case 'user': messages.push( <UserMessage key={id} message={content} date={date} owner={owner === user} username={user}/> ); break; case 'system': messages.push( <SystemMessage key={id} message={content} date={date}
Web Push Notifications
Beforehand we only had “notifications” that only works if the user views the web application.
Poor user experience
- No way for users to find out they have been contacted.
- Users say that it does not make sense for them to manually periodically check the application
Considerations
1. Provide “push notifications” that does not require user to open MaiMai up as one of their tabs.
2. Support as many web browsers and devices as possible.
- As we do not have a native mobile app, we need to rely on whatever protocol that is available for the web.
How we did?
Web Push notifications achieved using Service workers and Push API
1. Service workers
- Run on a different thread to the web app (non-blocking)
2. Push API
- “gives web applications the ability to receive messages pushed to them from a server, whether or not the web app is in the foreground, or even currently loaded, on a user agent”
What we did?
Initial server side configuration:
1. Server needs to generate and store a elliptic curve Diffie-Hellman (ECDH) public and private key pair.
"vapidKeys": { "publicKey": "BMPuJKF-1EwQ….", "privateKey": “…" },
2. Needs to have the service worker script ready
- This script serves as the instructions to the client on how to react to different situations.
3. Get user’s permission and install service worker
navigator.serviceWorker.register('/sw.js').then(() => { return navigator.serviceWorker.ready; }).then((serviceWorkerRegistration) => { BrowserNotification.reg = serviceWorkerRegistration; serviceWorkerRegistration.pushManager.getSubscription() .then((subscription) => { if (!subscription) { BrowserNotification.subscribe(); …
4. Get public key, create subscription and pass subscription details to server for storing
Meteor.call('getPushPublicKey', (err, res) => { if (err) return; reg.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey: BrowserNotification.urlBase64ToUint8Array(res) }).then((pushSubscription) => { BrowserNotification.sub = pushSubscription; BrowserNotification.isSubscribed = true; Meteor.call('setUserSubscription', pushSubscription.toJSON()); cb(); }); })
5. Subscription details contain the following:
1. Message server’s end point
2. Keys
- auth – authentication secret generated by the browser
- p256dh – client’s browser public key for encryption
{ "endpoint": "https://fcm.googleapis.com/fcm/send/fkLOH68QwQ4:APA9...", "keys": { "p256dh": "BLX5h_qHwDgrdqp-GGlua-aWyiIRzXUYNdUg84hsOy74Lag-EU…", "auth": "uv6nwQTejj2lAA9hPj… “ } }
6. Implemented server side hooks:
- New chat messages
- New notifications
Hooks call “newMessage” from our own web push module (WebPush)
7. To create a push message, we need to generate the following:
1. Headers
- Authorization (JSON Web Token)
- Header
- Payload
- Signature (Encrypted header + payload)
- Crypto-Key
- Public key of server
- Public key of client’s browser
- Encryption (random 16 byte salt)
2. Body
- Encrypted message
8. JSON Web Token generated using JWS package
const header = { typ: 'JWT', alg: 'ES256' }; const jwtPayload = { aud: audience, exp: Math.floor(Date.now() / 1000) + 86400, sub: subject }; const jwt = jws.sign({ header: header, payload: jwtPayload, privateKey: privateKey // the server's private key }); // this returns us the entire JSON Web Token
Crypto-Key is simply a concatenation of:
1. Public key of the server
- p256ecdsa=<sever’s public key>
2. Public key of the client’s browser
- dh=<subscription’s public key>
dh=<subscription’s public key>;p256ecdsa=<server’s public key>
9. The message contains the following:
- Title: of the push notification
- Body: of the push notification
- Redirect: link to go to upon clicking
- Tag: for combining of messages
let options = { title: username, body: message, redirect: "/chat/" + chatId, tag: chatId };
10. To encrypt the message, we used the library http_ece
const localCurve = crypto.createECDH('prime256v1'); const localPublicKey = localCurve.generateKeys(); const salt = urlBase64.encode(crypto.randomBytes(16)); ece.saveKey('webpushKey', localCurve, 'P-256'); const cipherText = ece.encrypt(payload, { keyid: 'webpushKey', dh: userPublicKey, salt: salt, authSecret: userAuth, padSize: 2 }); return { localPublicKey: localPublicKey, salt: salt, cipherText: cipherText };
11. We send a POST request to the subscription end point with the encrypted message and headers:
while (!successful && new Date() - timeout < 60000) { //assumes that after a min or ~60 tries and still unable to send and receive the subscription is down try { res = HTTP.call(requestDetails.method, requestDetails.endpoint, options); successful = true; addToUpdate = true; } catch (err) { if (err.response && err.response.statusCode == '410') { successful = true; unsuccessful.push(sub.endpoint); } setTimeout(()=>{}, 1000); }
12. Users will then receive the push notification on their browsers
- Desktop browsers must be opened to receive the notifications
- Android’s Chrome will receive in the background regardless of being opened or closed
On clicking the notification, it will go to the relevant window and redirect to the link.
13. The way to react to push notifications are scripted within the service worker script we installed earlier.
We specify 2 main events
- push: When receiving a push notification
- notificationclick: When clicking on a push notification
Push event has 3 main steps
1. Get all notifications that are within the same “tag”, this allows us to combine messages. Combine if more than one message.
const promiseChain = self.registration.getNotifications({tag: event.data.tag}) .then(notifications => { … if (notifications.length > 0) { //we need to combine options.body = "You have received new messages"; options.renotify = true;
2. Check if user is still viewing the app, if so do not show notification
return clients.matchAll() .then(clients => { let mustShowNotification = true; if (clients.length > 0) { for (let i = 0; i < clients.length; i++) { if (clients[i].visibilityState === 'visible') { mustShowNotification = false;
3. Show the notification
if (mustShowNotification) { // Show the notification. if (options) { return self.registration.showNotification( options.title ? options.title : "MaiMai", options);
notificationclick event redirects user to the page of the notification
event.waitUntil(clients.matchAll({ includeUncontrolled: true, type: 'window' }).then(activeClients => { if (activeClients.length > 0) { if ("navigate" in activeClients[0]) { activeClients[0].navigate(appUrl); activeClients[0].focus(); } else { //workaround for firefox
clients.openWindow(appUrl);
} } else { clients.openWindow(appUrl); } }) );
Final outcome
Users can now receive notifications without opening the web application.
Supported clients: 1. Desktop (Windows/Mac OSX):
- Chrome
- Firefox
2. Mobile (Android):
- Chrome (or any variants that is based of chrome)
- Firefox
Quality of Product
Intermediate Deliverables
Stage | Specification | Modules |
---|---|---|
Project Requirements | Market Research | Market Research |
Project Management | Minutes | Minutes |
Metrics | Schedule Metrics Bug Metrics | |
Risk | Risks | |
Change Management | Change Management | |
Diagrams | Use Diagrams Architecture Diagram |
Diagrams |
Design | Low-Fi Prototype High-Fi Prototype |
UI Prototype |
Testing | User Testing 1 | User Test 1 User Test 2 User Test 3 |
Deployment
MaiMai is deployed for production at http://www.app.maitwo.com
MaiMai is deployed for testing purpose at http://www.uat.maitwo.com
Learn more about us at http://www.maitwo.com
User Testing
User Testing | Date | Venue | Users | Link |
---|---|---|---|---|
User Testing 1 | 1st August 2016 - 8th August 2016 | Off-Site (At respective members' discretion) | 22 | User Testing 1 |
User Testing 2 | 12th September 2016 - 26th September 2016 | SIS GSR 2-7 & Off-Site (At respective members' discretion) | 38 | User Testing 2 |
User Testing 3 | 31st October 2016 - 11th November 2016 | Off-Site (At respective members' discretion) | 32 | User Testing 3 |
Reflection
Team Reflection
The journey so far has been tough but enjoyable learning experience for Team Stark. As a self-proposed IS480 project, we learnt how to make use of this opportunity to learn about running a start-up. For example, the importance of gathering feedbacks from actual users, validating ideas and features, followed by developing an application that caters to market needs. We have learnt about individual's strengths and weaknesses and worked towards complementing each other to produce quality work. Furthermore, given the guidance of our supervisor, mentor, and reviewers helps the team to overcome obstacles and stretch us to our maximum capability.
Individual Reflection