Create/update snippet with tags. DB migration to support tags

This commit is contained in:
unknown
2021-09-27 12:12:19 +02:00
parent 8c603dcd2f
commit bd7eaf3d17
10 changed files with 89 additions and 6 deletions

View File

@@ -77,7 +77,7 @@ docker run -p 5000:5000 -v /path/to/data:/app/data snippet-box
![Snippet screenshot](./.github/img/snippet.png)
- Edditor
- Editor
- Create and edit your snippets from simple and easy to use editor
![Editor screenshot](./.github/img/editor.png)

View File

@@ -25,7 +25,8 @@ export const SnippetForm = (props: Props): JSX.Element => {
language: '',
code: '',
docs: '',
isPinned: false
isPinned: false,
tags: ''
});
useEffect(() => {
@@ -109,11 +110,31 @@ export const SnippetForm = (props: Props): JSX.Element => {
id='language'
name='language'
value={formData.language}
placeholder='bash'
placeholder='python'
required
onChange={e => inputHandler(e)}
/>
</div>
{/* TAGS */}
<div className='mb-3'>
<label htmlFor='tags' className='form-label'>
Tags
</label>
<input
type='text'
className='form-control'
id='tags'
name='tags'
value={formData.tags}
placeholder='automation, files, loop'
required
onChange={e => inputHandler(e)}
/>
<div className='form-text'>
Language tag will be added automatically
</div>
</div>
<hr />
{/* CODE SECTION */}

View File

@@ -7,6 +7,7 @@ export interface NewSnippet {
code: string;
docs?: string;
isPinned: boolean;
tags: string;
}
export interface Snippet extends Model, NewSnippet {}

View File

@@ -10,6 +10,7 @@
"dev:client": "npm start --prefix=client",
"dev:server": "nodemon",
"dev": "npm-run-all -n --parallel dev:**",
"build:client": "npm run build prefix=client",
"build:clear": "rm -rf build",
"build:tsc": "tsc",
"build": "npm-run-all -n build:**"

View File

@@ -3,7 +3,7 @@ import { QueryTypes } from 'sequelize';
import { sequelize } from '../db';
import { asyncWrapper } from '../middleware';
import { SnippetModel } from '../models';
import { ErrorResponse } from '../utils';
import { ErrorResponse, tagsParser } from '../utils';
/**
* @description Create new snippet
@@ -12,7 +12,17 @@ import { ErrorResponse } from '../utils';
*/
export const createSnippet = asyncWrapper(
async (req: Request, res: Response, next: NextFunction): Promise<void> => {
const snippet = await SnippetModel.create(req.body);
const { language, tags } = <{ language: string; tags: string }>req.body;
const parsedTags = tagsParser(tags);
if (!parsedTags.includes(language.toLowerCase())) {
parsedTags.push(language.toLowerCase());
}
const snippet = await SnippetModel.create({
...req.body,
tags: parsedTags.join(',')
});
res.status(201).json({
data: snippet
@@ -81,7 +91,23 @@ export const updateSnippet = asyncWrapper(
);
}
snippet = await snippet.update(req.body);
// Check if language was changed. Edit tags if so
const { language: oldLanguage } = snippet;
const { language, tags } = <{ language: string; tags: string }>req.body;
let parsedTags = tagsParser(tags);
if (oldLanguage != language) {
parsedTags = parsedTags.filter(tag => tag != oldLanguage);
if (!parsedTags.includes(language)) {
parsedTags.push(language.toLowerCase());
}
}
snippet = await snippet.update({
...req.body,
tags: parsedTags.join(',')
});
res.status(200).json({
data: snippet

View File

@@ -0,0 +1,19 @@
import { DataTypes, QueryInterface, QueryTypes } from 'sequelize';
import { sequelize } from '../';
const { STRING } = DataTypes;
export const up = async (queryInterface: QueryInterface): Promise<void> => {
await queryInterface.addColumn('snippets', 'tags', {
type: STRING,
allowNull: true,
defaultValue: ''
});
await sequelize.query(`UPDATE snippets SET tags = language`, {
type: QueryTypes.UPDATE
});
};
export const down = async (queryInterface: QueryInterface): Promise<void> => {
await queryInterface.removeColumn('snippets', 'tags');
};

View File

@@ -41,6 +41,11 @@ export const SnippetModel = sequelize.define<SnippetInstance>('Snippet', {
allowNull: true,
defaultValue: 0
},
tags: {
type: STRING,
allowNull: true,
defaultValue: ''
},
createdAt: {
type: DATE
},

View File

@@ -8,6 +8,7 @@ export interface Snippet extends Model {
code: string;
docs: string;
isPinned: number;
tags: string;
}
export interface SnippetCreationAttributes

View File

@@ -1,2 +1,3 @@
export * from './Logger';
export * from './ErrorResponse';
export * from './tagsParser';

8
src/utils/tagsParser.ts Normal file
View File

@@ -0,0 +1,8 @@
export const tagsParser = (tags: string): string[] => {
const parsedTags = tags
.split(',')
.map(tag => tag.trim().toLowerCase())
.filter(String);
return parsedTags;
};