Skip to content

Commit

Permalink
Updated to v. 1.5.4
Browse files Browse the repository at this point in the history
  • Loading branch information
NickMaev committed Feb 4, 2019
1 parent 0a74368 commit e71bdda
Show file tree
Hide file tree
Showing 11 changed files with 2,234 additions and 5,948 deletions.
Binary file added PreviewImage.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ Project template available on [Visual Studio Marketplace](https://marketplace.vi
![](https://habrastorage.org/webt/zi/uw/th/ziuwthv_kafkor5tz00x8xwvgz8.png)
![](https://habrastorage.org/webt/9a/7k/f8/9a7kf8jlwhmc5hrrr4cwxuecxeg.png)
# Changes
##### v. 1.5.4 (2019-02-04)
* Added some minor features.
* Bug fixes: `collapsing of the Bootstrap navigation bar`, `fixed controller and frontend's service in person update case`.
* Updated dependencies.
##### v. 1.5.3 (2018-12-04)
* Added polyfills for supporting IE9, IE11: `@babel/polyfill`, `custom-event-polyfill`.
* Updated dependencies.
Expand Down
6 changes: 4 additions & 2 deletions ReactCoreBoilerplate/ClientApp/components/shared/TopMenu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { withRouter } from "react-router";
import { NavLink, Redirect } from "react-router-dom";
import Globals from "@Globals";
import AccountService from "@Services/AccountService";
import { Dropdown } from "bootstrap3-native";
import { Dropdown, Collapse } from "bootstrap3-native";
import bind from 'bind-decorator';

class TopMenu extends React.Component<{}, { logoutAction: boolean }> {
Expand All @@ -22,9 +22,11 @@ class TopMenu extends React.Component<{}, { logoutAction: boolean }> {
}

private elDropdown: HTMLAnchorElement;
private elCollapseButton: HTMLButtonElement;

componentDidMount() {
var dropdown = new Dropdown(this.elDropdown);
var collapse = new Collapse(this.elCollapseButton);
}

componentDidUpdate() {
Expand All @@ -37,7 +39,7 @@ class TopMenu extends React.Component<{}, { logoutAction: boolean }> {
return <div className="navbar navbar-default">
<div className="container-fluid">
<div className="navbar-header">
<button type="button" className="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<button ref={x => this.elCollapseButton = x} type="button" className="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span className="sr-only">Toggle navigation</span>
<span className="icon-bar"></span>
<span className="icon-bar"></span>
Expand Down
34 changes: 26 additions & 8 deletions ReactCoreBoilerplate/ClientApp/pages/ExamplePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ import { Helmet } from "react-helmet";
import { RouteComponentProps, withRouter } from "react-router";
import { IPersonModel } from "@Models/IPersonModel";
import { PersonStore } from "@Store/PersonStore";
import { ApplicationState } from "@Store/index";
import { ApplicationState, reducers } from "@Store/index";
import { connect } from "react-redux";
import { PagingBar } from "@Components/shared/PagingBar";
import PersonEditor from "@Components/person/PersonEditor";
import Loader from "@Components/shared/Loader";
import bind from 'bind-decorator';
import { ModalComponent } from "@Components/shared/ModalComponent";
import AwesomeDebouncePromise from "awesome-debounce-promise";
import { getPromiseFromAction } from "@Utils";

type Props = RouteComponentProps<{}> & typeof PersonStore.actionCreators & PersonStore.IState;

Expand Down Expand Up @@ -93,24 +94,41 @@ class ExamplePage extends React.Component<Props, IState> {
}

@bind
onClickPersonEditorAdd__saveBtn(e: React.MouseEvent<HTMLButtonElement>): void {
async onClickPersonEditorAdd__saveBtn(e: React.MouseEvent<HTMLButtonElement>) {
e.preventDefault();

if (!this.personEditorAdd.elForm.isValid()) {
// Form is not valid.
return;
}
this.props.addRequest(this.personEditorAdd.elForm.getData());
this.pagingBar.setLastPage();
this.elModalAdd.hide();

var result =
await getPromiseFromAction(
this.props.addRequest(this.personEditorAdd.elForm.getData())
);

if (!result.hasErrors) {
this.pagingBar.setLastPage();
this.elModalAdd.hide();
}
}

@bind
onClickPersonEditorEdit__saveBtn(e: React.MouseEvent<HTMLButtonElement>): void {
async onClickPersonEditorEdit__saveBtn(e: React.MouseEvent<HTMLButtonElement>) {
if (!this.personEditorEdit.elForm.isValid()) {
// Form is not valid.
return;
}

var data = this.personEditorEdit.elForm.getData();
this.props.updateRequest(data);
this.elModalEdit.hide();

var result = await getPromiseFromAction(
this.props.updateRequest(data)
);

if (!result.hasErrors) {
this.elModalEdit.hide();
}
}

@bind
Expand Down
2 changes: 1 addition & 1 deletion ReactCoreBoilerplate/ClientApp/services/PersonService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export default class PersonService extends ServiceBase {
}
public static async update(model: IPersonModel): Promise<Result<{}>> {
var result = await this.requestJson({
url: "/api/Person",
url: `/api/Person/${model.id}`,
method: "PATCH",
data: model
});
Expand Down
33 changes: 30 additions & 3 deletions ReactCoreBoilerplate/ClientApp/store/PersonStore.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { clone } from "@Utils";
import { Action, Reducer } from "redux";
import { AppThunkAction } from "./index";
import { AppThunkAction, AppThunkActionAsync } from "./index";
import PersonService from "@Services/PersonService";
import { IPersonModel } from "@Models/IPersonModel";
import { wait } from "domain-wait";
import Result from "@Models/Result";

export module PersonStore {

Expand All @@ -15,6 +16,7 @@ export module PersonStore {
}

export enum Actions {
FailureResponse = "PERSON_FAILURE_RESPONSE",
SearchRequest = "PERSON_SEARCH_REQUEST",
SearchResponse = "PERSON_SEARCH_RESPONSE",
AddRequest = "PERSON_ADD_REQUEST",
Expand All @@ -25,6 +27,10 @@ export module PersonStore {
DeleteResponse = "PERSON_DELETE_RESPONSE"
}

interface IFailureResponse {
type: Actions.FailureResponse;
}

interface IGetAllRequest {
type: Actions.SearchRequest;
}
Expand Down Expand Up @@ -62,6 +68,7 @@ export module PersonStore {
}

type KnownAction =
IFailureResponse |
IGetAllRequest | IGetAllResponse |
IAddRequest | IAddResponse |
IUpdateRequest | IUpdateResponse |
Expand All @@ -76,37 +83,53 @@ export module PersonStore {
dispatch({ type: Actions.SearchRequest });

var result = await PersonService.search(term);

if (!result.hasErrors) {
dispatch({ type: Actions.SearchResponse, payload: result.value });
} else {
dispatch({ type: Actions.FailureResponse });
}
});
},
addRequest: (model: IPersonModel): AppThunkAction<KnownAction> => async (dispatch, getState) => {
addRequest: (model: IPersonModel): AppThunkActionAsync<KnownAction, Result<number>> => async (dispatch, getState) => {

dispatch({ type: Actions.AddRequest });

var result = await PersonService.add(model);

if (!result.hasErrors) {
model.id = result.value;
dispatch({ type: Actions.AddResponse, payload: model });
} else {
dispatch({ type: Actions.FailureResponse });
}

return result;
},
updateRequest: (model: IPersonModel): AppThunkAction<KnownAction> => async (dispatch, getState) => {
updateRequest: (model: IPersonModel): AppThunkActionAsync<KnownAction, Result<{}>> => async (dispatch, getState) => {

dispatch({ type: Actions.UpdateRequest });

var result = await PersonService.update(model);

if (!result.hasErrors) {
dispatch({ type: Actions.UpdateResponse, payload: model });
} else {
dispatch({ type: Actions.FailureResponse });
}

return result;
},
deleteRequest: (id: number): AppThunkAction<KnownAction> => async (dispatch, getState) => {

dispatch({ type: Actions.DeleteRequest });

var result = await PersonService.delete(id);

if (!result.hasErrors) {
dispatch({ type: Actions.DeleteResponse, id });
} else {
dispatch({ type: Actions.FailureResponse });
}
}
}
Expand All @@ -124,6 +147,10 @@ export module PersonStore {
var cloneIndicators = () => clone(currentState.indicators);

switch (action.type) {
case Actions.FailureResponse:
var indicators = cloneIndicators();
indicators.operationLoading = false;
return { ...currentState, indicators };
case Actions.SearchRequest:
var indicators = cloneIndicators();
indicators.operationLoading = true;
Expand Down
2 changes: 1 addition & 1 deletion ReactCoreBoilerplate/Controllers/PersonController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ public IActionResult Add(PersonModel model)
return Json(result);
}

[HttpPatch("[action]")]
[HttpPatch("{id:int}")]
public IActionResult Update(PersonModel model)
{
if (model == null)
Expand Down
42 changes: 38 additions & 4 deletions ReactCoreBoilerplate/Services/PersonService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public virtual Result<List<PersonModel>> Search(string term = null)
if (!string.IsNullOrEmpty(term))
{
term = term.ToLower();
term = term.Trim();

var result =
PeopleList
Expand All @@ -46,21 +47,34 @@ public virtual Result<List<PersonModel>> Search(string term = null)

public virtual Result<int> Add(PersonModel model)
{
if (model == null)
if(model == null)
return Error<int>();
if (string.IsNullOrEmpty(model.FirstName))
if(string.IsNullOrEmpty(model.FirstName))
return Error<int>("First name not defined.");
if (string.IsNullOrEmpty(model.LastName))
if(string.IsNullOrEmpty(model.LastName))
return Error<int>("Last name not defined.");

TrimStrings(model);

var personExists =
PeopleList
.Any(x =>
x.FirstName == model.FirstName &&
x.LastName == model.LastName
);
if(personExists)
{
return Error<int>("Person with the same first name and last name already exists.");
}

var newId = PeopleList.Max(x => x?.Id ?? 0) + 1;
model.Id = newId;

PeopleList.Add(model);

return Ok(model.Id);
}

public virtual Result Update(PersonModel model)
{
if (model == null)
Expand All @@ -71,6 +85,20 @@ public virtual Result Update(PersonModel model)
if (person == null)
return Error($"Person with id = {model.Id} not found.");

TrimStrings(model);

var personExists =
PeopleList
.Any(x =>
x.Id != model.Id &&
x.FirstName == model.FirstName &&
x.LastName == model.LastName
);
if(personExists)
{
return Error("Person with the same first name and last name already exists.");
}

person.FirstName = model.FirstName;
person.LastName = model.LastName;

Expand All @@ -85,5 +113,11 @@ public virtual Result Delete(int id)
PeopleList.Remove(unit);
return Ok();
}

private static void TrimStrings(PersonModel model)
{
model.FirstName = model.FirstName.Trim();
model.LastName = model.LastName.Trim();
}
}
}
Loading

0 comments on commit e71bdda

Please sign in to comment.