Skip to content

Commit 9b67594

Browse files
committed
feat(component): add components and directive to request with states of the api
1 parent 3091d39 commit 9b67594

File tree

6 files changed

+252
-2
lines changed

6 files changed

+252
-2
lines changed

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,15 @@
66
"typings": "dist/esm/index.d.ts",
77
"module": "dist/esm/index.js",
88
"scripts": {
9-
"build": "npm run clean && npm run build:umd && npm run build:esm",
9+
"build": "npm run clean && npm run build:umd && npm run build:esm && npm run copy:sass",
1010
"build:qa": "npm run lint && npm run test && npm run build",
1111
"build:esm": "ngc -p tsconfig-esm.json",
1212
"build:test": "ngc -p tsconfig-test.json",
1313
"build:umd": "ngc",
1414
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s",
1515
"commit": "git-cz",
1616
"clean": "rimraf ./dist",
17+
"copy:sass": "cpx ./src/components/*.scss ./dist/esm/components && cpx ./src/components/*.scss ./dist/umd/components",
1718
"cover": "nyc report --reporter=lcov npm test",
1819
"doc": "typedoc --tsconfig tsconfig-esm.json --options typedoc.json src/",
1920
"gh:release": "node ./scripts/git-release",
@@ -48,6 +49,7 @@
4849
"codelyzer": "2.0.0-beta.3",
4950
"commitizen": "^2.8.6",
5051
"conventional-changelog-cli": "^1.2.0",
52+
"cpx": "1.5.0",
5153
"cz-conventional-changelog": "^1.2.0",
5254
"fluid-publish": "1.1.0",
5355
"github": "0.2.4",

src/components/index.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Request } from './request';
2+
import { StateLoading, StateEmpty, StateError } from './states';
3+
4+
export * from './request';
5+
export * from './states';
6+
7+
export const COMPONENTS = [
8+
Request,
9+
StateLoading,
10+
StateEmpty,
11+
StateError
12+
]

src/components/request.ts

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
import { Directive, ContentChild, EventEmitter, Input, Output } from '@angular/core';
2+
import { Http } from '@ramonornela/http';
3+
import { StateLoading, StateEmpty, StateError } from './states';
4+
5+
@Directive({
6+
selector: '[request]'
7+
})
8+
export class Request {
9+
@Input() url: string;
10+
@Input() params: Object;
11+
@Input() requestOptions: any;
12+
@Input() options: any;
13+
14+
@Output() loaded = new EventEmitter();
15+
16+
@ContentChild(StateLoading) loading: any;
17+
18+
@ContentChild(StateEmpty) noRecords: any;
19+
20+
@ContentChild(StateError) error: any;
21+
22+
constructor(
23+
private http: Http
24+
) {}
25+
26+
ngOnInit() {
27+
// default options
28+
let pluginsOptions = {
29+
'*': {
30+
'allow': false,
31+
'throwsException': false
32+
}
33+
};
34+
this.requestOptions = Object.assign(
35+
{},
36+
{ pluginsOptions },
37+
this.options
38+
);
39+
40+
this.request();
41+
}
42+
43+
request() {
44+
this.http.request(
45+
this.url,
46+
this.params,
47+
this.requestOptions,
48+
this.options
49+
).subscribe((result: any) => {
50+
51+
this.dismissLoading();
52+
53+
this.loaded.emit(result);
54+
55+
if (this.noRecords) {
56+
this.noRecords.present();
57+
}
58+
}, (error) => {
59+
this.dismissLoading();
60+
61+
if (this.error) {
62+
63+
if (!this.error.idRetry) {
64+
this.error.idRetry = this.url;
65+
}
66+
67+
if (!this.error.error) {
68+
this.error.error = error;
69+
}
70+
71+
this.error.present();
72+
}
73+
});
74+
}
75+
76+
private dismissLoading() {
77+
if (this.loading) {
78+
this.loading.dismiss();
79+
}
80+
}
81+
}

src/components/states.scss

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
loading {
2+
text-align: center;
3+
4+
ion-spinner {
5+
width: 100%;
6+
margin-top: 20px;
7+
margin-bottom: 20px;
8+
}
9+
}
10+
11+
empty {
12+
text-align: center;
13+
}
14+
15+
error {
16+
text-align: center;
17+
18+
.msg-exception {
19+
width: 100%;
20+
margin-top: 15px;
21+
margin-bottom: 15px;
22+
font-size: 16px;
23+
display: block;
24+
}
25+
}

