Skip to content

Commit

Permalink
Merge pull request #31 from davewalker5/MC-193-Edit-Retailer-Details
Browse files Browse the repository at this point in the history
MC-193 Add retailer details editor
  • Loading branch information
davewalker5 authored Nov 21, 2023
2 parents cece27a + dc3544b commit 739b81f
Show file tree
Hide file tree
Showing 26 changed files with 401 additions and 67 deletions.
12 changes: 8 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -216,16 +216,20 @@ MusicCatalogue.LookupTool --lookup "John Coltrane" "Blue Train" catalogue

<img src="diagrams/retailer-list.png" alt="Retailers List" width="600">

- The page operates in an identical manner to the "Artists" page, using the same alphabet filter
- Clicking on a row in the table navigates to the details page for that retailer:
- Clicking on the edit icon in a row navigates to the retailer details editing page for that retailer (see below)
- Clicking on a row in the table navigates to the details viewing page for that retailer:

<img src="diagrams/retailer-details.png" alt="Retailer Details" width="600">

- The map is only displayed if:
- Latitude and longitude are set against the retailer's record in the database
- The UI configuration file contains an API key for Google Maps
- Currently, the only way to set extended retailer details is directly on the database
- The intention is to add retailer maintenance, including geocoding postcodes, to the next release
- To edit the details for the current retailer, click on the "Edit" button to go to the retailer details editing page:

<img src="diagrams/retailer-editor.png" alt="Retailer Details" width="600">

- Currently, the latitude and longitude (required to display the map) must be derived using external resources and then entered manually
- The intention is to add postcode geocoding to the next release

### Album Lookup

