mirror of
https://github.com/shlinkio/shlink-web-client.git
synced 2025-03-14 02:08:41 +03:00
Migrated to TS first component where some dependency was being injected
This commit is contained in:
parent
eefea0c37b
commit
39663ba936
6 changed files with 68 additions and 59 deletions
10
package-lock.json
generated
10
package-lock.json
generated
|
@ -3410,6 +3410,16 @@
|
|||
"@types/react-router": "*"
|
||||
}
|
||||
},
|
||||
"@types/reactstrap": {
|
||||
"version": "8.5.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/reactstrap/-/reactstrap-8.5.1.tgz",
|
||||
"integrity": "sha512-oEedcEGoX8EqDymsjrjzTnmaf3FuDY9qKLZMA9cH1ZkkqBc2V4i2sJ6ssXEod+GHQ5XH2r52uvbMkjEkjEZHDQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"@types/react": "*",
|
||||
"popper.js": "^1.14.1"
|
||||
}
|
||||
},
|
||||
"@types/stack-utils": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-1.0.1.tgz",
|
||||
|
|
|
@ -83,6 +83,7 @@
|
|||
"@types/react-dom": "^16.9.8",
|
||||
"@types/react-redux": "^7.1.9",
|
||||
"@types/react-router-dom": "^5.1.5",
|
||||
"@types/reactstrap": "^8.5.1",
|
||||
"adm-zip": "^0.4.13",
|
||||
"autoprefixer": "^9.6.3",
|
||||
"babel-core": "7.0.0-bridge.0",
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
import React, { useRef } from 'react';
|
||||
import { UncontrolledTooltip } from 'reactstrap';
|
||||
import PropTypes from 'prop-types';
|
||||
|
||||
const propTypes = {
|
||||
onImport: PropTypes.func,
|
||||
createServers: PropTypes.func,
|
||||
fileRef: PropTypes.oneOfType([ PropTypes.object, PropTypes.node ]),
|
||||
};
|
||||
|
||||
// FIXME Replace with typescript: (ServersImporter)
|
||||
const ImportServersBtn = ({ importServersFromFile }) => {
|
||||
const ImportServersBtnComp = ({ createServers, fileRef, onImport = () => '' }) => {
|
||||
const ref = fileRef || useRef();
|
||||
const onChange = ({ target }) =>
|
||||
importServersFromFile(target.files[0])
|
||||
.then(createServers)
|
||||
.then(onImport)
|
||||
.then(() => {
|
||||
// Reset input after processing file
|
||||
target.value = null;
|
||||
});
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-outline-secondary mr-2"
|
||||
id="importBtn"
|
||||
onClick={() => ref.current.click()}
|
||||
>
|
||||
Import from file
|
||||
</button>
|
||||
<UncontrolledTooltip placement="top" target="importBtn">
|
||||
You can create servers by importing a CSV file with columns <b>name</b>, <b>apiKey</b> and <b>url</b>.
|
||||
</UncontrolledTooltip>
|
||||
|
||||
<input type="file" accept="text/csv" className="create-server__csv-select" ref={ref} onChange={onChange} />
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
ImportServersBtnComp.propTypes = propTypes;
|
||||
|
||||
return ImportServersBtnComp;
|
||||
};
|
||||
|
||||
export default ImportServersBtn;
|
46
src/servers/helpers/ImportServersBtn.tsx
Normal file
46
src/servers/helpers/ImportServersBtn.tsx
Normal file
|
@ -0,0 +1,46 @@
|
|||
import React, { useRef, RefObject, ChangeEvent, MutableRefObject } from 'react';
|
||||
import { UncontrolledTooltip } from 'reactstrap';
|
||||
import ServersImporter from '../services/ServersImporter';
|
||||
import { Server } from '../data';
|
||||
|
||||
type Ref<T> = RefObject<T> | MutableRefObject<T>;
|
||||
|
||||
interface ImportServersBtnProps {
|
||||
createServers: (servers: Server[]) => void;
|
||||
fileRef: Ref<HTMLInputElement>;
|
||||
onImport?: () => void;
|
||||
}
|
||||
|
||||
const ImportServersBtn = ({ importServersFromFile }: ServersImporter) => (
|
||||
{ createServers, fileRef, onImport = () => {} }: ImportServersBtnProps,
|
||||
) => {
|
||||
const ref = fileRef ?? useRef<HTMLInputElement>();
|
||||
const onChange = async ({ target }: ChangeEvent<HTMLInputElement>) =>
|
||||
importServersFromFile(target.files?.[0])
|
||||
.then(createServers)
|
||||
.then(onImport)
|
||||
.then(() => {
|
||||
// Reset input after processing file
|
||||
(target as { value: string | null }).value = null;
|
||||
});
|
||||
|
||||
return (
|
||||
<React.Fragment>
|
||||
<button
|
||||
type="button"
|
||||
className="btn btn-outline-secondary mr-2"
|
||||
id="importBtn"
|
||||
onClick={() => ref.current?.click()}
|
||||
>
|
||||
Import from file
|
||||
</button>
|
||||
<UncontrolledTooltip placement="top" target="importBtn">
|
||||
You can create servers by importing a CSV file with columns <b>name</b>, <b>apiKey</b> and <b>url</b>.
|
||||
</UncontrolledTooltip>
|
||||
|
||||
<input type="file" accept="text/csv" className="create-server__csv-select" ref={ref} onChange={onChange} />
|
||||
</React.Fragment>
|
||||
);
|
||||
};
|
||||
|
||||
export default ImportServersBtn;
|
|
@ -6,7 +6,7 @@ const CSV_MIME_TYPE = 'text/csv';
|
|||
export default class ServersImporter {
|
||||
public constructor(private readonly csvjson: CsvJson, private readonly fileReaderFactory: () => FileReader) {}
|
||||
|
||||
public importServersFromFile = async (file?: File): Promise<RegularServer[]> => {
|
||||
public importServersFromFile = async (file?: File | null): Promise<RegularServer[]> => {
|
||||
if (!file || file.type !== CSV_MIME_TYPE) {
|
||||
throw new Error('No file provided or file is not a CSV');
|
||||
}
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
import React from 'react';
|
||||
import { shallow } from 'enzyme';
|
||||
import { shallow, ShallowWrapper } from 'enzyme';
|
||||
import { UncontrolledTooltip } from 'reactstrap';
|
||||
import { Mock } from 'ts-mockery';
|
||||
import importServersBtnConstruct from '../../../src/servers/helpers/ImportServersBtn';
|
||||
import ServersImporter from '../../../src/servers/services/ServersImporter';
|
||||
|
||||
describe('<ImportServersBtn />', () => {
|
||||
let wrapper;
|
||||
let wrapper: ShallowWrapper;
|
||||
const onImportMock = jest.fn();
|
||||
const createServersMock = jest.fn();
|
||||
const serversImporterMock = {
|
||||
const serversImporterMock = Mock.of<ServersImporter>({
|
||||
importServersFromFile: jest.fn().mockResolvedValue([]),
|
||||
};
|
||||
});
|
||||
const click = jest.fn();
|
||||
const fileRef = {
|
||||
current: { click: jest.fn() },
|
||||
current: Mock.of<HTMLInputElement>({ click }),
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
onImportMock.mockReset();
|
||||
createServersMock.mockReset();
|
||||
serversImporterMock.importServersFromFile.mockClear();
|
||||
fileRef.current.click.mockReset();
|
||||
jest.clearAllMocks();
|
||||
|
||||
const ImportServersBtn = importServersBtnConstruct(serversImporterMock);
|
||||
|
||||
|
@ -39,7 +39,7 @@ describe('<ImportServersBtn />', () => {
|
|||
|
||||
btn.simulate('click');
|
||||
|
||||
expect(fileRef.current.click).toHaveBeenCalledTimes(1);
|
||||
expect(click).toHaveBeenCalledTimes(1);
|
||||
});
|
||||
|
||||
it('imports servers when file input changes', (done) => {
|
Loading…
Add table
Reference in a new issue