Updating snippets with tags

This commit is contained in:
unknown
2021-09-28 13:26:48 +02:00
parent 86ea246e90
commit 714793a407
11 changed files with 97 additions and 67 deletions

View File

@@ -1,3 +1,6 @@
### v1.2 (2021-09-28)
- Added support for tags ([#10](https://github.com/pawelmalak/snippet-box/issues/10))
### v1.1 (2021-09-24)
- Added pin icon directly to snippet card ([#4](https://github.com/pawelmalak/snippet-box/issues/4))
- Fixed issue with copying snippets ([#6](https://github.com/pawelmalak/snippet-box/issues/6))

View File

@@ -10,14 +10,8 @@ COPY . .
RUN mkdir -p ./public ./data
# Build server code
RUN npm run build
# Build client code
RUN cd ./client \
&& npm install \
&& npm run build \
&& cd .. \
# Build
RUN npm run build \
&& mv ./client/build/* ./public
# Clean up src files

View File

@@ -12,14 +12,8 @@ COPY . .
RUN mkdir -p ./public ./data
# Build server code
RUN npm run build
# Build client code
RUN cd ./client \
&& npm install \
&& npm run build \
&& cd .. \
# Build
RUN npm run build \
&& mv ./client/build/* ./public
# Clean up src files

View File

@@ -54,6 +54,10 @@ export const SnippetForm = (props: Props): JSX.Element => {
});
};
const tagsToString = (): string => {
return formData.tags.join(',');
};
const formHandler = (e: FormEvent) => {
e.preventDefault();
@@ -134,13 +138,13 @@ export const SnippetForm = (props: Props): JSX.Element => {
className='form-control'
id='tags'
name='tags'
// value={formData.tags}
value={tagsToString()}
placeholder='automation, files, loop'
onChange={e => stringToTags(e)}
/>
<div className='form-text'>
Tags should be separate with a comma. Language tag will be added
automatically
Tags should be separated with a comma. Language tag will be
added automatically
</div>
</div>
<hr />

View File

@@ -53,13 +53,13 @@ export const SnippetsContextProvider = (props: Props): JSX.Element => {
};
const setSnippet = (id: number): void => {
getSnippetById(id);
if (id < 0) {
setCurrentSnippet(null);
return;
}
getSnippetById(id);
const snippet = snippets.find(s => s.id === id);
if (snippet) {

View File

@@ -10,7 +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:client": "npm run build --prefix=client",
"build:clear": "rm -rf build",
"build:tsc": "tsc",
"build": "npm-run-all -n build:**"

View File

@@ -2,13 +2,15 @@ import { Request, Response, NextFunction } from 'express';
import { QueryTypes } from 'sequelize';
import { sequelize } from '../db';
import { asyncWrapper } from '../middleware';
import { SnippetModel, Snippet_TagModel } from '../models';
import {
SnippetInstance,
SnippetModel,
Snippet_TagModel,
TagModel
} from '../models';
import { ErrorResponse, getTags, tagParser, Logger } from '../utils';
ErrorResponse,
getTags,
tagParser,
Logger,
createTags
} from '../utils';
import { Body } from '../typescript/interfaces';
const logger = new Logger('snippets-controller');
@@ -19,11 +21,6 @@ const logger = new Logger('snippets-controller');
*/
export const createSnippet = asyncWrapper(
async (req: Request, res: Response, next: NextFunction): Promise<void> => {
interface Body {
language: string;
tags: string[];
}
// Get tags from request body
const { language, tags: requestTags } = <Body>req.body;
const parsedRequestTags = tagParser([
@@ -37,38 +34,8 @@ export const createSnippet = asyncWrapper(
tags: [...parsedRequestTags].join(',')
});
// Get all tags
const rawAllTags = await sequelize.query<{ id: number; name: string }>(
`SELECT * FROM tags`,
{ type: QueryTypes.SELECT }
);
const parsedAllTags = rawAllTags.map(tag => tag.name);
// Create array of new tags
const newTags = [...parsedRequestTags].filter(
tag => !parsedAllTags.includes(tag)
);
// Create new tags
if (newTags.length > 0) {
for (const tag of newTags) {
const { id, name } = await TagModel.create({ name: tag });
rawAllTags.push({ id, name });
}
}
// Associate tags with snippet
for (const tag of parsedRequestTags) {
const tagObj = rawAllTags.find(t => t.name == tag);
if (tagObj) {
await Snippet_TagModel.create({
snippet_id: snippet.id,
tag_id: tagObj.id
});
}
}
// Create tags
await createTags(parsedRequestTags, snippet.id);
// Get raw snippet values
const rawSnippet = snippet.get({ plain: true });
@@ -162,10 +129,28 @@ export const updateSnippet = asyncWrapper(
);
}
snippet = await snippet.update(req.body);
// Get tags from request body
const { language, tags: requestTags } = <Body>req.body;
let parsedRequestTags = tagParser([...requestTags, language.toLowerCase()]);
// Update snippet
snippet = await snippet.update({
...req.body,
tags: [...parsedRequestTags].join(',')
});
// Delete old tags and create new ones
await Snippet_TagModel.destroy({ where: { snippet_id: req.params.id } });
await createTags(parsedRequestTags, snippet.id);
// Get raw snippet values
const rawSnippet = snippet.get({ plain: true });
res.status(200).json({
data: snippet
data: {
...rawSnippet,
tags: [...parsedRequestTags]
}
});
}
);

View File

@@ -0,0 +1,9 @@
export interface Body {
title: string;
description?: string;
language: string;
code: string;
docs?: string;
isPinned: boolean;
tags: string[];
}

View File

@@ -2,3 +2,4 @@ export * from './Model';
export * from './Snippet';
export * from './Tag';
export * from './Snippet_Tag';
export * from './Body';

39
src/utils/createTags.ts Normal file
View File

@@ -0,0 +1,39 @@
import { sequelize } from '../db';
import { QueryTypes } from 'sequelize';
import { TagModel, Snippet_TagModel } from '../models';
export const createTags = async (
parsedTags: Set<string>,
snippetId: number
): Promise<void> => {
// Get all tags
const rawAllTags = await sequelize.query<{ id: number; name: string }>(
`SELECT * FROM tags`,
{ type: QueryTypes.SELECT }
);
const parsedAllTags = rawAllTags.map(tag => tag.name);
// Create array of new tags
const newTags = [...parsedTags].filter(tag => !parsedAllTags.includes(tag));
// Create new tags
if (newTags.length > 0) {
for (const tag of newTags) {
const { id, name } = await TagModel.create({ name: tag });
rawAllTags.push({ id, name });
}
}
// Associate tags with snippet
for (const tag of parsedTags) {
const tagObj = rawAllTags.find(t => t.name == tag);
if (tagObj) {
await Snippet_TagModel.create({
snippet_id: snippetId,
tag_id: tagObj.id
});
}
}
};

View File

@@ -2,3 +2,4 @@ export * from './Logger';
export * from './ErrorResponse';
export * from './tagParser';
export * from './getTags';
export * from './createTags';