/it2810-webutvikling-h18-prosjekt-3-gruppe--11

it2810-webutvikling-h18-prosjekt-3-11 created by GitHub Classroom

Primary LanguageJavaScript

IT2810 – Webutvikling | Prosjekt 3 (Gruppe 11), Høst 2018

Oppgavebeskrivelse

I dette prosjektet fikk vi i oppgave å designe og implementere en "Personal Information and Motivation Manager" app for mobil, med React Native. Hovedformålet her var å demonstrere funksjonaliteten og bruk av teknologien. Det tenkes her at brukeren motiveres ved at applikasjonen skal støtte en form for registrering av personlige mål og resultater, ved enten fysisk eller intellektuell aktivitet.

Mer informasjon om oppgaven kan finnes på Blackboard (krever tilgang).

Teknologi

Følgende er nødvendig for å kjøre prosjektet:

  • Expo (PC + mobil)
  • React Native V0.55.4
  • Node.js

Prosjektet er hovedsakelig drevet av:

  • React Native

Hvordan kjøre programmet

Klon dette prosjektet. Kjør deretter følgende linje i prosjektmappen:

expo start

Et vindu med en QR-kode vil åpnes i nettleseren din. Denne QR-koden skal i tillegg være tilgjengelig i kommandolinjen. Scan denne med Expo appen på en mobil enhet for å åpne applikasjonen. Foreløpig virker det som scanning av QR-kode kun fungerer på android -enheter.

Om applikasjonen

En to-do liste

Vi har laget en to-do list som hjelper en bruker med å holde styr på deres daglige mål. Appen kan minne bruker på at de burde opprette eller fullføre gjøremål i løpet av dagen ved hjelp av push-varsler. Vi valgte å bruke planlagte lokal notifikasjoner som det utover basic React Native UI-problematikk fordi vi følte funksjonaliteten samsvarte godt med formålet til en daglig to-do liste. Listen er tom ved initialisering og brukeren kan legge inn ønskede todos i liste ved å ta i bruk av input-fieldet med en tilhørende add-knapp. Appen har også en slette-funksjonalitet som kan brukes ved å sveipe, til venstre, en valgt todo fra listen som da blir slettet permanent.

Vi fikk ikke satt i ønsket funksjonalitet: Slette listen med todos etter midnatt #7) grunnet lite tid, og valgte heller å prioritere andre viktige funksjonaliteter. Hvis vi skulle gjort dette i etterkant ville det iallefall vært lurt å bruke staten for selectedTodoId: [] i TheList.js til å fjerne alle taskene som har vært skjekket av.

Komponentdiagram

Vi tok utgangspunkt i følgende komponentdiagram da vi utviklet applikasjonen. alt text

  • APP - TodayPage.js
  • NotificationSwitch - komponent som toggler lokal notifikasjon.
  • PopUp - komponent med alert som aktiveres når alle dagens mål er fullført.
  • ListComponent - komponent som generer en liste.
  • ListItem - komponent som inneholder listeinnhold.

Dette oppsettet ble noe anderledes under utvikling. F.eks. er ikke popup-en lenger en egen komponent, men del av en funksjon da dette viste seg mer hensiktsmessig.

Dependencies

Prosjektet ble initiert med expo sin mal istedenfor den blanke versjonen, slik at vi kunne lære av strukturen som allerede var laget. Vi benyttet oss av både komponenter som er i React Native og fra tredjepartsbiblioteker.

  • Expo API (Notifications, Permissions)
  • UI komponenter:
    • React Native (ListView, TextInput, View, Container, Content, Footer, Header, Title, Switch)
    • NativeBase (Button, CheckBox, Icon, List, ListItem, Text)

AsyncStorage

Vi samlet AsyncStorage funksjonene under ../api/AsyncStorage.js hvor det er skrevet ned funksjoner som bruker metoder fra AsyncStorage biblioteket. Vi skrev funksjoner for å hente, lagre og slette data og enkel håndtering av error. Det er også blitt brukt async/await i alle funksjonene. Denne funksjonaliteten gjør det enklere og mer lettvint å håndtere promises. Await venter på at en promise er satt som kan returnere resultatet så vi kan koble det til en verdi, og returnerer en error melding hvis ikke. Ved å sette inn funksjonene for AsyncStorage i en egen api, ble det lettere for oss å kunne bruke de på ulike deler av applikasjonen til å lagre/hente/slette data, ved å bare importere inn funkskjonene vi har skrevet. Dataten vi trengte å lagre/slette persistent gjaldt taskene i to-do listen, lagring av avskjekket tasks, og lagring av aktivering av notifikasjon. Alle funksjonene er bygd med async/await på AsyncStorage på metodene fra biblioteket. For lagring og henting av data blir det som blir hentet henholdsvis konvertert til JSON og parsed fra JSON til JavaScript, slik at man kan lagre mer enn en string i hver lagring.

 //../api/AsyncStorage.js
//Persisting(saving) data
    await AsyncStorage.setItem(key, JSON.stringify(value));

//Fetching data
    const value =  await AsyncStorage.getItem(key);
    const retrievedItem = JSON.parse(value);

