mirror of
https://github.com/Ocelot-Social-Community/Ocelot-Social.git
synced 2025-12-12 23:35:58 +00:00
hc experiment progress
This commit is contained in:
commit
4dbe142dcb
13
.editorconfig
Normal file
13
.editorconfig
Normal file
@ -0,0 +1,13 @@
|
||||
# editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
4
.eslintignore
Normal file
4
.eslintignore
Normal file
@ -0,0 +1,4 @@
|
||||
node_modules
|
||||
build
|
||||
.nuxt
|
||||
cypress/
|
||||
24
.eslintrc.js
Normal file
24
.eslintrc.js
Normal file
@ -0,0 +1,24 @@
|
||||
module.exports = {
|
||||
root: true,
|
||||
env: {
|
||||
browser: true,
|
||||
node: true
|
||||
},
|
||||
parserOptions: {
|
||||
parser: 'babel-eslint'
|
||||
},
|
||||
extends: [
|
||||
'plugin:vue/recommended',
|
||||
'plugin:prettier/recommended'
|
||||
],
|
||||
// required to lint *.vue files
|
||||
plugins: [
|
||||
'vue',
|
||||
'prettier'
|
||||
],
|
||||
// add your custom rules here
|
||||
rules: {
|
||||
'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off',
|
||||
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
|
||||
}
|
||||
}
|
||||
81
.gitignore
vendored
Normal file
81
.gitignore
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
# Created by .ignore support plugin (hsz.mobi)
|
||||
### Node template
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
# nuxt.js build output
|
||||
.nuxt
|
||||
|
||||
# Nuxt generate
|
||||
dist
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# Serverless directories
|
||||
.serverless
|
||||
|
||||
# IDE
|
||||
.idea
|
||||
6
.prettierrc
Normal file
6
.prettierrc
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"semi": false,
|
||||
"singleQuote": true,
|
||||
"tabWidth": 2,
|
||||
"bracketSpacing": true
|
||||
}
|
||||
21
README.md
Normal file
21
README.md
Normal file
@ -0,0 +1,21 @@
|
||||
# graphql-ui
|
||||
|
||||
> Human Connection GraphQL UI Prototype
|
||||
|
||||
## Build Setup
|
||||
|
||||
``` bash
|
||||
# install dependencies
|
||||
$ yarn install
|
||||
|
||||
# serve with hot reload at localhost:3000
|
||||
$ yarn run dev
|
||||
|
||||
# build for production and launch server
|
||||
$ yarn run build
|
||||
$ yarn start
|
||||
```
|
||||
|
||||
## Styleguide
|
||||
|
||||
All reusable Components (for example avatar) should be done inside the
|
||||
7
assets/README.md
Normal file
7
assets/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# ASSETS
|
||||
|
||||
**This directory is not required, you can delete it if you don't want to use it.**
|
||||
|
||||
This directory contains your un-compiled assets such as LESS, SASS, or JavaScript.
|
||||
|
||||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked).
|
||||
79
components/Logo.vue
Normal file
79
components/Logo.vue
Normal file
@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<div class="VueToNuxtLogo">
|
||||
<div class="Triangle Triangle--two"/>
|
||||
<div class="Triangle Triangle--one"/>
|
||||
<div class="Triangle Triangle--three"/>
|
||||
<div class="Triangle Triangle--four"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style>
|
||||
.VueToNuxtLogo {
|
||||
display: inline-block;
|
||||
animation: turn 2s linear forwards 1s;
|
||||
transform: rotateX(180deg);
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
height: 180px;
|
||||
width: 245px;
|
||||
}
|
||||
|
||||
.Triangle {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 0;
|
||||
height: 0;
|
||||
}
|
||||
|
||||
.Triangle--one {
|
||||
border-left: 105px solid transparent;
|
||||
border-right: 105px solid transparent;
|
||||
border-bottom: 180px solid #41b883;
|
||||
}
|
||||
|
||||
.Triangle--two {
|
||||
top: 30px;
|
||||
left: 35px;
|
||||
animation: goright 0.5s linear forwards 3.5s;
|
||||
border-left: 87.5px solid transparent;
|
||||
border-right: 87.5px solid transparent;
|
||||
border-bottom: 150px solid #3b8070;
|
||||
}
|
||||
|
||||
.Triangle--three {
|
||||
top: 60px;
|
||||
left: 35px;
|
||||
animation: goright 0.5s linear forwards 3.5s;
|
||||
border-left: 70px solid transparent;
|
||||
border-right: 70px solid transparent;
|
||||
border-bottom: 120px solid #35495e;
|
||||
}
|
||||
|
||||
.Triangle--four {
|
||||
top: 120px;
|
||||
left: 70px;
|
||||
animation: godown 0.5s linear forwards 3s;
|
||||
border-left: 35px solid transparent;
|
||||
border-right: 35px solid transparent;
|
||||
border-bottom: 60px solid #fff;
|
||||
}
|
||||
|
||||
@keyframes turn {
|
||||
100% {
|
||||
transform: rotateX(0deg);
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes godown {
|
||||
100% {
|
||||
top: 180px;
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes goright {
|
||||
100% {
|
||||
left: 70px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
7
components/README.md
Normal file
7
components/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# COMPONENTS
|
||||
|
||||
**This directory is not required, you can delete it if you don't want to use it.**
|
||||
|
||||
The components directory contains your Vue.js Components.
|
||||
|
||||
_Nuxt.js doesn't supercharge these components._
|
||||
7
layouts/README.md
Normal file
7
layouts/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# LAYOUTS
|
||||
|
||||
**This directory is not required, you can delete it if you don't want to use it.**
|
||||
|
||||
This directory contains your Application Layouts.
|
||||
|
||||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/views#layouts).
|
||||
61
layouts/default.vue
Normal file
61
layouts/default.vue
Normal file
@ -0,0 +1,61 @@
|
||||
<template>
|
||||
<div>
|
||||
<div class="main-navigation">
|
||||
<ds-container style="padding: .5rem 3rem .2rem;">
|
||||
<a
|
||||
v-router-link
|
||||
href="/">
|
||||
<ds-logo />
|
||||
</a>
|
||||
</ds-container>
|
||||
</div>
|
||||
<ds-container>
|
||||
<div style="padding: 5rem 2rem;">
|
||||
<nuxt/>
|
||||
</div>
|
||||
</ds-container>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss">
|
||||
@import 'vue-cion-design-system/src/system/tokens/generated/tokens.scss';
|
||||
|
||||
// Transition Easing
|
||||
$easeOut: cubic-bezier(0.19, 1, 0.22, 1);
|
||||
|
||||
.layout-enter-active {
|
||||
transition: opacity 80ms ease-out;
|
||||
transition-delay: 80ms;
|
||||
}
|
||||
.layout-leave-active {
|
||||
transition: opacity 80ms ease-in;
|
||||
}
|
||||
.layout-enter,
|
||||
.layout-leave-active {
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
// slide up ease
|
||||
.slide-up-enter-active {
|
||||
transition: all 500ms $easeOut;
|
||||
transition-delay: 20ms;
|
||||
opacity: 1;
|
||||
transform: translate3d(0, 0, 0);
|
||||
}
|
||||
.slide-up-enter,
|
||||
.slide-up-leave-active {
|
||||
opacity: 0;
|
||||
box-shadow: none;
|
||||
transform: translate3d(0, 15px, 0);
|
||||
}
|
||||
|
||||
.main-navigation {
|
||||
background: #fff;
|
||||
}
|
||||
|
||||
.tags {
|
||||
.ds-tag {
|
||||
margin-right: $space-xx-small;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
8
middleware/README.md
Normal file
8
middleware/README.md
Normal file
@ -0,0 +1,8 @@
|
||||
# MIDDLEWARE
|
||||
|
||||
**This directory is not required, you can delete it if you don't want to use it.**
|
||||
|
||||
This directory contains your application middleware.
|
||||
The middleware lets you define custom function to be ran before rendering a page or a group of pages (layouts).
|
||||
|
||||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing#middleware).
|
||||
148
nuxt.config.js
Normal file
148
nuxt.config.js
Normal file
@ -0,0 +1,148 @@
|
||||
const pkg = require('./package')
|
||||
|
||||
module.exports = {
|
||||
mode: 'universal',
|
||||
|
||||
transition: {
|
||||
name: 'slide-up',
|
||||
mode: 'out-in'
|
||||
},
|
||||
/*
|
||||
** Headers of the page
|
||||
*/
|
||||
head: {
|
||||
title: 'Human Connection',
|
||||
titleTemplate: '%s - Human Connection',
|
||||
meta: [
|
||||
{ charset: 'utf-8' },
|
||||
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
|
||||
{ hid: 'description', name: 'description', content: pkg.description }
|
||||
],
|
||||
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }]
|
||||
},
|
||||
|
||||
/*
|
||||
** Customize the progress-bar color
|
||||
*/
|
||||
loading: {
|
||||
color: '#86b31e',
|
||||
height: '2px',
|
||||
duration: 20000
|
||||
},
|
||||
|
||||
/*
|
||||
** Global CSS
|
||||
*/
|
||||
css: [],
|
||||
|
||||
/*
|
||||
** Plugins to load before mounting the App
|
||||
*/
|
||||
plugins: [
|
||||
{ src: '~/plugins/design-system.js', ssr: true },
|
||||
{ src: '~/plugins/vue-directives.js', ssr: false }
|
||||
],
|
||||
|
||||
router: {
|
||||
// middleware: [
|
||||
// 'maintenance',
|
||||
// 'check-auth',
|
||||
// 'authenticated'
|
||||
// ],
|
||||
linkActiveClass: 'router-active-link'
|
||||
},
|
||||
/* router: {
|
||||
routes: [
|
||||
{
|
||||
name: 'index',
|
||||
path: '/',
|
||||
component: 'pages/index.vue'
|
||||
},
|
||||
{
|
||||
name: 'post-slug',
|
||||
path: '/post/:slug',
|
||||
component: 'pages/post/_slug.vue',
|
||||
children: [
|
||||
{
|
||||
path: 'more-info',
|
||||
component: 'pages/post/_slug.vue'
|
||||
},
|
||||
{
|
||||
path: 'take-action',
|
||||
component: 'pages/post/_slug.vue'
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}, */
|
||||
|
||||
/*
|
||||
** Nuxt.js modules
|
||||
*/
|
||||
modules: ['@nuxtjs/apollo'],
|
||||
|
||||
// Give apollo module options
|
||||
apollo: {
|
||||
tokenName: 'yourApolloTokenName', // optional, default: apollo-token
|
||||
tokenExpires: 10, // optional, default: 7 (days)
|
||||
includeNodeModules: true, // optional, default: false (this includes graphql-tag for node_modules folder)
|
||||
authenticationType: 'Basic', // optional, default: 'Bearer'
|
||||
// optional
|
||||
errorHandler(error) {
|
||||
console.log(
|
||||
'%cError',
|
||||
'background: red; color: white; padding: 2px 4px; border-radius: 3px; font-weight: bold;',
|
||||
error.message
|
||||
)
|
||||
},
|
||||
// required
|
||||
clientConfigs: {
|
||||
default: {
|
||||
// required
|
||||
httpEndpoint: 'http://localhost:4000',
|
||||
// optional
|
||||
// See https://www.apollographql.com/docs/link/links/http.html#options
|
||||
httpLinkOptions: {
|
||||
credentials: 'same-origin'
|
||||
},
|
||||
// You can use `wss` for secure connection (recommended in production)
|
||||
// Use `null` to disable subscriptions
|
||||
// wsEndpoint: 'ws://localhost:4000', // optional
|
||||
// LocalStorage token
|
||||
tokenName: 'apollo-token', // optional
|
||||
// Enable Automatic Query persisting with Apollo Engine
|
||||
persisting: false, // Optional
|
||||
// Use websockets for everything (no HTTP)
|
||||
// You need to pass a `wsEndpoint` for this to work
|
||||
websocketsOnly: false // Optional
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
manifest: {
|
||||
name: 'Human-Connection.org',
|
||||
description: 'Human-Connection.org',
|
||||
theme_color: '#ffffff',
|
||||
lang: 'de'
|
||||
},
|
||||
|
||||
/*
|
||||
** Build configuration
|
||||
*/
|
||||
build: {
|
||||
/*
|
||||
** You can extend webpack config here
|
||||
*/
|
||||
extend(config, ctx) {
|
||||
// Run ESLint on save
|
||||
if (ctx.isDev && ctx.isClient) {
|
||||
config.module.rules.push({
|
||||
enforce: 'pre',
|
||||
test: /\.(js|vue)$/,
|
||||
loader: 'eslint-loader',
|
||||
exclude: /(node_modules)/
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
package.json
Normal file
37
package.json
Normal file
@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "hc-webapp-next",
|
||||
"version": "1.0.0",
|
||||
"description": "Human Connection GraphQL UI Prototype",
|
||||
"author": "Grzegorz Leoniec",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"dev": "cross-env NODE_ENV=development nodemon server/index.js --watch server",
|
||||
"build": "nuxt build",
|
||||
"start": "cross-env NODE_ENV=production node server/index.js",
|
||||
"generate": "nuxt generate",
|
||||
"lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
|
||||
"styleguide": "(cd ./styleguide && yarn dev)",
|
||||
"styleguide:build": "(cd ./styleguide && yarn build:lib) && yarn upgrade file:./styleguide",
|
||||
"precommit": "npm run lint"
|
||||
},
|
||||
"dependencies": {
|
||||
"@nuxtjs/apollo": "^4.0.0-rc3",
|
||||
"cross-env": "^5.2.0",
|
||||
"express": "^4.16.3",
|
||||
"graphql-tag": "^2.10.0",
|
||||
"nuxt": "^2.0.0",
|
||||
"vue-cion-design-system": "file:./styleguide"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^10.0.1",
|
||||
"eslint": "^5.0.1",
|
||||
"eslint-config-prettier": "^3.1.0",
|
||||
"eslint-loader": "^2.0.0",
|
||||
"eslint-plugin-prettier": "3.0.0",
|
||||
"eslint-plugin-vue": "^4.0.0",
|
||||
"node-sass": "^4.9.3",
|
||||
"nodemon": "^1.11.0",
|
||||
"prettier": "1.14.3",
|
||||
"sass-loader": "^7.1.0"
|
||||
}
|
||||
}
|
||||
6
pages/README.md
Normal file
6
pages/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
# PAGES
|
||||
|
||||
This directory contains your Application Views and Routes.
|
||||
The framework reads all the `*.vue` files inside this directory and create the router of your application.
|
||||
|
||||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/routing).
|
||||
115
pages/index.vue
Normal file
115
pages/index.vue
Normal file
@ -0,0 +1,115 @@
|
||||
<template>
|
||||
<div>
|
||||
<no-ssr>
|
||||
<ds-flex
|
||||
:width="{ base: '100%' }"
|
||||
gutter="base">
|
||||
<ds-flex-item
|
||||
v-for="post in Post"
|
||||
:width="{ base: '100%', xs: '100%', md: '50%', xl: '33%' }"
|
||||
:key="post.id">
|
||||
<a
|
||||
v-router-link
|
||||
:href="href(post)"
|
||||
>
|
||||
<ds-card
|
||||
:header="post.title"
|
||||
:image="post.image"
|
||||
style="cursor: pointer">
|
||||
<ds-avatar
|
||||
:image="post.author.User.avatar"
|
||||
size="32px" /> <b class="username">{{ post.author.User.name }}</b>
|
||||
<ds-space />
|
||||
<div v-html="post.contentExcerpt" />
|
||||
<template slot="footer">
|
||||
<span>
|
||||
<ds-icon name="comments" /> <small v-if="post.commentsCount">{{ post.commentsCount }}</small>
|
||||
</span>
|
||||
|
||||
<span>
|
||||
<ds-icon name="heart-o" /> <small v-if="post.shoutedCount">{{ post.shoutedCount }}</small>
|
||||
</span>
|
||||
</template>
|
||||
</ds-card>
|
||||
</a>
|
||||
</ds-flex-item>
|
||||
</ds-flex>
|
||||
</no-ssr>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
// Initialize your apollo data
|
||||
Post: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
tags() {
|
||||
return this.Post ? this.Post[0].tags.map(tag => tag.name) : '-'
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
href(post) {
|
||||
return this.$router.resolve({
|
||||
name: 'post-slug',
|
||||
params: { slug: post.slug }
|
||||
}).href
|
||||
}
|
||||
},
|
||||
apollo: {
|
||||
Post: {
|
||||
query: gql(`
|
||||
query {
|
||||
Post {
|
||||
id
|
||||
title
|
||||
contentExcerpt
|
||||
slug
|
||||
image
|
||||
author {
|
||||
User {
|
||||
avatar
|
||||
slug
|
||||
name
|
||||
}
|
||||
}
|
||||
tags {
|
||||
name
|
||||
}
|
||||
commentsCount
|
||||
comments(orderBy: _id_desc) {
|
||||
id
|
||||
content
|
||||
author {
|
||||
User {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
categories {
|
||||
name
|
||||
}
|
||||
shoutedCount
|
||||
shoutedBy {
|
||||
name
|
||||
friends {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
variables() {
|
||||
return {
|
||||
id: this.$route.query.post || 'p1'
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
56
pages/post/_slug.vue
Normal file
56
pages/post/_slug.vue
Normal file
@ -0,0 +1,56 @@
|
||||
<template>
|
||||
<div>
|
||||
<no-ssr>
|
||||
<ds-flex gutter="small">
|
||||
<ds-flex-item>
|
||||
<transition
|
||||
name="slide-up"
|
||||
appear>
|
||||
<nuxt-child />
|
||||
</transition>
|
||||
</ds-flex-item>
|
||||
<ds-flex-item :width="{ base: '200px' }">
|
||||
<ds-menu
|
||||
:routes="routes" />
|
||||
</ds-flex-item>
|
||||
</ds-flex>
|
||||
</no-ssr>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
routes: [
|
||||
{
|
||||
name: 'Post',
|
||||
path: `/post/${this.$route.params.slug}`,
|
||||
children: [
|
||||
{
|
||||
name: 'Kommentare',
|
||||
path: `/post/${this.$route.params.slug}#comments`
|
||||
},
|
||||
{
|
||||
name: 'Miteinandere reden',
|
||||
path: `/post/${this.$route.params.slug}#lets-talk`
|
||||
},
|
||||
{
|
||||
name: 'Versus',
|
||||
path: `/post/${this.$route.params.slug}#versus`
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
name: 'Mehr Info',
|
||||
path: `/post/${this.$route.params.slug}/more-info`
|
||||
},
|
||||
{
|
||||
name: 'Aktiv werden',
|
||||
path: `/post/${this.$route.params.slug}/take-action`
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
189
pages/post/_slug/index.vue
Normal file
189
pages/post/_slug/index.vue
Normal file
@ -0,0 +1,189 @@
|
||||
<template>
|
||||
<ds-card
|
||||
v-if="post"
|
||||
:image="post.image"
|
||||
:header="post.title"
|
||||
class="post-card">
|
||||
<a
|
||||
v-router-link
|
||||
:href="$router.resolve({ name: 'profile-slug', params: { slug: post.author.User.slug } }).href">
|
||||
<ds-avatar
|
||||
:image="post.author.User.avatar"
|
||||
size="32px" /> <b class="username">{{ post.author.User.name }}</b>
|
||||
</a>
|
||||
<ds-space margin-bottom="small" />
|
||||
<div
|
||||
class="content"
|
||||
v-html="post.content" />
|
||||
<ds-space margin-top="large"/>
|
||||
<div class="tags">
|
||||
<ds-icon name="compass" /> <ds-tag
|
||||
v-for="category in post.categories"
|
||||
:key="category.id">{{ category.name }}</ds-tag>
|
||||
</div>
|
||||
<template v-if="post.tags && post.tags.length">
|
||||
<div class="tags">
|
||||
<ds-icon name="tags" /> <ds-tag
|
||||
v-for="tag in post.tags"
|
||||
:key="tag.id"><ds-icon name="tag" /> {{ tag.name }}</ds-tag>
|
||||
</div>
|
||||
</template>
|
||||
<ds-space margin-bottom="large" />
|
||||
<ds-section
|
||||
slot="footer">
|
||||
<h3 style="margin-top: 0;">
|
||||
<span>
|
||||
<ds-icon name="comments" />
|
||||
<ds-tag
|
||||
v-if="post.commentsCount"
|
||||
style="transform: scale(.8); margin-top: -4px; margin-left: -12px; position: absolute;"
|
||||
color="primary"
|
||||
round>
|
||||
{{ post.commentsCount }}
|
||||
</ds-tag> Comments
|
||||
</span>
|
||||
</h3>
|
||||
<ds-space margin-bottom="large" />
|
||||
<div
|
||||
v-if="post.commentsCount"
|
||||
id="comments"
|
||||
class="comments">
|
||||
<div
|
||||
v-for="comment in post.comments"
|
||||
:key="comment.id"
|
||||
class="comment">
|
||||
<ds-space margin-bottom="x-small">
|
||||
<a
|
||||
v-router-link
|
||||
:href="$router.resolve({ name: 'profile-slug', params: { slug: comment.author.User.slug } }).href">
|
||||
<ds-avatar
|
||||
:image="comment.author.User.avatar"
|
||||
size="24px" /> <b class="username">{{ comment.author.User.name }}</b>
|
||||
</a>
|
||||
</ds-space>
|
||||
<div
|
||||
style="padding-left: 32px;"
|
||||
v-html="comment.content" />
|
||||
</div>
|
||||
<ds-space margin-bottom="small" />
|
||||
</div>
|
||||
<div v-else>
|
||||
<p style="text-align: center; opacity: .5;">NO COMMENTS</p>
|
||||
</div>
|
||||
</ds-section>
|
||||
</ds-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export default {
|
||||
transition: {
|
||||
name: 'slide-up',
|
||||
mode: 'out-in'
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
post: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
Post(post) {
|
||||
this.post = post[0]
|
||||
}
|
||||
},
|
||||
apollo: {
|
||||
Post: {
|
||||
query: gql(`
|
||||
query Post($slug: String!) {
|
||||
Post(slug: $slug) {
|
||||
id
|
||||
title
|
||||
content
|
||||
slug
|
||||
image
|
||||
author {
|
||||
User {
|
||||
slug
|
||||
name
|
||||
avatar
|
||||
}
|
||||
}
|
||||
tags {
|
||||
name
|
||||
}
|
||||
commentsCount
|
||||
comments(orderBy: _id_desc) {
|
||||
id
|
||||
content
|
||||
author {
|
||||
User {
|
||||
slug
|
||||
name
|
||||
avatar
|
||||
}
|
||||
}
|
||||
}
|
||||
categories {
|
||||
name
|
||||
}
|
||||
shoutedBy {
|
||||
name
|
||||
friends {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
variables() {
|
||||
return {
|
||||
slug: this.$route.params.slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import 'vue-cion-design-system/src/system/tokens/generated/tokens.scss';
|
||||
|
||||
.post-card {
|
||||
// max-width: 800px;
|
||||
margin: auto;
|
||||
|
||||
.content {
|
||||
br {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.comments {
|
||||
margin-top: $space-small;
|
||||
|
||||
.comment {
|
||||
margin-top: $space-small;
|
||||
position: relative;
|
||||
}
|
||||
}
|
||||
|
||||
.ds-card-image {
|
||||
img {
|
||||
max-height: 300px;
|
||||
object-fit: cover;
|
||||
object-position: center;
|
||||
}
|
||||
}
|
||||
.ds-card-footer {
|
||||
padding: 0;
|
||||
border-radius: 0 0 $border-radius-large $border-radius-large;
|
||||
overflow: hidden;
|
||||
|
||||
.ds-section {
|
||||
padding: $space-base;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
118
pages/post/_slug/more-info.vue
Normal file
118
pages/post/_slug/more-info.vue
Normal file
@ -0,0 +1,118 @@
|
||||
<template>
|
||||
<ds-card>
|
||||
<h2 style="margin-bottom: .2em;">Mehr Informationen</h2>
|
||||
<p>Hier findest du weitere infos zum Thema.</p>
|
||||
<ds-space/>
|
||||
<h3><ds-icon name="compass" /> Themenkategorien</h3>
|
||||
<div class="tags">
|
||||
<ds-tag
|
||||
v-for="category in post.categories"
|
||||
:key="category.id">{{ category.name }}</ds-tag>
|
||||
</div>
|
||||
<template v-if="post.tags && post.tags.length">
|
||||
<h3><ds-icon name="tags" /> Schlagwörter</h3>
|
||||
<div class="tags">
|
||||
<ds-tag
|
||||
v-for="tag in post.tags"
|
||||
:key="tag.id"><ds-icon name="tag" /> {{ tag.name }}</ds-tag>
|
||||
</div>
|
||||
</template>
|
||||
<h3>Verwandte Beiträge</h3>
|
||||
<ds-section style="margin: 0 -1.5rem; padding: 1.5rem;">
|
||||
<ds-flex
|
||||
v-if="post.relatedContributions && post.relatedContributions.length"
|
||||
gutter="small">
|
||||
<ds-flex-item
|
||||
v-for="relatedPost in post.relatedContributions"
|
||||
:key="relatedPost.id"
|
||||
:width="{ base: '50%' }">
|
||||
<a
|
||||
v-router-link
|
||||
:href="$router.resolve({ name: 'post-slug', params: { slug: relatedPost.slug } }).href">
|
||||
<ds-card
|
||||
:image="relatedPost.image"
|
||||
:header="relatedPost.title"
|
||||
class="related-post">
|
||||
<div v-html="relatedPost.contentExcerpt" />
|
||||
</ds-card>
|
||||
</a>
|
||||
</ds-flex-item>
|
||||
</ds-flex>
|
||||
<ds-space
|
||||
v-else
|
||||
style="text-align: center; padding-top: 2em; opacity: .6;">
|
||||
No related Posts
|
||||
</ds-space>
|
||||
</ds-section>
|
||||
<ds-space margin-bottom="large" />
|
||||
</ds-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export default {
|
||||
transition: {
|
||||
name: 'slide-up',
|
||||
mode: 'out-in'
|
||||
},
|
||||
computed: {
|
||||
post() {
|
||||
return this.Post ? this.Post[0] : {}
|
||||
}
|
||||
},
|
||||
apollo: {
|
||||
Post: {
|
||||
query: gql(`
|
||||
query Post($slug: String!) {
|
||||
Post(slug: $slug) {
|
||||
id
|
||||
title
|
||||
tags {
|
||||
id
|
||||
name
|
||||
}
|
||||
categories {
|
||||
id
|
||||
name
|
||||
}
|
||||
relatedContributions(first: 2) {
|
||||
id
|
||||
title
|
||||
slug
|
||||
image
|
||||
contentExcerpt
|
||||
shoutedCount
|
||||
commentsCount
|
||||
}
|
||||
shoutedCount
|
||||
shoutedBy {
|
||||
name
|
||||
friends {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
variables() {
|
||||
return {
|
||||
slug: this.$route.params.slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
@import 'vue-cion-design-system/src/system/tokens/generated/tokens.scss';
|
||||
|
||||
.related-post {
|
||||
box-shadow: $box-shadow-base;
|
||||
|
||||
.ds-card-image {
|
||||
max-height: 80px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
52
pages/post/_slug/take-action.vue
Normal file
52
pages/post/_slug/take-action.vue
Normal file
@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<ds-card header="Werde aktiv!">
|
||||
<p>Was kann ich tun? Hier findest du mögliche Projekte, Aktioner, etc.</p>
|
||||
</ds-card>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export default {
|
||||
transition: {
|
||||
name: 'slide-up',
|
||||
mode: 'out-in'
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
Post: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
tags() {
|
||||
return this.Post ? this.Post[0].tags.map(tag => tag.name) : '-'
|
||||
}
|
||||
},
|
||||
apollo: {
|
||||
Post: {
|
||||
query: gql(`
|
||||
query {
|
||||
Post {
|
||||
id
|
||||
title
|
||||
tags {
|
||||
name
|
||||
}
|
||||
categories {
|
||||
name
|
||||
}
|
||||
shoutedCount
|
||||
shoutedBy {
|
||||
name
|
||||
friends {
|
||||
name
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
172
pages/profile/_slug.vue
Normal file
172
pages/profile/_slug.vue
Normal file
@ -0,0 +1,172 @@
|
||||
<template>
|
||||
<div>
|
||||
<ds-card v-if="user && user.image">
|
||||
<p>PROFILE IMAGE</p>
|
||||
</ds-card>
|
||||
<no-ssr>
|
||||
<ds-space/>
|
||||
<ds-flex
|
||||
v-if="user"
|
||||
:width="{ base: '100%' }"
|
||||
gutter="base">
|
||||
<ds-flex-item :width="{ base: '30%' }">
|
||||
<ds-card style="position: relative; height: auto;">
|
||||
<ds-avatar
|
||||
:image="user.avatar"
|
||||
class="profile-avatar"
|
||||
size="120px" />
|
||||
<h3 style="text-align: center;">{{ user.name }}</h3>
|
||||
<ds-space/>
|
||||
<ds-flex :size="{ base: '100%' }">
|
||||
<ds-flex-item style="text-align: center;">
|
||||
<ds-text
|
||||
size="x-large"
|
||||
style="margin-bottom: 0;">{{ user.followedByCount }}</ds-text>
|
||||
<ds-text size="small">Fans</ds-text>
|
||||
</ds-flex-item>
|
||||
<ds-flex-item style="text-align: center;">
|
||||
<ds-text
|
||||
size="x-large"
|
||||
style="margin-bottom: 0;">{{ user.friendsCount }}</ds-text>
|
||||
<ds-text size="small">Freunde</ds-text>
|
||||
</ds-flex-item>
|
||||
</ds-flex>
|
||||
<ds-space margin-bottom="small"/>
|
||||
</ds-card>
|
||||
<ds-space/>
|
||||
<h2 style="text-align: center; margin-bottom: 10px;">Netzwerk</h2>
|
||||
<ds-card style="position: relative; height: auto;">
|
||||
<template v-if="user.friends.length">
|
||||
<ds-space
|
||||
v-for="friend in user.friends"
|
||||
:key="friend.id"
|
||||
margin-top="x-small"
|
||||
margin-bottom="x-small">
|
||||
<a
|
||||
v-router-link
|
||||
:href="$router.resolve({ name: 'profile-slug', params: { slug: friend.slug } }).href">
|
||||
<ds-avatar
|
||||
:image="friend.avatar"
|
||||
size="32px" /> <b class="username">{{ friend.name }}</b>
|
||||
</a>
|
||||
</ds-space>
|
||||
</template>
|
||||
<template v-else>
|
||||
<p style="text-align: center; opacity: .5;">NO FRIENDS</p>
|
||||
</template>
|
||||
</ds-card>
|
||||
</ds-flex-item>
|
||||
<ds-flex-item :width="{ base: '70%' }">
|
||||
<ds-flex
|
||||
:width="{ base: '100%' }"
|
||||
gutter="small">
|
||||
<ds-flex-item
|
||||
v-for="item in user.contributions"
|
||||
:width="{ base: '100%', md: '100%', xl: '50%' }"
|
||||
:key="item.Post.id">
|
||||
<a
|
||||
v-router-link
|
||||
:href="href(item.Post)"
|
||||
>
|
||||
<ds-card
|
||||
:header="item.Post.title"
|
||||
:image="item.Post.image"
|
||||
style="cursor: pointer">
|
||||
<div v-html="item.Post.contentExcerpt" />
|
||||
<template slot="footer">
|
||||
<span>
|
||||
<ds-icon name="comments" /> <small v-if="item.Post.commentsCount">{{ item.Post.commentsCount }}</small>
|
||||
</span>
|
||||
|
||||
<span>
|
||||
<ds-icon name="heart-o" /> <small v-if="item.Post.shoutedCount">{{ item.Post.shoutedCount }}</small>
|
||||
</span>
|
||||
</template>
|
||||
</ds-card>
|
||||
</a>
|
||||
</ds-flex-item>
|
||||
</ds-flex>
|
||||
</ds-flex-item>
|
||||
</ds-flex>
|
||||
</no-ssr>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import gql from 'graphql-tag'
|
||||
|
||||
export default {
|
||||
transition: {
|
||||
name: 'slide-up',
|
||||
mode: 'out-in'
|
||||
},
|
||||
|
||||
data() {
|
||||
return {
|
||||
User: []
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
user() {
|
||||
return this.User ? this.User[0] : {}
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
href(post) {
|
||||
return this.$router.resolve({
|
||||
name: 'post-slug',
|
||||
params: { slug: post.slug }
|
||||
}).href
|
||||
}
|
||||
},
|
||||
apollo: {
|
||||
User: {
|
||||
query: gql(`
|
||||
query User($slug: String!) {
|
||||
User(slug: $slug) {
|
||||
id
|
||||
name
|
||||
avatar
|
||||
friendsCount
|
||||
friends {
|
||||
id
|
||||
name
|
||||
slug
|
||||
avatar
|
||||
}
|
||||
badgesCount
|
||||
followingCount
|
||||
followedByCount
|
||||
contributionsCount
|
||||
contributions {
|
||||
Post {
|
||||
id
|
||||
slug
|
||||
title
|
||||
contentExcerpt
|
||||
shoutedCount
|
||||
commentsCount
|
||||
image
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
`),
|
||||
variables() {
|
||||
return {
|
||||
slug: this.$route.params.slug
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.profile-avatar {
|
||||
display: block;
|
||||
margin: auto;
|
||||
margin-top: -60px;
|
||||
border: #fff 5px solid;
|
||||
}
|
||||
</style>
|
||||
7
plugins/README.md
Normal file
7
plugins/README.md
Normal file
@ -0,0 +1,7 @@
|
||||
# PLUGINS
|
||||
|
||||
**This directory is not required, you can delete it if you don't want to use it.**
|
||||
|
||||
This directory contains your Javascript plugins that you want to run before mounting the root Vue.js application.
|
||||
|
||||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/plugins).
|
||||
5
plugins/design-system.js
Normal file
5
plugins/design-system.js
Normal file
@ -0,0 +1,5 @@
|
||||
import Vue from 'vue'
|
||||
import DesignSystem from 'vue-cion-design-system'
|
||||
import 'vue-cion-design-system/dist/system.css'
|
||||
|
||||
Vue.use(DesignSystem)
|
||||
33
plugins/vue-directives.js
Normal file
33
plugins/vue-directives.js
Normal file
@ -0,0 +1,33 @@
|
||||
import Vue from 'vue'
|
||||
|
||||
export default ({ app }) => {
|
||||
Vue.directive('focus', {
|
||||
// When the bound element is inserted into the DOM...
|
||||
inserted: (el, binding) => {
|
||||
// Focus the element
|
||||
Vue.nextTick(() => {
|
||||
if (binding.value !== false) {
|
||||
el.focus()
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
Vue.directive('router-link', {
|
||||
bind: (el, binding) => {
|
||||
binding.clickEventListener = e => {
|
||||
if (!e.metaKey && !e.ctrlKey) {
|
||||
e.preventDefault()
|
||||
app.router.push(el.getAttribute('href'))
|
||||
}
|
||||
}
|
||||
el.addEventListener('click', binding.clickEventListener)
|
||||
},
|
||||
unbind: (el, binding) => {
|
||||
// cleanup
|
||||
if (binding.clickEventListener) {
|
||||
el.removeEventListener('click', binding.clickEventListener)
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
34
server/index.js
Normal file
34
server/index.js
Normal file
@ -0,0 +1,34 @@
|
||||
const express = require('express')
|
||||
const consola = require('consola')
|
||||
const { Nuxt, Builder } = require('nuxt')
|
||||
const app = express()
|
||||
const host = process.env.HOST || '127.0.0.1'
|
||||
const port = process.env.PORT || 3000
|
||||
|
||||
app.set('port', port)
|
||||
|
||||
// Import and Set Nuxt.js options
|
||||
let config = require('../nuxt.config.js')
|
||||
config.dev = !(process.env.NODE_ENV === 'production')
|
||||
|
||||
async function start() {
|
||||
// Init Nuxt.js
|
||||
const nuxt = new Nuxt(config)
|
||||
|
||||
// Build only in dev mode
|
||||
if (config.dev) {
|
||||
const builder = new Builder(nuxt)
|
||||
await builder.build()
|
||||
}
|
||||
|
||||
// Give nuxt middleware to express
|
||||
app.use(nuxt.render)
|
||||
|
||||
// Listen the server
|
||||
app.listen(port, host)
|
||||
consola.ready({
|
||||
message: `Server listening on http://${host}:${port}`,
|
||||
badge: true
|
||||
})
|
||||
}
|
||||
start()
|
||||
10
static/README.md
Normal file
10
static/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# STATIC
|
||||
|
||||
**This directory is not required, you can delete it if you don't want to use it.**
|
||||
|
||||
This directory contains your static files.
|
||||
Each file inside this directory is mapped to `/`.
|
||||
|
||||
Example: `/static/robots.txt` is mapped as `/robots.txt`.
|
||||
|
||||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#static).
|
||||
BIN
static/favicon.ico
Normal file
BIN
static/favicon.ico
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
10
store/README.md
Normal file
10
store/README.md
Normal file
@ -0,0 +1,10 @@
|
||||
# STORE
|
||||
|
||||
**This directory is not required, you can delete it if you don't want to use it.**
|
||||
|
||||
This directory contains your Vuex Store files.
|
||||
Vuex Store option is implemented in the Nuxt.js framework.
|
||||
|
||||
Creating a file in this directory activate the option in the framework automatically.
|
||||
|
||||
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/vuex-store).
|
||||
1
styleguide
Submodule
1
styleguide
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit 83cba8953c8773515c803cac835f568bbb5f62b5
|
||||
Loading…
x
Reference in New Issue
Block a user