src/components/states.ts

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
import { Component, Directive, Input, Optional } from '@angular/core';
2+
import { ViewController } from 'ionic-angular';
3+
import { Http } from '@ramonornela/http';
4+
5+
@Component({
6+
selector: 'loading',
7+
template: `
8+
<div *ngIf="enabled">
9+
<ion-spinner [name]="name" [mode]="mode" [color]="color"></ion-spinner>
10+
<div *ngIf="text">{{text}}</div>
11+
<ng-content></ng-content>
12+
</div>`
13+
})
14+
export class StateLoading {
15+
enabled: boolean = true;
16+
17+
@Input() mode: string;
18+
19+
@Input() color: string;
20+
21+
@Input() name: string;
22+
23+
@Input() text: string;
24+
25+
present() {
26+
this.enabled = true;
27+
}
28+
29+
dismiss() {
30+
this.enabled = false;
31+
}
32+
}
33+
34+
@Component({
35+
selector: 'empty',
36+
template: `
37+
<div *ngIf="enabled">
38+
<ng-content></ng-content>
39+
</div>
40+
`
41+
})
42+
export class StateEmpty {
43+
enabled: boolean = false;
44+
45+
@Input() variableBind: any;
46+
47+
constructor(
48+
@Optional() private ctrl: ViewController
49+
) {}
50+
51+
present() {
52+
this.enabled = false;
53+
let dataBind = this.ctrl._cmp.instance[this.variableBind];
54+
55+
if (this.ctrl && this.ctrl._cmp && this.variableBind && !dataBind) {
56+
this.enabled = true;
57+
}
58+
}
59+
60+
dismiss() {
61+
this.enabled = false;
62+
}
63+
}
64+
65+
@Component({
66+
selector: 'error',
67+
template: `
68+
<div *ngIf="enabled">
69+
<span class="msg-exception">{{msgException}}</span>
70+
<button ion-button (click)="retryRequest()">
71+
<span>
72+
<ng-content></ng-content>
73+
{{messageRetry}}
74+
</span>
75+
</button>
76+
</div>`
77+
})
78+
export class StateError {
79+
enabled: boolean = false;
80+
81+
private id: string;
82+
83+
private msgException;
84+
85+
@Input() messageRetry: string = 'Tentar novamente';
86+
87+
@Input() messageCallback: Function;
88+
89+
@Input() error: any;
90+
91+
constructor(private http: Http) {}
92+
93+
@Input()
94+
set messageException(message: string) {
95+
this.msgException = message;
96+
}
97+
98+
@Input()
99+
set idRetry(id: string) {
100+
this.id = id;
101+
}
102+
103+
retryRequest() {
104+
this.http.retryRequest(this.id);
105+
}
106+
107+
present() {
108+
if (!this.msgException) {
109+
if (!this.error) {
110+
throw new Error('Error is required!');
111+
}
112+
113+
if (typeof this.messageCallback !== 'function') {
114+
let messageError = this.messageCallback;
115+
throw new Error(`${messageError} is not function`);
116+
}
117+
this.msgException = this.messageCallback.call(null, this.error);
118+
}
119+
120+
this.enabled = true;
121+
}
122+
123+
dismiss() {
124+
this.enabled = false;
125+
}
126+
}

src/module.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,13 @@
11
import { NgModule } from '@angular/core';
2-
import { LoadingController } from 'ionic-angular';
2+
import { IonicModule, LoadingController } from 'ionic-angular';
33
import { HttpPluginsToken } from '@ramonornela/http';
44
import { LoadingIonicPlugin, NoConnectionPlugin } from './providers';
5+
import { COMPONENTS } from './components';
56

67
@NgModule({
8+
imports: [ IonicModule.forRoot(null) ],
9+
exports: [ COMPONENTS ],
10+
declarations: [ COMPONENTS ],
711
providers: [
812
{ provide: HttpPluginsToken, useClass: LoadingIonicPlugin, deps: [ LoadingController ], multi: true },
913
{ provide: HttpPluginsToken, useClass: NoConnectionPlugin, multi: true }

0 commit comments

Comments
 (0)