Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions ngrx-http-tracking/.prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# Add files here to ignore them from prettier formatting

/dist
/coverage
31 changes: 31 additions & 0 deletions ngrx-http-tracking/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"trailingComma": "es5",
"tabWidth": 4,
"semi": true,
"bracketSpacing": true,
"singleQuote": true,
"printWidth": 120,
"useTabs": false,
"arrowParens": "avoid",
"htmlWhitespaceSensitivity": "strict",
"overrides": [
{
"files": "*.json",
"options": {
"tabWidth": 2
}
},
{
"files": "*.scss",
"options": {
"tabWidth": 2
}
},
{
"files": "*.css",
"options": {
"tabWidth": 2
}
}
]
}
10 changes: 2 additions & 8 deletions ngrx-http-tracking/angular.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,7 @@
"polyfills": "projects/demo/src/polyfills.ts",
"tsConfig": "projects/demo/tsconfig.app.json",
"inlineStyleLanguage": "scss",
"assets": [
"projects/demo/src/favicon.ico",
"projects/demo/src/assets"
],
"assets": ["projects/demo/src/favicon.ico", "projects/demo/src/assets"],
"styles": ["projects/demo/src/styles.scss"],
"scripts": []
},
Expand Down Expand Up @@ -93,10 +90,7 @@
"tsConfig": "projects/demo/tsconfig.spec.json",
"karmaConfig": "projects/demo/karma.conf.js",
"inlineStyleLanguage": "scss",
"assets": [
"projects/demo/src/favicon.ico",
"projects/demo/src/assets"
],
"assets": ["projects/demo/src/favicon.ico", "projects/demo/src/assets"],
"styles": ["projects/demo/src/styles.scss"],
"scripts": []
}
Expand Down
16 changes: 16 additions & 0 deletions ngrx-http-tracking/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion ngrx-http-tracking/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,8 @@
"karma-coverage": "~2.0.3",
"karma-jasmine": "~4.0.0",
"karma-jasmine-html-reporter": "~1.7.0",
"prettier": "^3.0.2",
"ng-packagr": "^16.1.0",
"typescript": "~5.1.3"
}
}
}
77 changes: 37 additions & 40 deletions ngrx-http-tracking/projects/demo/karma.conf.js
Original file line number Diff line number Diff line change
@@ -1,44 +1,41 @@
// Karma configuration file, see link for more information
// https://karma-runner.github.io/1.0/config/configuration-file.html

module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage'),
require('@angular-devkit/build-angular/plugins/karma')
],
client: {
jasmine: {
// you can add configuration options for Jasmine here
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
// for example, you can disable the random execution with `random: false`
// or set a specific seed with `seed: 4321`
},
clearContext: false // leave Jasmine Spec Runner output visible in browser
},
jasmineHtmlReporter: {
suppressAll: true // removes the duplicated traces
},
coverageReporter: {
dir: require('path').join(__dirname, '../../coverage/demo'),
subdir: '.',
reporters: [
{ type: 'html' },
{ type: 'text-summary' }
]
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true
});
module.exports = function(config) {
config.set({
basePath: '',
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-jasmine'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('karma-coverage'),
require('@angular-devkit/build-angular/plugins/karma'),
],
client: {
jasmine: {
// you can add configuration options for Jasmine here
// the possible options are listed at https://jasmine.github.io/api/edge/Configuration.html
// for example, you can disable the random execution with `random: false`
// or set a specific seed with `seed: 4321`
},
clearContext: false, // leave Jasmine Spec Runner output visible in browser
},
jasmineHtmlReporter: {
suppressAll: true, // removes the duplicated traces
},
coverageReporter: {
dir: require('path').join(__dirname, '../../coverage/demo'),
subdir: '.',
reporters: [{ type: 'html' }, { type: 'text-summary' }],
},
reporters: ['progress', 'kjhtml'],
port: 9876,
colors: true,
logLevel: config.LOG_INFO,
autoWatch: true,
browsers: ['Chrome'],
singleRun: false,
restartOnFileChange: true,
});
};
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,15 @@ import { AnimalApiResponse } from './animals.models';

