mirror of
https://github.com/OneUptime/oneuptime.git
synced 2026-04-06 00:32:12 +02:00
add file service.
This commit is contained in:
@@ -1,11 +1,13 @@
|
||||
import { Column } from 'typeorm';
|
||||
import ColumnLength from '../Types/Database/ColumnLength';
|
||||
import ColumnType from '../Types/Database/ColumnType';
|
||||
import SlugifyColumn from '../Types/Database/SlugifyColumn';
|
||||
import TableColumn from '../Types/Database/TableColumn';
|
||||
import TableColumnType from '../Types/Database/TableColumnType';
|
||||
import ObjectID from '../Types/ObjectID';
|
||||
import BaseModel from './BaseModel';
|
||||
|
||||
@SlugifyColumn('name', 'slug')
|
||||
export default class FileModel extends BaseModel {
|
||||
public constructor(id?: ObjectID) {
|
||||
super(id);
|
||||
@@ -37,4 +39,12 @@ export default class FileModel extends BaseModel {
|
||||
length: ColumnLength.ShortText,
|
||||
})
|
||||
public type?: string = undefined;
|
||||
|
||||
@TableColumn({ required: true, unique: true, type: TableColumnType.Slug })
|
||||
@Column({
|
||||
nullable: false,
|
||||
type: ColumnType.Slug,
|
||||
length: ColumnLength.Slug,
|
||||
})
|
||||
public slug?: string = undefined;
|
||||
}
|
||||
|
||||
10
CommonServer/Services/FileService.ts
Normal file
10
CommonServer/Services/FileService.ts
Normal file
@@ -0,0 +1,10 @@
|
||||
import PostgresDatabase from '../Infrastructure/PostgresDatabase';
|
||||
import File from 'Model/Models/File';
|
||||
import DatabaseService from './DatabaseService';
|
||||
|
||||
export class Service extends DatabaseService<File> {
|
||||
public constructor(postgresDatabase?: PostgresDatabase) {
|
||||
super(File, postgresDatabase);
|
||||
}
|
||||
}
|
||||
export default new Service();
|
||||
@@ -0,0 +1,79 @@
|
||||
import React, {
|
||||
FunctionComponent,
|
||||
ReactElement,
|
||||
useEffect,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { useDropzone } from 'react-dropzone';
|
||||
|
||||
export interface ComponentProps {
|
||||
initialValue?: undefined | string;
|
||||
onClick?: undefined | (() => void);
|
||||
placeholder?: undefined | string;
|
||||
className?: undefined | string;
|
||||
onChange?: undefined | ((value: string) => void);
|
||||
value?: string | undefined;
|
||||
readOnly?: boolean | undefined;
|
||||
type?: 'text' | 'number' | 'date';
|
||||
onFocus?: (() => void) | undefined;
|
||||
onBlur?: (() => void) | undefined;
|
||||
dataTestId?: string;
|
||||
}
|
||||
|
||||
const FilePicker: FunctionComponent<ComponentProps> = (
|
||||
props: ComponentProps
|
||||
): ReactElement => {
|
||||
|
||||
const [files, setFiles] = useState<Array<File>>([]);
|
||||
const [fileObjectURLs, setFileObjectURLs] = useState<Array<string>>([]);
|
||||
const { getRootProps, getInputProps } = useDropzone({
|
||||
accept: {
|
||||
'image/*': []
|
||||
},
|
||||
onDrop: acceptedFiles => {
|
||||
setFiles(acceptedFiles.map(file => Object.assign(file, {
|
||||
preview: URL.createObjectURL(file)
|
||||
})));
|
||||
}
|
||||
});
|
||||
|
||||
const thumbs = files.map((file) => {
|
||||
|
||||
const url: string = URL.createObjectURL(file);
|
||||
const urlArr = [...fileObjectURLs]
|
||||
urlArr.push(url);
|
||||
|
||||
setFileObjectURLs(urlArr);
|
||||
|
||||
return (<div className='file-picker-thumb' key={file.name}>
|
||||
<div className='file-picker-thumb-inner'>
|
||||
<img
|
||||
src={url}
|
||||
className='file-picker-img'
|
||||
// Revoke data uri after image is loaded
|
||||
onLoad={() => { URL.revokeObjectURL(url) }}
|
||||
/>
|
||||
</div>
|
||||
</div>)
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
// Make sure to revoke the data uris to avoid memory leaks, will run on unmount
|
||||
return () => fileObjectURLs.forEach(fileURL => URL.revokeObjectURL(fileURL));
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<section className="container">
|
||||
<div {...getRootProps({ className: 'dropzone' })}>
|
||||
<input {...getInputProps()} />
|
||||
<p>Drag 'n' drop some files here, or click to select files</p>
|
||||
</div>
|
||||
<aside className='file-picker-thumb-container'>
|
||||
{thumbs}
|
||||
</aside>
|
||||
</section>
|
||||
);
|
||||
|
||||
};
|
||||
|
||||
export default FilePicker;
|
||||
|
||||
@@ -289,4 +289,39 @@
|
||||
border-style: dashed;
|
||||
border-radius: 500px;
|
||||
width: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// File Picker.
|
||||
|
||||
.file-picker-thumbs-container {
|
||||
display: 'flex';
|
||||
flex-direction: 'row';
|
||||
flex-wrap: 'wrap';
|
||||
margin-top: "16px"
|
||||
}
|
||||
|
||||
.file-picker-thumb {
|
||||
display: 'inline-flex';
|
||||
border-radius: "2px";
|
||||
border: '1px solid #eaeaea';
|
||||
margin-bottom: 8;
|
||||
margin-right: 8;
|
||||
width: 100;
|
||||
height: 100,;
|
||||
padding: 4;
|
||||
box-sizing: 'border-box'
|
||||
};
|
||||
|
||||
.file-picker-thumb-inner {
|
||||
display: 'flex';
|
||||
min-width: 0;
|
||||
overflow: 'hidden'
|
||||
};
|
||||
|
||||
.file-picker-img {
|
||||
display: 'block';
|
||||
width: 'auto';
|
||||
height: '100%'
|
||||
};
|
||||
@@ -3,13 +3,22 @@ import { PostgresAppInstance } from 'CommonServer/Infrastructure/PostgresDatabas
|
||||
import Express, { ExpressApplication } from 'CommonServer/Utils/Express';
|
||||
import logger from 'CommonServer/Utils/Logger';
|
||||
import App from 'CommonServer/Utils/StartServer';
|
||||
import AuthenticationAPI from './API/AuthenticationAPI';
|
||||
import File from 'Model/Models/File';
|
||||
import FileService, {
|
||||
Service as FileServiceType,
|
||||
} from 'CommonServer/Services/FileService';
|
||||
import BaseAPI from 'CommonServer/API/BaseAPI';
|
||||
|
||||
const app: ExpressApplication = Express.getExpressApp();
|
||||
|
||||
const APP_NAME: string = 'File';
|
||||
|
||||
app.use([`/${APP_NAME}`, '/'], AuthenticationAPI);
|
||||
app.use(
|
||||
new BaseAPI<File, FileServiceType>(
|
||||
File,
|
||||
FileService
|
||||
).getRouter()
|
||||
);
|
||||
|
||||
const init: Function = async (): Promise<void> => {
|
||||
try {
|
||||
|
||||
8
File/package-lock.json
generated
8
File/package-lock.json
generated
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"name": "File",
|
||||
"name": "file",
|
||||
"version": "1.0.0",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "File",
|
||||
"name": "file",
|
||||
"version": "1.0.0",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
@@ -42,7 +42,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@faker-js/faker": "^6.3.1",
|
||||
"@types/jest": "^27.4.1",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/node": "^17.0.22",
|
||||
"jest": "^27.5.1",
|
||||
"ts-jest": "^27.1.4"
|
||||
@@ -5119,7 +5119,7 @@
|
||||
"requires": {
|
||||
"@faker-js/faker": "^6.3.1",
|
||||
"@types/crypto-js": "^4.1.1",
|
||||
"@types/jest": "^27.4.1",
|
||||
"@types/jest": "^27.5.2",
|
||||
"@types/nanoid-dictionary": "^4.2.0",
|
||||
"@types/node": "^17.0.22",
|
||||
"@types/uuid": "^8.3.4",
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
import { Entity } from 'typeorm';
|
||||
import FileModel from 'Common/Models/FileModel';
|
||||
import SingularPluralName from 'Common/Types/Database/SingularPluralName';
|
||||
import Route from 'Common/Types/API/Route';
|
||||
import CrudApiEndpoint from 'Common/Types/Database/CrudApiEndpoint';
|
||||
|
||||
@SingularPluralName('File', 'Files')
|
||||
@Entity({
|
||||
name: 'File',
|
||||
})
|
||||
@CrudApiEndpoint(new Route('/file'))
|
||||
export default class Label extends FileModel {
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user