Skip to content

Commit

Permalink
Add to-do app and its features
Browse files Browse the repository at this point in the history
  • Loading branch information
Johnatan Dias committed Jul 10, 2019
1 parent d2b5a0d commit cff92ad
Show file tree
Hide file tree
Showing 42 changed files with 8,000 additions and 54 deletions.
1 change: 1 addition & 0 deletions .gitignore
Expand Up @@ -2,6 +2,7 @@

# compiled output
/dist
/build
/tmp
/out-tsc
# Only exists if Bazel was run
Expand Down
5 changes: 5 additions & 0 deletions .vscode/settings.json
@@ -0,0 +1,5 @@
{
"files.associations": {
"*.webapp": "json",
},
}
79 changes: 79 additions & 0 deletions .vscode/tasks.json
@@ -0,0 +1,79 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Developer mode (Watch)",
"type": "npm",
"script": "start",
"problemMatcher": [],
"presentation": {
"reveal": "silent",
"panel": "dedicated"
},
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "Build app",
"type": "npm",
"script": "build",
"problemMatcher": [],
"presentation": {
"reveal": "silent",
"panel": "dedicated"
}
},
{
"label": "Install app",
"type": "npm",
"script": "app:install",
"problemMatcher": [],
"presentation": {
"reveal": "silent",
"panel": "dedicated"
}
},
{
"label": "Uninstall app",
"type": "npm",
"script": "app:uninstall",
"problemMatcher": [],
"presentation": {
"reveal": "silent",
"panel": "dedicated"
}
},
{
"label": "Update app",
"type": "npm",
"script": "app:update",
"problemMatcher": [],
"presentation": {
"reveal": "silent",
"panel": "dedicated"
}
},
{
"label": "Start app",
"type": "npm",
"script": "app:start",
"problemMatcher": [],
"presentation": {
"reveal": "silent",
"panel": "dedicated"
}
},
{
"label": "Stop app",
"type": "npm",
"script": "app:stop",
"problemMatcher": [],
"presentation": {
"reveal": "silent",
"panel": "dedicated"
}
}
]
}
41 changes: 26 additions & 15 deletions README.md
@@ -1,27 +1,38 @@
# MyFirstAngularAppKaios
# Sample Angular app for KaiOS

This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 8.1.0.
Simple example of a to-do list, for more information see [KaiOS Developer Portal](https://developer.kaiostech.com/getting-started/build-your-first-app/sample-code#angular)

## Development server
![](./docs/to-do-on-input.png)
![](./docs/to-do.png)

Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
In portrait devices

## Code scaffolding
![](./docs/to-do-portrait.gif)

Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
In landscape devices

## Build
![](./docs/to-do-landscape.gif)

Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
## Start

## Running unit tests
```console
npm run start
# or
yarn start
```

Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
## Build app

## Running end-to-end tests
```console
npm run build
# or
yarn build
```

Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
## Send the app to a KaiOS device

## Further help

To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
```console
npm run app:install
# or
yarn app:install
```
9 changes: 5 additions & 4 deletions angular.json
Expand Up @@ -13,14 +13,14 @@
"build": {
"builder": "@angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/my-first-angular-app-kaios",
"outputPath": "build",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": false,
"assets": [
"src/favicon.ico",
"src/manifest.webapp",
"src/assets"
],
"styles": [
Expand Down Expand Up @@ -115,6 +115,7 @@
}
}
}
}},
}
},
"defaultProject": "my-first-angular-app-kaios"
}
}
Binary file added docs/to-do-landscape.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/to-do-on-input.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/to-do-portrait.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added docs/to-do.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
14 changes: 10 additions & 4 deletions package.json
@@ -1,13 +1,18 @@
{
"name": "my-first-angular-app-kaios",
"version": "0.0.0",
"version": "1.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"build": "ng build --prod",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
"e2e": "ng e2e",
"app:install": "kdeploy build install",
"app:uninstall": "kdeploy build uninstall",
"app:update": "kdeploy build update",
"app:start": "kdeploy build start",
"app:stop": "kdeploy build stop"
},
"private": true,
"dependencies": {
Expand Down Expand Up @@ -42,6 +47,7 @@
"protractor": "~5.4.0",
"ts-node": "~7.0.0",
"tslint": "~5.15.0",
"typescript": "~3.4.3"
"typescript": "~3.4.3",
"kdeploy": "kaiostech/kdeploy"
}
}
24 changes: 5 additions & 19 deletions src/app/app.component.html
@@ -1,20 +1,6 @@
<!--The content below is only a placeholder and can be replaced.-->
<div style="text-align:center">
<h1>
Welcome to {{ title }}!
</h1>
<img width="300" alt="Angular Logo" src="data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNTAgMjUwIj4KICAgIDxwYXRoIGZpbGw9IiNERDAwMzEiIGQ9Ik0xMjUgMzBMMzEuOSA2My4ybDE0LjIgMTIzLjFMMTI1IDIzMGw3OC45LTQzLjcgMTQuMi0xMjMuMXoiIC8+CiAgICA8cGF0aCBmaWxsPSIjQzMwMDJGIiBkPSJNMTI1IDMwdjIyLjItLjFWMjMwbDc4LjktNDMuNyAxNC4yLTEyMy4xTDEyNSAzMHoiIC8+CiAgICA8cGF0aCAgZmlsbD0iI0ZGRkZGRiIgZD0iTTEyNSA1Mi4xTDY2LjggMTgyLjZoMjEuN2wxMS43LTI5LjJoNDkuNGwxMS43IDI5LjJIMTgzTDEyNSA1Mi4xem0xNyA4My4zaC0zNGwxNy00MC45IDE3IDQwLjl6IiAvPgogIDwvc3ZnPg==">
<div id="app">
<app-header title="ToDo List"></app-header>
<app-input label="New task"></app-input>
<app-todo></app-todo>
<app-softkey></app-softkey>
</div>
<h2>Here are some links to help you start: </h2>
<ul>
<li>
<h2><a target="_blank" rel="noopener" href="https://angular.io/tutorial">Tour of Heroes</a></h2>
</li>
<li>
<h2><a target="_blank" rel="noopener" href="https://angular.io/cli">CLI Documentation</a></h2>
</li>
<li>
<h2><a target="_blank" rel="noopener" href="https://blog.angular.io/">Angular blog</a></h2>
</li>
</ul>

