Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 714793a

Browse files
Updating snippets with tags
1 parent 86ea246 commit 714793a

File tree

11 files changed

+97
-67
lines changed

11 files changed

+97
-67
lines changed

‎CHANGELOG.md‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
### v1.2 (2021年09月28日)
2+
- Added support for tags ([#10](https://github.com/pawelmalak/snippet-box/issues/10))
3+
14
### v1.1 (2021年09月24日)
25
- Added pin icon directly to snippet card ([#4](https://github.com/pawelmalak/snippet-box/issues/4))
36
- Fixed issue with copying snippets ([#6](https://github.com/pawelmalak/snippet-box/issues/6))

‎Dockerfile‎

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,8 @@ COPY . .
1010

1111
RUN mkdir -p ./public ./data
1212

13-
# Build server code
14-
RUN npm run build
15-
16-
# Build client code
17-
RUN cd ./client \
18-
&& npm install \
19-
&& npm run build \
20-
&& cd .. \
13+
# Build
14+
RUN npm run build \
2115
&& mv ./client/build/* ./public
2216

2317
# Clean up src files

‎Dockerfile.arm‎

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,8 @@ COPY . .
1212

1313
RUN mkdir -p ./public ./data
1414

15-
# Build server code
16-
RUN npm run build
17-
18-
# Build client code
19-
RUN cd ./client \
20-
&& npm install \
21-
&& npm run build \
22-
&& cd .. \
15+
# Build
16+
RUN npm run build \
2317
&& mv ./client/build/* ./public
2418

2519
# Clean up src files

‎client/src/components/Snippets/SnippetForm.tsx‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,10 @@ export const SnippetForm = (props: Props): JSX.Element => {
5454
});
5555
};
5656

57+
const tagsToString = (): string => {
58+
return formData.tags.join(',');
59+
};
60+
5761
const formHandler = (e: FormEvent) => {
5862
e.preventDefault();
5963

@@ -134,13 +138,13 @@ export const SnippetForm = (props: Props): JSX.Element => {
134138
className='form-control'
135139
id='tags'
136140
name='tags'
137-
// value={formData.tags}
141+
value={tagsToString()}
138142
placeholder='automation, files, loop'
139143
onChange={e => stringToTags(e)}
140144
/>
141145
<div className='form-text'>
142-
Tags should be separate with a comma. Language tag will be added
143-
automatically
146+
Tags should be separated with a comma. Language tag will be
147+
added automatically
144148
</div>
145149
</div>
146150
<hr />

‎client/src/store/SnippetsContext.tsx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,13 @@ export const SnippetsContextProvider = (props: Props): JSX.Element => {
5353
};
5454

5555
const setSnippet = (id: number): void => {
56-
getSnippetById(id);
57-
5856
if (id < 0) {
5957
setCurrentSnippet(null);
6058
return;
6159
}
6260

61+
getSnippetById(id);
62+
6363
const snippet = snippets.find(s => s.id === id);
6464

6565
if (snippet) {

‎package.json‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
"dev:client": "npm start --prefix=client",
1111
"dev:server": "nodemon",
1212
"dev": "npm-run-all -n --parallel dev:**",
13-
"build:client": "npm run build prefix=client",
13+
"build:client": "npm run build --prefix=client",
1414
"build:clear": "rm -rf build",
1515
"build:tsc": "tsc",
1616
"build": "npm-run-all -n build:**"

‎src/controllers/snippets.ts‎

Lines changed: 30 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,15 @@ import { Request, Response, NextFunction } from 'express';
22
import { QueryTypes } from 'sequelize';
33
import { sequelize } from '../db';
44
import { asyncWrapper } from '../middleware';
5+
import { SnippetModel, Snippet_TagModel } from '../models';
56
import {
6-
SnippetInstance,
7-
SnippetModel,
8-
Snippet_TagModel,
9-
TagModel
10-
} from '../models';
11-
import { ErrorResponse, getTags, tagParser, Logger } from '../utils';
7+
ErrorResponse,
8+
getTags,
9+
tagParser,
10+
Logger,
11+
createTags
12+
} from '../utils';
13+
import { Body } from '../typescript/interfaces';
1214

1315
const logger = new Logger('snippets-controller');
1416

@@ -19,11 +21,6 @@ const logger = new Logger('snippets-controller');
1921
*/
2022
export const createSnippet = asyncWrapper(
2123
async (req: Request, res: Response, next: NextFunction): Promise<void> => {
22-
interface Body {
23-
language: string;
24-
tags: string[];
25-
}
26-
2724
// Get tags from request body
2825
const { language, tags: requestTags } = <Body>req.body;
2926
const parsedRequestTags = tagParser([
@@ -37,38 +34,8 @@ export const createSnippet = asyncWrapper(
3734
tags: [...parsedRequestTags].join(',')
3835
});
3936

40-
// Get all tags
41-
const rawAllTags = await sequelize.query<{ id: number; name: string }>(
42-
`SELECT * FROM tags`,
43-
{ type: QueryTypes.SELECT }
44-
);
45-
46-
const parsedAllTags = rawAllTags.map(tag => tag.name);
47-
48-
// Create array of new tags
49-
const newTags = [...parsedRequestTags].filter(
50-
tag => !parsedAllTags.includes(tag)
51-
);
52-
53-
// Create new tags
54-
if (newTags.length > 0) {
55-
for (const tag of newTags) {
56-
const { id, name } = await TagModel.create({ name: tag });
57-
rawAllTags.push({ id, name });
58-
}
59-
}
60-
61-
// Associate tags with snippet
62-
for (const tag of parsedRequestTags) {
63-
const tagObj = rawAllTags.find(t => t.name == tag);
64-
65-
if (tagObj) {
66-
await Snippet_TagModel.create({
67-
snippet_id: snippet.id,
68-
tag_id: tagObj.id
69-
});
70-
}
71-
}
37+
// Create tags
38+
await createTags(parsedRequestTags, snippet.id);
7239

7340
// Get raw snippet values
7441
const rawSnippet = snippet.get({ plain: true });
@@ -162,10 +129,28 @@ export const updateSnippet = asyncWrapper(
162129
);
163130
}
164131

165-
snippet = await snippet.update(req.body);
132+
// Get tags from request body
133+
const { language, tags: requestTags } = <Body>req.body;
134+
let parsedRequestTags = tagParser([...requestTags, language.toLowerCase()]);
135+
136+
// Update snippet
137+
snippet = await snippet.update({
138+
...req.body,
139+
tags: [...parsedRequestTags].join(',')
140+
});
141+
142+
// Delete old tags and create new ones
143+
await Snippet_TagModel.destroy({ where: { snippet_id: req.params.id } });
144+
await createTags(parsedRequestTags, snippet.id);
145+
146+
// Get raw snippet values
147+
const rawSnippet = snippet.get({ plain: true });
166148

167149
res.status(200).json({
168-
data: snippet
150+
data: {
151+
...rawSnippet,
152+
tags: [...parsedRequestTags]
153+
}
169154
});
170155
}
171156
);

‎src/typescript/interfaces/Body.ts‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
export interface Body {
2+
title: string;
3+
description?: string;
4+
language: string;
5+
code: string;
6+
docs?: string;
7+
isPinned: boolean;
8+
tags: string[];
9+
}

‎src/typescript/interfaces/index.ts‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export * from './Model';
22
export * from './Snippet';
33
export * from './Tag';
44
export * from './Snippet_Tag';
5+
export * from './Body';

‎src/utils/createTags.ts‎

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import { sequelize } from '../db';
2+
import { QueryTypes } from 'sequelize';
3+
import { TagModel, Snippet_TagModel } from '../models';
4+
5+
export const createTags = async (
6+
parsedTags: Set<string>,
7+
snippetId: number
8+
): Promise<void> => {
9+
// Get all tags
10+
const rawAllTags = await sequelize.query<{ id: number; name: string }>(
11+
`SELECT * FROM tags`,
12+
{ type: QueryTypes.SELECT }
13+
);
14+
15+
const parsedAllTags = rawAllTags.map(tag => tag.name);
16+
17+
// Create array of new tags
18+
const newTags = [...parsedTags].filter(tag => !parsedAllTags.includes(tag));
19+
20+
// Create new tags
21+
if (newTags.length > 0) {
22+
for (const tag of newTags) {
23+
const { id, name } = await TagModel.create({ name: tag });
24+
rawAllTags.push({ id, name });
25+
}
26+
}
27+
28+
// Associate tags with snippet
29+
for (const tag of parsedTags) {
30+
const tagObj = rawAllTags.find(t => t.name == tag);
31+
32+
if (tagObj) {
33+
await Snippet_TagModel.create({
34+
snippet_id: snippetId,
35+
tag_id: tagObj.id
36+
});
37+
}
38+
}
39+
};

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /