Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions backend/.gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
.idea
node_modules
lib
.env
dev.env

dev.env
dev.env
4 changes: 2 additions & 2 deletions backend/test.env
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
TOKEN_SECRET=TEST123456
NEO4J_URI=bolt://34.239.207.33:32848
NEO4J_URI=bolt://100.26.212.97:32898
NEO4J_USER=neo4j
NEO4J_PASSWORD=discriminations-beginners-tubes
NEO4J_PASSWORD=journals-knives-employee
NEO4J_DATABASE=
3 changes: 3 additions & 0 deletions no-nuxt-pls/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -88,3 +88,6 @@ sw.*

# Vim swap files
*.swp

.nuxt-storybook
storybook-static
42 changes: 29 additions & 13 deletions no-nuxt-pls/README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,36 @@
# no-nuxt-pls

## Build Setup

```bash
# install dependencies
$ npm install

# serve with hot reload at localhost:3000
$ npm run dev
## Installation
Run
```
npm install
```
to install all depedencies. But be warned it will install ~3200 packages
that are able to break you project without you beeing able to find the issues
easily. Your file manager will love it.

# build for production and launch server
$ npm run build
$ npm run start
## Run Developer Mode
You can start a dev server with hot reload by running:
```
npm run dev
```

# generate static project
$ npm run generate
## Build and Deploy
To build the project for deployment run:
```
npm run build
```
in your project directory.
If you have not generated the static project before run:
```
npm run generate
```
but be careful it takes 100 hours to generate for a simple hello world site.
That's called efficency and good design.
Finally you can start the project with:
```
npm run start
```

## Details
For detailed explanation on how things work, check out [Nuxt.js docs](https://nuxtjs.org).
89 changes: 89 additions & 0 deletions no-nuxt-pls/components/LoginForm/LoginForm.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
<template>
<form class="login-form" @submit.prevent="submitLogin">
<fieldset>
<legend>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🚀 For using semantic html.

Login
</legend>
<div>
<label for="email">E-Mail:</label>
<input
id="email"
v-model="email"
type="email"
name="email"
size="25"
/>
</div>
<div>
<label for="password">Password:</label>
<input
id="password"
v-model="password"
type="password"
name="password"
size="25"
/>
</div>
<div v-if="error" class="error">
{{ error.message }}
</div>
<div>
<button type="submit">Login</button>
</div>
</fieldset>
</form>
</template>

<script>
import gql from 'graphql-tag';
import { mapActions } from 'vuex';
const LOGIN_MUTATION = gql`mutation ($email: String!, $password: String!){ login(email: $email, password: $password) }`;
export default {
data() {
return {
error: null,
email: '',
password: '',
}
},
methods: {
...mapActions('auth', ['login']),
async submitLogin() {
const { email, password } = this;
const { data } = await this.$apollo.mutate({mutation: LOGIN_MUTATION, variables: { email, password }});
if (data.login) {
await this.$apolloHelpers.onLogin(data.login);
await this.$router.push('/');
} else {
this.error = { message: 'Oops! Something went wrong.' };
}
}
}
}
/*
@Component
export default class LoginForm extends Vue {
@Prop() public token: string = this.$store.state.auth.token;
public email: string = '';
public password: string = '';
@Action('auth')
async submitLogin(): Promise<void> {
const { login } = await this.$a
const res = await this.$apollo.mutate({mutation: gql`mutation ($email: String!, $password: String!){
login(email: $email, password: $password)
}`, variables: {email: this.email, password: this.password}}).then((data: any) => data.login as string);
await this.$app.$apolloHelpers.onLogin(res);
this.$store.commit('login', { email: this.email, password: this.password });
}
}; */
</script>

<style scoped>
</style>
Comment on lines +67 to +89
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
/*
@Component
export default class LoginForm extends Vue {
@Prop() public token: string = this.$store.state.auth.token;
public email: string = '';
public password: string = '';
@Action('auth')
async submitLogin(): Promise<void> {
const { login } = await this.$a
const res = await this.$apollo.mutate({mutation: gql`mutation ($email: String!, $password: String!){
login(email: $email, password: $password)
}`, variables: {email: this.email, password: this.password}}).then((data: any) => data.login as string);
await this.$app.$apolloHelpers.onLogin(res);
this.$store.commit('login', { email: this.email, password: this.password });
}
}; */
</script>
<style scoped>
</style>

git?

77 changes: 77 additions & 0 deletions no-nuxt-pls/components/Menu/Menu.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
<template>
<nav class="bg-gray-800">
<div class="max-w-7xl mx-auto px-2 sm:px-6 lg:px-8">
<div class="relative flex items-center justify-between h-16">
<div class="absolute inset-y-0 left-0 flex items-center sm:hidden">
<button @click="burgerShow = !burgerShow" class="inline-flex items-center justify-center p-2 rounded-md text-gray-400 hover:text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-inset focus:ring-white" aria-expanded="false">
<span class="sr-only">Open main menu</span>
<svg class="block h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 6h16M4 12h16M4 18h16" />
</svg>
<svg class="hidden h-6 w-6" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
<div class="absolute inset-y-auto right-0 hidden sm:block sm:ml-6">
<template v-if="token">
<button class="text-gray-300 bg-gray-600 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium" @click="logout">Logout</button>
</template>
<template v-else>
<span class="text-gray-300 p-3">You are not logged in.</span>
<button class="text-gray-300 bg-gray-600 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium"><nuxt-link to="/Login">Login</nuxt-link></button>
</template>
</div>
</div>
</div>
<transition name="burger">
<div v-show="burgerShow" class="visible md:hidden">
<div class="px-2 pt-2 pb-3 space-y-1">
<div v-if="token">
<button class="text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium" @click="logout">Logout</button>
</div>
<div v-else>
<button class="text-gray-300 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium"><nuxt-link to="/Login">Login</nuxt-link></button>
</div>
</div>
</div>
</transition>
</nav>
</template>

<script>
export default {
data() {
return {
token: '',
burgerShow: false,
}
},
mounted() {
this.setupMenu();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a better way to do this which also supports server-side-rendering. See step 5: https://github.com/Systems-Development-and-Frameworks/homework/tree/main/exercises/7#instructions

Setting the token in mounted will make the unauthenticated page is visible for a second. Plus, you get this nasty "boiling hydration" runtime error.

},
methods: {
setupMenu(){
this.token = this.$apolloHelpers.getToken();
},
logout() {
this.token = null;
this.$apolloHelpers.onLogout();
window.location.reload(false);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to avoid window and document because of SSR. This might not be a problem here, but it's good practice to simply avoid it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, I don't understand why you reload the page. The authentication state should be reactive and components should react to it.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forcing a page reload contradicts the whole purpose of using a SPA.

},
},
};
</script>

<style>
.burger-enter-active, .burger-leave-active {
transition: all 0.5s;
}
.burger-enter, .burger-leave-to {
opacity: 0;
}
</style>
4 changes: 2 additions & 2 deletions no-nuxt-pls/components/NewsForm/NewsForm.vue
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<template>
<form aria-label="Create NewsItem" @submit.prevent="submitTitle">
<input aria-label="CreateTitle" type="text" v-model="title" placeholder="Type title here">
<button type="submit">Create</button>
<input class="border border-grey-light" aria-label="CreateTitle" type="text" v-model="title" placeholder="Type title here">
<button class="text-white bg-green-500 hover:bg-green-800 hover:text-white px-3 py-2 rounded-md text-sm font-medium" type="submit">Create</button>
</form>
</template>

Expand Down
39 changes: 34 additions & 5 deletions no-nuxt-pls/components/NewsItem/NewsItem.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,42 @@
<template>
<div>
<h2>{{news.title}} ({{news.votes}})</h2>
<h2 class="text-xl text-center font-bold leading-7 text-gray-900 sm:text-2xl sm:truncate">{{news.title}} ({{news.votes}})</h2>
<br>
<button @click="updateNews(1)">Upvote</button>
<button @click="updateNews(-1)">Downvote</button>
<button @click="deleteNews">Remove</button>
<p>
Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce consequat pulvinar convallis. Vivamus iaculis,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because you seem to be such a big fan of deeply nested npm dependencies: You know lorem-ipsum? https://github.com/knicklabs/lorem-ipsum.js#readme
Even more: https://github.com/templeman/awesome-ipsum

odio ut ornare dignissim, dui nunc sollicitudin metus, quis pellentesque dui orci nec leo. Aliquam imperdiet
quam sit amet orci molestie convallis. Nullam odio ex, ornare vel efficitur laoreet, suscipit eu odio. Aliquam
ac nisi vitae leo fermentum mollis. Orci varius natoque penatibus et magnis dis parturient montes, nascetur
ridiculus mus. Sed suscipit nulla nisl, vel dictum ex blandit nec. Nunc interdum nunc risus, ut molestie lacus
sollicitudin sit amet. Phasellus ut nibh tortor.
</p>
<br>
<button class="text-black bg-gray-200 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium" v-if="token" @click="updateNews(1)">Upvote</button>
<button class="text-black bg-gray-200 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium" v-if="token" @click="updateNews(-1)">Downvote</button>
<button class="text-black bg-gray-200 hover:bg-gray-700 hover:text-white px-3 py-2 rounded-md text-sm font-medium" v-if="authorId === news.author.id">Edit</button>
<button class="text-black bg-red-300 hover:bg-red-600 hover:text-white px-3 py-2 rounded-md text-sm font-medium" v-if="authorId === news.author.id" @click="deleteNews">Delete</button>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's where I get the following error:

client.js?06a0:97 TypeError: Cannot read property 'id' of undefined
    at Proxy.render (NewsItem.vue?a1bb:57)
    at VueComponent.Vue._render (vue.runtime.esm.js?2b0e:3548)
    at VueComponent.updateComponent (vue.runtime.esm.js?2b0e:4055)
    at Watcher.get (vue.runtime.esm.js?2b0e:4479)
    at new Watcher (vue.runtime.esm.js?2b0e:4468)
    at mountComponent (vue.runtime.esm.js?2b0e:4073)
    at VueComponent.Vue.$mount (vue.runtime.esm.js?2b0e:8415)
    at init (vue.runtime.esm.js?2b0e:3118)
    at createComponent (vue.runtime.esm.js?2b0e:5978)
    at createElm (vue.runtime.esm.js?2b0e:5925)

</div>
</template>

<script lang="ts">
<script>

export default {
props: {
news: Object,
token: String,
authorId: String,
},

methods: {
updateNews(value) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You have a bug here. Clicking downvote and upvote has the same effect.

this.$emit('update', this.news);
},
deleteNews() {
this.$emit('remove', this.news);
}
}
}
/*
import { Vue, Component, Prop, Emit } from 'nuxt-property-decorator';
import { Item } from '@/interface/item';

Expand All @@ -27,6 +55,7 @@ export default class NewsItem extends Vue {
}

}
*/
</script>

<style scoped>
Expand Down
Loading