- App
- Moodboard
- Wireframe
- Maquette
- Technologies
- multilingual
- Security
- Test
- Continuous integration
- Screenshots
- Contact
This website was created for a photographer, it's a full stack javascript project.
The visitor can browse the website, explore the galleries, contat the photographer...
The client, the photographer, can admin the website:
- edit the gallery
- edit the home caroussel
- post the picture of the month
- see average rating of the month photo
The super Admin can do the same plus:
- edit the email
- create or delete an admin
- node.js
- mysql
- SQL database
- bcrypt
- jsonwebtoken
- express
- middleware
- vue.js
- vue-i18n
- vuex
- vueRouter
- vuelidate
- vue-axios
- vuex-persistedstate
- bootstrap-vue
- multer
- vue-cool-lightbox
- ...
The website is multilingual, i use vue-i18n
Local Switcher example (use to switch language):
<template>
<div class="locale-switcher">
<select v-model="$i18n.locale">
<option value="fr">🇫🇷</option>
<option value="en">🇬🇧</option>
<option value="es">🇪🇸</option>
<option value="de">🇩🇪</option>
<option value="zh_CN">🇨🇳</option>
<option value="ru">🇷🇺</option>
<option value="ja">🇯🇵</option>
</select>
</div>
</template>
Example of use:
<h3>{{ $t("Biographie.third_Title") }}</h3>
- XSS: (cross-site scripting) all exterior data are check
- CSRF: (Cross Site Request Forgery) the admin route are protected by a midlleware checking token (JWT)
- Injection flaws: all input are properly filtered, plus the framework is secure
- Token, Hash Password (B-crypt), middleware, handle file format, check input...
Unit test: Vue-test-utils, Jest
A good test mut be quick to execute, easy to understand, and test one behavior at a time
Simple test Example:
Title Component
<template>
<h1 class="titrePage" data-test="titre-h1">{{ titre }}</h1>
</template>
<script>
/**
* @module component - TitreDePage
* @param {string} - titre
*/
export default {
name: "TitreDePage",
props: { titre: String },
};
</script>
Let's test it :
import { mount } from '@vue/test-utils'
import TitrePage from '@/components/Global/TitrePage.vue'
describe('TitrePage.vue', () => {
let wrapper
beforeAll(() => {
wrapper = mount(TitrePage, {
propsData: { titre: 'new titre' }
})
})
describe('Title of page', () => {
it('should be defined', () => {
expect(wrapper.exists()).toBeTruthy()
})
it('should containe h1', () => {
const titreH1 = wrapper.find('[data-test="titre-h1"]')
expect(titreH1.exists()).toBeTruthy()
expect(titreH1.tagName = 'h1').toBeTruthy()
})
it('renders props.titre when passed', () => {
const titre = 'new titre'
expect(wrapper.text()).toMatch(titre)
})
})
afterAll(() => {
wrapper.destroy()
})
})
- Travis Ci
- Coverall.io
Gallery:
Biography- multilingual:
Admin - edit gallery:
Super admin - edit admin:
Template email:
Project is: Finish