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

Editor #40

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion config-overrides.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ const MonacoWebpackPlugin = require("monaco-editor-webpack-plugin");
module.exports = function override(config, env) {
config.plugins.push(
new MonacoWebpackPlugin({
languages: ["json", "xml"],
languages: ["json", "xml", "yaml"],
})
);
return config;
Expand Down
10 changes: 7 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
"@data-driven-forms/pf4-component-mapper": "^3.6.1",
"@data-driven-forms/react-form-renderer": "^3.6.1",
"@konveyor/lib-ui": "^4.0.1",
"@patternfly/react-code-editor": "4.2.59",
"@patternfly/react-core": "4.121.1",
"@patternfly/react-table": "4.27.7",
"@patternfly/react-code-editor": "4.2.76",
"@patternfly/react-core": "4.128.2",
"@patternfly/react-table": "4.27.24",
"@react-keycloak/web": "^3.4.0",
"@redhat-cloud-services/frontend-components-notifications": "^3.1.0",
"@testing-library/jest-dom": "^5.11.4",
Expand All @@ -20,12 +20,14 @@
"@types/react-dom": "^17.0.0",
"axios": "^0.21.1",
"file-saver": "^2.0.5",
"js-yaml": "^4.1.0",
"keycloak-js": "^13.0.0",
"moment": "^2.29.1",
"monaco-editor": "^0.24.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-dropzone": "^11.3.2",
"react-measure": "^2.5.2",
"react-moment": "^1.1.1",
"react-monaco-editor": "^0.43.0",
"react-redux": "^7.2.4",
Expand Down Expand Up @@ -96,6 +98,8 @@
"@types/enzyme": "^3.10.8",
"@types/enzyme-adapter-react-16": "^1.0.6",
"@types/file-saver": "^2.0.2",
"@types/js-yaml": "^4.0.1",
"@types/react-measure": "^2.0.6",
"@types/react-redux": "^7.1.16",
"@types/react-router-dom": "^5.1.7",
"@types/redux-logger": "^3.0.8",
Expand Down
1 change: 1 addition & 0 deletions src/Paths.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ export enum Paths {

documentList = "/ns-document/:namespaceId/documents",
uploadDocument = "/ns-document/:namespaceId/documents/~upload",
createDocument = "/ns-document/:namespaceId/documents/~new",
}

export interface OptionalCompanyRoute {
Expand Down
46 changes: 46 additions & 0 deletions src/api/models.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -165,3 +165,49 @@ export interface ConfigPropertyRepresentation {
options: string[];
secret: boolean;
}

// Documents
export type DocumentType = "INVOICE" | "CREDIT_NOTE";

export interface InputModel<T> {
kind: DocumentType;
spec: T;
}

export interface InvoiceInputModel {
serie: string;
numero: number;
proveedor: {
ruc: string;
razonSocial: string;
};
cliente: {
tipoDocumentoIdentidad: string;
numeroDocumentoIdentidad: string;
nombre: string;
};
detalle: DocumentLineInputModel[];
}

export interface CreditNoteInputModel {
serie: string;
numero: number;
serieNumeroComprobanteAfectado: string;
descripcionSustentoDeNota: string
proveedor: {
ruc: string;
razonSocial: string;
};
cliente: {
tipoDocumentoIdentidad: string;
numeroDocumentoIdentidad: string;
nombre: string;
};
detalle: DocumentLineInputModel[];
}

export interface DocumentLineInputModel {
descripcion: string;
cantidad: number;
precioUnitario: number;
}
13 changes: 12 additions & 1 deletion src/api/rest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
KeysMetadataRepresentation,
ComponentRepresentation,
ServerInfoRepresentation,
InputModel,
} from "./models";

const USER_NAMESPACES = "/user/namespaces";
Expand Down Expand Up @@ -322,6 +323,16 @@ export const getDocuments = (
);
};

export const createDocument = (
namespaceId: string,
inputModel: InputModel<any>
): AxiosPromise => {
const url = `${DOCUMENTS.replaceAll(":namespaceId", namespaceId)}`;
return APIClient.post(url, inputModel, {
headers: { Accept: "application/json" },
});
};