Vi brukte AsyncStorage i TodayPage.js og TheList.js til å lagre henholdsvis notifikasjons valg og tasks. I begge komponentene har de en componentDidMount(){...} hvor vi bruker retrievedData(key){...} med nøkkelen til dataen man vil ha til å hente dataen hvis den er lagret lokalt. Her må Promise objektet man får fra retrievedData(key){...} håndteres, derav med then./catch. Hvis det ikke er noen data lagret lokalt vil den bare bruke standard dataen i konstruktøren. I TodayPage.js hver gang man toggler svitsjen vil den kjøre storeData(key, value){...} og lagre staten lokalt:

    //Toggle daily reminder
    toggleNotification = (value) => {
        ...
        //Save toggled daily reminder to AsyncStorage
        storeData('dailyReminder', value);
    };

I TheList.js når man legger inn en ny task vil man hver gang lagre lista med tasks lokalt, med storeData(key, value){...}:

    addNewTodoInput = (txt) => {
        if (!(this.state.task === "")) {
            let listOfTodos = this.state.listOfTodos;
            listOfTodos.push({id: new Date(), task: txt});
            storeData('todoData', listOfTodos);
            this.setState({listOfTodos: listOfTodos})
        }
    }

Samme gjelder for hver gang man sjekker av en boks, onCheckBoxPress(id) {...storeData('checkedTodoData', tmp);...} og når man sletter data, hvor vi bare erstatter dataen med den nye oppdaterte listen og lagrer den, deleteRow(secId, rowId, rowMap) {... storeData('todoData', newData);...}.

Hver <ListItem/>/task slettes via innebygde variabler i tredjepart biblioteket NativeBase, derfor var det lettere å lagre hele den nye lista hver gang man fjerner et element, kontra å lagre hver task med en unik nøkkel, som så fjernes via nøkkelen med AsyncStorage biblioteket. Dermed brukte vi ikke removeData(key) {...}, som kunne vært et alternativt om vi hadde lagret hver task individuellt, istenfor i en array.

Testing

  • Til testing har vi, slik oppgaven ber om, benyttet oss av Jest.
  • Snapshot testing for å sjekke om at UI komponenter rendrer riktig.
  • Vi hadde originalt tenkt å skrive Async tester for api’ene, men vi hadde problemer med å forstå bruk av Jest tilstrekkelig til å skrive den mengden tester vi skulle ønske i løpet av det begrensede tidsrommet vi hadde til å jobbe med applikasjonen.
    • For eksempel for notifikasjoner; i følge Expo Github dokumentasjonen er Android scheduled notifikasjoner for uforutsigbar å testes. Vi så på testing av notifikasjon for ios sin også for å se om det var mulig å skrive en enkel test, men det virket som man måtte ha inn en del andre tredjeparts biblioteker, f.eks. notifikasjons lytter, som var litt utenfor omfanget vårt. Derfor valgte vi å la være å skrive en test for dette.
    • For AsyncStorage hadde vi problemer å forstå async / await tester, som trolig har med måten funksjonene er skrevet opp på. Promises blir for eksempel løst når man bruker funksjonen. Muligens ville dette vært lettere hvis man håndterte Promise objektene man får inni hver funksjon og ikke utenfor, når man bruker funksjonen? Av testing med async / await virket som det var mest håndtering av Promises og resolves, dermed ble det en utfordring for oss med tanke på måten vi skrev funksjonene som nevnt ovenfor.

Hindringer underveis

Da vi startet å bygge applikasjonen hadde vi to vulnerabilities i React Native, i pakkene ws (high vulnerability) og lodash (low vulnerability). For å bli kvitt dem oppdaterte vi React Native til en nyere versjon, 0.57.0. Denne versjonen av React Native viste seg å ikke være kompatibel med Expo, slik at vi ikke fikk til å bruke dem sammen. For å kunne utvikle måtte vi altså nedgradere tilbake versjon 0.55.4, til tross for at dette vil si at vi har vulnerabilities i programmet.

Vi opplevde også utfordring med å sjekke funksjonalitet på mobil. Ingen på gruppen hadde mobil med IOS, så for å verifisere at appen fungerte på IOS lot vi bekjente med IOS-enheter teste ut appen. Noen gruppemedlemmer opplevde også problemer med Expo-appen, hvilket spiste opp mye tid.

En annen hindring som vi burde ha sett på tidligere var testing for async/await, slik som nevnt under testing punktet. På grunn av dårlig disponering av tid fra gruppens side måtte vi prioritere andre funksjonaliteter og medførte derfor at denne biten ble nedprioritert.

PLATTFORMUAVHENGIGHET

Vi har testet og verifisert at appen fungerer slik ønsket på både Android og IOS. Som tidligere nevnt hadde ingen av gruppemedlemmene IOS og hadde derfor begrenset mulighet til å teste på IOS da simulatoren krever autentisering. Vi har testet på Android med Samsung Galaxy S7 Edge (v8.0.0), Samsung Galaxy S8 (v8.0.0) og LG V30 (v8.0.0). På IOS har vi fått testa for iPhone 8 (v12.0.0).

Gruppemedlemmer

Credits

Tredjeparts UI bibliotek:

NativeBase: https://nativebase.io/

Expo API: Expo notifikasjon dokumentasjon