Skip to content
This repository has been archived by the owner on Nov 25, 2022. It is now read-only.

Commit

Permalink
Add Data Mapper to Admin
Browse files Browse the repository at this point in the history
  • Loading branch information
EdisonPeM committed Apr 9, 2021
1 parent 3acc4ce commit 47ebbc9
Show file tree
Hide file tree
Showing 5 changed files with 277 additions and 24 deletions.
98 changes: 98 additions & 0 deletions admin/src/components/DataMapper/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import React, { useState } from "react";
import PropTypes from "prop-types";

import { Button } from "@buffetjs/core";
import { Row } from "../common";
import { TableWrapper } from "./styles";

import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import { faTrashAlt } from "@fortawesome/free-solid-svg-icons";

function DataMapper({ data, mapper, onSuccess, onCancel }) {
const { fieldsInfo, parsedData } = data;
const [importItems, setImportItems] = useState(parsedData);

console.log(mapper);

const deleteItem = (item) => () => {
const importItemsFiltered = importItems.filter(
(importItems) => importItems !== item
);
setImportItems(importItemsFiltered);
};

const handleUploadItems = () => onSuccess(importItems);
return (
<div className="pt-3 col-12">
<Row>
<h2>Map the Import Data to Destination Field</h2>
<TableWrapper>
<table>
<thead>
<tr>
{fieldsInfo.map(({ fieldName }) => (
<th key={fieldName}>{fieldName}</th>
))}
<th>Del</th>
</tr>
</thead>
<tbody>
{importItems.map((row, i) => (
<tr key={i}>
{fieldsInfo.map(({ fieldName }, j) => {
const cell = row[fieldName];

if (cell === undefined || cell === null)
return <td key={j}>-</td>;

if (typeof cell === "object")
return <td key={j}>{JSON.stringify(cell)}</td>;

return <td key={j}>{`${cell}`}</td>;
})}
<td>
<button onClick={deleteItem(row)}>
<FontAwesomeIcon icon={faTrashAlt} />
</button>
</td>
</tr>
))}
</tbody>
</table>
</TableWrapper>
</Row>
<Row>
{
<p>
Count of Items to Import: <strong>{importItems.length}</strong>
</p>
}
</Row>
<Row>
<Button label="Import Data" onClick={handleUploadItems} />
<Button
className="ml-3"
label="Cancel"
color="delete"
onClick={onCancel}
/>
</Row>
</div>
);
}

DataMapper.defaultProps = {
data: {},
mapper: {},
onSuccess: () => {},
onCancel: () => {},
};

DataMapper.propTypes = {
data: PropTypes.any,
mapper: PropTypes.any,
onSuccess: PropTypes.func,
onCancel: PropTypes.func,
};

export default DataMapper;
73 changes: 73 additions & 0 deletions admin/src/components/DataMapper/styles.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import styled from "styled-components";

const TableWrapper = styled.div`
width: 100%;
overflow-x: auto;
background: white;
margin-top: 1rem;
border-radius: 4px;
border: 1px solid #e3e9f3;
max-height: 250px;
table {
width: 100%;
text-align: center;
th,
td {
padding: 15px;
}
th {
min-width: 15ch;
background-color: #f3f3f4;
font-weight: bold;
}
th:last-child {
min-width: 50px;
width: 50px;
}
td:last-child {
opacity: 0.5;
border-left: 1px solid #ccc;
cursor: pointer;
max-width: 50px;
padding: 0;
button {
border: none;
outline: none;
padding: 15px;
background: transparent;
font-size: 1.2rem;
}
&:hover {
opacity: 1;
}
}
tbody {
tr {
&:nth-child(even) {
background-color: #fafafa;
}
&:hover {
background-color: #efefef;
}
}
}
td {
max-width: 15ch;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
}
`;

export { TableWrapper };
14 changes: 9 additions & 5 deletions admin/src/containers/App/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,21 +28,25 @@ const navLinks = [
},
];

const App = () => {
function App() {
const userContentTypes = useContentTypes();
console.log(userContentTypes);

return (
<Layout navLinks={navLinks}>
<Switch>
<Route path={pathTo("import")} component={ImportPage} />
<Route path={pathTo("export")} component={ExportPage} />
<Route path={pathTo("import")}>
<ImportPage contentTypes={userContentTypes} />
</Route>
<Route path={pathTo("export")}>
<ExportPage contentTypes={userContentTypes} />
</Route>
<Route>
{/* Default Route Retur to Import Page */}
<Redirect to={pathTo("import")} />
</Route>
</Switch>
</Layout>
);
};
}