42 changes: 39 additions & 3 deletions src/app/app.component.ts
@@ -1,10 +1,46 @@
import { Component } from '@angular/core';
import { Component, HostListener, OnInit } from '@angular/core';
import { TodoService } from './shared/components/todo/todo.service';
import { NavigationService } from './core/services/navigation.service';

@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
title = 'my-first-angular-app-kaios';
export class AppComponent implements OnInit {
constructor(private todoService: TodoService, private navigationService: NavigationService) { }

ngOnInit() {
this.navigationService.init();
}

@HostListener('document:keydown.enter')
onEnter() {
const [currentItem, currentIndex] = this.navigationService.getCurrentItem();
if (currentItem.nodeName === 'INPUT' && 'value' in currentItem && currentItem.value) {
this.todoService.add({ name: currentItem.value, completed: false });
currentItem.value = '';
} else {
this.todoService.toggleComplete(currentIndex - 1);
}
}

@HostListener('document:keydown.arrowdown')
onArrowDown() {
this.navigationService.Down();
}

@HostListener('document:keydown.arrowup')
onArrowUp() {
this.navigationService.Up();
}

@HostListener('document:keydown.softright')
onSoftRight() {
const [currentItem, currentIndex] = this.navigationService.getCurrentItem();
if (currentItem.nodeName === 'SPAN') {
this.todoService.remove(currentIndex - 1);
this.navigationService.Up();
}
}
}
4 changes: 3 additions & 1 deletion src/app/app.module.ts
Expand Up @@ -2,13 +2,15 @@ import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';
import { SharedModule } from './shared/shared.module';

@NgModule({
declarations: [
AppComponent
],
imports: [
BrowserModule
BrowserModule,
SharedModule
],
providers: [],
bootstrap: [AppComponent]
Expand Down
12 changes: 12 additions & 0 deletions src/app/core/services/navigation.service.spec.ts
@@ -0,0 +1,12 @@
import { TestBed } from '@angular/core/testing';

import { NavigationService } from './navigation.service';

describe('NavigationService', () => {
beforeEach(() => TestBed.configureTestingModule({}));

it('should be created', () => {
const service: NavigationService = TestBed.get(NavigationService);
expect(service).toBeTruthy();
});
});
69 changes: 69 additions & 0 deletions src/app/core/services/navigation.service.ts
@@ -0,0 +1,69 @@
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class NavigationService {
public currentItem: Subject<Element> = new Subject<Element>();

public init() {
const firstElement = this.getAllElements()[0];
firstElement.setAttribute('nav-selected', 'true');
firstElement.setAttribute('nav-index', '0');
// tslint:disable-next-line: no-unused-expression
'focus' in firstElement && firstElement.focus();
}

private getAllElements(): NodeListOf<Element | HTMLInputElement> {
return document.querySelectorAll('[nav-selectable]');
}

private getCurrentElement(): HTMLInputElement | Element {
return document.querySelector('[nav-selected=true]');
}

private getTheIndexOfTheSelectedElement(current?: Element): number {
const currentElement = current || this.getCurrentElement();
return currentElement ? parseInt(currentElement.getAttribute('nav-index'), 10) : 0;
}

public getCurrentItem(): [HTMLInputElement | Element, number] {
const item = this.getCurrentElement();
const index = this.getTheIndexOfTheSelectedElement(item);
return [item, index];
}

// tslint:disable-next-line: no-shadowed-variable
private selectElement(selectElement: Element): void {
[].forEach.call(this.getAllElements(), (element: Element | HTMLInputElement, index: number) => {
const selectThisElement = element === selectElement;
element.setAttribute('nav-selected', selectThisElement.toString());
element.setAttribute('nav-index', index.toString());

// tslint:disable-next-line: no-unused-expression
selectThisElement && this.currentItem.next(element);

if (element.nodeName === 'INPUT') {
selectThisElement
// tslint:disable-next-line: no-unused-expression
? 'focus' in element && element.focus()
: 'blur' in element && element.blur();
}
});
}

public Down(): void {
const allElements = this.getAllElements();
const currentIndex = this.getTheIndexOfTheSelectedElement();
const goToFirstElement = currentIndex + 1 > allElements.length - 1;
const setIndex = goToFirstElement ? 0 : currentIndex + 1;
this.selectElement(allElements[setIndex] || allElements[0]);
}

public Up(): void {
const allElements = this.getAllElements();
const currentIndex = this.getTheIndexOfTheSelectedElement();
const goToLastElement = currentIndex === 0;
const setIndex = goToLastElement ? allElements.length - 1 : currentIndex - 1;
this.selectElement(allElements[setIndex] || allElements[0]);
}
}

0 comments on commit cff92ad

Please sign in to comment.