Expand Down
Binary file modified diagrams/retailer-details.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added diagrams/retailer-editor.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified diagrams/retailer-list.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: 2 additions & 2 deletions docker/api/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
FROM mcr.microsoft.com/dotnet/core/aspnet:latest
COPY musiccatalogue.api-1.20.0.0 /opt/musiccatalogue.api-1.20.0.0
WORKDIR /opt/musiccatalogue.api-1.20.0.0/bin
COPY musiccatalogue.api-1.21.0.0 /opt/musiccatalogue.api-1.21.0.0
WORKDIR /opt/musiccatalogue.api-1.21.0.0/bin
ENTRYPOINT [ "./MusicCatalogue.Api" ]
4 changes: 2 additions & 2 deletions docker/ui/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM node:20-alpine
COPY musiccatalogue.ui-1.20.0.0 /opt/musiccatalogue.ui-1.20.0.0
WORKDIR /opt/musiccatalogue.ui-1.20.0.0
COPY musiccatalogue.ui-1.21.0.0 /opt/musiccatalogue.ui-1.21.0.0
WORKDIR /opt/musiccatalogue.ui-1.21.0.0
RUN npm install
RUN npm run build
ENTRYPOINT [ "npm", "start" ]
13 changes: 12 additions & 1 deletion src/MusicCatalogue.Api/Controllers/RetailersController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,18 @@ public async Task<ActionResult<Retailer>> AddRetailerAsync([FromBody] Retailer t
[Route("")]
public async Task<ActionResult<Retailer?>> UpdateRetailerAsync([FromBody] Retailer template)
{
var retailer = await _factory.Retailers.UpdateAsync(template.Id, template.Name);
var retailer = await _factory.Retailers.UpdateAsync(
template.Id,
template.Name,
template.Address1,
template.Address2,
template.Town,
template.County,
template.PostCode,
template.Country,
template.Latitude,
template.Longitude,
template.WebSite);
return retailer;
}

Expand Down
5 changes: 4 additions & 1 deletion src/MusicCatalogue.Entities/Reporting/ReportEntityBase.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
namespace MusicCatalogue.Entities.Reporting
using System.Diagnostics.CodeAnalysis;

namespace MusicCatalogue.Entities.Reporting
{
[ExcludeFromCodeCoverage]
public class ReportEntityBase
{
public int Id { get; set; }
Expand Down
19 changes: 7 additions & 12 deletions src/music-catalogue-ui/components/albumPurchaseDetails.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import config from "../config.json";
import pages from "../helpers/navigation";
import { apiCreateRetailer } from "@/helpers/apiRetailers";
import { apiSetAlbumPurchaseDetails } from "@/helpers/apiAlbums";
import FormInputField from "./formInputField";

/**
* Form to set the album purchase details for an album
Expand Down Expand Up @@ -120,18 +121,12 @@ const AlbumPurchaseDetails = ({ artist, album, navigate, logout }) => {
/>
</div>
</div>
<div className="form-group mt-3">
<label className={styles.purchaseDetailsFormLabel}>
Retailer
</label>
<input
className="form-control mt-1"
placeholder="Retailer Name"
name="retailer"
value={retailerName}
onChange={(e) => setRetailerName(e.target.value)}
/>
</div>
<FormInputField
label="Retailer Name"
name="retailer"
value={retailerName}
setValue={setRetailerName}
/>
<div className="d-grid gap-2 mt-3">
<span className={styles.purchaseDetailsError}>
{errorMessage}
Expand Down
10 changes: 10 additions & 0 deletions src/music-catalogue-ui/components/componentPicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import MonthlySpendReport from "./monthlySpendReport";
import GenreList from "./genreList";
import RetailerList from "./retailerList";
import RetailerDetails from "./retailerDetails";
import RetailerEditor from "./retailerEditor";

/**
* Component using the current context to select and render the current page
Expand Down Expand Up @@ -81,6 +82,15 @@ const ComponentPicker = ({ context, mapsApiKey, navigate, logout }) => {
<RetailerDetails
mapsApiKey={mapsApiKey}
retailer={context.retailer}
navigate={navigate}
logout={logout}
/>
);
case pages.retailerEditor:
return (
<RetailerEditor
retailer={context.retailer}
navigate={navigate}
logout={logout}
/>
);
Expand Down
6 changes: 0 additions & 6 deletions src/music-catalogue-ui/components/export.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,6 @@
padding-bottom: 20px;
}

.exportFormLabel {
font-size: 14px;
font-weight: 600;
color: rgb(34, 34, 34);
}

.exportButton {
float: right;
}
Expand Down
17 changes: 7 additions & 10 deletions src/music-catalogue-ui/components/exportCatalogue.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import styles from "./export.module.css";
import { useCallback, useState } from "react";
import { apiRequestCatalogueExport } from "@/helpers/apiDataExchange";
import FormInputField from "./formInputField";

/**
* Component to prompt for an export file name and request an export of the catalogue
Expand Down Expand Up @@ -49,16 +50,12 @@ const ExportCatalogue = ({ logout }) => {
<></>
)}
<div>
<div className="form-group mt-3">
<label className={styles.exportFormLabel}>File Name</label>
<input
className="form-control mt-1"
placeholder="File name"
name="fileName"
value={fileName}
onChange={(e) => setFileName(e.target.value)}
/>
</div>
<FormInputField
label="File Name"
name="fileName"
value={fileName}
setValue={setFileName}
/>
<br />
<div className={styles.exportButton}>
<button
Expand Down
18 changes: 18 additions & 0 deletions src/music-catalogue-ui/components/formInputField.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import styles from "./formInputField.module.css";

const FormInputField = ({ label, name, value, setValue }) => {
return (
<div className="form-group mt-3">
<label className={styles.retailerEditorInputLabel}>{label}</label>
<input
className="form-control"
placeholder={label}
name={name}
value={value}
onChange={(e) => setValue(e.target.value)}
/>
</div>
);
};

export default FormInputField;
5 changes: 5 additions & 0 deletions src/music-catalogue-ui/components/formInputField.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.retailerEditorInputLabel {
font-size: 14px;
font-weight: 600;
color: rgb(34, 34, 34);
}
4 changes: 3 additions & 1 deletion src/music-catalogue-ui/components/locationMap.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import GoogleMapReact from "google-map-react";
import { useState } from "react";
import styles from "./locationMap.module.css";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faMapMarkerAlt } from "@fortawesome/free-solid-svg-icons";

const LocationMap = ({ apiKey, latitude, longitude }) => {
const [location, setLocation] = useState({ lat: latitude, lng: longitude });
Expand All @@ -13,7 +15,7 @@ const LocationMap = ({ apiKey, latitude, longitude }) => {
defaultCenter={location}
defaultZoom={15}
>
<div className={styles.locationMapMarker}></div>
<FontAwesomeIcon icon={faMapMarkerAlt} size="3x" color="red" />
</GoogleMapReact>
</div>
</>
Expand Down
12 changes: 0 additions & 12 deletions src/music-catalogue-ui/components/locationMap.module.css
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,3 @@
height: 300px;
margin-bottom: 30px;
}

.locationMapMarker {
color: white;
background: red;
padding: 8px 8px;
display: inline-flex;
text-align: center;
align-items: center;
justify-content: center;
border-radius: 100%;
transform: translate(-50%, -50%);
}
28 changes: 21 additions & 7 deletions src/music-catalogue-ui/components/retailerDetails.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import pages from "../helpers/navigation";
import LocationMap from "./locationMap";
import styles from "./retailerDetails.module.css";

Expand All @@ -6,18 +7,21 @@ import styles from "./retailerDetails.module.css";
* @param {*} param0
* @returns
*/
const RetailerDetails = ({ mapsApiKey, retailer, logout }) => {
// Create map properties
const haveCoordinates =
retailer.latitude != null && retailer.longitude != null;
const title = `${retailer.name} - ${retailer.town}`;
const RetailerDetails = ({ mapsApiKey, retailer, navigate, logout }) => {
// Set a flag indicating if we have enough data to show the map
const canShowMap = retailer.latitude != null && retailer.longitude != null;

const title =
retailer.town != null
? `${retailer.name} - ${retailer.town}`
: retailer.name;

return (
<>
<div className="row mb-2 pageTitle">
<h5 className="themeFontColor text-center">{title}</h5>
</div>
{haveCoordinates == true ? (
{canShowMap == true ? (
<LocationMap
apiKey={mapsApiKey}
latitude={retailer.latitude}
Expand Down Expand Up @@ -52,7 +56,7 @@ const RetailerDetails = ({ mapsApiKey, retailer, logout }) => {
</tr>
<tr>
<th>Postcode:</th>
<td>{retailer.postcode}</td>
<td>{retailer.postCode}</td>
</tr>
<tr>
<th>Country:</th>
Expand All @@ -72,6 +76,16 @@ const RetailerDetails = ({ mapsApiKey, retailer, logout }) => {
)}
</tbody>
</table>
<div className={styles.retailerDetailsButtonContainer}>
<button
className="btn btn-primary"
onClick={() =>
navigate({ page: pages.retailerEditor, retailer: retailer })
}
>
Edit
</button>
</div>
</div>
</>
);
Expand Down
4 changes: 4 additions & 0 deletions src/music-catalogue-ui/components/retailerDetails.module.css
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
.retailerDetailsContainer * td {
padding: 5px;
}

.retailerDetailsButtonContainer {
margin-top: 20px;
}
Loading

0 comments on commit 739b81f

Please sign in to comment.