before suspend
This commit is contained in:
		
							
								
								
									
										24
									
								
								.eslintrc
									
									
									
									
									
								
							
							
						
						
									
										24
									
								
								.eslintrc
									
									
									
									
									
								
							@@ -11,7 +11,8 @@
 | 
				
			|||||||
	},
 | 
						},
 | 
				
			||||||
	"env": {
 | 
						"env": {
 | 
				
			||||||
		"es6": true,
 | 
							"es6": true,
 | 
				
			||||||
		"browser": true
 | 
							"browser": true,
 | 
				
			||||||
 | 
							"vue/setup-compiler-macros": true
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	"rules": {
 | 
						"rules": {
 | 
				
			||||||
		"semi": [
 | 
							"semi": [
 | 
				
			||||||
@@ -23,11 +24,22 @@
 | 
				
			|||||||
			"error",
 | 
								"error",
 | 
				
			||||||
			"tab"
 | 
								"tab"
 | 
				
			||||||
		],
 | 
							],
 | 
				
			||||||
		"vue/html-closing-bracket-spacing": ["error", {
 | 
							"vue/html-closing-bracket-spacing": [
 | 
				
			||||||
			"startTag": "never",
 | 
								"error",
 | 
				
			||||||
			"endTag": "never",
 | 
								{
 | 
				
			||||||
			"selfClosingTag": "never"
 | 
									"startTag": "never",
 | 
				
			||||||
		}],
 | 
									"endTag": "never",
 | 
				
			||||||
 | 
									"selfClosingTag": "never"
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							],
 | 
				
			||||||
 | 
							"vue/component-api-style": [
 | 
				
			||||||
 | 
								"error",
 | 
				
			||||||
 | 
								[
 | 
				
			||||||
 | 
									"script-setup",
 | 
				
			||||||
 | 
									"composition"
 | 
				
			||||||
 | 
								]
 | 
				
			||||||
 | 
								// "script-setup", "composition", "composition-vue2", or "options"
 | 
				
			||||||
 | 
							],
 | 
				
			||||||
		"indent": [
 | 
							"indent": [
 | 
				
			||||||
			"error",
 | 
								"error",
 | 
				
			||||||
			"tab"
 | 
								"tab"
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										8
									
								
								TODO
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								TODO
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,8 @@
 | 
				
			|||||||
 | 
					- use quill vue
 | 
				
			||||||
 | 
					- add linenumbering
 | 
				
			||||||
 | 
					- add yntax highlighning
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- pinia
 | 
				
			||||||
 | 
					- harden Api-Platform
 | 
				
			||||||
 | 
					- learn tailwind
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -2,20 +2,18 @@
 | 
				
			|||||||
	<div class="container-fluid">
 | 
						<div class="container-fluid">
 | 
				
			||||||
		<div class="row">
 | 
							<div class="row">
 | 
				
			||||||
			<div class="col">
 | 
								<div class="col">
 | 
				
			||||||
				<nav-bar
 | 
									<the-navbar
 | 
				
			||||||
					:user="user"
 | 
										@invalidate-user="onUserInvalidate"
 | 
				
			||||||
					@invalidate-user="onInvalidateUser"
 | 
					 | 
				
			||||||
				/>
 | 
									/>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		<div class="row mt-5 main-content">
 | 
							<div class="row mt-5 main-content">
 | 
				
			||||||
			<div class="col-xl-3">
 | 
								<div class="col-xl-3">
 | 
				
			||||||
				<sidebar/>
 | 
									<the-sidebar/>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
			<div class="col-xl-9">
 | 
								<div class="col-xl-9">
 | 
				
			||||||
				<router-view
 | 
									<router-view
 | 
				
			||||||
					:quote="quote"
 | 
					 | 
				
			||||||
					@user-authenticated="onUserAuthenticated"
 | 
										@user-authenticated="onUserAuthenticated"
 | 
				
			||||||
				/>
 | 
									/>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
@@ -24,58 +22,41 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
		<div class="row">
 | 
							<div class="row">
 | 
				
			||||||
			<div class="col">
 | 
								<div class="col">
 | 
				
			||||||
				<footer-component/>
 | 
									<the-footer/>
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
		</div>
 | 
							</div>
 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script setup>
 | 
				
			||||||
import axios from 'axios'
 | 
					import axios from 'axios'
 | 
				
			||||||
 | 
					import { useRoute } from 'vue-router'
 | 
				
			||||||
 | 
					//import RouterView from 'vue-router'
 | 
				
			||||||
 | 
					import TheNavbar from '@/components/TheNavbar'
 | 
				
			||||||
 | 
					import TheSidebar from '@/components/TheSidebar'
 | 
				
			||||||
 | 
					import TheFooter from '@/components/TheFooter'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import routerView from 'vue-router'
 | 
					if (window.user) {
 | 
				
			||||||
import NavBar from '@/components/TheNavbar'
 | 
						const { user } = window
 | 
				
			||||||
import Sidebar from '@/components/TheSidebar'
 | 
					 | 
				
			||||||
import FooterComponent from '@/components/TheFooter'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
	name: 'App',
 | 
					 | 
				
			||||||
	components: {
 | 
					 | 
				
			||||||
		routerView,
 | 
					 | 
				
			||||||
		Sidebar,
 | 
					 | 
				
			||||||
		NavBar,
 | 
					 | 
				
			||||||
		FooterComponent
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	data() {
 | 
					 | 
				
			||||||
		return {
 | 
					 | 
				
			||||||
			user: null,
 | 
					 | 
				
			||||||
			quote: null
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	mounted() {
 | 
					 | 
				
			||||||
		if (window.user) {
 | 
					 | 
				
			||||||
			this.user = window.user
 | 
					 | 
				
			||||||
			console.log(this.user)
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		if (window.quote) {
 | 
					 | 
				
			||||||
			this.quote = window.quote
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	methods: {
 | 
					 | 
				
			||||||
		onUserAuthenticated(userUri) {
 | 
					 | 
				
			||||||
			console.log('authenticated')
 | 
					 | 
				
			||||||
			axios
 | 
					 | 
				
			||||||
				.get(userUri)
 | 
					 | 
				
			||||||
				.then((response) => {
 | 
					 | 
				
			||||||
					this.user = response.data
 | 
					 | 
				
			||||||
				})
 | 
					 | 
				
			||||||
			this.$router.push('/')
 | 
					 | 
				
			||||||
		},
 | 
					 | 
				
			||||||
		onInvalidateUser() {
 | 
					 | 
				
			||||||
			console.log('invalidated')
 | 
					 | 
				
			||||||
			this.user = null
 | 
					 | 
				
			||||||
			window.user = null
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					if (window.quote) {
 | 
				
			||||||
 | 
						const { quote } = window
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const onUserAuthenticated = (userUri) => {
 | 
				
			||||||
 | 
						//console.log('authenticated')
 | 
				
			||||||
 | 
						axios
 | 
				
			||||||
 | 
							.get(userUri)
 | 
				
			||||||
 | 
							.then((response) => {
 | 
				
			||||||
 | 
								this.user = response.data
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						this.$router.push('/')
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const onUserInvalidate = () => {
 | 
				
			||||||
 | 
						//console.log('invalidated')
 | 
				
			||||||
 | 
						this.user = null
 | 
				
			||||||
 | 
						window.user = null
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,7 +17,7 @@
 | 
				
			|||||||
		</div>
 | 
							</div>
 | 
				
			||||||
		<router-link
 | 
							<router-link
 | 
				
			||||||
			v-else
 | 
								v-else
 | 
				
			||||||
			v-bind="$props"
 | 
								:to="{ name: props.to }"
 | 
				
			||||||
		>
 | 
							>
 | 
				
			||||||
			<span
 | 
								<span
 | 
				
			||||||
				:class="`fa fa-lg fa-fw  ${fa}`"
 | 
									:class="`fa fa-lg fa-fw  ${fa}`"
 | 
				
			||||||
@@ -29,21 +29,20 @@
 | 
				
			|||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script setup>
 | 
				
			||||||
 | 
					import { computed } from 'vue'
 | 
				
			||||||
import { RouterLink } from 'vue-router'
 | 
					import { RouterLink } from 'vue-router'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					const props = defineProps({
 | 
				
			||||||
	props: {
 | 
						to: {
 | 
				
			||||||
		...RouterLink.props,
 | 
							type: String,
 | 
				
			||||||
		fa: {
 | 
							required: true
 | 
				
			||||||
			type: String,
 | 
					 | 
				
			||||||
			default: ''
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
	computed: {
 | 
						fa: {
 | 
				
			||||||
		isExternal() {
 | 
							type: String,
 | 
				
			||||||
			return typeof this.to === 'string' && this.to.startsWith('http')
 | 
							default: ''
 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const isExternal = computed(() => props.to.startsWith('http'))
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,10 +2,10 @@
 | 
				
			|||||||
	<div class="container box">
 | 
						<div class="container box">
 | 
				
			||||||
		<form @submit.prevent="handleSubmit">
 | 
							<form @submit.prevent="handleSubmit">
 | 
				
			||||||
			<div
 | 
								<div
 | 
				
			||||||
				v-if="error"
 | 
									v-if="errorMessage"
 | 
				
			||||||
				class="alert alert-danger"
 | 
									class="alert alert-danger mt-2"
 | 
				
			||||||
			>
 | 
								>
 | 
				
			||||||
				{{ error }}
 | 
									{{ errorMessage }}
 | 
				
			||||||
			</div>
 | 
								</div>
 | 
				
			||||||
			<div class="form-group mt-2">
 | 
								<div class="form-group mt-2">
 | 
				
			||||||
				<label for="exampleInputEmail1">Username</label>
 | 
									<label for="exampleInputEmail1">Username</label>
 | 
				
			||||||
@@ -52,57 +52,44 @@
 | 
				
			|||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script setup>
 | 
				
			||||||
 | 
					import { ref, defineEmits } from 'vue'
 | 
				
			||||||
import axios from 'axios'
 | 
					import axios from 'axios'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					const username = ref('')
 | 
				
			||||||
	name: 'LoginForm',
 | 
					const password = ref('')
 | 
				
			||||||
	/*
 | 
					const errorMessage = ref('')
 | 
				
			||||||
	props: {
 | 
					const isLoading = ref(false)
 | 
				
			||||||
		user: {
 | 
					const emit = defineEmits(['user-authenticated'])
 | 
				
			||||||
			Type: Object
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	 */
 | 
					 | 
				
			||||||
	data() {
 | 
					 | 
				
			||||||
		return {
 | 
					 | 
				
			||||||
			username: '',
 | 
					 | 
				
			||||||
			password: '',
 | 
					 | 
				
			||||||
			error: '',
 | 
					 | 
				
			||||||
			isLoading: false
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	methods: {
 | 
					 | 
				
			||||||
		handleSubmit() {
 | 
					 | 
				
			||||||
			console.log('handle submit')
 | 
					 | 
				
			||||||
			this.isLoading = true
 | 
					 | 
				
			||||||
			this.error = ''
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			axios
 | 
					const handleSubmit = () => {
 | 
				
			||||||
				.post('/login', {
 | 
						//console.log('handle submit')
 | 
				
			||||||
					username: this.username,
 | 
						isLoading.value = true
 | 
				
			||||||
					password: this.password
 | 
					 | 
				
			||||||
				})
 | 
					 | 
				
			||||||
				.then((response) => {
 | 
					 | 
				
			||||||
					console.log(response.headers)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
					this.$emit('user-authenticated', response.headers.location)
 | 
						axios
 | 
				
			||||||
					this.username = ''
 | 
							.post('/login', {
 | 
				
			||||||
					this.password = ''
 | 
								username: username.value,
 | 
				
			||||||
				})
 | 
								password: password.value
 | 
				
			||||||
				.catch((error) => {
 | 
							})
 | 
				
			||||||
					console.log(error.response.data)
 | 
							.then((response) => {
 | 
				
			||||||
					if (error.response.data.error) {
 | 
								//console.log(response.headers)
 | 
				
			||||||
						this.error = error.response.data.error
 | 
					
 | 
				
			||||||
					} else {
 | 
								emit('user-authenticated', response.headers.location)
 | 
				
			||||||
						this.error = 'Unknown error'
 | 
								username.value = ''
 | 
				
			||||||
					}
 | 
								password.value = ''
 | 
				
			||||||
				})
 | 
							})
 | 
				
			||||||
				.finally(() => {
 | 
							.catch((error) => {
 | 
				
			||||||
					this.isLoading = false
 | 
								console.log(error)
 | 
				
			||||||
				})
 | 
								console.log(error.response.data)
 | 
				
			||||||
		}
 | 
								if (error.response.data.error) {
 | 
				
			||||||
	}
 | 
									errorMessage.value = error.response.data.error
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									errorMessage.value = 'Unknown error'
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							.finally(() => {
 | 
				
			||||||
 | 
								isLoading.value = false
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										14
									
								
								assets/js/components/TheAbout.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								assets/js/components/TheAbout.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<div>
 | 
				
			||||||
 | 
							Bio:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Symfonycast
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default {
 | 
				
			||||||
 | 
						name: 'TheAbout'
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
@@ -14,6 +14,14 @@
 | 
				
			|||||||
								alt="Spookie"
 | 
													alt="Spookie"
 | 
				
			||||||
							>
 | 
												>
 | 
				
			||||||
						</router-link>
 | 
											</router-link>
 | 
				
			||||||
 | 
											<div>
 | 
				
			||||||
 | 
												<router-link
 | 
				
			||||||
 | 
													:to="{ name: 'About'}"
 | 
				
			||||||
 | 
													class="d-inline-block mx-auto"
 | 
				
			||||||
 | 
												>
 | 
				
			||||||
 | 
													About Me
 | 
				
			||||||
 | 
												</router-link>
 | 
				
			||||||
 | 
											</div>
 | 
				
			||||||
					</div>
 | 
										</div>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
				<div class="col md-4 text-left">
 | 
									<div class="col md-4 text-left">
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -116,37 +116,30 @@
 | 
				
			|||||||
	</nav>
 | 
						</nav>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script setup>
 | 
				
			||||||
import axios from 'axios'
 | 
					import axios from 'axios'
 | 
				
			||||||
 | 
					 | 
				
			||||||
import 'vue-navigation-bar/dist/vue-navigation-bar.css'
 | 
					import 'vue-navigation-bar/dist/vue-navigation-bar.css'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					const props = defineProps({
 | 
				
			||||||
	name: 'TheNavbar',
 | 
						user: {
 | 
				
			||||||
	components: {},
 | 
							type: Object,
 | 
				
			||||||
	props: {
 | 
							default() {
 | 
				
			||||||
		user: {
 | 
								return {
 | 
				
			||||||
			type: Object,
 | 
									username: 'tracer'
 | 
				
			||||||
			default: null
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	data: () => ({}),
 | 
					 | 
				
			||||||
	computed: {
 | 
					 | 
				
			||||||
		isLoggedIn() {
 | 
					 | 
				
			||||||
			return !!this.user
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	methods: {
 | 
					 | 
				
			||||||
		logout() {
 | 
					 | 
				
			||||||
			console.log('logout')
 | 
					 | 
				
			||||||
			axios
 | 
					 | 
				
			||||||
				.get('/logout')
 | 
					 | 
				
			||||||
				.then(this.$emit('invalidate-user'))
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					})
 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style>
 | 
					const isLoggedIn = () => (!!this.user)
 | 
				
			||||||
</style>
 | 
					
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
 | 
					const logout = () => ({
 | 
				
			||||||
 | 
						axios
 | 
				
			||||||
 | 
						.get('/logout')
 | 
				
			||||||
 | 
							.then(this.$emit('invalidate-user'))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -30,6 +30,11 @@ export default {
 | 
				
			|||||||
				url: 'Projects',
 | 
									url: 'Projects',
 | 
				
			||||||
				fa: 'fa-file-code-o',
 | 
									fa: 'fa-file-code-o',
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
 | 
								{
 | 
				
			||||||
 | 
									name: 'Blog',
 | 
				
			||||||
 | 
									url: 'Blog',
 | 
				
			||||||
 | 
									fa: 'fa-file-text-o',
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				name: 'Gitea',
 | 
									name: 'Gitea',
 | 
				
			||||||
				url: 'https://git.24unix.net',
 | 
									url: 'https://git.24unix.net',
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										38
									
								
								assets/js/components/blog/BlogCard.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								assets/js/components/blog/BlogCard.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,38 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<div
 | 
				
			||||||
 | 
							class="
 | 
				
			||||||
 | 
					      flex
 | 
				
			||||||
 | 
					      m-2
 | 
				
			||||||
 | 
					      gap-2
 | 
				
			||||||
 | 
					      items-center
 | 
				
			||||||
 | 
					      shadow-md
 | 
				
			||||||
 | 
					      w-1/4
 | 
				
			||||||
 | 
					      flex-grow
 | 
				
			||||||
 | 
					      rounded
 | 
				
			||||||
 | 
					      overflow-hidden
 | 
				
			||||||
 | 
					    "
 | 
				
			||||||
 | 
							style="border: 1px solid #eee"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							<img
 | 
				
			||||||
 | 
								src="https://via.placeholder.com/150"
 | 
				
			||||||
 | 
								style="background: #cccccc"
 | 
				
			||||||
 | 
								width="150"
 | 
				
			||||||
 | 
								height="150"
 | 
				
			||||||
 | 
								alt="placeholder"
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
							<router-link :to="{ name: 'BlogPost', params: { id: post.id } }">
 | 
				
			||||||
 | 
								{{ post.title }}<br>
 | 
				
			||||||
 | 
								User: {{ post.userId }}
 | 
				
			||||||
 | 
							</router-link>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					<script setup>
 | 
				
			||||||
 | 
					console.log('BlogCard')
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						post: {
 | 
				
			||||||
 | 
							type: Object,
 | 
				
			||||||
 | 
							required: true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					const post = { ...props.post }
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
							
								
								
									
										34
									
								
								assets/js/components/blog/BlogIndex.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								assets/js/components/blog/BlogIndex.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,34 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<div
 | 
				
			||||||
 | 
							class="
 | 
				
			||||||
 | 
					      flex
 | 
				
			||||||
 | 
					      m-2
 | 
				
			||||||
 | 
					      gap-2
 | 
				
			||||||
 | 
					      items-center
 | 
				
			||||||
 | 
					      shadow-md
 | 
				
			||||||
 | 
					      w-1/4
 | 
				
			||||||
 | 
					      flex-grow
 | 
				
			||||||
 | 
					      rounded
 | 
				
			||||||
 | 
					      overflow-hidden
 | 
				
			||||||
 | 
					    "
 | 
				
			||||||
 | 
							style="border: 1px solid #eee"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							BlogIndex
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<BlogCard
 | 
				
			||||||
 | 
								v-for="post in blogPosts"
 | 
				
			||||||
 | 
								:key="post.id"
 | 
				
			||||||
 | 
								:post="post"
 | 
				
			||||||
 | 
							/>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script setup>
 | 
				
			||||||
 | 
					import useResource from '@/composables/useResource'
 | 
				
			||||||
 | 
					//import useUser from '@/composables/useUser'
 | 
				
			||||||
 | 
					import BlogCard from '@/components/blog/BlogCard'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { items: blogPosts, fetchAll } = useResource('https://jsonplaceholder.typicode.com/posts')
 | 
				
			||||||
 | 
					fetchAll()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
							
								
								
									
										51
									
								
								assets/js/components/blog/BlogPost.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								assets/js/components/blog/BlogPost.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,51 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<div
 | 
				
			||||||
 | 
							v-if="blogPost"
 | 
				
			||||||
 | 
							class="
 | 
				
			||||||
 | 
					      flex
 | 
				
			||||||
 | 
					      m-2
 | 
				
			||||||
 | 
					      gap-2
 | 
				
			||||||
 | 
					      items-center
 | 
				
			||||||
 | 
					      shadow-md
 | 
				
			||||||
 | 
					      w-1/4
 | 
				
			||||||
 | 
					      flex-grow
 | 
				
			||||||
 | 
					      rounded
 | 
				
			||||||
 | 
					      overflow-hidden
 | 
				
			||||||
 | 
					    "
 | 
				
			||||||
 | 
							style="border: 1px solid #eee"
 | 
				
			||||||
 | 
						>
 | 
				
			||||||
 | 
							BlogIPost
 | 
				
			||||||
 | 
							<img
 | 
				
			||||||
 | 
								src="https://via.placeholder.com/150"
 | 
				
			||||||
 | 
								style="background: #cccccc"
 | 
				
			||||||
 | 
								width="150"
 | 
				
			||||||
 | 
								height="150"
 | 
				
			||||||
 | 
								alt="placeholder"
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
							user {{ blogPost.userId }}:
 | 
				
			||||||
 | 
							<div v-if="user">
 | 
				
			||||||
 | 
								"{{ user.name }}
 | 
				
			||||||
 | 
							</div>
 | 
				
			||||||
 | 
							<br>
 | 
				
			||||||
 | 
							{{ blogPost.title }}<br>
 | 
				
			||||||
 | 
							{{ blogPost.body }}
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script setup>
 | 
				
			||||||
 | 
					import { watch } from 'vue'
 | 
				
			||||||
 | 
					import { useRoute } from 'vue-router'
 | 
				
			||||||
 | 
					import useResource from '@/composables/useResource'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const route = useRoute()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { item: blogPost, fetchOne: fetchOneBlog } = useResource('https://jsonplaceholder.typicode.com/posts')
 | 
				
			||||||
 | 
					fetchOneBlog(route.params.id)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const { item: user, fetchOne: fetchOneUser } = useResource('https://jsonplaceholder.typicode.com/users')
 | 
				
			||||||
 | 
					watch(
 | 
				
			||||||
 | 
						() => ({ ...blogPost.value }),
 | 
				
			||||||
 | 
						() => fetchOneUser(blogPost.value.userId)
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
							
								
								
									
										60
									
								
								assets/js/components/pages/PagesIndex.vue
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								assets/js/components/pages/PagesIndex.vue
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,60 @@
 | 
				
			|||||||
 | 
					<template>
 | 
				
			||||||
 | 
						<div class="box ma7 p-5">
 | 
				
			||||||
 | 
							<h2
 | 
				
			||||||
 | 
								v-if="page"
 | 
				
			||||||
 | 
								v-html="page.name"
 | 
				
			||||||
 | 
							/>
 | 
				
			||||||
 | 
							<div
 | 
				
			||||||
 | 
								v-if="page"
 | 
				
			||||||
 | 
								v-html="page.content"
 | 
				
			||||||
 | 
							/>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							<router-link
 | 
				
			||||||
 | 
								:to="editTarget"
 | 
				
			||||||
 | 
								variant="outline"
 | 
				
			||||||
 | 
							>
 | 
				
			||||||
 | 
								<button>
 | 
				
			||||||
 | 
									<i class="fa fa-2x fa-fw fa-edit"/>
 | 
				
			||||||
 | 
								</button>
 | 
				
			||||||
 | 
							</router-link>
 | 
				
			||||||
 | 
							<hr>
 | 
				
			||||||
 | 
						</div>
 | 
				
			||||||
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					<script setup>
 | 
				
			||||||
 | 
					import { reactive, watchEffect, computed } from 'vue'
 | 
				
			||||||
 | 
					import axios from 'axios'
 | 
				
			||||||
 | 
					//import h from 'highlightjs'
 | 
				
			||||||
 | 
					//import hi from 'highlightjs-line-numbers.js'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					//hi.highlightAll()
 | 
				
			||||||
 | 
					//hi.initLineNumbersOnLoad()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const props = defineProps({
 | 
				
			||||||
 | 
						slug: {
 | 
				
			||||||
 | 
							type: String,
 | 
				
			||||||
 | 
							required: true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					let page = reactive({ name: '', slug: '' })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const editTarget = computed(() => {
 | 
				
			||||||
 | 
						if (page) {
 | 
				
			||||||
 | 
							return `/pages/edit/${page.slug}`
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return ''
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const getPagesDetails = async (slug) => {
 | 
				
			||||||
 | 
						console.log('get page details')
 | 
				
			||||||
 | 
						await axios.get(`/api/pages?slug=${slug}`)
 | 
				
			||||||
 | 
							.then((response) => {
 | 
				
			||||||
 | 
								page = response.data['hydra:member']
 | 
				
			||||||
 | 
								console.log(page)
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// watch fpr slug
 | 
				
			||||||
 | 
					watchEffect(() => getPagesDetails(props.slug))
 | 
				
			||||||
 | 
					</script>
 | 
				
			||||||
@@ -6,28 +6,57 @@
 | 
				
			|||||||
		<tabs-group @tabActivated="tabActivated">
 | 
							<tabs-group @tabActivated="tabActivated">
 | 
				
			||||||
			<tab-content title="Visual Editor">
 | 
								<tab-content title="Visual Editor">
 | 
				
			||||||
				<div class="editor mt-2">
 | 
									<div class="editor mt-2">
 | 
				
			||||||
					<VueEditor
 | 
										<QuillEditor
 | 
				
			||||||
						v-model="page.content"
 | 
											ref="editor"
 | 
				
			||||||
						:editor-options="editorOptions"
 | 
											theme="snow"
 | 
				
			||||||
 | 
											:content="JSON.parse(page.content)"
 | 
				
			||||||
 | 
											:options="editorOptions"
 | 
				
			||||||
						:disabled="isVueEditorDisabled"
 | 
											:disabled="isVueEditorDisabled"
 | 
				
			||||||
					/>
 | 
										/>
 | 
				
			||||||
 | 
										<button
 | 
				
			||||||
 | 
											class="btn btn-primary mt-3 mb-2"
 | 
				
			||||||
 | 
											@click="saveContent"
 | 
				
			||||||
 | 
										>
 | 
				
			||||||
 | 
											Save
 | 
				
			||||||
 | 
										</button>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
			</tab-content>
 | 
								</tab-content>
 | 
				
			||||||
			<tab-content title="Raw Content">
 | 
								<tab-content title="Preview">
 | 
				
			||||||
 | 
									<div class="preview mt-2 no-overflow">
 | 
				
			||||||
 | 
										<QuillEditor
 | 
				
			||||||
 | 
											ref="preview"
 | 
				
			||||||
 | 
											theme="bubble"
 | 
				
			||||||
 | 
											class="no-overflow"
 | 
				
			||||||
 | 
											:content="JSON.parse(page.content)"
 | 
				
			||||||
 | 
											:options="editorOptions"
 | 
				
			||||||
 | 
											:disabled="true"
 | 
				
			||||||
 | 
										/>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
									<!--
 | 
				
			||||||
				<div>
 | 
									<div>
 | 
				
			||||||
					<textarea
 | 
										<textarea
 | 
				
			||||||
						v-model="page.content"
 | 
											v-model="page.content"
 | 
				
			||||||
						class="p-fluid pages-editor-raw"
 | 
											class="p-fluid pages-editor-raw"
 | 
				
			||||||
					/>
 | 
										/>
 | 
				
			||||||
				</div>
 | 
									</div>
 | 
				
			||||||
 | 
									-->
 | 
				
			||||||
 | 
								</tab-content>
 | 
				
			||||||
 | 
								<tab-content title="Delta">
 | 
				
			||||||
 | 
									<div class="editor mt-2">
 | 
				
			||||||
 | 
										<textarea
 | 
				
			||||||
 | 
											ref="delta"
 | 
				
			||||||
 | 
											v-model="page.content"
 | 
				
			||||||
 | 
											class="p-fluid pages-editor-raw"
 | 
				
			||||||
 | 
										/>
 | 
				
			||||||
 | 
									</div>
 | 
				
			||||||
 | 
									<button
 | 
				
			||||||
 | 
										class="btn btn-primary mt-3 mb-2"
 | 
				
			||||||
 | 
										@click="saveDelta"
 | 
				
			||||||
 | 
									>
 | 
				
			||||||
 | 
										Save
 | 
				
			||||||
 | 
									</button>
 | 
				
			||||||
			</tab-content>
 | 
								</tab-content>
 | 
				
			||||||
		</tabs-group>
 | 
							</tabs-group>
 | 
				
			||||||
		<button
 | 
					 | 
				
			||||||
			class="btn btn-primary mt-3 mb-2"
 | 
					 | 
				
			||||||
			@click="saveContent"
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
			Save
 | 
					 | 
				
			||||||
		</button>
 | 
					 | 
				
			||||||
	</div>
 | 
						</div>
 | 
				
			||||||
	<div v-else>
 | 
						<div v-else>
 | 
				
			||||||
		<i class="fa fa-spinner fa-spin fa-3x fa-fw"/>
 | 
							<i class="fa fa-spinner fa-spin fa-3x fa-fw"/>
 | 
				
			||||||
@@ -39,20 +68,31 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import axios from 'axios'
 | 
					import axios from 'axios'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// Basic Use - Covers most scenarios
 | 
					import 'highlight.js/styles/tomorrow-night-blue.css'
 | 
				
			||||||
// https://github.com/davidroyer/vue2-editor => docs apply for version 3, too
 | 
					import hljs from 'highlight.js'
 | 
				
			||||||
import { VueEditor } from 'vue3-editor'
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
import hljs from 'highlightjs'
 | 
					//import Quill from 'quill'
 | 
				
			||||||
import 'highlightjs/styles/dracula.css'
 | 
					import { Quill, QuillEditor } from '@vueup/vue-quill'
 | 
				
			||||||
 | 
					import '@vueup/vue-quill/dist/vue-quill.snow.css'
 | 
				
			||||||
 | 
					import '@vueup/vue-quill/dist/vue-quill.bubble.css'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import htmlEditButton from 'quill-html-edit-button'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import TabsGroup from '@/components/tabs/TabsGroup'
 | 
					import TabsGroup from '@/components/tabs/TabsGroup'
 | 
				
			||||||
import TabContent from '@/components/tabs/TabContent'
 | 
					import TabContent from '@/components/tabs/TabContent'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Quill
 | 
				
			||||||
 | 
					//	.register('modules/syntax', syntax, false)
 | 
				
			||||||
 | 
						.register('modules/htmlEditButton', htmlEditButton)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					hljs.configure({
 | 
				
			||||||
 | 
						languages: ['javascript', 'php', 'swift']
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					export default {
 | 
				
			||||||
	name: 'PagesEdit',
 | 
						name: 'PagesEdit',
 | 
				
			||||||
	components: {
 | 
						components: {
 | 
				
			||||||
		VueEditor,
 | 
							QuillEditor,
 | 
				
			||||||
		TabsGroup,
 | 
							TabsGroup,
 | 
				
			||||||
		TabContent
 | 
							TabContent
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
@@ -62,12 +102,15 @@ export default {
 | 
				
			|||||||
		isVueEditorDisabled: false,
 | 
							isVueEditorDisabled: false,
 | 
				
			||||||
		editorOptions: {
 | 
							editorOptions: {
 | 
				
			||||||
			modules: {
 | 
								modules: {
 | 
				
			||||||
 | 
									htmlEditButton: {
 | 
				
			||||||
 | 
										debug: true
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
				syntax: {
 | 
									syntax: {
 | 
				
			||||||
					highlight: (text) => hljs.highlightAuto(text).value
 | 
										highlight: (text) => hljs.highlightAuto(text).value
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			},
 | 
								}
 | 
				
			||||||
			theme: 'snow'
 | 
							},
 | 
				
			||||||
		}
 | 
							theme: 'snow'
 | 
				
			||||||
	}),
 | 
						}),
 | 
				
			||||||
	beforeMount() {
 | 
						beforeMount() {
 | 
				
			||||||
		const { slug } = this.$route.params
 | 
							const { slug } = this.$route.params
 | 
				
			||||||
@@ -81,13 +124,24 @@ export default {
 | 
				
			|||||||
	},
 | 
						},
 | 
				
			||||||
	methods: {
 | 
						methods: {
 | 
				
			||||||
		saveContent() {
 | 
							saveContent() {
 | 
				
			||||||
 | 
								this.page.content = JSON.stringify(this.$refs.editor.getContents())
 | 
				
			||||||
			axios
 | 
								axios
 | 
				
			||||||
				.put(`/api/pages/${this.page.id}`, this.page)
 | 
									.put(`/api/pages/${this.page.id}`, this.page)
 | 
				
			||||||
				.then(() => {
 | 
									.then(() => {
 | 
				
			||||||
					this.$router.push({
 | 
										//this.$router.push({
 | 
				
			||||||
						name: 'Pages',
 | 
										//	name: 'Pages',
 | 
				
			||||||
						params: { slug: this.page.slug }
 | 
										//	params: { slug: this.page.slug }
 | 
				
			||||||
					})
 | 
										//})
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							saveDelta() {
 | 
				
			||||||
 | 
								axios
 | 
				
			||||||
 | 
									.put(`/api/pages/${this.page.id}`, this.page)
 | 
				
			||||||
 | 
									.then(() => {
 | 
				
			||||||
 | 
										//this.$router.push({
 | 
				
			||||||
 | 
										//	name: 'Pages',
 | 
				
			||||||
 | 
										//	params: { slug: this.page.slug }
 | 
				
			||||||
 | 
										//})
 | 
				
			||||||
				})
 | 
									})
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
		tabActivated(name) {
 | 
							tabActivated(name) {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,69 +0,0 @@
 | 
				
			|||||||
<template>
 | 
					 | 
				
			||||||
	<div class="box ma7 p-5">
 | 
					 | 
				
			||||||
		<h2
 | 
					 | 
				
			||||||
			v-if="page"
 | 
					 | 
				
			||||||
			v-html="page.name"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
		<div
 | 
					 | 
				
			||||||
			v-if="page"
 | 
					 | 
				
			||||||
			v-html="page.content"
 | 
					 | 
				
			||||||
		/>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		<router-link
 | 
					 | 
				
			||||||
			:to="editTarget"
 | 
					 | 
				
			||||||
			variant="outline"
 | 
					 | 
				
			||||||
		>
 | 
					 | 
				
			||||||
			<button>
 | 
					 | 
				
			||||||
				<i class="fa fa-2x fa-fw fa-edit"/>
 | 
					 | 
				
			||||||
			</button>
 | 
					 | 
				
			||||||
		</router-link>
 | 
					 | 
				
			||||||
		<hr>
 | 
					 | 
				
			||||||
	</div>
 | 
					 | 
				
			||||||
</template>
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
<script>
 | 
					 | 
				
			||||||
import axios from 'axios'
 | 
					 | 
				
			||||||
//import h from 'highlightjs'
 | 
					 | 
				
			||||||
//import hi from 'highlightjs-line-numbers.js'
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
//hi.highlightAll()
 | 
					 | 
				
			||||||
//hi.initLineNumbersOnLoad()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
export default {
 | 
					 | 
				
			||||||
	name: 'PagesDisplay',
 | 
					 | 
				
			||||||
	props: {
 | 
					 | 
				
			||||||
		slug: {
 | 
					 | 
				
			||||||
			type: String,
 | 
					 | 
				
			||||||
			required: true
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	data: () => ({
 | 
					 | 
				
			||||||
		page: null
 | 
					 | 
				
			||||||
	}),
 | 
					 | 
				
			||||||
	computed: {
 | 
					 | 
				
			||||||
		editTarget() {
 | 
					 | 
				
			||||||
			if (this.page) {
 | 
					 | 
				
			||||||
				return `/pages/edit/${this.page.slug}`
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return ''
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	beforeMount() {
 | 
					 | 
				
			||||||
		this.getPagesDetails()
 | 
					 | 
				
			||||||
		this.$watch(
 | 
					 | 
				
			||||||
			() => this.slug,
 | 
					 | 
				
			||||||
			() => {
 | 
					 | 
				
			||||||
				this.getPagesDetails()
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		)
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	methods: {
 | 
					 | 
				
			||||||
		async getPagesDetails() {
 | 
					 | 
				
			||||||
			await axios.get(`/api/pages?slug=${this.slug}`)
 | 
					 | 
				
			||||||
				.then((response) => {
 | 
					 | 
				
			||||||
					[this.page] = response.data['hydra:member']
 | 
					 | 
				
			||||||
				})
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
</script>
 | 
					 | 
				
			||||||
@@ -5,6 +5,7 @@
 | 
				
			|||||||
				v-for="title in tabTitles"
 | 
									v-for="title in tabTitles"
 | 
				
			||||||
				:key="title"
 | 
									:key="title"
 | 
				
			||||||
				:class="{ selected: title === selectedTitle }"
 | 
									:class="{ selected: title === selectedTitle }"
 | 
				
			||||||
 | 
									class="btn"
 | 
				
			||||||
				@click="handleClick(title)"
 | 
									@click="handleClick(title)"
 | 
				
			||||||
			>
 | 
								>
 | 
				
			||||||
				{{ title }}
 | 
									{{ title }}
 | 
				
			||||||
@@ -39,7 +40,9 @@ export default {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<style>
 | 
					<style lang="scss">
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@import "~styles/app.scss";
 | 
				
			||||||
.tabs {
 | 
					.tabs {
 | 
				
			||||||
	width: auto;
 | 
						width: auto;
 | 
				
			||||||
	margin: 0 auto;
 | 
						margin: 0 auto;
 | 
				
			||||||
@@ -56,15 +59,20 @@ export default {
 | 
				
			|||||||
	text-align: center;
 | 
						text-align: center;
 | 
				
			||||||
	padding: 10px 20px;
 | 
						padding: 10px 20px;
 | 
				
			||||||
	margin-right: 10px;
 | 
						margin-right: 10px;
 | 
				
			||||||
	background-color: #ddd;
 | 
						background-color: #2e2e2e;
 | 
				
			||||||
	border-radius: 5px;
 | 
						border-radius: 5px;
 | 
				
			||||||
	color: black;
 | 
						color: #999999;
 | 
				
			||||||
	cursor: pointer;
 | 
						cursor: pointer;
 | 
				
			||||||
	transition: 0.4s all ease-out;
 | 
						transition: 0.4s all ease-out;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.tabs-header li.selected {
 | 
					.tabs-header li.selected {
 | 
				
			||||||
	background-color: #0984e3;
 | 
						background-color: $primary;
 | 
				
			||||||
	color: white;
 | 
						color: $jet-black;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.tabs-header li.selected:hover {
 | 
				
			||||||
 | 
						border-color: $body-color;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -50,36 +50,38 @@
 | 
				
			|||||||
	</div>
 | 
						</div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
<script>
 | 
					<script setup>
 | 
				
			||||||
 | 
					import { ref, reactive } from 'vue'
 | 
				
			||||||
 | 
					import { useRouter, useRoute } from 'vue-router'
 | 
				
			||||||
import axios from 'axios'
 | 
					import axios from 'axios'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
export default {
 | 
					const user = reactive(null)
 | 
				
			||||||
	name: 'ProfileView',
 | 
					const isLoading = ref(true)
 | 
				
			||||||
	data: () => ({
 | 
					const router = useRouter()
 | 
				
			||||||
		user: null,
 | 
					const route = useRoute()
 | 
				
			||||||
		isLoading: true
 | 
					 | 
				
			||||||
	}),
 | 
					 | 
				
			||||||
	computed: {
 | 
					 | 
				
			||||||
		getUserEndpoint() {
 | 
					 | 
				
			||||||
			if (this.$route.params.username) {
 | 
					 | 
				
			||||||
				return `/api/users?username=${this.$route.params.username}`
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			return '/api/users?username=tracer'
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
	mounted() {
 | 
					 | 
				
			||||||
		axios
 | 
					 | 
				
			||||||
			.get(this.getUserEndpoint)
 | 
					 | 
				
			||||||
			.then((response) => {
 | 
					 | 
				
			||||||
				console.log(response);
 | 
					 | 
				
			||||||
				[this.user] = response.data['hydra:member']
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
				console.log(this.user)
 | 
					// if there is no param, we go to our own profile, elso to the login
 | 
				
			||||||
				this.isLoading = false
 | 
					
 | 
				
			||||||
			})
 | 
					if (route.params.username) {
 | 
				
			||||||
			.catch((error) => {
 | 
						console.log('we have the username')
 | 
				
			||||||
				console.log(error)
 | 
					} else if (window.user) {
 | 
				
			||||||
			})
 | 
						console.log(window.user)
 | 
				
			||||||
	}
 | 
					} else {
 | 
				
			||||||
 | 
						router.push({ name: 'LoginForm' })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const userEndpoint = '/api/users?username=tracer'
 | 
				
			||||||
 | 
					axios
 | 
				
			||||||
 | 
						.get(userEndpoint)
 | 
				
			||||||
 | 
						.then((response) => {
 | 
				
			||||||
 | 
							//console.log(response);
 | 
				
			||||||
 | 
							[user.value] = response.data['hydra:member']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							//console.log(this.user)
 | 
				
			||||||
 | 
							isLoading.value = false
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						.catch(() => {
 | 
				
			||||||
 | 
							//console.log(error)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										29
									
								
								assets/js/composables/useResource.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								assets/js/composables/useResource.js
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					import { ref } from 'vue'
 | 
				
			||||||
 | 
					import axios from 'axios'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export default function useResource(resource) {
 | 
				
			||||||
 | 
						console.log('useBlog')
 | 
				
			||||||
 | 
						const items = ref([])
 | 
				
			||||||
 | 
						const item = ref(null)
 | 
				
			||||||
 | 
						const fetchAll = async () => {
 | 
				
			||||||
 | 
							await axios
 | 
				
			||||||
 | 
								.get(resource)
 | 
				
			||||||
 | 
								.then((response) => {
 | 
				
			||||||
 | 
									items.value = response.data
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						const fetchOne = async (id) => {
 | 
				
			||||||
 | 
							console.log('fetchOne', id)
 | 
				
			||||||
 | 
							await axios
 | 
				
			||||||
 | 
								.get(`${resource}/${id}`)
 | 
				
			||||||
 | 
								.then((response) => {
 | 
				
			||||||
 | 
									item.value = response.data
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return {
 | 
				
			||||||
 | 
							items,
 | 
				
			||||||
 | 
							fetchAll,
 | 
				
			||||||
 | 
							item,
 | 
				
			||||||
 | 
							fetchOne
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -11,10 +11,11 @@ import 'bootstrap/dist/js/bootstrap'
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
import { createPinia } from 'pinia'
 | 
					import { createPinia } from 'pinia'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import VueHighLightJS from 'vue3-highlightjs'
 | 
					//import { QuillEditor } from '@vueup/vue-quill'
 | 
				
			||||||
import 'vue3-highlightjs/styles/dracula.css'
 | 
					//import '@vueup/vue-quill/dist/vue-quill.snow.css'
 | 
				
			||||||
 | 
					//import '@vueup/vue-quill/dist/vue-quill.bubble.css'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import Router from '@/router'
 | 
					import router from '@/router'
 | 
				
			||||||
import AppLink from '@/components/AppLink'
 | 
					import AppLink from '@/components/AppLink'
 | 
				
			||||||
import App from '@/App'
 | 
					import App from '@/App'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -48,7 +49,7 @@ _paq.push(['enableLinkTracking']);
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
createApp(App)
 | 
					createApp(App)
 | 
				
			||||||
	.component('AppLink', AppLink)
 | 
						.component('AppLink', AppLink)
 | 
				
			||||||
 | 
					//	.component('QuillEditor', QuillEditor)
 | 
				
			||||||
	.use(createPinia())
 | 
						.use(createPinia())
 | 
				
			||||||
	.use(VueHighLightJS)
 | 
						.use(router)
 | 
				
			||||||
	.use(Router)
 | 
					 | 
				
			||||||
	.mount('#app')
 | 
						.mount('#app')
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,14 @@
 | 
				
			|||||||
import { createRouter, createWebHistory } from 'vue-router'
 | 
					import { createRouter, createWebHistory } from 'vue-router'
 | 
				
			||||||
import LoginForm from '@/components/LoginForm'
 | 
					import LoginForm from '@/components/LoginForm'
 | 
				
			||||||
import Quotes from '@/components/quotes'
 | 
					import Quotes from '@/components/quotes'
 | 
				
			||||||
import Pages from '@/components/pages'
 | 
					import Pages from '@/components/pages/PagesIndex'
 | 
				
			||||||
import PagesEdit from '@/components/pages/edit'
 | 
					import PagesEdit from '@/components/pages/edit'
 | 
				
			||||||
import ProjectsList from '@/components/projects'
 | 
					import ProjectsList from '@/components/projects'
 | 
				
			||||||
import ProjectsDetails from '@/components/projects/ProjectDetails'
 | 
					import ProjectsDetails from '@/components/projects/ProjectDetails'
 | 
				
			||||||
 | 
					import BlogIndex from '@/components/blog/BlogIndex'
 | 
				
			||||||
 | 
					import BlogPost from '@/components/blog/BlogPost'
 | 
				
			||||||
import ProfileView from '@/components/users/ProfileView'
 | 
					import ProfileView from '@/components/users/ProfileView'
 | 
				
			||||||
 | 
					import TheAbout from '@/components/TheAbout'
 | 
				
			||||||
import NotFound from '@/components/NotFound'
 | 
					import NotFound from '@/components/NotFound'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const routes = [
 | 
					const routes = [
 | 
				
			||||||
@@ -14,6 +17,11 @@ const routes = [
 | 
				
			|||||||
		name: 'Home',
 | 
							name: 'Home',
 | 
				
			||||||
		component: Quotes
 | 
							component: Quotes
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							path: '/about',
 | 
				
			||||||
 | 
							name: 'About',
 | 
				
			||||||
 | 
							component: TheAbout
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		path: '/form_login',
 | 
							path: '/form_login',
 | 
				
			||||||
		name: 'LoginForm',
 | 
							name: 'LoginForm',
 | 
				
			||||||
@@ -29,6 +37,16 @@ const routes = [
 | 
				
			|||||||
		name: 'ProjectDetails',
 | 
							name: 'ProjectDetails',
 | 
				
			||||||
		component: ProjectsDetails
 | 
							component: ProjectsDetails
 | 
				
			||||||
	},
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							path: '/blog',
 | 
				
			||||||
 | 
							name: 'Blog',
 | 
				
			||||||
 | 
							component: BlogIndex
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
 | 
						{
 | 
				
			||||||
 | 
							path: '/blog/post/:id',
 | 
				
			||||||
 | 
							name: 'BlogPost',
 | 
				
			||||||
 | 
							component: BlogPost
 | 
				
			||||||
 | 
						},
 | 
				
			||||||
	{
 | 
						{
 | 
				
			||||||
		path: '/pages/:slug',
 | 
							path: '/pages/:slug',
 | 
				
			||||||
		name: 'Pages',
 | 
							name: 'Pages',
 | 
				
			||||||
@@ -57,10 +75,12 @@ const router = createRouter({
 | 
				
			|||||||
	routes
 | 
						routes
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* eslint-disable */
 | 
					/*
 | 
				
			||||||
router.beforeEach((to) => {
 | 
					router.beforeEach((to) => {
 | 
				
			||||||
	if (to.meta.requiredAuth && !window.user) {
 | 
						if (to.meta.requiredAuth && !window.user) {
 | 
				
			||||||
		return { name: 'LoginForm' }
 | 
							return { name: 'LoginForm' }
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
})
 | 
					})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
export default router
 | 
					export default router
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -68,6 +68,11 @@ $mango: #FF8040;
 | 
				
			|||||||
  height: 650px !important;
 | 
					  height: 650px !important;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.no-overflow {
 | 
				
			||||||
 | 
					  overflow-y: visible !important;
 | 
				
			||||||
 | 
					  height: auto !important;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.ql-syntax {
 | 
					.ql-syntax {
 | 
				
			||||||
  background-color: #222222;
 | 
					  background-color: #222222;
 | 
				
			||||||
  border: 1px solid #888;
 | 
					  border: 1px solid #888;
 | 
				
			||||||
@@ -85,11 +90,37 @@ $mango: #FF8040;
 | 
				
			|||||||
  word-wrap: break-word;
 | 
					  word-wrap: break-word;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ql-editor {
 | 
				
			||||||
 | 
					  counter-reset: line;
 | 
				
			||||||
 | 
					  padding-left: 0;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ql-editor div:before {
 | 
				
			||||||
 | 
					  counter-increment: line;
 | 
				
			||||||
 | 
					  content: counter(line);
 | 
				
			||||||
 | 
					  display: inline-block;
 | 
				
			||||||
 | 
					  border-right: 1px solid red;
 | 
				
			||||||
 | 
					  padding: 0 .5em;
 | 
				
			||||||
 | 
					  margin-right: .5em;
 | 
				
			||||||
 | 
					  color: #888
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.ql-syntax pre:before {
 | 
				
			||||||
 | 
					  counter-increment: line;
 | 
				
			||||||
 | 
					  content: counter(line);
 | 
				
			||||||
 | 
					  display: inline-block;
 | 
				
			||||||
 | 
					  border-right: 1px solid #ddd;
 | 
				
			||||||
 | 
					  padding: 2px .5em;
 | 
				
			||||||
 | 
					  margin-right: .5em;
 | 
				
			||||||
 | 
					  color: #888
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					/*
 | 
				
			||||||
pre span.hljs-tag::before, span.hljs-attr::before {
 | 
					pre span.hljs-tag::before, span.hljs-attr::before {
 | 
				
			||||||
  content: "xxx";
 | 
					  content: "xxx";
 | 
				
			||||||
  display: inline-block;
 | 
					  display: inline-block;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.wrapper {
 | 
					.wrapper {
 | 
				
			||||||
  clear: both;
 | 
					  clear: both;
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										14
									
								
								package.json
									
									
									
									
									
								
							
							
						
						
									
										14
									
								
								package.json
									
									
									
									
									
								
							@@ -26,28 +26,26 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "dependencies": {
 | 
					    "dependencies": {
 | 
				
			||||||
        "@fortawesome/fontawesome-free": "^6.1.1",
 | 
					        "@fortawesome/fontawesome-free": "^6.1.1",
 | 
				
			||||||
 | 
					        "@vueup/vue-quill": "^1.0.0-beta.8",
 | 
				
			||||||
        "axios": "^0.27.1",
 | 
					        "axios": "^0.27.1",
 | 
				
			||||||
        "bootsdark": "^1.0.16",
 | 
					        "bootsdark": "^1.0.16",
 | 
				
			||||||
        "bootstrap": "^5.1.3",
 | 
					        "bootstrap": "^5.1.3",
 | 
				
			||||||
        "ckeditor": "^4.12.1",
 | 
					        "eslint": "^8.15.0",
 | 
				
			||||||
        "ckeditor4": "^4.18.0",
 | 
					 | 
				
			||||||
        "eslint": "^8.14.0",
 | 
					 | 
				
			||||||
        "eslint-config-airbnb-base": "^15.0.0",
 | 
					        "eslint-config-airbnb-base": "^15.0.0",
 | 
				
			||||||
        "eslint-plugin-import": "^2.26.0",
 | 
					        "eslint-plugin-import": "^2.26.0",
 | 
				
			||||||
        "eslint-plugin-vue": "^8.7.1",
 | 
					        "eslint-plugin-vue": "^8.7.1",
 | 
				
			||||||
        "fork-awesome": "^1.2.0",
 | 
					        "fork-awesome": "^1.2.0",
 | 
				
			||||||
        "highlightjs": "^9.16.2",
 | 
					        "highlight.js": "^11.5.1",
 | 
				
			||||||
        "highlightjs-line-numbers.js": "^2.8.0",
 | 
					 | 
				
			||||||
        "husky": "^7.0.4",
 | 
					        "husky": "^7.0.4",
 | 
				
			||||||
        "less": "^4.1.2",
 | 
					        "less": "^4.1.2",
 | 
				
			||||||
        "marked": "^4.0.15",
 | 
					        "marked": "^4.0.15",
 | 
				
			||||||
        "pinia": "^2.0.14",
 | 
					        "pinia": "^2.0.14",
 | 
				
			||||||
        "popper.js": "^1.16.1",
 | 
					        "popper.js": "^1.16.1",
 | 
				
			||||||
        "primevue": "^3.12.6",
 | 
					        "primevue": "^3.12.6",
 | 
				
			||||||
 | 
					        "quill": "^1.3.7",
 | 
				
			||||||
 | 
					        "quill-html-edit-button": "^2.2.12",
 | 
				
			||||||
        "vue": "3",
 | 
					        "vue": "3",
 | 
				
			||||||
        "vue-navigation-bar": "^5.0.0",
 | 
					        "vue-navigation-bar": "^5.0.0",
 | 
				
			||||||
        "vue-router": "4",
 | 
					        "vue-router": "4"
 | 
				
			||||||
        "vue3-editor": "^0.1.1",
 | 
					 | 
				
			||||||
        "vue3-highlightjs": "^1.0.5"
 | 
					 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,7 +35,7 @@ Encore
 | 
				
			|||||||
		styles: path.resolve(__dirname, 'assets', 'styles')
 | 
							styles: path.resolve(__dirname, 'assets', 'styles')
 | 
				
			||||||
	})
 | 
						})
 | 
				
			||||||
	.enableSassLoader()
 | 
						.enableSassLoader()
 | 
				
			||||||
	.enableVueLoader()
 | 
						.enableVueLoader(() => {}, { runtimeCompilerBuild: false })
 | 
				
			||||||
	.enableTypeScriptLoader()
 | 
						.enableTypeScriptLoader()
 | 
				
			||||||
	.autoProvidejQuery()
 | 
						.autoProvidejQuery()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user