/time-controller

A hybrid mobile application to manage your time spent.

Primary LanguageTypeScriptApache License 2.0Apache-2.0

Time Controller Application

Keywords: Angular, Ionic, Cordova, Android, Typescript, Bootstrap, Time, Management

Try it online (stackblitz.com)

Try it on your phone (Android 9 apk)

Current layout in 2019/08/08

Current layout gif

Introduction

An application which can let you:

  • Mark when you do what.

  • Show record data with a vertical timeline chart.

  • Edit the record easily.

  • Give full statistic data and chart.

  • Save and export the record data to external storage.

Dev record link

Timeline dev record details

20190715

Environment setting, serve, build, signature

Install, serve and package

npm, Ionic, Cordova, Angular, Android Studio, Android SDK

npm install -g ionic cordova
cd time-controller
ionic serve
ionic cordova build android --prod --release
First time: keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias
Move app-release-unsigned.apk to root path:
C:\'Program Files'\Java\jdk1.8.0_211\bin\jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore my-release-key.jks app-release-unsigned.apk my-alias
C:\Users\JINGJIAWEI\AppData\Local\Android\Sdk\build-tools\29.0.1\zipalign -v 4 app-release-unsigned.apk TimeController.apk
C:\Users\JINGJIAWEI\AppData\Local\Android\Sdk\build-tools\29.0.1\apksigner verify TimeController.apk

Path before SDK tools and apk:

C:\WorkPlace\Github\WorkRep\time-controller\platforms\android\app\build\outputs\apk\release
C:\Users\JINGJIAWEI\AppData\Local\Android\Sdk\build-tools\29.0.1

Reference info Ionic document deploying

20190718

Data structure, static Html, bootstrap import

Obj.some(obj => obj.label === label))
Obj.reduce((prev, curr) => prev.id < curr.id ? prev : curr).id;

20190721

Calculate chart length, rewrite, border situation, bugfix

  • Bugfix:
let xxx = list.filter(...)[index].someLabel,
let xxx = someValue // list would be changed -> pass value via reference, be cautious

20190722

Scroll bar, clock time, Html adjust, Angular update

npm i @angular-devkit/build-angular @angular-devkit/architect@latest @angular-devkit/core@latest @angular-devkit/schematics@latest

20190724

Bugfix, map scales, adjust template

  • get UTC and local time.
dateObj.getMonth() // Local
dateObj.getUTCMonth() // UTC
  • Set loop timer in Ionic.
setTimeout(() => {...}, 500); // NG
setInterval(() => {...}, 500); // OK
  • PS drawing scales and arrange the template steps & hot keys
ctrl + J
ctrl + T
move
ctrl + shift + alt + T

20190725

Input range, range display, variables rename, bug fix

document.getElementById('rangeTime').addEventListener('change', () => { //console.log('valueChanged');
document.getElementById('rangeTime').addEventListener('input', () => { //console.log('valueChanging');

20190726

Drag time display in real time, color trans, font color, color picker

20190727

Color picker page module, Adjust template, Placeholder Font Color

@NgModule({
  entryComponents: [ColorPickerPage],
  imports: [ColorPickerPageModule],
  providers: [ColorPickerPage],
})
// entryComponent
this.XXXXX = this.navParams.get('setting');
this.popCtrl.getTop().then(p => p.dismiss(YYYYY));
// parentComponent
  async onColorPicking(event: Event) {
    const comp = await this.pop.create({
      component: ColorPickerPage,
      event,
      componentProps: {setting: XXXXX,}
    });
    comp.onDidDismiss().then((data) => {YYYYY = data.data});
    return await comp.present();
  }
.phBlack::placeholder { /* Chrome, Firefox, Opera, Safari 10.1+ */
  color: black;
  opacity: 1; /* Firefox */
}

20190728

Alert controller, Adjust template, Date picker

const alert = await this.alertController.create({
  header: 'Ooouch, nothing performed',
  subHeader: 'On click label button',
  message: 'Current event is the same as button clicked when adding record. Try to choose another one.',
  buttons: [{
    text: 'Confirm',
    role: 'cancel',
    cssClass: 'secondary',
    handler: () => {console.log('Alert'); }
  }]});
await alert.present();

20190729

Ionic storage, Date picker, Bugfix

20190730

History data edit, Bugfix

  • Delete object in object[] via object.attr
  list.splice(list.indexOf(list.filter((obj: { timestamp: number; }) => obj.timestamp === x)[0]), 1);
  • Sort object[] via object.attr
  r.sort((prev: { timestamp: number; }, curr: { timestamp: number; }) => {
    return prev.timestamp - curr.timestamp;
  });
  • Notice .pop(), .splice(), .filter() have returns, do not make such mistake
  // filter out
  result = XXX.filter();
  // filter left
  XXX.filter();
  result = XXX;

20190731

On device debug, Bug fix

Summary

ionic serve --devapp
ionic cordova run android --device -l --debug --verbose
chrome://inspect/#devices
IonicStorageModule.forRoot({name: '__mydb', driverOrder: ['websql', 'indexeddb', 'sqlite']})

await this.storageDB.ready().then(async () => {
      await this.dbInit();
    }).catch(e => {console.error(e); });

Details

20190801

Bug fix

  • Bug fix:

    OK 1.Local DB init fix.

    OK 2.Change date range and direct click label giving wrong position insert. And wrong label current.

    OK 3.Days with null record shows white.

    OK 4.Time range time display keep uncorrect position after date range return to today. => match time now.

    OK 5.Template adjustment: scroll none, px offset, shining box border

  • Delete useless comment

  • Package

20190805

Export / import data via file

import { File } from '@ionic-native/file/ngx'; // OK
import { File } from '@ionic-native/file'; // NG

20190807

Statistic chart, ion-datetime, ionic navigating lifecycle event

  chartRender() {
    const chart = new CanvasJS.Chart('chartContainer', {
      animationEnabled: true,
      exportEnabled: false,
      title: {
        text: 'Statistic chart'
      },
      data: [{
        type: 'pie',
        showInLegend: true,
        toolTipContent: '<b>{name}</b>: ${y} (#percent%)',
        indexLabel: '{name} - #percent%',
        dataPoints: this.renderDataList,
      }]
    });
    chart.render();
  }
// Ready
ionViewDidLoad() {} // A & B
// Before
ionViewWillEnter() {} // B
ionViewWillLeave() {} // A
// After
ionViewDidEnter() {} // B
ionViewDidLeave() {} // A
  • Bug fix
this.timeoffset = new Date().getTimezoneOffset() * 60;
this.timeStart = this.dateStart ? Math.floor(Date.parse(this.dateStart) / 1000  + this.timeoffset) : 0;
  • Template adjustment

20190808

Tslint check, flesh button

tslint -p tsconfig.json -c tslint.json -o output.txt
button.flash::after {
  content: "";
  z-index: -1;
  position: absolute;
  background: white;
  top: -50%;
  left: 5%;
  bottom: -50%;
  width: 1.5em;
  transform: translate3d(-200%, 0, 0) rotate(35deg);
}
button.flash:disabled::after {
  transition: transform 0.2s ease-in-out;
  transform: translate3d(500%, 0, 0) rotate(35deg);
}

TODO