From 8fa017beedbaec0d3b8a90356071f697c777b16f Mon Sep 17 00:00:00 2001 From: Kurt Hutten Date: Sun, 8 Nov 2020 18:39:56 +1100 Subject: [PATCH] Allow for new parts to be created --- .vscode/settings.json | 3 ++- api/src/graphql/users.sdl.js | 2 +- api/src/services/users/users.js | 6 ++++- web/src/Routes.js | 1 + web/src/components/Part2Cell/Part2Cell.js | 24 ++++++++++++++++++- web/src/components/PartProfile/PartProfile.js | 5 ++-- web/src/layouts/MainLayout/MainLayout.js | 9 +++---- web/src/pages/NewPart2Page/NewPart2Page.js | 20 ++++++++++++++++ .../NewPart2Page/NewPart2Page.stories.js | 7 ++++++ .../pages/NewPart2Page/NewPart2Page.test.js | 11 +++++++++ 10 files changed, 78 insertions(+), 10 deletions(-) create mode 100644 web/src/pages/NewPart2Page/NewPart2Page.js create mode 100644 web/src/pages/NewPart2Page/NewPart2Page.stories.js create mode 100644 web/src/pages/NewPart2Page/NewPart2Page.test.js diff --git a/.vscode/settings.json b/.vscode/settings.json index 65a4f69..76d6767 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -17,6 +17,7 @@ "./web/src/Routes.js", ], "cSpell.words": [ - "Uploader" + "Uploader", + "redwoodjs" ] } diff --git a/api/src/graphql/users.sdl.js b/api/src/graphql/users.sdl.js index b714d64..1830193 100644 --- a/api/src/graphql/users.sdl.js +++ b/api/src/graphql/users.sdl.js @@ -9,7 +9,7 @@ export const schema = gql` image: String bio: String Parts: [Part]! - Part(partTitle: String!): Part + Part(partTitle: String): Part Reaction: [PartReaction]! Comment: [Comment]! } diff --git a/api/src/services/users/users.js b/api/src/services/users/users.js index f0c8a01..cae1557 100644 --- a/api/src/services/users/users.js +++ b/api/src/services/users/users.js @@ -1,6 +1,7 @@ import { db } from 'src/lib/db' import { requireAuth } from 'src/lib/auth' import { requireOwnership } from 'src/lib/owner' +import { UserInputError } from '@redwoodjs/api' export const users = () => { requireAuth({ role: 'admin' }) @@ -43,6 +44,9 @@ export const updateUserByUserName = async ({ userName, input }) => { if(input.userName) { input.userName = input.userName.replace(/([^a-zA-Z\d_:])/g, '-') } + if(input.userName && ['new', 'edit', 'update'].includes(input.userName)) { //TODO complete this and use a regexp so that it's not case sensitive, don't want someone with the userName eDiT + throw new UserInputError(`You've tried to used a protected word as you userName, try something other than `) + } return db.user.update({ data: input, where: { userName }, @@ -58,7 +62,7 @@ export const deleteUser = ({ id }) => { export const User = { Parts: (_obj, { root }) => db.user.findOne({ where: { id: root.id } }).Part(), - Part: (_obj, { root, ...rest }) => db.part.findOne({where: { title_userId: { + Part: (_obj, { root, ...rest }) => _obj.partTitle && db.part.findOne({where: { title_userId: { title: _obj.partTitle, userId: root.id, }}}), diff --git a/web/src/Routes.js b/web/src/Routes.js index 437b3e4..547071b 100644 --- a/web/src/Routes.js +++ b/web/src/Routes.js @@ -17,6 +17,7 @@ const Routes = () => { {/* Ownership enforced routes */} + {/* End ownership enforced routes */} diff --git a/web/src/components/Part2Cell/Part2Cell.js b/web/src/components/Part2Cell/Part2Cell.js index 6f1e886..a9016c4 100644 --- a/web/src/components/Part2Cell/Part2Cell.js +++ b/web/src/components/Part2Cell/Part2Cell.js @@ -5,7 +5,7 @@ import { useAuth } from '@redwoodjs/auth' import PartProfile from 'src/components/PartProfile' export const QUERY = gql` - query FIND_PART_BY_USERNAME_TITLE($userName: String!, $partTitle: String!, $currentUserId: String) { + query FIND_PART_BY_USERNAME_TITLE($userName: String!, $partTitle: String, $currentUserId: String) { userPart: userName(userName: $userName) { id name @@ -52,6 +52,18 @@ const UPDATE_PART_MUTATION = gql` } } ` +const CREATE_PART_MUTATION = gql` + mutation CreatePartMutation($input: CreatePartInput!) { + createPart(input: $input) { + id + title + user { + id + userName + } + } + } +` const TOGGLE_REACTION_MUTATION = gql` mutation ToggleReactionMutation($input: TogglePartReactionInput!) { togglePartReaction(input: $input){ @@ -84,7 +96,17 @@ export const Success = ({ userPart, variables: {isEditable}, refetch}) => { addMessage('Part updated.', { classes: 'rw-flash-success' }) }, }) + const [createUser] = useMutation(CREATE_PART_MUTATION, { + onCompleted: ({createPart}) => { + navigate(routes.part2({userName: createPart?.user?.userName, partTitle: createPart?.title})) + addMessage('Part Created.', { classes: 'rw-flash-success' }) + }, + }) const onSave = (id, input) => { + if(!id) { + createUser({ variables: { input } }) + return + } updateUser({ variables: { id, input } }) } diff --git a/web/src/components/PartProfile/PartProfile.js b/web/src/components/PartProfile/PartProfile.js index 874e0ad..9a7facc 100644 --- a/web/src/components/PartProfile/PartProfile.js +++ b/web/src/components/PartProfile/PartProfile.js @@ -33,6 +33,7 @@ const PartProfile = ({ title: part?.title, mainImage: part?.mainImage, description: part?.description, + userId: userPart?.id, }) const setProperty = (property, value) => setInput({ ...input, @@ -43,7 +44,7 @@ const PartProfile = ({ const onImageUpload = ({cloudinaryPublicId}) => setProperty('mainImage', cloudinaryPublicId) const onEditSaveClick = () => { if (isEditable) { - onSave(part.id, input) + input.title && onSave(part?.id, input) return } navigate(routes.editPart2({userName: userPart.userName, partTitle: part.title})) @@ -98,7 +99,7 @@ const PartProfile = ({ {/* main project center column */}
- { input?.mainImage && {
    -
  • - {/* */} - - {/* */} +
  • +
  • { isAuthenticated ? diff --git a/web/src/pages/NewPart2Page/NewPart2Page.js b/web/src/pages/NewPart2Page/NewPart2Page.js new file mode 100644 index 0000000..bd316a9 --- /dev/null +++ b/web/src/pages/NewPart2Page/NewPart2Page.js @@ -0,0 +1,20 @@ +import { useAuth } from '@redwoodjs/auth' + +import MainLayout from 'src/layouts/MainLayout' +import Part2Cell from 'src/components/Part2Cell' + + +const NewPart2Page = ({userName}) => { + const { currentUser } = useAuth() + return ( + + + + ) +} + +export default NewPart2Page diff --git a/web/src/pages/NewPart2Page/NewPart2Page.stories.js b/web/src/pages/NewPart2Page/NewPart2Page.stories.js new file mode 100644 index 0000000..71d540a --- /dev/null +++ b/web/src/pages/NewPart2Page/NewPart2Page.stories.js @@ -0,0 +1,7 @@ +import NewPart2Page from './NewPart2Page' + +export const generated = () => { + return +} + +export default { title: 'Pages/NewPart2Page' } diff --git a/web/src/pages/NewPart2Page/NewPart2Page.test.js b/web/src/pages/NewPart2Page/NewPart2Page.test.js new file mode 100644 index 0000000..439a42b --- /dev/null +++ b/web/src/pages/NewPart2Page/NewPart2Page.test.js @@ -0,0 +1,11 @@ +import { render } from '@redwoodjs/testing' + +import NewPart2Page from './NewPart2Page' + +describe('NewPart2Page', () => { + it('renders successfully', () => { + expect(() => { + render() + }).not.toThrow() + }) +})