export default App;
12 changes: 10 additions & 2 deletions admin/src/containers/ExportPage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,10 @@
*/

import React, { memo } from "react";
// import PropTypes from "prop-types";
import PropTypes from "prop-types";
import { Block } from "../../components/common";

function ImportPage() {
function ImportPage({ contentTypes }) {
return (
<Block
title="Export"
Expand All @@ -20,4 +20,12 @@ function ImportPage() {
);
}

ImportPage.defaultProps = {
contentTypes: [],
};

ImportPage.propTypes = {
contentTypes: PropTypes.array,
};

export default memo(ImportPage);
104 changes: 87 additions & 17 deletions admin/src/containers/ImportPage/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@
*/

import React, { memo, useState } from "react";
// import PropTypes from "prop-types";
import PropTypes from "prop-types";
import UploadFileForm from "../../components/UploadFileForm";
import RawInputForm from "../../components/RawInputForm";
import DataMapper from "../../components/DataMapper";

import { Block, Row } from "../../components/common";
import { Select, Label } from "@buffetjs/core";
Expand All @@ -20,20 +21,36 @@ const importSourcesOptions = [
{ label: "Raw text", value: "raw" },
];

function ImportPage() {
function ImportPage({ contentTypes }) {
const [sourceImports, setSourceImports] = useState("upload");
const [importDest, setImportDest] = useState("");
const [analysis, setAnalysis] = useState(null);
const [mapper, setMapper] = useState(null);

const handleSelectSouceImports = ({ target: { value } }) => {
setSourceImports(value);
};

const handleSelectImportDestination = ({ target: { value } }) => {
setImportDest(value);
};

const analizeImports = async (body) => {
// if (importDest === "")
// return strapi.notification.toggle({
// type: "warning",
// message: "import.destination.empty",
// });

try {
const response = await request(`/${pluginId}/pre-analyze`, {
method: "POST",
body,
});

console.log(response);
setMapper(contentTypes.find(({ uid }) => uid === importDest));
setAnalysis(response);

strapi.notification.toggle({
type: "success",
message: "import.analyze.success",
Expand All @@ -47,30 +64,83 @@ function ImportPage() {
}
};

const uploadData = (dataToUpload) => {
console.log(dataToUpload);
if (dataToUpload.length === 0) {
strapi.notification.toggle({
type: "warning",
message: "import.items.empty",
});
}

setMapper(null);
setAnalysis(null);
};

const cancelUpload = () => {
setMapper(null);
setAnalysis(null);
};

return (
<Block
title="General"
description="Configure the Import Source & Destination"
style={{ marginBottom: 12 }}
>
<Row>
<div className="pt-3 col-sm-6">
<Label htmlFor="importSource">Import Source</Label>
<Select
name="importSource"
options={importSourcesOptions}
value={sourceImports}
onChange={handleSelectSouceImports}
/>
</div>
</Row>
{sourceImports === "upload" ? (
<UploadFileForm onSubmit={analizeImports} />
{analysis === null ? (
<>
<Row>
<div className="pt-3 col-sm-6">
<Label htmlFor="importSource">Import Source</Label>
<Select
name="importSource"
options={importSourcesOptions}
value={sourceImports}
onChange={handleSelectSouceImports}
/>
</div>
<div className="pt-3 col-sm-6">
<Label htmlFor="importDest">Import Destination</Label>
<Select
name="importDest"
options={[
{ label: "Select Import Destination", value: "" },
].concat(
contentTypes.map(({ uid, info, apiID }) => ({
label: info.label || apiID,
value: uid,
}))
)}
value={importDest}
onChange={handleSelectImportDestination}
/>
</div>
</Row>
{sourceImports === "upload" ? (
<UploadFileForm onSubmit={analizeImports} />
) : (
<RawInputForm onSubmit={analizeImports} />
)}
</>
) : (
<RawInputForm onSubmit={analizeImports} />
<DataMapper
data={analysis}
mapper={mapper}
onSuccess={uploadData}
onCancel={cancelUpload}
/>
)}
</Block>
);
}

ImportPage.defaultProps = {
contentTypes: [],
};

ImportPage.propTypes = {
contentTypes: PropTypes.array,
};

export default memo(ImportPage);

0 comments on commit 47ebbc9

Please sign in to comment.