Skip to content

Commit

Permalink
Merge branch 'master' into tx-setup
Browse files Browse the repository at this point in the history
  • Loading branch information
Arjun-Go committed Oct 10, 2024
2 parents 689a2a5 + e82138b commit 4ef8199
Show file tree
Hide file tree
Showing 30 changed files with 1,516 additions and 205 deletions.
5 changes: 5 additions & 0 deletions .git-hooks/pre-commit
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#!/bin/sh

yarn lint

yarn test
38 changes: 38 additions & 0 deletions .github/workflows/build_publish.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
name: Build and Release
on:
push:
branches:
- master
workflow_dispatch:
jobs:
build-release:
name: Build the web app and make a zip release
runs-on: ubuntu-latest
steps:
- name: Checkout to repository
uses: actions/checkout@v3

- name: Setup Node.js 16.x
uses: actions/setup-node@v1
with:
node-version: "16.x"

- name: Install dependencies
run: yarn install

- name: Run tests
run: yarn test

- name: Build the app
run: yarn build-prod

- name: Zip the build
run: zip -r person-management-app.zip build

- name: Release
uses: softprops/action-gh-release@v1
with:
name: Build ${{ github.run_number }}
tag_name: v-${{ github.run_number }}
files: person-management-app.zip
token: ${{secrets.BAHMNI_PAT}}
24 changes: 24 additions & 0 deletions .github/workflows/validate_PR.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
name: Workflow to validate PRs

on:
pull_request:
branches: [master]

jobs:
build-release:
name: Build the web app and make a zip release
runs-on: ubuntu-latest
steps:
- name: Checkout to repository
uses: actions/checkout@v3

- name: Setup Node.js 16.x
uses: actions/setup-node@v1
with:
node-version: "16.x"

- name: Install dependencies
run: yarn install

- name: Run tests
run: yarn test
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,3 +94,7 @@ Tests will be written with Jest and Enzyme.

To run the tests:
Run **`yarn test`**

## Release

Github Artifacts are created with the help of workflow which contains the build of the person-management-app. The workflow runs on any changes in the master branch and releases a new build. All releases can be accessed [here](https://github.com/Arjun-Go/person-management-app/releases).
26 changes: 26 additions & 0 deletions modify-build-index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const fs = require('fs');

const indexPath = 'build/index.html';
let html = fs.readFileSync(indexPath, 'utf8');

const cssHrefRegex = /href="\.\/static\/css\/([^"]+\.css)"/;
const cssMatch = html.match(cssHrefRegex);
if (cssMatch) {
const originalHref = cssMatch[0];
const cssFilename = cssMatch[1];
const newHref = `href="/person-management/static/css/${cssFilename}"`;

html = html.replace(originalHref, newHref);
}

const jsHrefRegex = /src="\.\/static\/js\/([^"]+\.js)"/;
const jsMatch = html.match(jsHrefRegex);
if (jsMatch) {
const originalHref = jsMatch[0];
const jsFilename = jsMatch[1];
const newHref = `src="/person-management/static/js/${jsFilename}"`;

html = html.replace(originalHref, newHref);
}