export const getDocumentFile = (
namespaceId: string,
documentId: string
Expand Down Expand Up @@ -366,7 +377,7 @@ export const retrySendDocument = (

return APIClient.post(
url,
{ a: "s" },
{},
{
headers: { Accept: "application/json" },
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { ToolbarDocument } from "./toolbar-document";
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import React from "react";

import {
ToggleGroup,
ToggleGroupItem,
ToolbarChip,
} from "@patternfly/react-core";

export interface IToolbarDocumentProps {
docTypeValue?: ToolbarChip;
docTypeOptions: ToolbarChip[];
onDocTypeChange: (value: ToolbarChip) => void;
}

export const ToolbarDocument: React.FC<IToolbarDocumentProps> = ({
docTypeValue,
docTypeOptions,
onDocTypeChange,
}) => {
return (
<ToggleGroup>
{docTypeOptions.map((elem) => (
<ToggleGroupItem
key={elem.key}
text={elem.node}
buttonId={elem.key}
isSelected={elem.key === docTypeValue?.key}
onChange={(isSelected, event) => {
const id = event.currentTarget.id;
const selectedOption = docTypeOptions.find((f) => f.key === id);
if (selectedOption) {
onDocTypeChange(selectedOption);
}
}}
/>
))}
</ToggleGroup>
);
};
199 changes: 199 additions & 0 deletions src/pages/documents/create-document/create-document.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
import React, { useCallback, useEffect, useMemo, useState } from "react";
import { useParams } from "react-router-dom";
import Measure from "react-measure";
import yaml from "js-yaml";

import {
ActionGroup,
Button,
ButtonVariant,
PageSection,
Split,
SplitItem,
Stack,
StackItem,
ToolbarChip,
} from "@patternfly/react-core";
import { CodeEditor, Language } from "@patternfly/react-code-editor";

import { SimplePageSection } from "shared/components";

import { NamespaceRoute, formatPath, Paths } from "Paths";
import { DocumentType, InputModel } from "api/models";

import { DEFAULT_INVOICE } from "./templates/invoice/invoice";
import { DEFAULT_CREDIT_NOTE } from "./templates/creditnote/creditnote";

import { ToolbarDocument } from "./components/toolbar-document";

import "./editor.scss";
import { createDocument } from "api/rest";

type DocumentListType = {
[key in DocumentType]: {
template: any;
};
};

const documentTypeData: DocumentListType = {
INVOICE: {
template: DEFAULT_INVOICE,
},
CREDIT_NOTE: {
template: DEFAULT_CREDIT_NOTE,
},
};

interface DocumentTypeChip extends ToolbarChip {
key: DocumentType;
}

const documentTypes: DocumentTypeChip[] = [
{
key: "INVOICE",
node: "Boleta/factura",
},
{
key: "CREDIT_NOTE",
node: "Nota de crédito",
},
];

export const CreateDocument: React.FC = () => {
// Router
const { namespaceId } = useParams<NamespaceRoute>();

// Editor
const [code, setCode] = useState("");

const onEditorDidMount = (editor: any, monaco: any) => {
editor.layout();
editor.focus();
monaco.editor.getModels()[0].updateOptions({ tabSize: 2 });
};

// Document type
const [documentType, setDocumentType] = useState<DocumentTypeChip>();

useEffect(() => {
if (documentType) {
const templateObj = documentTypeData[documentType.key].template;
setCode(yaml.dump(templateObj));
}
}, [documentType]);

// Form
const [isSubmitting, setIsSubmitting] = useState(false);
const [submitError, setSubmitError] = useState<any>();

const onSave = () => {
try {
const obj = yaml.load(code);
setIsSubmitting(true);
createDocument(namespaceId, obj as InputModel<any>)
.then(() => {
setIsSubmitting(false);
})
.catch((error) => {
setIsSubmitting(false);
setSubmitError(error);
});
} catch (error) {
setSubmitError(error);
}
};

return (
<>
<SimplePageSection
title="Crear XML"
breadcrumbs={[
{
title: "Documentos",
path: formatPath(Paths.documentList, {
namespaceId,
}),
},
{
title: "create",
path: "",
},
]}
/>
<PageSection>
<Stack hasGutter>
<StackItem>
<Split hasGutter>
<SplitItem>
<ToolbarDocument
docTypeValue={documentType}
docTypeOptions={documentTypes}
onDocTypeChange={(value) => {
setDocumentType(value as DocumentTypeChip);
}}
/>
</SplitItem>
</Split>
</StackItem>
<StackItem isFilled>
<Measure bounds>
{({ measureRef, contentRect }) => (
<div
ref={measureRef}
className="ocs-yaml-editor__root"
style={{ minHeight: 100, height: "100%" }}
>
<div className="ocs-yaml-editor__wrapper">
<CodeEditor
code={code}
language={Language.yaml}
isDarkTheme
isMinimapVisible
isLineNumbersVisible
isCopyEnabled
isDownloadEnabled
isLanguageLabelVisible
onChange={(value) => setCode(value || "")}
onEditorDidMount={onEditorDidMount}
height={
contentRect.bounds
? `${contentRect.bounds.height - 53}px`
: `100px`
}
width={
contentRect.bounds
? `${contentRect.bounds.width - 17}px`
: "100%"
}
/>
</div>
</div>
)}
</Measure>
</StackItem>
<StackItem>
<ActionGroup>
<Button
type="submit"
aria-label="submit"
variant={ButtonVariant.primary}
isDisabled={isSubmitting}
onClick={onSave}
>
Crear
</Button>
<Button
type="button"
aria-label="cancel"
variant={ButtonVariant.link}
isDisabled={isSubmitting}
>
Cancelar
</Button>
</ActionGroup>
</StackItem>
</Stack>
</PageSection>
</>
);
};
14 changes: 14 additions & 0 deletions src/pages/documents/create-document/editor.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
.ocs-yaml-editor {
&__root {
flex: 1;
position: relative;
}

&__wrapper {
position: absolute;
top: 0;
right: 0;
left: 0;
bottom: 0;
}
}
1 change: 1 addition & 0 deletions src/pages/documents/create-document/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export { CreateDocument as default } from "./create-document";
Loading