@Injectable()
export class AnimalsApiService {
constructor(public http: HttpClient) {
console.log(http);
console.log(this);
}
constructor(public http: HttpClient) {
console.log(http);
console.log(this);
}

public fetchAnimals = () => {
return this.http
.get<AnimalApiResponse>(
'https://api.publicapis.org/entries?category=animals&https=true'
)
.pipe(
map((response) => response.entries),
delay(200) // .2 Second delay for simulation
);
};
public fetchAnimals = () => {
return this.http.get<AnimalApiResponse>('https://api.publicapis.org/entries?category=animals&https=true').pipe(
map(response => response.entries),
delay(200) // .2 Second delay for simulation
);
};
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ import { createTrackingActions } from 'ngrx-http-tracking';
import { createAction } from '@ngrx/store';

const ANIMAL_NAMESPACE = 'animals';
export const fetchAnimals = createTrackingActions<void, AnimalsEntity[]>(
ANIMAL_NAMESPACE,
'fetchAnimals'
);
export const fetchAnimals = createTrackingActions<void, AnimalsEntity[]>(ANIMAL_NAMESPACE, 'fetchAnimals');

export const clearAnimals = createAction(`[${ANIMAL_NAMESPACE}] clearAnimals`);
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,17 @@ import * as AnimalsActions from './animals.actions';

@Injectable()
export class AnimalsEffects {
fetchAnimals$ = createTrackingEffect(
this.actions$,
AnimalsActions.fetchAnimals,
this.api.fetchAnimals,
'Could not load animals',
(context) => {
console.log('Animals Successfully loaded');
console.log('Request: ', context.request);
console.log('Payload: ', context.payload);
}
);
fetchAnimals$ = createTrackingEffect(
this.actions$,
AnimalsActions.fetchAnimals,
this.api.fetchAnimals,
'Could not load animals',
context => {
console.log('Animals Successfully loaded');
console.log('Request: ', context.request);
console.log('Payload: ', context.payload);
}
);

constructor(
private readonly actions$: Actions,
private api: AnimalsApiService
) {}
constructor(private readonly actions$: Actions, private api: AnimalsApiService) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,22 @@ import * as AnimalsSelectors from './animals.selectors';

@Injectable()
export class AnimalsFacade {
/**
* Combine pieces of state using createSelector,
* and expose them as observables through the facade.
*/
loaded$ = this.httpTracker.isLoaded(AnimalsActions.fetchAnimals);
allAnimals$ = this.store.pipe(select(AnimalsSelectors.getAllAnimals));
selectedAnimals$ = this.store.pipe(select(AnimalsSelectors.getSelected));
/**
* Combine pieces of state using createSelector,
* and expose them as observables through the facade.
*/
loaded$ = this.httpTracker.isLoaded(AnimalsActions.fetchAnimals);
allAnimals$ = this.store.pipe(select(AnimalsSelectors.getAllAnimals));
selectedAnimals$ = this.store.pipe(select(AnimalsSelectors.getSelected));

fetchAnimals() {
this.store.dispatch(AnimalsActions.fetchAnimals.loading());
return AnimalsActions.fetchAnimals;
}
fetchAnimals() {
this.store.dispatch(AnimalsActions.fetchAnimals.loading());
return AnimalsActions.fetchAnimals;
}

clearAnimals() {
this.store.dispatch(AnimalsActions.clearAnimals());
}
clearAnimals() {
this.store.dispatch(AnimalsActions.clearAnimals());
}

constructor(
private readonly store: Store,
private httpTracker: HttpTrackingFacade
) {}
constructor(private readonly store: Store, private httpTracker: HttpTrackingFacade) {}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,16 @@
* Interface for the 'Animals' data
*/
export interface AnimalsEntity {
API: string; // Primary ID
Description: string;
Auth: string;
HTTPS: boolean;
Cors: string;
Link: string;
Category: string;
API: string; // Primary ID
Description: string;
Auth: string;
HTTPS: boolean;
Cors: string;
Link: string;
Category: string;
}

export interface AnimalApiResponse {
count: number;
entries: AnimalsEntity[];
count: number;
entries: AnimalsEntity[];
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,28 +7,25 @@ import { AnimalsEntity } from './animals.models';
export const ANIMALS_FEATURE_KEY = 'animals';

export interface State extends EntityState<AnimalsEntity> {
selectedId?: string; // which Animals record has been selected
selectedId?: string; // which Animals record has been selected
}

export interface AnimalsPartialState {
readonly [ANIMALS_FEATURE_KEY]: State;
readonly [ANIMALS_FEATURE_KEY]: State;
}

export const animalsAdapter: EntityAdapter<AnimalsEntity> =
createEntityAdapter<AnimalsEntity>({
selectId: (entity) => entity.API,
});
export const animalsAdapter: EntityAdapter<AnimalsEntity> = createEntityAdapter<AnimalsEntity>({
selectId: entity => entity.API,
});

export const initialState: State = animalsAdapter.getInitialState({});

const animalsReducer = createReducer(
initialState,
on(AnimalsActions.fetchAnimals.loaded, (state, { payload }) =>
animalsAdapter.setAll(payload, { ...state })
),
on(AnimalsActions.clearAnimals, (state) => animalsAdapter.removeAll(state))
initialState,
on(AnimalsActions.fetchAnimals.loaded, (state, { payload }) => animalsAdapter.setAll(payload, { ...state })),
on(AnimalsActions.clearAnimals, state => animalsAdapter.removeAll(state))
);

export function reducer(state: State | undefined, action: Action) {
return animalsReducer(state, action);
return animalsReducer(state, action);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,16 @@ import { createFeatureSelector, createSelector } from '@ngrx/store';
import { ANIMALS_FEATURE_KEY, State, animalsAdapter } from './animals.reducer';

// Lookup the 'Animals' feature state managed by NgRx
export const getAnimalsState =
createFeatureSelector<State>(ANIMALS_FEATURE_KEY);
export const getAnimalsState = createFeatureSelector<State>(ANIMALS_FEATURE_KEY);

const { selectAll, selectEntities } = animalsAdapter.getSelectors();

export const getAllAnimals = createSelector(getAnimalsState, (state: State) =>
selectAll(state)
);
export const getAllAnimals = createSelector(getAnimalsState, (state: State) => selectAll(state));

export const getAnimalsEntities = createSelector(
getAnimalsState,
(state: State) => selectEntities(state)
);
export const getAnimalsEntities = createSelector(getAnimalsState, (state: State) => selectEntities(state));

export const getSelectedId = createSelector(
getAnimalsState,
(state: State) => state.selectedId
);
export const getSelectedId = createSelector(getAnimalsState, (state: State) => state.selectedId);

export const getSelected = createSelector(
getAnimalsEntities,
getSelectedId,
(entities, selectedId) => (selectedId ? entities[selectedId] : undefined)
export const getSelected = createSelector(getAnimalsEntities, getSelectedId, (entities, selectedId) =>
selectedId ? entities[selectedId] : undefined
);
Loading