fs.writeFileSync(indexPath, html);
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test --env=jsdom --watchAll=false",
"build-prod": "react-scripts build && node modify-build-index.js",
"eject": "react-scripts eject"
},
"resolutions": {
Expand Down
8 changes: 5 additions & 3 deletions src/App.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
import React, { Component } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import FormContainer from './containers/FormContainer';
import CreatePerson from './containers/CreatePerson';
import PersonDashboard from './containers/PersonDashboard';
import './index.css';
import EditPerson from './containers/EditPerson';

class App extends Component {
render() {
return (
<BrowserRouter>
<BrowserRouter basename="/person-management">
<Switch>
<Route path="/new" exact component={FormContainer} />
<Route path="/new" exact component={CreatePerson} />
<Route path="/search" exact component={PersonDashboard} />
<Route path="/edit/:uuid" exact component={EditPerson} />
<Route path="/" component={PersonDashboard} />
</Switch>
</BrowserRouter>
Expand Down
96 changes: 96 additions & 0 deletions src/api/personApi.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
import { Constants } from '../components/common/constants';

export async function getPersonAttributeTypeUuid(attributeName) {
try {
const url =
Constants.personAttributeType + '?q=' + attributeName + '&v=default';
const response = await fetch(url).then(function(response) {
if (!response.status === 200) {
throw Error({ response: response });
}
return response.json();
});
return response.results[0].uuid;
} catch (error) {
console.error(error);
return error.response;
}
}

export async function savePerson(payload) {
try {
return await fetch(Constants.person, {
method: 'POST',
body: JSON.stringify(payload),
headers: {
'Content-Type': 'application/json',
Accept: 'application/json'
},
credentials: 'include'
});
} catch (error) {
console.error(error);
return error.response;
}
}

export async function searchPerson(person) {
try {
const url =
Constants.person +
'?q=' +
person +
'&v=custom%3Auuid%2Cdisplay%2Cage%2Cgender%2CdateCreated';
return await fetch(url, {
method: 'GET',
credentials: 'include'
});
} catch (error) {
console.error(error);
return error.response;
}
}

export async function fetchPerson(uuid) {
try {
const url = Constants.person + '/' + uuid;
return await fetch(url, {
method: 'GET',
credentials: 'include'
});
} catch (error) {
console.error(error);
return error.response;
}
}

export async function updatePerson(uuid, payload) {
try {
const url = Constants.person + '/' + uuid;
return await fetch(url, {
method: 'POST',
body: JSON.stringify(payload),
headers: {
'Content-Type': 'application/json',
Accept: 'application/json'
},
credentials: 'include'
});
} catch (error) {
console.error(error);
return error.response;
}
}

export async function fetchPersonAttributeConfig() {
try {
const url = Constants.registrationConfig;
return await fetch(url, {
method: 'GET',
credentials: 'include'
});
} catch (error) {
console.error(error);
return error.response;
}
}
20 changes: 19 additions & 1 deletion src/components/common/Button.css
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
.buttonContainer {
display: flex;
justify-content: flex-end;
padding: 0 0 0 2%;
justify-content: space-evenly;
}

.buttonWithSpinner {
Expand All @@ -27,6 +28,23 @@
background-color: #9b9b9b;
}

.cancelButtonWithSpinner {
border: none;
border-radius: var(--border-radius);
height: var(--height);
background-color: #393939;
color: white;
margin-bottom: 50px;
margin-right: 1rem;
padding: 0 45px;
width: 155px;
cursor: pointer;
}

.cancelButtonWithSpinner:hover {
background-color: #595959;
}

.spinner {
position: relative;
border-radius: 50%;
Expand Down
4 changes: 3 additions & 1 deletion src/components/common/Button.js
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,9 @@ const Button = props => {
return (
<div className="buttonContainer">
<button
className="buttonWithSpinner"
className={
value === 'Cancel' ? 'cancelButtonWithSpinner' : 'buttonWithSpinner'
}
disabled={disabled}
onClick={onClick}
>
Expand Down
4 changes: 2 additions & 2 deletions src/components/common/Checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';
import PropTypes from 'prop-types';

const Checkbox = props => {
const { name, title, onChange, checked } = props;
const { name, title, onChange, checked, disabled } = props;
return (
<div className="form-input">
<div className="input-label">
Expand All @@ -20,7 +20,7 @@ const Checkbox = props => {
id="checkbox"
/>
<label className="labelCheckbox" htmlFor="checkbox">
<span />
<span style={{ cursor: disabled ? 'not-allowed' : 'pointer' }} />
</label>
<span id="estimatedTitle">{title}</span>
</div>
Expand Down
5 changes: 5 additions & 0 deletions src/components/common/Dropdown.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
select:disabled {
background: #dddddd;
cursor: not-allowed;
pointer-events: all !important;
}
40 changes: 40 additions & 0 deletions src/components/common/Dropdown.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import PropTypes from 'prop-types';
import React from 'react';
import './Dropdown.css';

const Dropdown = props => {
const { name, required, title, items, onChange, value, disabled } = props;
return (
<div className="form-input">
<div className="input-label">
<label className={required ? 'required' : null}>{title}</label>
</div>
<div>
<select
className="div-select"
name={name}
value={value}
onChange={onChange}
disabled={disabled}
>
{items.map(item => {
return (
<option key={item} value={item}>
{item}
</option>
);
})}
</select>
</div>
</div>
);
};

Dropdown.propTypes = {
title: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
value: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired
};

export default Dropdown;
5 changes: 5 additions & 0 deletions src/components/common/Input.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
input:disabled {
background: #dddddd;
cursor: not-allowed;
pointer-events: all !important;
}
10 changes: 8 additions & 2 deletions src/components/common/Input.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import React from 'react';
import PropTypes from 'prop-types';
import './Input.css';

const Input = props => {
const {
Expand All @@ -13,7 +14,9 @@ const Input = props => {
placeholder,
required,
min,
max
max,
pattern,
disabled
} = props;
return (
<div className="form-input">
Expand All @@ -23,6 +26,7 @@ const Input = props => {
<div className="div-input">
<label>
<input
autoComplete="off"
name={name}
type={type}
value={value}
Expand All @@ -31,6 +35,8 @@ const Input = props => {
required={required}
min={min}
max={max}
pattern={pattern}
disabled={disabled}
/>
</label>
</div>
Expand All @@ -39,7 +45,7 @@ const Input = props => {
};

Input.propTypes = {
type: PropTypes.oneOf(['text', 'number', 'date']).isRequired,
type: PropTypes.oneOf(['text', 'number', 'date', 'tel', 'email']).isRequired,
title: PropTypes.string.isRequired,
name: PropTypes.string.isRequired,
onChange: PropTypes.func.isRequired,
Expand Down
Loading

0 comments on commit 4ef8199

Please sign in to comment.