reset - start a new Portfolio with Adonis js

This commit is contained in:
Tutur33
2023-11-04 23:08:14 +01:00
parent 66c9f26ad5
commit b956f81990
96 changed files with 21633 additions and 375 deletions
+56
View File
@@ -0,0 +1,56 @@
{
"typescript": true,
"commands": [
"./commands",
"@adonisjs/core/build/commands/index.js",
"@adonisjs/repl/build/commands",
"@adonisjs/lucid/build/commands"
],
"exceptionHandlerNamespace": "App/Exceptions/Handler",
"aliases": {
"App": "app",
"Config": "config",
"Database": "database",
"Contracts": "contracts"
},
"preloads": [
"./start/routes",
"./start/kernel"
],
"providers": [
"./providers/AppProvider",
"@adonisjs/core",
"@adonisjs/session",
"@adonisjs/view",
"@adonisjs/shield",
"@adonisjs/lucid",
"@adonisjs/auth"
],
"metaFiles": [
{
"pattern": "public/**",
"reloadServer": false
},
{
"pattern": "resources/views/**/*.edge",
"reloadServer": false
}
],
"aceProviders": [
"@adonisjs/repl"
],
"tests": {
"suites": [
{
"name": "functional",
"files": [
"tests/functional/**/*.spec(.ts|.js)"
],
"timeout": 60000
}
]
},
"testProviders": [
"@japa/preset-adonis/TestsProvider"
]
}
+15
View File
@@ -0,0 +1,15 @@
root = true
[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.json]
insert_final_newline = false
[*.md]
trim_trailing_whitespace = false
+8
View File
@@ -0,0 +1,8 @@
PORT=3333
HOST=0.0.0.0
NODE_ENV=development
APP_KEY=-WaTKbETBJLut7cGRKrYHRqW1tqnxDad
DRIVE_DISK=local
SESSION_DRIVER=cookie
CACHE_VIEWS=false
DB_CONNECTION=sqlite
+3
View File
@@ -0,0 +1,3 @@
NODE_ENV=test
ASSETS_DRIVER=fake
SESSION_DRIVER=memory
+7
View File
@@ -0,0 +1,7 @@
node_modules
build
coverage
.vscode
.DS_STORE
.env
tmp
+1
View File
@@ -0,0 +1 @@
build
+16
View File
@@ -0,0 +1,16 @@
/*
|--------------------------------------------------------------------------
| Ace Commands
|--------------------------------------------------------------------------
|
| This file is the entry point for running ace commands.
|
*/
require('reflect-metadata')
require('source-map-support').install({ handleUncaughtExceptions: false })
const { Ignitor } = require('@adonisjs/core/build/standalone')
new Ignitor(__dirname)
.ace()
.handle(process.argv.slice(2))
+575
View File
@@ -0,0 +1,575 @@
{
"commands": {
"dump:rcfile": {
"settings": {},
"commandPath": "@adonisjs/core/build/commands/DumpRc",
"commandName": "dump:rcfile",
"description": "Dump contents of .adonisrc.json file along with defaults",
"args": [],
"aliases": [],
"flags": []
},
"list:routes": {
"settings": {
"loadApp": true,
"stayAlive": true
},
"commandPath": "@adonisjs/core/build/commands/ListRoutes/index",
"commandName": "list:routes",
"description": "List application routes",
"args": [],
"aliases": [],
"flags": [
{
"name": "verbose",
"propertyName": "verbose",
"type": "boolean",
"description": "Display more information"
},
{
"name": "reverse",
"propertyName": "reverse",
"type": "boolean",
"alias": "r",
"description": "Reverse routes display"
},
{
"name": "methods",
"propertyName": "methodsFilter",
"type": "array",
"alias": "m",
"description": "Filter routes by method"
},
{
"name": "patterns",
"propertyName": "patternsFilter",
"type": "array",
"alias": "p",
"description": "Filter routes by the route pattern"
},
{
"name": "names",
"propertyName": "namesFilter",
"type": "array",
"alias": "n",
"description": "Filter routes by route name"
},
{
"name": "json",
"propertyName": "json",
"type": "boolean",
"description": "Output as JSON"
},
{
"name": "table",
"propertyName": "table",
"type": "boolean",
"description": "Output as Table"
},
{
"name": "max-width",
"propertyName": "maxWidth",
"type": "number",
"description": "Specify maximum rendering width. Ignored for JSON Output"
}
]
},
"generate:key": {
"settings": {},
"commandPath": "@adonisjs/core/build/commands/GenerateKey",
"commandName": "generate:key",
"description": "Generate a new APP_KEY secret",
"args": [],
"aliases": [],
"flags": []
},
"repl": {
"settings": {
"loadApp": true,
"environment": "repl",
"stayAlive": true
},
"commandPath": "@adonisjs/repl/build/commands/AdonisRepl",
"commandName": "repl",
"description": "Start a new REPL session",
"args": [],
"aliases": [],
"flags": []
},
"db:seed": {
"settings": {
"loadApp": true
},
"commandPath": "@adonisjs/lucid/build/commands/DbSeed",
"commandName": "db:seed",
"description": "Execute database seeders",
"args": [],
"aliases": [],
"flags": [
{
"name": "connection",
"propertyName": "connection",
"type": "string",
"description": "Define a custom database connection for the seeders",
"alias": "c"
},
{
"name": "interactive",
"propertyName": "interactive",
"type": "boolean",
"description": "Run seeders in interactive mode",
"alias": "i"
},
{
"name": "files",
"propertyName": "files",
"type": "array",
"description": "Define a custom set of seeders files names to run",
"alias": "f"
},
{
"name": "compact-output",
"propertyName": "compactOutput",
"type": "boolean",
"description": "A compact single-line output"
}
]
},
"db:wipe": {
"settings": {
"loadApp": true
},
"commandPath": "@adonisjs/lucid/build/commands/DbWipe",
"commandName": "db:wipe",
"description": "Drop all tables, views and types in database",
"args": [],
"aliases": [],
"flags": [
{
"name": "connection",
"propertyName": "connection",
"type": "string",
"description": "Define a custom database connection",
"alias": "c"
},
{
"name": "drop-views",
"propertyName": "dropViews",
"type": "boolean",
"description": "Drop all views"
},
{
"name": "drop-types",
"propertyName": "dropTypes",
"type": "boolean",
"description": "Drop all custom types (Postgres only)"
},
{
"name": "force",
"propertyName": "force",
"type": "boolean",
"description": "Explicitly force command to run in production"
}
]
},
"db:truncate": {
"settings": {
"loadApp": true
},
"commandPath": "@adonisjs/lucid/build/commands/DbTruncate",
"commandName": "db:truncate",
"description": "Truncate all tables in database",
"args": [],
"aliases": [],
"flags": [
{
"name": "connection",
"propertyName": "connection",
"type": "string",
"description": "Define a custom database connection",
"alias": "c"
},
{
"name": "force",
"propertyName": "force",
"type": "boolean",
"description": "Explicitly force command to run in production"
}
]
},
"make:model": {
"settings": {
"loadApp": true
},
"commandPath": "@adonisjs/lucid/build/commands/MakeModel",
"commandName": "make:model",
"description": "Make a new Lucid model",
"args": [
{
"type": "string",
"propertyName": "name",
"name": "name",
"required": true,
"description": "Name of the model class"
}
],
"aliases": [],
"flags": [
{
"name": "migration",
"propertyName": "migration",
"type": "boolean",
"alias": "m",
"description": "Generate the migration for the model"
},
{
"name": "controller",
"propertyName": "controller",
"type": "boolean",
"alias": "c",
"description": "Generate the controller for the model"
},
{
"name": "factory",
"propertyName": "factory",
"type": "boolean",
"alias": "f",
"description": "Generate a factory for the model"
}
]
},
"make:migration": {
"settings": {
"loadApp": true
},
"commandPath": "@adonisjs/lucid/build/commands/MakeMigration",
"commandName": "make:migration",
"description": "Make a new migration file",
"args": [
{
"type": "string",
"propertyName": "name",
"name": "name",
"required": true,
"description": "Name of the migration file"
}
],
"aliases": [],
"flags": [
{
"name": "connection",
"propertyName": "connection",
"type": "string",
"description": "The connection flag is used to lookup the directory for the migration file"
},
{
"name": "folder",
"propertyName": "folder",
"type": "string",
"description": "Pre-select a migration directory"
},
{
"name": "create",
"propertyName": "create",
"type": "string",
"description": "Define the table name for creating a new table"
},
{
"name": "table",
"propertyName": "table",
"type": "string",
"description": "Define the table name for altering an existing table"
}
]
},
"make:seeder": {
"settings": {},
"commandPath": "@adonisjs/lucid/build/commands/MakeSeeder",
"commandName": "make:seeder",
"description": "Make a new Seeder file",
"args": [
{
"type": "string",
"propertyName": "name",
"name": "name",
"required": true,
"description": "Name of the seeder class"
}
],
"aliases": [],
"flags": []
},
"make:factory": {
"settings": {},
"commandPath": "@adonisjs/lucid/build/commands/MakeFactory",
"commandName": "make:factory",
"description": "Make a new factory",
"args": [
{
"type": "string",
"propertyName": "model",
"name": "model",
"required": true,
"description": "The name of the model"
}
],
"aliases": [],
"flags": [
{
"name": "model-path",
"propertyName": "modelPath",
"type": "string",
"description": "The path to the model"
},
{
"name": "exact",
"propertyName": "exact",
"type": "boolean",
"description": "Create the factory with the exact name as provided",
"alias": "e"
}
]
},
"migration:run": {
"settings": {
"loadApp": true
},
"commandPath": "@adonisjs/lucid/build/commands/Migration/Run",
"commandName": "migration:run",
"description": "Migrate database by running pending migrations",
"args": [],
"aliases": [],
"flags": [
{
"name": "connection",
"propertyName": "connection",
"type": "string",
"description": "Define a custom database connection",
"alias": "c"
},
{
"name": "force",
"propertyName": "force",
"type": "boolean",
"description": "Explicitly force to run migrations in production"
},
{
"name": "dry-run",
"propertyName": "dryRun",
"type": "boolean",
"description": "Do not run actual queries. Instead view the SQL output"
},
{
"name": "compact-output",
"propertyName": "compactOutput",
"type": "boolean",
"description": "A compact single-line output"
},
{
"name": "disable-locks",
"propertyName": "disableLocks",
"type": "boolean",
"description": "Disable locks acquired to run migrations safely"
}
]
},
"migration:rollback": {
"settings": {
"loadApp": true
},
"commandPath": "@adonisjs/lucid/build/commands/Migration/Rollback",
"commandName": "migration:rollback",
"description": "Rollback migrations to a specific batch number",
"args": [],
"aliases": [],
"flags": [
{
"name": "connection",
"propertyName": "connection",
"type": "string",
"description": "Define a custom database connection",
"alias": "c"
},
{
"name": "force",
"propertyName": "force",
"type": "boolean",
"description": "Explictly force to run migrations in production"
},
{
"name": "dry-run",
"propertyName": "dryRun",
"type": "boolean",
"description": "Do not run actual queries. Instead view the SQL output"
},
{
"name": "batch",
"propertyName": "batch",
"type": "number",
"description": "Define custom batch number for rollback. Use 0 to rollback to initial state"
},
{
"name": "compact-output",
"propertyName": "compactOutput",
"type": "boolean",
"description": "A compact single-line output"
},
{
"name": "disable-locks",
"propertyName": "disableLocks",
"type": "boolean",
"description": "Disable locks acquired to run migrations safely"
}
]
},
"migration:status": {
"settings": {
"loadApp": true
},
"commandPath": "@adonisjs/lucid/build/commands/Migration/Status",
"commandName": "migration:status",
"description": "View migrations status",
"args": [],
"aliases": [],
"flags": [
{
"name": "connection",
"propertyName": "connection",
"type": "string",
"description": "Define a custom database connection",
"alias": "c"
}
]
},
"migration:reset": {
"settings": {
"loadApp": true
},
"commandPath": "@adonisjs/lucid/build/commands/Migration/Reset",
"commandName": "migration:reset",
"description": "Rollback all migrations",
"args": [],
"aliases": [],
"flags": [
{
"name": "connection",
"propertyName": "connection",
"type": "string",
"description": "Define a custom database connection",
"alias": "c"
},
{
"name": "force",
"propertyName": "force",
"type": "boolean",
"description": "Explicitly force command to run in production"
},
{
"name": "dry-run",
"propertyName": "dryRun",
"type": "boolean",
"description": "Do not run actual queries. Instead view the SQL output"
},
{
"name": "disable-locks",
"propertyName": "disableLocks",
"type": "boolean",
"description": "Disable locks acquired to run migrations safely"
}
]
},
"migration:refresh": {
"settings": {
"loadApp": true
},
"commandPath": "@adonisjs/lucid/build/commands/Migration/Refresh",
"commandName": "migration:refresh",
"description": "Rollback and migrate database",
"args": [],
"aliases": [],
"flags": [
{
"name": "connection",
"propertyName": "connection",
"type": "string",
"description": "Define a custom database connection",
"alias": "c"
},
{
"name": "force",
"propertyName": "force",
"type": "boolean",
"description": "Explicitly force command to run in production"
},
{
"name": "dry-run",
"propertyName": "dryRun",
"type": "boolean",
"description": "Do not run actual queries. Instead view the SQL output"
},
{
"name": "seed",
"propertyName": "seed",
"type": "boolean",
"description": "Run seeders"
},
{
"name": "disable-locks",
"propertyName": "disableLocks",
"type": "boolean",
"description": "Disable locks acquired to run migrations safely"
}
]
},
"migration:fresh": {
"settings": {
"loadApp": true
},
"commandPath": "@adonisjs/lucid/build/commands/Migration/Fresh",
"commandName": "migration:fresh",
"description": "Drop all tables and re-migrate the database",
"args": [],
"aliases": [],
"flags": [
{
"name": "connection",
"propertyName": "connection",
"type": "string",
"description": "Define a custom database connection",
"alias": "c"
},
{
"name": "force",
"propertyName": "force",
"type": "boolean",
"description": "Explicitly force command to run in production"
},
{
"name": "seed",
"propertyName": "seed",
"type": "boolean",
"description": "Run seeders"
},
{
"name": "drop-views",
"propertyName": "dropViews",
"type": "boolean",
"description": "Drop all views"
},
{
"name": "drop-types",
"propertyName": "dropTypes",
"type": "boolean",
"description": "Drop all custom types (Postgres only)"
},
{
"name": "disable-locks",
"propertyName": "disableLocks",
"type": "boolean",
"description": "Disable locks acquired to run migrations safely"
}
]
}
},
"aliases": {}
}
+34
View File
@@ -0,0 +1,34 @@
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import User from 'App/Models/User'
import CreateUserValidator from 'App/Validators/CreateUserValidator'
export default class AuthController {
async index ({ view }: HttpContextContract) {
return view.render('auth')
}
async login ({request, auth, response, session}: HttpContextContract) {
const email = request.input('loginemail')
const password = request.input('loginpassword')
try {
await auth.use('web').attempt(email, password)
response.redirect().toRoute('home')
} catch {
session.flash({error: "Identifiant ou mot de passe incorrect"})
response.redirect().back()
}
}
async signup({ request, response }: HttpContextContract) {
const playload = await request.validate(CreateUserValidator)
await User.create(playload)
return response.redirect().toRoute('home')
}
async logout({ auth, response }:HttpContextContract) {
await auth.logout()
return response.redirect().back()
}
}
+33
View File
@@ -0,0 +1,33 @@
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
import ModifPseudoValidator from 'App/Validators/ModifPseudoValidator'
import ModifEmailValidator from 'App/Validators/ModifEmailValidator'
export default class ComptesController {
async index({ view }: HttpContextContract) {
return view.render('compte')
}
async modifpseudo({ request, auth, session, response }: HttpContextContract) {
const user = auth.user
await request.validate(ModifPseudoValidator)
user!.pseudo = request.input('pseudo')
await user!.save()
session.flash({success: "Username updated successfully"})
response.redirect().back()
}
async modifemail({ request, auth, session, response }: HttpContextContract) {
const user = auth.user
await request.validate(ModifEmailValidator)
user!.email = request.input('email')
await user!.save()
session.flash({success: "Email updated successfully"})
response.redirect().back()
}
}
+8
View File
@@ -0,0 +1,8 @@
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class HomeController {
async index ({ view }: HttpContextContract) {
return view.render('index')
}
}
@@ -0,0 +1,13 @@
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class ProjectsController {
async nups({ view }: HttpContextContract) {
return view.render('projects/nups/project-nups')
}
async nupsWeb({ view }: HttpContextContract) {
return view.render('projects/nups/nups')
}
}
+9
View File
@@ -0,0 +1,9 @@
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class TermsController {
async index({ view }: HttpContextContract) {
return view.render('terms')
}
}
+29
View File
@@ -0,0 +1,29 @@
/*
|--------------------------------------------------------------------------
| Http Exception Handler
|--------------------------------------------------------------------------
|
| AdonisJs will forward all exceptions occurred during an HTTP request to
| the following class. You can learn more about exception handling by
| reading docs.
|
| The exception handler extends a base `HttpExceptionHandler` which is not
| mandatory, however it can do lot of heavy lifting to handle the errors
| properly.
|
*/
import Logger from '@ioc:Adonis/Core/Logger'
import HttpExceptionHandler from '@ioc:Adonis/Core/HttpExceptionHandler'
export default class ExceptionHandler extends HttpExceptionHandler {
protected statusPages = {
'403': 'errors/unauthorized',
'404': 'errors/not-found',
'500..599': 'errors/server-error',
}
constructor() {
super(Logger)
}
}
+76
View File
@@ -0,0 +1,76 @@
import { AuthenticationException } from '@adonisjs/auth/build/standalone'
import type { GuardsList } from '@ioc:Adonis/Addons/Auth'
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
/**
* Auth middleware is meant to restrict un-authenticated access to a given route
* or a group of routes.
*
* You must register this middleware inside `start/kernel.ts` file under the list
* of named middleware.
*/
export default class AuthMiddleware {
/**
* The URL to redirect to when request is Unauthorized
*/
protected redirectTo = '/login'
/**
* Authenticates the current HTTP request against a custom set of defined
* guards.
*
* The authentication loop stops as soon as the user is authenticated using any
* of the mentioned guards and that guard will be used by the rest of the code
* during the current request.
*/
protected async authenticate(auth: HttpContextContract['auth'], guards: (keyof GuardsList)[]) {
/**
* Hold reference to the guard last attempted within the for loop. We pass
* the reference of the guard to the "AuthenticationException", so that
* it can decide the correct response behavior based upon the guard
* driver
*/
let guardLastAttempted: string | undefined
for (let guard of guards) {
guardLastAttempted = guard
if (await auth.use(guard).check()) {
/**
* Instruct auth to use the given guard as the default guard for
* the rest of the request, since the user authenticated
* succeeded here
*/
auth.defaultGuard = guard
return true
}
}
/**
* Unable to authenticate using any guard
*/
throw new AuthenticationException(
'Unauthorized access',
'E_UNAUTHORIZED_ACCESS',
guardLastAttempted,
this.redirectTo,
)
}
/**
* Handle request
*/
public async handle (
{ auth }: HttpContextContract,
next: () => Promise<void>,
customGuards: (keyof GuardsList)[]
) {
/**
* Uses the user defined guards or the default guard mentioned in
* the config file
*/
const guards = customGuards.length ? customGuards : [auth.name]
await this.authenticate(auth, guards)
await next()
}
}
+21
View File
@@ -0,0 +1,21 @@
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
/**
* Silent auth middleware can be used as a global middleware to silent check
* if the user is logged-in or not.
*
* The request continues as usual, even when the user is not logged-in.
*/
export default class SilentAuthMiddleware {
/**
* Handle request
*/
public async handle({ auth }: HttpContextContract, next: () => Promise<void>) {
/**
* Check if user is logged-in or not. If yes, then `ctx.auth.user` will be
* set to the instance of the currently logged in user.
*/
await auth.check()
await next()
}
}
+33
View File
@@ -0,0 +1,33 @@
import { DateTime } from 'luxon'
import Hash from '@ioc:Adonis/Core/Hash'
import { column, beforeSave, BaseModel } from '@ioc:Adonis/Lucid/Orm'
export default class User extends BaseModel {
@column({ isPrimary: true })
public id: number
@column()
public pseudo: string
@column()
public email: string
@column({ serializeAs: null })
public password: string
@column()
public rememberMeToken: string | null
@column.dateTime({ autoCreate: true })
public createdAt: DateTime
@column.dateTime({ autoCreate: true, autoUpdate: true })
public updatedAt: DateTime
@beforeSave()
public static async hashPassword (user: User) {
if (user.$dirty.password) {
user.password = await Hash.make(user.password)
}
}
}
+49
View File
@@ -0,0 +1,49 @@
import { schema, CustomMessages, rules } from '@ioc:Adonis/Core/Validator'
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class CreateUserValidator {
constructor(protected ctx: HttpContextContract) {}
/*
* Define schema to validate the "shape", "type", "formatting" and "integrity" of data.
*
* For example:
* 1. The username must be of data type string. But then also, it should
* not contain special characters or numbers.
* ```
* schema.string([ rules.alpha() ])
* ```
*
* 2. The email must be of data type string, formatted as a valid
* email. But also, not used by any other user.
* ```
* schema.string([
* rules.email(),
* rules.unique({ table: 'users', column: 'email' }),
* ])
* ```
*/
public schema = schema.create({
pseudo: schema.string(),
email: schema.string({}, [rules.email(), rules.unique({ table: 'users', column: 'email' }) ]),
password: schema.string({}, [rules.minLength(4), rules.confirmed() ])
})
/**
* Custom messages for validation failures. You can make use of dot notation `(.)`
* for targeting nested fields and array expressions `(*)` for targeting all
* children of an array. For example:
*
* {
* 'profile.username.required': 'Username is required',
* 'scores.*.number': 'Define scores as valid numbers'
* }
*
*/
public messages: CustomMessages = {
required: 'The {{ field }} is required to create a new account',
'email.email': 'Vous devez saisir un email dans le champ email',
'email.unique': 'Email is already in use',
'password.minLength': 'The password must be at least 4 characters long'
}
}
+46
View File
@@ -0,0 +1,46 @@
import { schema, CustomMessages, rules } from '@ioc:Adonis/Core/Validator'
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class ModifEmailValidator {
constructor(protected ctx: HttpContextContract) {}
/*
* Define schema to validate the "shape", "type", "formatting" and "integrity" of data.
*
* For example:
* 1. The username must be of data type string. But then also, it should
* not contain special characters or numbers.
* ```
* schema.string([ rules.alpha() ])
* ```
*
* 2. The email must be of data type string, formatted as a valid
* email. But also, not used by any other user.
* ```
* schema.string([
* rules.email(),
* rules.unique({ table: 'users', column: 'email' }),
* ])
* ```
*/
public schema = schema.create({
email: schema.string({}, [rules.email(), rules.unique({ table: 'users', column: 'email' }) ])
})
/**
* Custom messages for validation failures. You can make use of dot notation `(.)`
* for targeting nested fields and array expressions `(*)` for targeting all
* children of an array. For example:
*
* {
* 'profile.username.required': 'Username is required',
* 'scores.*.number': 'Define scores as valid numbers'
* }
*
*/
public messages: CustomMessages = {
required: 'The {{ field }} is required to modifie email',
'email.email': 'You must enter an email in the email field',
'email.unique': 'Email is already in use'
}
}
+45
View File
@@ -0,0 +1,45 @@
import { schema, CustomMessages, rules } from '@ioc:Adonis/Core/Validator'
import type { HttpContextContract } from '@ioc:Adonis/Core/HttpContext'
export default class ModifPseudoValidator {
constructor(protected ctx: HttpContextContract) {}
/*
* Define schema to validate the "shape", "type", "formatting" and "integrity" of data.
*
* For example:
* 1. The username must be of data type string. But then also, it should
* not contain special characters or numbers.
* ```
* schema.string([ rules.alpha() ])
* ```
*
* 2. The email must be of data type string, formatted as a valid
* email. But also, not used by any other user.
* ```
* schema.string([
* rules.email(),
* rules.unique({ table: 'users', column: 'email' }),
* ])
* ```
*/
public schema = schema.create({
pseudo: schema.string({}, [rules.minLength(3)])
})
/**
* Custom messages for validation failures. You can make use of dot notation `(.)`
* for targeting nested fields and array expressions `(*)` for targeting all
* children of an array. For example:
*
* {
* 'profile.username.required': 'Username is required',
* 'scores.*.number': 'Define scores as valid numbers'
* }
*
*/
public messages: CustomMessages = {
required: 'The {{ field }} is required to modifie pseudo',
'pseudo.minLength': 'The pseudo must be at least 3 characters long'
}
}
+19
View File
@@ -0,0 +1,19 @@
import { listDirectoryFiles } from '@adonisjs/core/build/standalone'
import Application from '@ioc:Adonis/Core/Application'
/*
|--------------------------------------------------------------------------
| Exporting an array of commands
|--------------------------------------------------------------------------
|
| Instead of manually exporting each file from this directory, we use the
| helper `listDirectoryFiles` to recursively collect and export an array
| of filenames.
|
| Couple of things to note:
|
| 1. The file path must be relative from the project root and not this directory.
| 2. We must ignore this file to avoid getting into an infinite loop
|
*/
export default listDirectoryFiles(__dirname, Application.appRoot, ['./commands/index'])
+276
View File
@@ -0,0 +1,276 @@
/**
* Config source: https://git.io/JfefZ
*
* Feel free to let us know via PR, if you find something broken in this config
* file.
*/
import proxyAddr from 'proxy-addr'
import Env from '@ioc:Adonis/Core/Env'
import Application from '@ioc:Adonis/Core/Application'
import type { ServerConfig } from '@ioc:Adonis/Core/Server'
import type { LoggerConfig } from '@ioc:Adonis/Core/Logger'
import type { ProfilerConfig } from '@ioc:Adonis/Core/Profiler'
import type { ValidatorConfig } from '@ioc:Adonis/Core/Validator'
import type { AssetsManagerConfig } from '@ioc:Adonis/Core/AssetsManager'
/*
|--------------------------------------------------------------------------
| Application secret key
|--------------------------------------------------------------------------
|
| The secret to encrypt and sign different values in your application.
| Make sure to keep the `APP_KEY` as an environment variable and secure.
|
| Note: Changing the application key for an existing app will make all
| the cookies invalid and also the existing encrypted data will not
| be decrypted.
|
*/
export const appKey: string = Env.get('APP_KEY')
/*
|--------------------------------------------------------------------------
| Http server configuration
|--------------------------------------------------------------------------
|
| The configuration for the HTTP(s) server. Make sure to go through all
| the config properties to make keep server secure.
|
*/
export const http: ServerConfig = {
/*
|--------------------------------------------------------------------------
| Allow method spoofing
|--------------------------------------------------------------------------
|
| Method spoofing enables defining custom HTTP methods using a query string
| `_method`. This is usually required when you are making traditional
| form requests and wants to use HTTP verbs like `PUT`, `DELETE` and
| so on.
|
*/
allowMethodSpoofing: false,
/*
|--------------------------------------------------------------------------
| Subdomain offset
|--------------------------------------------------------------------------
*/
subdomainOffset: 2,
/*
|--------------------------------------------------------------------------
| Request Ids
|--------------------------------------------------------------------------
|
| Setting this value to `true` will generate a unique request id for each
| HTTP request and set it as `x-request-id` header.
|
*/
generateRequestId: false,
/*
|--------------------------------------------------------------------------
| Trusting proxy servers
|--------------------------------------------------------------------------
|
| Define the proxy servers that AdonisJs must trust for reading `X-Forwarded`
| headers.
|
*/
trustProxy: proxyAddr.compile('loopback'),
/*
|--------------------------------------------------------------------------
| Generating Etag
|--------------------------------------------------------------------------
|
| Whether or not to generate an etag for every response.
|
*/
etag: false,
/*
|--------------------------------------------------------------------------
| JSONP Callback
|--------------------------------------------------------------------------
*/
jsonpCallbackName: 'callback',
/*
|--------------------------------------------------------------------------
| Cookie settings
|--------------------------------------------------------------------------
*/
cookie: {
domain: '',
path: '/',
maxAge: '2h',
httpOnly: true,
secure: false,
sameSite: false,
},
}
/*
|--------------------------------------------------------------------------
| Logger
|--------------------------------------------------------------------------
*/
export const logger: LoggerConfig = {
/*
|--------------------------------------------------------------------------
| Application name
|--------------------------------------------------------------------------
|
| The name of the application you want to add to the log. It is recommended
| to always have app name in every log line.
|
| The `APP_NAME` environment variable is automatically set by AdonisJS by
| reading the `name` property from the `package.json` file.
|
*/
name: Env.get('APP_NAME'),
/*
|--------------------------------------------------------------------------
| Toggle logger
|--------------------------------------------------------------------------
|
| Enable or disable logger application wide
|
*/
enabled: true,
/*
|--------------------------------------------------------------------------
| Logging level
|--------------------------------------------------------------------------
|
| The level from which you want the logger to flush logs. It is recommended
| to make use of the environment variable, so that you can define log levels
| at deployment level and not code level.
|
*/
level: Env.get('LOG_LEVEL', 'info'),
/*
|--------------------------------------------------------------------------
| Pretty print
|--------------------------------------------------------------------------
|
| It is highly advised NOT to use `prettyPrint` in production, since it
| can have huge impact on performance.
|
*/
prettyPrint: Env.get('NODE_ENV') === 'development',
}
/*
|--------------------------------------------------------------------------
| Profiler
|--------------------------------------------------------------------------
*/
export const profiler: ProfilerConfig = {
/*
|--------------------------------------------------------------------------
| Toggle profiler
|--------------------------------------------------------------------------
|
| Enable or disable profiler
|
*/
enabled: true,
/*
|--------------------------------------------------------------------------
| Blacklist actions/row labels
|--------------------------------------------------------------------------
|
| Define an array of actions or row labels that you want to disable from
| getting profiled.
|
*/
blacklist: [],
/*
|--------------------------------------------------------------------------
| Whitelist actions/row labels
|--------------------------------------------------------------------------
|
| Define an array of actions or row labels that you want to whitelist for
| the profiler. When whitelist is defined, then `blacklist` is ignored.
|
*/
whitelist: [],
}
/*
|--------------------------------------------------------------------------
| Validator
|--------------------------------------------------------------------------
|
| Configure the global configuration for the validator. Here's the reference
| to the default config https://git.io/JT0WE
|
*/
export const validator: ValidatorConfig = {}
/*
|--------------------------------------------------------------------------
| Assets
|--------------------------------------------------------------------------
|
| Configure the asset manager you are using to compile the frontend assets
|
*/
export const assets: AssetsManagerConfig = {
/*
|--------------------------------------------------------------------------
| Driver
|--------------------------------------------------------------------------
|
| Currently we only support webpack encore and may introduce more drivers
| in the future
|
*/
driver: Env.get('ASSETS_DRIVER'),
/*
|--------------------------------------------------------------------------
| Public path
|--------------------------------------------------------------------------
|
| Directory to search for the "manifest.json" and the "entrypoints.json"
| files
|
*/
publicPath: Application.publicPath('assets'),
/*
|--------------------------------------------------------------------------
| Script tag
|--------------------------------------------------------------------------
|
| Define attributes for the entryPointScripts tags
|
*/
script: {
attributes: {
defer: true,
},
},
/*
|--------------------------------------------------------------------------
| Style tag
|--------------------------------------------------------------------------
|
| Define attributes for the entryPointStyles tags
|
*/
style: {
attributes: {},
},
}
+86
View File
@@ -0,0 +1,86 @@
/**
* Config source: https://git.io/JY0mp
*
* Feel free to let us know via PR, if you find something broken in this config
* file.
*/
import type { AuthConfig } from '@ioc:Adonis/Addons/Auth'
/*
|--------------------------------------------------------------------------
| Authentication Mapping
|--------------------------------------------------------------------------
|
| List of available authentication mapping. You must first define them
| inside the `contracts/auth.ts` file before mentioning them here.
|
*/
const authConfig: AuthConfig = {
guard: 'web',
guards: {
/*
|--------------------------------------------------------------------------
| Web Guard
|--------------------------------------------------------------------------
|
| Web guard uses classic old school sessions for authenticating users.
| If you are building a standard web application, it is recommended to
| use web guard with session driver
|
*/
web: {
driver: 'session',
provider: {
/*
|--------------------------------------------------------------------------
| Driver
|--------------------------------------------------------------------------
|
| Name of the driver
|
*/
driver: 'lucid',
/*
|--------------------------------------------------------------------------
| Identifier key
|--------------------------------------------------------------------------
|
| The identifier key is the unique key on the model. In most cases specifying
| the primary key is the right choice.
|
*/
identifierKey: 'id',
/*
|--------------------------------------------------------------------------
| Uids
|--------------------------------------------------------------------------
|
| Uids are used to search a user against one of the mentioned columns. During
| login, the auth module will search the user mentioned value against one
| of the mentioned columns to find their user record.
|
*/
uids: ['email'],
/*
|--------------------------------------------------------------------------
| Model
|--------------------------------------------------------------------------
|
| The model to use for fetching or finding users. The model is imported
| lazily since the config files are read way earlier in the lifecycle
| of booting the app and the models may not be in a usable state at
| that time.
|
*/
model: () => import('App/Models/User'),
},
},
},
}
export default authConfig
+205
View File
@@ -0,0 +1,205 @@
/**
* Config source: https://git.io/Jfefn
*
* Feel free to let us know via PR, if you find something broken in this config
* file.
*/
import type { BodyParserConfig } from '@ioc:Adonis/Core/BodyParser'
const bodyParserConfig: BodyParserConfig = {
/*
|--------------------------------------------------------------------------
| White listed methods
|--------------------------------------------------------------------------
|
| HTTP methods for which body parsing must be performed. It is a good practice
| to avoid body parsing for `GET` requests.
|
*/
whitelistedMethods: ['POST', 'PUT', 'PATCH', 'DELETE'],
/*
|--------------------------------------------------------------------------
| JSON parser settings
|--------------------------------------------------------------------------
|
| The settings for the JSON parser. The types defines the request content
| types which gets processed by the JSON parser.
|
*/
json: {
encoding: 'utf-8',
limit: '1mb',
strict: true,
types: [
'application/json',
'application/json-patch+json',
'application/vnd.api+json',
'application/csp-report',
],
},
/*
|--------------------------------------------------------------------------
| Form parser settings
|--------------------------------------------------------------------------
|
| The settings for the `application/x-www-form-urlencoded` parser. The types
| defines the request content types which gets processed by the form parser.
|
*/
form: {
encoding: 'utf-8',
limit: '1mb',
queryString: {},
/*
|--------------------------------------------------------------------------
| Convert empty strings to null
|--------------------------------------------------------------------------
|
| Convert empty form fields to null. HTML forms results in field string
| value when the field is left blank. This option normalizes all the blank
| field values to "null"
|
*/
convertEmptyStringsToNull: true,
types: ['application/x-www-form-urlencoded'],
},
/*
|--------------------------------------------------------------------------
| Raw body parser settings
|--------------------------------------------------------------------------
|
| Raw body just reads the request body stream as a plain text, which you
| can process by hand. This must be used when request body type is not
| supported by the body parser.
|
*/
raw: {
encoding: 'utf-8',
limit: '1mb',
queryString: {},
types: ['text/*'],
},
/*
|--------------------------------------------------------------------------
| Multipart parser settings
|--------------------------------------------------------------------------
|
| The settings for the `multipart/form-data` parser. The types defines the
| request content types which gets processed by the form parser.
|
*/
multipart: {
/*
|--------------------------------------------------------------------------
| Auto process
|--------------------------------------------------------------------------
|
| The auto process option will process uploaded files and writes them to
| the `tmp` folder. You can turn it off and then manually use the stream
| to pipe stream to a different destination.
|
| It is recommended to keep `autoProcess=true`. Unless you are processing bigger
| file sizes.
|
*/
autoProcess: true,
/*
|--------------------------------------------------------------------------
| Files to be processed manually
|--------------------------------------------------------------------------
|
| You can turn off `autoProcess` for certain routes by defining
| routes inside the following array.
|
| NOTE: Make sure the route pattern starts with a leading slash.
|
| Correct
| ```js
| /projects/:id/file
| ```
|
| Incorrect
| ```js
| projects/:id/file
| ```
*/
processManually: [],
/*
|--------------------------------------------------------------------------
| Temporary file name
|--------------------------------------------------------------------------
|
| When auto processing is on. We will use this method to compute the temporary
| file name. AdonisJs will compute a unique `tmpPath` for you automatically,
| However, you can also define your own custom method.
|
*/
// tmpFileName () {
// },
/*
|--------------------------------------------------------------------------
| Encoding
|--------------------------------------------------------------------------
|
| Request body encoding
|
*/
encoding: 'utf-8',
/*
|--------------------------------------------------------------------------
| Convert empty strings to null
|--------------------------------------------------------------------------
|
| Convert empty form fields to null. HTML forms results in field string
| value when the field is left blank. This option normalizes all the blank
| field values to "null"
|
*/
convertEmptyStringsToNull: true,
/*
|--------------------------------------------------------------------------
| Max Fields
|--------------------------------------------------------------------------
|
| The maximum number of fields allowed in the request body. The field includes
| text inputs and files both.
|
*/
maxFields: 1000,
/*
|--------------------------------------------------------------------------
| Request body limit
|--------------------------------------------------------------------------
|
| The total limit to the multipart body. This includes all request files
| and fields data.
|
*/
limit: '20mb',
/*
|--------------------------------------------------------------------------
| Types
|--------------------------------------------------------------------------
|
| The types that will be considered and parsed as multipart body.
|
*/
types: ['multipart/form-data'],
},
}
export default bodyParserConfig
+134
View File
@@ -0,0 +1,134 @@
/**
* Config source: https://git.io/JfefC
*
* Feel free to let us know via PR, if you find something broken in this config
* file.
*/
import type { CorsConfig } from '@ioc:Adonis/Core/Cors'
const corsConfig: CorsConfig = {
/*
|--------------------------------------------------------------------------
| Enabled
|--------------------------------------------------------------------------
|
| A boolean to enable or disable CORS integration from your AdonisJs
| application.
|
| Setting the value to `true` will enable the CORS for all HTTP request. However,
| you can define a function to enable/disable it on per request basis as well.
|
*/
enabled: false,
// You can also use a function that return true or false.
// enabled: (request) => request.url().startsWith('/api')
/*
|--------------------------------------------------------------------------
| Origin
|--------------------------------------------------------------------------
|
| Set a list of origins to be allowed for `Access-Control-Allow-Origin`.
| The value can be one of the following:
|
| https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Origin
|
| Boolean (true) - Allow current request origin.
| Boolean (false) - Disallow all.
| String - Comma separated list of allowed origins.
| Array - An array of allowed origins.
| String (*) - A wildcard (*) to allow all request origins.
| Function - Receives the current origin string and should return
| one of the above values.
|
*/
origin: true,
/*
|--------------------------------------------------------------------------
| Methods
|--------------------------------------------------------------------------
|
| An array of allowed HTTP methods for CORS. The `Access-Control-Request-Method`
| is checked against the following list.
|
| Following is the list of default methods. Feel free to add more.
*/
methods: ['GET', 'HEAD', 'POST', 'PUT', 'DELETE'],
/*
|--------------------------------------------------------------------------
| Headers
|--------------------------------------------------------------------------
|
| List of headers to be allowed for `Access-Control-Allow-Headers` header.
| The value can be one of the following:
|
| https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Request-Headers
|
| Boolean(true) - Allow all headers mentioned in `Access-Control-Request-Headers`.
| Boolean(false) - Disallow all headers.
| String - Comma separated list of allowed headers.
| Array - An array of allowed headers.
| Function - Receives the current header and should return one of the above values.
|
*/
headers: true,
/*
|--------------------------------------------------------------------------
| Expose Headers
|--------------------------------------------------------------------------
|
| A list of headers to be exposed by setting `Access-Control-Expose-Headers`.
| header. By default following 6 simple response headers are exposed.
|
| Cache-Control
| Content-Language
| Content-Type
| Expires
| Last-Modified
| Pragma
|
| In order to add more headers, simply define them inside the following array.
|
| https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Expose-Headers
|
*/
exposeHeaders: [
'cache-control',
'content-language',
'content-type',
'expires',
'last-modified',
'pragma',
],
/*
|--------------------------------------------------------------------------
| Credentials
|--------------------------------------------------------------------------
|
| Toggle `Access-Control-Allow-Credentials` header. If value is set to `true`,
| then header will be set, otherwise not.
|
| https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Allow-Credentials
|
*/
credentials: true,
/*
|--------------------------------------------------------------------------
| MaxAge
|--------------------------------------------------------------------------
|
| Define `Access-Control-Max-Age` header in seconds.
| https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Access-Control-Max-Age
|
*/
maxAge: 90,
}
export default corsConfig
+58
View File
@@ -0,0 +1,58 @@
/**
* Config source: https://git.io/JesV9
*
* Feel free to let us know via PR, if you find something broken in this config
* file.
*/
import Env from '@ioc:Adonis/Core/Env'
import Application from '@ioc:Adonis/Core/Application'
import type { DatabaseConfig } from '@ioc:Adonis/Lucid/Database'
const databaseConfig: DatabaseConfig = {
/*
|--------------------------------------------------------------------------
| Connection
|--------------------------------------------------------------------------
|
| The primary connection for making database queries across the application
| You can use any key from the `connections` object defined in this same
| file.
|
*/
connection: Env.get('DB_CONNECTION'),
connections: {
/*
|--------------------------------------------------------------------------
| SQLite
|--------------------------------------------------------------------------
|
| Configuration for the SQLite database. Make sure to install the driver
| from npm when using this connection
|
| npm i sqlite3
|
*/
sqlite: {
client: 'sqlite',
connection: {
filename: Application.tmpPath('db.sqlite3'),
},
pool: {
afterCreate: (conn, cb) => {
conn.run('PRAGMA foreign_keys=true', cb)
}
},
migrations: {
naturalSort: true,
},
useNullAsDefault: true,
healthCheck: false,
debug: false,
},
}
}
export default databaseConfig
+149
View File
@@ -0,0 +1,149 @@
/**
* Config source: https://git.io/JBt3o
*
* Feel free to let us know via PR, if you find something broken in this config
* file.
*/
import Env from '@ioc:Adonis/Core/Env'
import { driveConfig } from '@adonisjs/core/build/config'
import Application from '@ioc:Adonis/Core/Application'
/*
|--------------------------------------------------------------------------
| Drive Config
|--------------------------------------------------------------------------
|
| The `DriveConfig` relies on the `DisksList` interface which is
| defined inside the `contracts` directory.
|
*/
export default driveConfig({
/*
|--------------------------------------------------------------------------
| Default disk
|--------------------------------------------------------------------------
|
| The default disk to use for managing file uploads. The value is driven by
| the `DRIVE_DISK` environment variable.
|
*/
disk: Env.get('DRIVE_DISK'),
disks: {
/*
|--------------------------------------------------------------------------
| Local
|--------------------------------------------------------------------------
|
| Uses the local file system to manage files. Make sure to turn off serving
| files when not using this disk.
|
*/
local: {
driver: 'local',
visibility: 'public',
/*
|--------------------------------------------------------------------------
| Storage root - Local driver only
|--------------------------------------------------------------------------
|
| Define an absolute path to the storage directory from where to read the
| files.
|
*/
root: Application.tmpPath('uploads'),
/*
|--------------------------------------------------------------------------
| Serve files - Local driver only
|--------------------------------------------------------------------------
|
| When this is set to true, AdonisJS will configure a files server to serve
| files from the disk root. This is done to mimic the behavior of cloud
| storage services that has inbuilt capabilities to serve files.
|
*/
serveFiles: true,
/*
|--------------------------------------------------------------------------
| Base path - Local driver only
|--------------------------------------------------------------------------
|
| Base path is always required when "serveFiles = true". Also make sure
| the `basePath` is unique across all the disks using "local" driver and
| you are not registering routes with this prefix.
|
*/
basePath: '/uploads',
},
/*
|--------------------------------------------------------------------------
| S3 Driver
|--------------------------------------------------------------------------
|
| Uses the S3 cloud storage to manage files. Make sure to install the s3
| drive separately when using it.
|
|**************************************************************************
| npm i @adonisjs/drive-s3
|**************************************************************************
|
*/
// s3: {
// driver: 's3',
// visibility: 'public',
// key: Env.get('S3_KEY'),
// secret: Env.get('S3_SECRET'),
// region: Env.get('S3_REGION'),
// bucket: Env.get('S3_BUCKET'),
// endpoint: Env.get('S3_ENDPOINT'),
//
// // For minio to work
// // forcePathStyle: true,
// },
/*
|--------------------------------------------------------------------------
| GCS Driver
|--------------------------------------------------------------------------
|
| Uses the Google cloud storage to manage files. Make sure to install the GCS
| drive separately when using it.
|
|**************************************************************************
| npm i @adonisjs/drive-gcs
|**************************************************************************
|
*/
// gcs: {
// driver: 'gcs',
// visibility: 'public',
// keyFilename: Env.get('GCS_KEY_FILENAME'),
// bucket: Env.get('GCS_BUCKET'),
/*
|--------------------------------------------------------------------------
| Uniform ACL - Google cloud storage only
|--------------------------------------------------------------------------
|
| When using the Uniform ACL on the bucket, the "visibility" option is
| ignored. Since, the files ACL is managed by the google bucket policies
| directly.
|
|**************************************************************************
| Learn more: https://cloud.google.com/storage/docs/uniform-bucket-level-access
|**************************************************************************
|
| The following option just informs drive whether your bucket is using uniform
| ACL or not. The actual setting needs to be toggled within the Google cloud
| console.
|
*/
// usingUniformAcl: false,
// },
},
})
+96
View File
@@ -0,0 +1,96 @@
/**
* Config source: https://git.io/JfefW
*
* Feel free to let us know via PR, if you find something broken in this config
* file.
*/
import Env from '@ioc:Adonis/Core/Env'
import { hashConfig } from '@adonisjs/core/build/config'
/*
|--------------------------------------------------------------------------
| Hash Config
|--------------------------------------------------------------------------
|
| The `HashConfig` relies on the `HashList` interface which is
| defined inside `contracts` directory.
|
*/
export default hashConfig({
/*
|--------------------------------------------------------------------------
| Default hasher
|--------------------------------------------------------------------------
|
| By default we make use of the argon hasher to hash values. However, feel
| free to change the default value
|
*/
default: Env.get('HASH_DRIVER', 'scrypt'),
list: {
/*
|--------------------------------------------------------------------------
| scrypt
|--------------------------------------------------------------------------
|
| Scrypt mapping uses the Node.js inbuilt crypto module for creating
| hashes.
|
| We are using the default configuration recommended within the Node.js
| documentation.
| https://nodejs.org/api/crypto.html#cryptoscryptpassword-salt-keylen-options-callback
|
*/
scrypt: {
driver: 'scrypt',
cost: 16384,
blockSize: 8,
parallelization: 1,
saltSize: 16,
keyLength: 64,
maxMemory: 32 * 1024 * 1024,
},
/*
|--------------------------------------------------------------------------
| Argon
|--------------------------------------------------------------------------
|
| Argon mapping uses the `argon2` driver to hash values.
|
| Make sure you install the underlying dependency for this driver to work.
| https://www.npmjs.com/package/phc-argon2.
|
| npm install phc-argon2
|
*/
argon: {
driver: 'argon2',
variant: 'id',
iterations: 3,
memory: 4096,
parallelism: 1,
saltSize: 16,
},
/*
|--------------------------------------------------------------------------
| Bcrypt
|--------------------------------------------------------------------------
|
| Bcrypt mapping uses the `bcrypt` driver to hash values.
|
| Make sure you install the underlying dependency for this driver to work.
| https://www.npmjs.com/package/phc-bcrypt.
|
| npm install phc-bcrypt
|
*/
bcrypt: {
driver: 'bcrypt',
rounds: 10,
},
},
})
+116
View File
@@ -0,0 +1,116 @@
/**
* Config source: https://git.io/JeYHp
*
* Feel free to let us know via PR, if you find something broken in this config
* file.
*/
import Env from '@ioc:Adonis/Core/Env'
import Application from '@ioc:Adonis/Core/Application'
import { sessionConfig } from '@adonisjs/session/build/config'
export default sessionConfig({
/*
|--------------------------------------------------------------------------
| Enable/Disable sessions
|--------------------------------------------------------------------------
|
| Setting the following property to "false" will disable the session for the
| entire application
|
*/
enabled: true,
/*
|--------------------------------------------------------------------------
| Driver
|--------------------------------------------------------------------------
|
| The session driver to use. You can choose between one of the following
| drivers.
|
| - cookie (Uses signed cookies to store session values)
| - file (Uses filesystem to store session values)
| - redis (Uses redis. Make sure to install "@adonisjs/redis" as well)
|
| Note: Switching drivers will make existing sessions invalid.
|
*/
driver: Env.get('SESSION_DRIVER'),
/*
|--------------------------------------------------------------------------
| Cookie name
|--------------------------------------------------------------------------
|
| The name of the cookie that will hold the session id.
|
*/
cookieName: 'adonis-session',
/*
|--------------------------------------------------------------------------
| Clear session when browser closes
|--------------------------------------------------------------------------
|
| Whether or not you want to destroy the session when browser closes. Setting
| this value to `true` will ignore the `age`.
|
*/
clearWithBrowser: false,
/*
|--------------------------------------------------------------------------
| Session age
|--------------------------------------------------------------------------
|
| The duration for which session stays active after no activity. A new HTTP
| request to the server is considered as activity.
|
| The value can be a number in milliseconds or a string that must be valid
| as per https://npmjs.org/package/ms package.
|
| Example: `2 days`, `2.5 hrs`, `1y`, `5s` and so on.
|
*/
age: '2h',
/*
|--------------------------------------------------------------------------
| Cookie values
|--------------------------------------------------------------------------
|
| The cookie settings are used to setup the session id cookie and also the
| driver will use the same values.
|
*/
cookie: {
path: '/',
httpOnly: true,
sameSite: false,
},
/*
|--------------------------------------------------------------------------
| Configuration for the file driver
|--------------------------------------------------------------------------
|
| The file driver needs absolute path to the directory in which sessions
| must be stored.
|
*/
file: {
location: Application.tmpPath('sessions'),
},
/*
|--------------------------------------------------------------------------
| Redis driver
|--------------------------------------------------------------------------
|
| The redis connection you want session driver to use. The same connection
| must be defined inside `config/redis.ts` file as well.
|
*/
redisConnection: 'local',
})
+236
View File
@@ -0,0 +1,236 @@
/**
* Config source: https://git.io/Jvwvt
*
* Feel free to let us know via PR, if you find something broken in this config
* file.
*/
import { ShieldConfig } from '@ioc:Adonis/Addons/Shield'
/*
|--------------------------------------------------------------------------
| Content Security Policy
|--------------------------------------------------------------------------
|
| Content security policy filters out the origins not allowed to execute
| and load resources like scripts, styles and fonts. There are wide
| variety of options to choose from.
*/
export const csp: ShieldConfig['csp'] = {
/*
|--------------------------------------------------------------------------
| Enable/disable CSP
|--------------------------------------------------------------------------
|
| The CSP rules are disabled by default for seamless onboarding.
|
*/
enabled: false,
/*
|--------------------------------------------------------------------------
| Directives
|--------------------------------------------------------------------------
|
| All directives are defined in camelCase and here is the list of
| available directives and their possible values.
|
| https://content-security-policy.com
|
| @example
| directives: {
| defaultSrc: ["'self'", '@nonce', 'cdnjs.cloudflare.com']
| }
|
*/
directives: {},
/*
|--------------------------------------------------------------------------
| Report only
|--------------------------------------------------------------------------
|
| Setting `reportOnly=true` will not block the scripts from running and
| instead report them to a URL.
|
*/
reportOnly: false,
}
/*
|--------------------------------------------------------------------------
| CSRF Protection
|--------------------------------------------------------------------------
|
| CSRF Protection adds another layer of security by making sure, actionable
| routes does have a valid token to execute an action.
|
*/
export const csrf: ShieldConfig['csrf'] = {
/*
|--------------------------------------------------------------------------
| Enable/Disable CSRF
|--------------------------------------------------------------------------
*/
enabled: true,
/*
|--------------------------------------------------------------------------
| Routes to Ignore
|--------------------------------------------------------------------------
|
| Define an array of route patterns that you want to ignore from CSRF
| validation. Make sure the route patterns are started with a leading
| slash. Example:
|
| `/foo/bar`
|
| Also you can define a function that is evaluated on every HTTP Request.
| ```
| exceptRoutes: ({ request }) => request.url().includes('/api')
| ```
|
*/
exceptRoutes: [],
/*
|--------------------------------------------------------------------------
| Enable Sharing Token Via Cookie
|--------------------------------------------------------------------------
|
| When the following flag is enabled, AdonisJS will drop `XSRF-TOKEN`
| cookie that frontend frameworks can read and return back as a
| `X-XSRF-TOKEN` header.
|
| The cookie has `httpOnly` flag set to false, so it is little insecure and
| can be turned off when you are not using a frontend framework making
| AJAX requests.
|
*/
enableXsrfCookie: true,
/*
|--------------------------------------------------------------------------
| Methods to Validate
|--------------------------------------------------------------------------
|
| Define an array of HTTP methods to be validated for a valid CSRF token.
|
*/
methods: ['POST', 'PUT', 'PATCH', 'DELETE'],
}
/*
|--------------------------------------------------------------------------
| DNS Prefetching
|--------------------------------------------------------------------------
|
| DNS prefetching allows browsers to proactively perform domain name
| resolution in background.
|
| Learn more at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-DNS-Prefetch-Control
|
*/
export const dnsPrefetch: ShieldConfig['dnsPrefetch'] = {
/*
|--------------------------------------------------------------------------
| Enable/disable this feature
|--------------------------------------------------------------------------
*/
enabled: true,
/*
|--------------------------------------------------------------------------
| Allow or Dis-Allow Explicitly
|--------------------------------------------------------------------------
|
| The `enabled` boolean does not set `X-DNS-Prefetch-Control` header. However
| the `allow` boolean controls the value of `X-DNS-Prefetch-Control` header.
|
| - When `allow = true`, then `X-DNS-Prefetch-Control = 'on'`
| - When `allow = false`, then `X-DNS-Prefetch-Control = 'off'`
|
*/
allow: true,
}
/*
|--------------------------------------------------------------------------
| Iframe Options
|--------------------------------------------------------------------------
|
| xFrame defines whether or not your website can be embedded inside an
| iframe. Choose from one of the following options.
|
| - DENY
| - SAMEORIGIN
| - ALLOW-FROM http://example.com
|
| Learn more at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
*/
export const xFrame: ShieldConfig['xFrame'] = {
enabled: true,
action: 'DENY',
}
/*
|--------------------------------------------------------------------------
| Http Strict Transport Security
|--------------------------------------------------------------------------
|
| A security to ensure that a browser always makes a connection over
| HTTPS.
|
| Learn more at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Strict-Transport-Security
|
*/
export const hsts: ShieldConfig['hsts'] = {
enabled: true,
/*
|--------------------------------------------------------------------------
| Max Age
|--------------------------------------------------------------------------
|
| Control, how long the browser should remember that a site is only to be
| accessed using HTTPS.
|
*/
maxAge: '180 days',
/*
|--------------------------------------------------------------------------
| Include Subdomains
|--------------------------------------------------------------------------
|
| Apply rules on the subdomains as well.
|
*/
includeSubDomains: true,
/*
|--------------------------------------------------------------------------
| Preloading
|--------------------------------------------------------------------------
|
| Google maintains a service to register your domain and it will preload
| the HSTS policy. Learn more https://hstspreload.org/
|
*/
preload: false,
}
/*
|--------------------------------------------------------------------------
| No Sniff
|--------------------------------------------------------------------------
|
| Browsers have a habit of sniffing content-type of a response. Which means
| files with .txt extension containing Javascript code will be executed as
| Javascript. You can disable this behavior by setting nosniff to false.
|
| Learn more at https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Content-Type-Options
|
*/
export const contentTypeSniffing: ShieldConfig['contentTypeSniffing'] = {
enabled: true,
}
+89
View File
@@ -0,0 +1,89 @@
/**
* Config source: https://git.io/Jfefl
*
* Feel free to let us know via PR, if you find something broken in this config
* file.
*/
import { AssetsConfig } from '@ioc:Adonis/Core/Static'
const staticConfig: AssetsConfig = {
/*
|--------------------------------------------------------------------------
| Enabled
|--------------------------------------------------------------------------
|
| A boolean to enable or disable serving static files. The static files
| are served from the `public` directory inside the application root.
| However, you can override the default path inside `.adonisrc.json`
| file.
|
|
*/
enabled: true,
/*
|--------------------------------------------------------------------------
| Handling Dot Files
|--------------------------------------------------------------------------
|
| Decide how you want the static assets server to handle the `dotfiles`.
| By default, we ignore them as if they don't exists. However, you
| can choose between one of the following options.
|
| - ignore: Behave as if the file doesn't exists. Results in 404.
| - deny: Deny access to the file. Results in 403.
| - allow: Serve the file contents
|
*/
dotFiles: 'ignore',
/*
|--------------------------------------------------------------------------
| Generating Etag
|--------------------------------------------------------------------------
|
| Handle whether or not to generate etags for the files. Etag allows browser
| to utilize the cache when file hasn't been changed.
|
*/
etag: true,
/*
|--------------------------------------------------------------------------
| Set Last Modified
|--------------------------------------------------------------------------
|
| Whether or not to set the `Last-Modified` header in the response. Uses
| the file system's last modified value.
|
*/
lastModified: true,
/*
|--------------------------------------------------------------------------
| Max age
|--------------------------------------------------------------------------
|
| Set the value for the max-age directive. Set a higher value in production
| if you fingerprint your assets.
|
| Learn more: https://docs.adonisjs.com/guides/deployment#serving-static-assets
|
*/
maxAge: 0,
/*
|--------------------------------------------------------------------------
| Immutable
|--------------------------------------------------------------------------
|
| Set the immutable directive. Set it to `true` if the assets are generated
| with a fingerprint. In others words the file name changes when the file
| contents change.
|
*/
immutable: false,
}
export default staticConfig
+73
View File
@@ -0,0 +1,73 @@
/**
* Contract source: https://git.io/JOdz5
*
* Feel free to let us know via PR, if you find something broken in this
* file.
*/
import User from 'App/Models/User'
declare module '@ioc:Adonis/Addons/Auth' {
/*
|--------------------------------------------------------------------------
| Providers
|--------------------------------------------------------------------------
|
| The providers are used to fetch users. The Auth module comes pre-bundled
| with two providers that are `Lucid` and `Database`. Both uses database
| to fetch user details.
|
| You can also create and register your own custom providers.
|
*/
interface ProvidersList {
/*
|--------------------------------------------------------------------------
| User Provider
|--------------------------------------------------------------------------
|
| The following provider uses Lucid models as a driver for fetching user
| details from the database for authentication.
|
| You can create multiple providers using the same underlying driver with
| different Lucid models.
|
*/
user: {
implementation: LucidProviderContract<typeof User>
config: LucidProviderConfig<typeof User>
}
}
/*
|--------------------------------------------------------------------------
| Guards
|--------------------------------------------------------------------------
|
| The guards are used for authenticating users using different drivers.
| The auth module comes with 3 different guards.
|
| - SessionGuardContract
| - BasicAuthGuardContract
| - OATGuardContract ( Opaque access token )
|
| Every guard needs a provider for looking up users from the database.
|
*/
interface GuardsList {
/*
|--------------------------------------------------------------------------
| Web Guard
|--------------------------------------------------------------------------
|
| The web guard uses sessions for maintaining user login state. It uses
| the `user` provider for fetching user details.
|
*/
web: {
implementation: SessionGuardContract<'user', 'web'>
config: SessionGuardConfig<'user'>
client: SessionClientContract<'user'>
}
}
}
+13
View File
@@ -0,0 +1,13 @@
/**
* Contract source: https://git.io/JBt3I
*
* Feel free to let us know via PR, if you find something broken in this contract
* file.
*/
import type { InferDisksFromConfig } from '@adonisjs/core/build/config'
import type driveConfig from '../config/drive'
declare module '@ioc:Adonis/Core/Drive' {
interface DisksList extends InferDisksFromConfig<typeof driveConfig> {}
}
+23
View File
@@ -0,0 +1,23 @@
/**
* Contract source: https://git.io/JTm6U
*
* Feel free to let us know via PR, if you find something broken in this contract
* file.
*/
declare module '@ioc:Adonis/Core/Env' {
/*
|--------------------------------------------------------------------------
| Getting types for validated environment variables
|--------------------------------------------------------------------------
|
| The `default` export from the "../env.ts" file exports types for the
| validated environment variables. Here we merge them with the `EnvTypes`
| interface so that you can enjoy intellisense when using the "Env"
| module.
|
*/
type CustomTypes = typeof import('../env').default
interface EnvTypes extends CustomTypes {}
}
+31
View File
@@ -0,0 +1,31 @@
/**
* Contract source: https://git.io/JfefG
*
* Feel free to let us know via PR, if you find something broken in this contract
* file.
*/
declare module '@ioc:Adonis/Core/Event' {
/*
|--------------------------------------------------------------------------
| Define typed events
|--------------------------------------------------------------------------
|
| You can define types for events inside the following interface and
| AdonisJS will make sure that all listeners and emit calls adheres
| to the defined types.
|
| For example:
|
| interface EventsList {
| 'new:user': UserModel
| }
|
| Now calling `Event.emit('new:user')` will statically ensure that passed value is
| an instance of the the UserModel only.
|
*/
interface EventsList {
//
}
}
+13
View File
@@ -0,0 +1,13 @@
/**
* Contract source: https://git.io/Jfefs
*
* Feel free to let us know via PR, if you find something broken in this contract
* file.
*/
import type { InferListFromConfig } from '@adonisjs/core/build/config'
import type hashConfig from '../config/hash'
declare module '@ioc:Adonis/Core/Hash' {
interface HashersList extends InferListFromConfig<typeof hashConfig> {}
}
+18
View File
@@ -0,0 +1,18 @@
/**
* Contract source: https://bit.ly/3DP1ypf
*
* Feel free to let us know via PR, if you find something broken in this contract
* file.
*/
import '@japa/runner'
declare module '@japa/runner' {
interface TestContext {
// Extend context
}
interface Test<TestData> {
// Extend test
}
}
+1
View File
@@ -0,0 +1 @@
// import Factory from '@ioc:Adonis/Lucid/Factory'
@@ -0,0 +1,21 @@
import BaseSchema from '@ioc:Adonis/Lucid/Schema'
export default class extends BaseSchema {
protected tableName = 'users'
public async up() {
this.schema.createTable(this.tableName, (table) => {
table.increments('id').primary()
table.string('pseudo', 50).notNullable
table.string('email', 255).notNullable().unique()
table.string('password', 180).notNullable()
table.string('remember_me_token').nullable()
table.timestamp('created_at', { useTz: true }).notNullable()
table.timestamp('updated_at', { useTz: true }).notNullable()
})
}
public async down() {
this.schema.dropTable(this.tableName)
}
}
+26
View File
@@ -0,0 +1,26 @@
/*
|--------------------------------------------------------------------------
| Validating Environment Variables
|--------------------------------------------------------------------------
|
| In this file we define the rules for validating environment variables.
| By performing validation we ensure that your application is running in
| a stable environment with correct configuration values.
|
| This file is read automatically by the framework during the boot lifecycle
| and hence do not rename or move this file to a different location.
|
*/
import Env from '@ioc:Adonis/Core/Env'
export default Env.rules({
HOST: Env.schema.string({ format: 'host' }),
PORT: Env.schema.number(),
APP_KEY: Env.schema.string(),
APP_NAME: Env.schema.string(),
CACHE_VIEWS: Env.schema.boolean(),
SESSION_DRIVER: Env.schema.string(),
DRIVE_DISK: Env.schema.enum(['local'] as const),
NODE_ENV: Env.schema.enum(['development', 'production', 'test'] as const),
})
-159
View File
@@ -1,159 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" href="styles.css">
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:400,900">
<title>Portfolio - Arthur</title>
</head>
<body>
<header>
<h1 lang="fr">Portfolio</h1>
<h1 lang="en">Portfolio</h1>
<h1 lang="zh">文件夹</h1>
<nav>
<ul lang="fr">
<li><a href="#">Accueil</a></li>
<li><a href="#about">À propos</a></li>
<li><a href="#projects">Projets</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
<ul lang="en">
<li><a href="#">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#projects">Projects</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
<ul lang="zh">
<li><a href="#"></a></li>
<li><a href="#about">关于</a></li>
<li><a href="#projects">项目</a></li>
<li><a href="#contact">接触</a></li>
</ul>
</nav>
</header>
<main>
<div class="main-left">
<h2 lang="fr">Salut ! 👋🏻<br>Je m'appelle Arthur.</h2>
<h2 lang="en">Hi! 👋🏻<br>I'm Arthur.</h2>
<h2 lang="zh">干草那里!👋🏻<br>我是亚瑟。</h2>
<h3 lang="fr">Fondateur</h3>
<h3 lang="en">Founder</h3>
<h3 lang="zh">创始人</h3>
<div class="barre-verticale">
<p lang="fr">Je suis un jeune français passionné de développement, je suis un autodidacte et ma créativité ne connaît pas de limites. Chaque pixel que je modifie raconte une histoire. Passionné par la transformation d'idées en expériences visuellement captivantes, je crée des projets qui repoussent les limites de l'innovation en matière de design.</p>
<p lang="en">I am a young Frenchman with a passion for development, I am a self-taught learner and my creativity knows no limits. Every pixel I edit tells a story. Passionate about transforming ideas into visually captivating experiences, I create projects that push the boundaries of design innovation.</p>
<p lang="zh">我是一名年轻的法国人,对发展充满热情,我是一名自学成才的学习者,我的创造力是无限的。我编辑的每个像素都讲述一个故事。我热衷于将想法转化为视觉上令人着迷的体验,我创建的项目突破了设计创新的界限。</p>
</div>
<p class="citation" lang="fr">"Au milieu de chaque difficulté se trouve une opportunité."</p>
<p class="citation" lang="en">"In the middle of every difficulty lies opportunity."</p>
<p class="citation" lang="zh">"每一个困难之中都蕴藏着机遇。"</p>
<p class="citation-auth">Albert Einstein</p>
<ul class="div-lien">
<a href="https://www.instagram.com/arthur.pbty/" target="_blank"><div><img src="img/logo insta.png" alt="Logo">Instagram</div></a>
<a href="https://github.com/Tutur33" target="_blank"><div><img src="img/logo github.png" alt="Logo">Github</div></a>
<a href="https://discord.gg/HxgaA44CPh" target="_blank"><div><img src="img/Logo Discord.png" alt="Logo">Discord</div></a>
<a href="http://tuturp33.000webhostapp.com" target="_blank" lang="fr"><div><img src="img/other.png" alt="Logo">Autre...</div></a>
<a href="http://tuturp33.000webhostapp.com" target="_blank" lang="en"><div><img src="img/other.png" alt="Logo">Other...</div></a>
<a href="http://tuturp33.000webhostapp.com" target="_blank" lang="zh"><div><img src="img/other.png" alt="Logo">其他...</div></a>
</ul>
</div>
<div class="main-right">
<img src="img/pp.jpg" alt="Photo de profil" class="pp" lang="fr">
<img src="img/pp.jpg" alt="Profile picture" class="pp" lang="en">
<img src="img/pp.jpg" alt="个人资料图片" class="pp" lang="zh">
</div>
</main>
<section id="about">
<h2 lang="fr">À propos</h2>
<h2 lang="en">About</h2>
<h2 lang="zh">关于</h2>
<p lang="fr">Bonjour ! Je suis Arthur, un développeur passionné basé en France. Mon parcours dans le monde du développement est une aventure inspirante. Chaque ligne de code que j'écris est une étape vers la création d'expériences uniques et captivantes. Je suis animé par la volonté de donner vie à des idées et de les modeler en designs innovants.</p>
<p lang="en">Good morning ! I'm Arthur, a passionate developer based in France. My journey in the world of development is an inspiring adventure. Every line of code I write is a step toward creating unique and engaging experiences. I am driven by the desire to bring ideas to life and shape them into innovative designs.</p>
<p lang="zh">早上好 !我是 Arthur,一位来自法国的充满热情的开发人员。我在发展世界中的旅程是一次鼓舞人心的冒险。我编写的每一行代码都是朝着创造独特且引人入胜的体验迈出的一步。我的动力来自于将想法变为现实并将其转化为创新设计的愿望。</p>
<h3 lang="fr">Mon parcours</h3>
<h3 lang="en">My background</h3>
<h3 lang="zh">我的背景</h3>
<p lang="fr">J'ai acquis de l'expérience dans le développement web en travaillant sur divers projets, allant du front-end au back-end. J'ai une maîtrise approfondie des langages tels que HTML, CSS, JavaScript, et j'ai travaillé avec des frameworks modernes comme React et Node.js.</p>
<p lang="en">I gained experience in web development working on various projects, ranging from front-end to back-end. I have a deep command of languages like HTML, CSS, JavaScript, and have worked with modern frameworks like React and Node.js.</p>
<p lang="zh">我在从前端到后端的各种项目中获得了 Web 开发经验。我对 HTML、CSS、JavaScript 等语言有深入的了解,并且使用过 React 和 Node.js 等现代框架。</p>
<h3 lang="fr">Ma philosophie</h3>
<h3 lang="en">My philosophy</h3>
<h3 lang="en">我的理念</h3>
<p lang="fr">Je crois fermement que chaque difficulté est une opportunité de créer quelque chose de nouveau et de passionnant. Mon approche consiste à allier fonctionnalité et esthétique pour offrir des expériences utilisateur exceptionnelles.</p>
<p lang="en">I firmly believe that every difficulty is an opportunity to create something new and exciting. My approach is to combine functionality and aesthetics to deliver exceptional user experiences.</p>
<p lang="zh">我坚信,每一次困难都是创造新的、令人兴奋的事物的机会。我的方法是将功能和美学结合起来,提供卓越的用户体验。</p>
<h3 lang="fr">Mes compétences</h3>
<h3 lang="en">My skills</h3>
<h3 lang="zh">我的技能</h3>
<p lang="fr">Développement web, design web, développement d'applications, gestion de projet.</p>
<p lang="en">Web development, web design, application development, project management.</p>
<p lang="zh">网页开发、网页设计、应用程序开发、项目管理。</p>
<h3 lang="fr">Mes intérêts</h3>
<h3 lang="en">My interests</h3>
<h3 lang="zh">我的兴趣</h3>
<p lang="fr">En dehors du développement, j'adore explorer de nouveaux endroits, la photographie, et lire des livres sur la technologie et la créativité. Et faire de la voile !</p>
<p lang="en">Outside of development, I love exploring new places, photography, and reading books about technology and creativity. And go sailing!</p>
<p lang="zh">除了开发之外,我喜欢探索新的地方、摄影以及阅读有关技术和创造力的书籍。去航行吧!</p>
<h3 lang="fr">Ma vision</h3>
<h3 lang="en">My vision</h3>
<h3 lang="zh">我的愿景</h3>
<p lang="fr">Mon objectif est de continuer à apprendre, innover et inspirer à travers mes projets. Je souhaite contribuer à la création d'un web meilleur et plus captivant pour tous.</p>
<p lang="en">My visionMy goal is to continue to learn, innovate and inspire through my projects. I want to help create a better, more engaging web for everyone.</p>
<p lang="zh">我的愿景我的目标是通过我的项目继续学习、创新和启发。我想帮助每个人创建一个更好、更具吸引力的网络。</p>
<p lang="fr">N'hésitez pas à me contacter si vous avez des questions ou si vous souhaitez collaborer sur un projet passionnant. Vous pouvez me joindre via [votre adresse e-mail] ou me suivre sur les réseaux sociaux en utilisant les liens ci-dessous.</p>
<p lang="en">Please feel free to contact me if you have any questions or would like to collaborate on an exciting project. You can reach me via [your email address] or follow me on social media using the links below.</p>
<p lang="zh">如果您有任何疑问或想合作开展一个令人兴奋的项目,请随时与我联系。您可以通过[您的电子邮件地址]联系我,或使用下面的链接在社交媒体上关注我。</p>
</section>
<section id="projects">
<h2 lang="fr">Projets</h2>
<h2 lang="en">Projects</h2>
<h2 lang="zh">项目</h2>
<div class="all_projects">
<div>1</div>
<div>2</div>
<div>3</div>
<div>4</div>
<div>5</div>
<div>6</div>
<div>7</div>
<div>8</div>
</div>
</section>
<section id="contact">
<h2 lang="fr">Contact</h2>
<h2 lang="en">Contact</h2>
<h2 lang="zh">接触</h2>
<form action="envoyer.php" method="post">
<label for="nom">Nom :</label>
<input type="text" id="nom" name="nom" required>
<br>
<label for="email">E-mail :</label>
<input type="email" id="email" name="email" required>
<br>
<label for="message">Message :</label>
<textarea id="message" name="message" rows="4" required></textarea>
<br>
<input type="submit" value="Envoyer">
</form>
</section>
<script src="script.js"></script>
</body>
</html>
+16131
View File
File diff suppressed because it is too large Load Diff
+78
View File
@@ -0,0 +1,78 @@
{
"name": "nups-web",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "node ace serve --watch",
"build": "node ace build --production",
"start": "node server.js",
"test": "node ace test",
"lint": "eslint . --ext=.ts",
"format": "prettier --write ."
},
"eslintConfig": {
"extends": [
"plugin:adonis/typescriptApp",
"prettier"
],
"plugins": [
"prettier"
],
"rules": {
"prettier/prettier": [
"error"
]
}
},
"eslintIgnore": [
"build"
],
"prettier": {
"trailingComma": "es5",
"semi": false,
"singleQuote": true,
"useTabs": false,
"quoteProps": "consistent",
"bracketSpacing": true,
"arrowParens": "always",
"printWidth": 100
},
"devDependencies": {
"@adonisjs/assembler": "^5.9.6",
"@babel/core": "^7.23.2",
"@babel/preset-env": "^7.23.2",
"@japa/preset-adonis": "^1.2.0",
"@japa/runner": "^2.5.1",
"@symfony/webpack-encore": "^4.1.1",
"@types/proxy-addr": "^2.0.2",
"@types/source-map-support": "^0.5.9",
"adonis-preset-ts": "^2.1.0",
"eslint": "^8.52.0",
"eslint-config-prettier": "^9.0.0",
"eslint-plugin-adonis": "^2.1.1",
"eslint-plugin-prettier": "^5.0.1",
"pino-pretty": "^10.2.3",
"prettier": "^3.0.3",
"typescript": "~4.6",
"webpack": "^5.89.0",
"webpack-cli": "^4.10.0",
"youch": "^3.3.2",
"youch-terminal": "^2.2.3"
},
"dependencies": {
"@adonisjs/auth": "^8.2.3",
"@adonisjs/core": "^5.9.0",
"@adonisjs/lucid": "^18.4.2",
"@adonisjs/repl": "^3.1.11",
"@adonisjs/session": "^6.4.0",
"@adonisjs/shield": "^7.1.1",
"@adonisjs/view": "^6.2.0",
"bootstrap": "^5.3.2",
"luxon": "^3.4.3",
"phc-argon2": "^1.1.4",
"proxy-addr": "^2.0.7",
"reflect-metadata": "^0.1.13",
"source-map-support": "^0.5.21",
"sqlite3": "^5.1.6"
}
}
+21
View File
@@ -0,0 +1,21 @@
import type { ApplicationContract } from '@ioc:Adonis/Core/Application'
export default class AppProvider {
constructor(protected app: ApplicationContract) {}
public register() {
// Register your own bindings
}
public async boot() {
// IoC container is ready
}
public async ready() {
// App is ready
}
public async shutdown() {
// Cleanup, since app is going down
}
}

Before

Width:  |  Height:  |  Size: 44 KiB

After

Width:  |  Height:  |  Size: 44 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 892 B

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 4.7 MiB

+52
View File
@@ -0,0 +1,52 @@
{
"entrypoints": {
"index": {
"css": [
"http://localhost:8080/assets/index.css"
],
"js": [
"http://localhost:8080/assets/index.js"
]
},
"form": {
"css": [
"http://localhost:8080/assets/form.css"
],
"js": [
"http://localhost:8080/assets/form.js"
]
},
"compte": {
"css": [
"http://localhost:8080/assets/compte.css"
],
"js": [
"http://localhost:8080/assets/compte.js"
]
},
"terms": {
"css": [
"http://localhost:8080/assets/terms.css"
],
"js": [
"http://localhost:8080/assets/terms.js"
]
},
"project-nups": {
"css": [
"http://localhost:8080/assets/project-nups.css"
],
"js": [
"http://localhost:8080/assets/project-nups.js"
]
},
"nups": {
"css": [
"http://localhost:8080/assets/nups.css"
],
"js": [
"http://localhost:8080/assets/nups.js"
]
}
}
}
+15
View File
@@ -0,0 +1,15 @@
{
"assets/index.css": "http://localhost:8080/assets/index.css",
"assets/index.js": "http://localhost:8080/assets/index.js",
"assets/form.css": "http://localhost:8080/assets/form.css",
"assets/form.js": "http://localhost:8080/assets/form.js",
"assets/compte.css": "http://localhost:8080/assets/compte.css",
"assets/compte.js": "http://localhost:8080/assets/compte.js",
"assets/terms.css": "http://localhost:8080/assets/terms.css",
"assets/terms.js": "http://localhost:8080/assets/terms.js",
"assets/project-nups.css": "http://localhost:8080/assets/project-nups.css",
"assets/project-nups.js": "http://localhost:8080/assets/project-nups.js",
"assets/nups.css": "http://localhost:8080/assets/nups.css",
"assets/nups.js": "http://localhost:8080/assets/nups.js",
"assets/images/landing.jpg": "http://localhost:8080/assets/images/landing.6d6841c3.jpg"
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 684 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 407 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 MiB

Before

Width:  |  Height:  |  Size: 49 KiB

After

Width:  |  Height:  |  Size: 49 KiB

Before

Width:  |  Height:  |  Size: 185 KiB

After

Width:  |  Height:  |  Size: 185 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

+48
View File
@@ -0,0 +1,48 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="100mm"
height="100mm"
viewBox="0 0 100 100"
version="1.1"
id="svg5"
xml:space="preserve"
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
sodipodi:docname="logo.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
id="namedview7"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
inkscape:document-units="mm"
showgrid="false"
showguides="true"
inkscape:zoom="1"
inkscape:cx="195"
inkscape:cy="202"
inkscape:window-width="1280"
inkscape:window-height="971"
inkscape:window-x="1272"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" /><defs
id="defs2" /><g
inkscape:label="Calque 1"
inkscape:groupmode="layer"
id="layer1"><path
style="fill:#ffffff;stroke-width:0.235958"
d="M 0,0 V 100 H 36 V 85 H 15 V 13.9 L 64,48.5 V 30 L 21.5,0 Z"
id="path992"
sodipodi:nodetypes="cccccccccc" /><path
style="fill:#ffffff;stroke-width:0.235958"
d="M 100,100 V 0 H 64 V 15 H 85 V 86.1 L 36,51.5 V 70 l 42.5,30 z"
id="path1046"
sodipodi:nodetypes="cccccccccc" /></g></svg>

After

Width:  |  Height:  |  Size: 1.6 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

+164
View File
@@ -0,0 +1,164 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 1600 853.33333"
width="300"
height="160"
fill-rule="nonzero"
version="1.1"
id="svg353"
sodipodi:docname="icons8-microsoft-onedrive-2019 (1).svg"
inkscape:version="1.2.2 (732a01da63, 2022-12-09)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview355"
pagecolor="#505050"
bordercolor="#eeeeee"
borderopacity="1"
inkscape:showpageshadow="0"
inkscape:pageopacity="0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#505050"
showgrid="false"
inkscape:zoom="4"
inkscape:cx="118"
inkscape:cy="98.5"
inkscape:window-width="1280"
inkscape:window-height="971"
inkscape:window-x="1272"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg353" />
<defs
id="defs336">
<linearGradient
x1="24.5"
y1="7.0320001"
x2="24.5"
y2="22.851999"
gradientUnits="userSpaceOnUse"
id="color-1">
<stop
offset="0"
stop-color="#0571bf"
id="stop316" />
<stop
offset="1"
stop-color="#0268ba"
id="stop318" />
</linearGradient>
<linearGradient
x1="14.228"
y1="14.219"
x2="14.228"
y2="32.761002"
gradientUnits="userSpaceOnUse"
id="color-2">
<stop
offset="0"
stop-color="#1684da"
id="stop321" />
<stop
offset="1"
stop-color="#107cd4"
id="stop323" />
</linearGradient>
<linearGradient
x1="38.228001"
y1="18.746"
x2="38.228001"
y2="34.097"
gradientUnits="userSpaceOnUse"
id="color-3">
<stop
offset="0"
stop-color="#138cdd"
id="stop326" />
<stop
offset="1"
stop-color="#0c7dd4"
id="stop328" />
</linearGradient>
<linearGradient
x1="17.129999"
y1="24.083"
x2="31.145"
y2="41.333"
gradientUnits="userSpaceOnUse"
id="color-4">
<stop
offset="0"
stop-color="#27a7ea"
id="stop331" />
<stop
offset="1"
stop-color="#1c94e3"
id="stop333" />
</linearGradient>
</defs>
<g
fill="#ffffff"
fill-rule="nonzero"
stroke="none"
stroke-width="1"
stroke-linecap="butt"
stroke-linejoin="miter"
stroke-miterlimit="10"
stroke-dasharray="none"
stroke-dashoffset="0"
font-family="none"
font-weight="none"
font-size="none"
text-anchor="none"
style="mix-blend-mode:normal"
id="g339"
transform="scale(6.25,3.3333333)">
<path
d="M 0,256 V 0 h 256 v 256 z"
id="bgRectangle" />
</g>
<g
fill="none"
fill-rule="nonzero"
stroke="none"
stroke-width="1"
stroke-linecap="butt"
stroke-linejoin="miter"
stroke-miterlimit="10"
stroke-dasharray="none"
stroke-dashoffset="0"
font-family="none"
font-weight="none"
font-size="none"
text-anchor="none"
style="mix-blend-mode:normal"
id="g351"
transform="matrix(3.3333247,0,0,3.3333247,387.51971,22.159094)">
<g
transform="scale(5.33333)"
id="g349">
<path
d="M 24.5,7 C 16.492,7 10,13.492 10,21.5 10,29.508 16.492,36 24.5,36 32.508,36 39,29.508 39,21.5 39,13.492 32.508,7 24.5,7 Z"
fill="url(#color-1)"
id="path341"
style="fill:url(#color-1)" />
<path
d="M 16.155,14.972 C 14.835,14.467 13.402,14.191 11.905,14.191 5.33,14.191 0,19.521 0,26.096 0,28.572 0.757,30.87 2.05,32.774 2.111,32.748 18.495,25.885 28.456,21.886 22.952,18.568 17.903,15.641 16.155,14.972 Z"
fill="url(#color-2)"
id="path343"
style="fill:url(#color-2)" />
<path
d="m 48,28.373 c 0,-5.317 -4.31,-9.627 -9.627,-9.627 -0.997,0 -1.958,0.152 -2.863,0.433 -0.996,0.31 -3.652,1.342 -7.054,2.708 8.377,5.05 17.79,10.996 18.252,11.288 C 47.525,31.76 48,30.123 48,28.373 Z"
fill="url(#color-3)"
id="path345"
style="fill:url(#color-3)" />
<path
d="M 46.709,33.175 C 46.246,32.883 36.834,26.937 28.457,21.887 18.495,25.885 2.111,32.748 2.05,32.774 2.467,33.388 5.627,38 11.904,38 c 5.03,0 16.176,0 26.354,0 5.411,0 7.89,-3.854 8.451,-4.825 z"
fill="url(#color-4)"
id="path347"
style="fill:url(#color-4)" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 310 KiB

After

Width:  |  Height:  |  Size: 310 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 426 B

+89
View File
@@ -0,0 +1,89 @@
/* Réinitialisation des styles par défaut du navigateur */
body, h1, h2, ul, li, label, input, button {
margin: 0;
padding: 0;
border: 0;
}
/* Style de base pour le corps de la page */
body {
font-family: Arial, sans-serif;
background-color: #f5f5f5;
color: #333;
margin: 0;
padding: 0;
}
/* Style de l'en-tête (h1) */
h1 {
font-size: 24px;
margin: 20px;
}
/* Style de la liste (ul) */
ul {
list-style: none;
background-color: #ffffff28;
padding: 20px;
border-radius: 5px;
margin: 20px;
}
/* Style des titres de section (h2) */
h2 {
font-size: 20px;
margin-bottom: 10px;
}
/* Style des éléments de liste (li) */
li {
margin-bottom: 10px;
}
/* Style des formulaires */
form {
display: flex;
flex-direction: column;
align-items: center;
}
/* Style des labels des formulaires */
label {
font-weight: bold;
margin-bottom: 5px;
}
/* Style des champs de saisie (input) */
input {
padding: 5px;
border: 1px solid #ccc;
border-radius: 5px;
margin-bottom: 10px;
}
/* Style des boutons */
button,
a {
padding: 10px 20px;
background-color: #007bff;
color: #fff;
border: none;
border-radius: 5px;
cursor: pointer;
text-decoration: none;
}
/* Style des boutons au survol */
button:hover,
a:hover {
background-color: #0056b3;
}
a {
margin: 20px;
}
.dark-mode-theme {
background-color: #1c1c1e;
color: #fefefe;
}
+288
View File
@@ -0,0 +1,288 @@
@import url('https://fonts.googleapis.com/css?family=Poppins:400,500,600,700,800,900');
body{
font-family: 'Poppins', sans-serif;
font-weight: 300;
font-size: 15px;
line-height: 1.7;
color: #c4c3ca;
background-color: #1f2029;
overflow-x: hidden;
}
a {
cursor: pointer;
transition: all 200ms linear;
}
a:hover {
text-decoration: none;
}
.link {
color: #c4c3ca;
}
.link:hover {
color: #ffeba7;
}
p {
font-weight: 500;
font-size: 14px;
line-height: 1.7;
}
h4 {
font-weight: 600;
}
h6 span{
padding: 0 20px;
text-transform: uppercase;
font-weight: 700;
}
.section{
position: relative;
width: 100%;
display: block;
}
.full-height{
min-height: 100vh;
}
[type="checkbox"]:checked,
[type="checkbox"]:not(:checked){
position: absolute;
left: -9999px;
}
.checkbox:checked + label,
.checkbox:not(:checked) + label{
position: relative;
display: block;
text-align: center;
width: 60px;
height: 16px;
border-radius: 8px;
padding: 0;
margin: 10px auto;
cursor: pointer;
background-color: #ffeba7;
}
.checkbox:checked + label:before,
.checkbox:not(:checked) + label:before{
position: absolute;
display: block;
width: 36px;
height: 36px;
border-radius: 50%;
color: #ffeba7;
background-color: #102770;
font-family: 'unicons';
content: '\eb4f';
z-index: 20;
top: -10px;
left: -10px;
line-height: 36px;
text-align: center;
font-size: 24px;
transition: all 0.5s ease;
}
.checkbox:checked + label:before {
transform: translateX(44px) rotate(-270deg);
}
.card-3d-wrap {
position: relative;
width: 440px;
max-width: 100%;
height: 400px;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
perspective: 800px;
margin-top: 60px;
}
.card-3d-wrapper {
width: 100%;
height: 100%;
position:absolute;
top: 0;
left: 0;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
transition: all 600ms ease-out;
}
.card-front, .card-back {
width: 100%;
height: 100%;
background-color: #2a2b38;
background-image: url('https://s3-us-west-2.amazonaws.com/s.cdpn.io/1462889/pat.svg');
background-position: bottom center;
background-repeat: no-repeat;
background-size: 300%;
position: absolute;
border-radius: 6px;
left: 0;
top: 0;
-webkit-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-backface-visibility: hidden;
-moz-backface-visibility: hidden;
-o-backface-visibility: hidden;
backface-visibility: hidden;
}
.card-back {
transform: rotateY(180deg);
}
.checkbox:checked ~ .card-3d-wrap .card-3d-wrapper {
transform: rotateY(180deg);
}
.center-wrap{
position: absolute;
width: 100%;
padding: 0 35px;
top: 50%;
left: 0;
transform: translate3d(0, -50%, 35px) perspective(100px);
z-index: 20;
display: block;
}
.form-group{
position: relative;
display: block;
margin: 0;
padding: 0;
}
.form-style {
padding: 13px 20px;
padding-left: 55px;
height: 48px;
width: 100%;
font-weight: 500;
border-radius: 4px;
font-size: 14px;
line-height: 22px;
letter-spacing: 0.5px;
outline: none;
color: #c4c3ca;
background-color: #1f2029;
border: none;
-webkit-transition: all 200ms linear;
transition: all 200ms linear;
box-shadow: 0 4px 8px 0 rgba(21,21,21,.2);
}
.form-style:focus,
.form-style:active {
border: none;
outline: none;
box-shadow: 0 4px 8px 0 rgba(21,21,21,.2);
}
.input-icon {
position: absolute;
top: 0;
left: 18px;
height: 48px;
font-size: 24px;
line-height: 48px;
text-align: left;
color: #ffeba7;
-webkit-transition: all 200ms linear;
transition: all 200ms linear;
}
.form-group input:-ms-input-placeholder {
color: #c4c3ca;
opacity: 0.7;
-webkit-transition: all 200ms linear;
transition: all 200ms linear;
}
.form-group input::-moz-placeholder {
color: #c4c3ca;
opacity: 0.7;
-webkit-transition: all 200ms linear;
transition: all 200ms linear;
}
.form-group input:-moz-placeholder {
color: #c4c3ca;
opacity: 0.7;
-webkit-transition: all 200ms linear;
transition: all 200ms linear;
}
.form-group input::-webkit-input-placeholder {
color: #c4c3ca;
opacity: 0.7;
-webkit-transition: all 200ms linear;
transition: all 200ms linear;
}
.form-group input:focus:-ms-input-placeholder {
opacity: 0;
-webkit-transition: all 200ms linear;
transition: all 200ms linear;
}
.form-group input:focus::-moz-placeholder {
opacity: 0;
-webkit-transition: all 200ms linear;
transition: all 200ms linear;
}
.form-group input:focus:-moz-placeholder {
opacity: 0;
-webkit-transition: all 200ms linear;
transition: all 200ms linear;
}
.form-group input:focus::-webkit-input-placeholder {
opacity: 0;
-webkit-transition: all 200ms linear;
transition: all 200ms linear;
}
.btn{
border-radius: 4px;
height: 44px;
font-size: 13px;
font-weight: 600;
text-transform: uppercase;
-webkit-transition : all 200ms linear;
transition: all 200ms linear;
padding: 0 30px;
letter-spacing: 1px;
display: -webkit-inline-flex;
display: -ms-inline-flexbox;
display: inline-flex;
-webkit-align-items: center;
-moz-align-items: center;
-ms-align-items: center;
align-items: center;
-webkit-justify-content: center;
-moz-justify-content: center;
-ms-justify-content: center;
justify-content: center;
-ms-flex-pack: center;
text-align: center;
border: none;
background-color: #ffeba7;
color: #102770;
box-shadow: 0 8px 24px 0 rgba(255,235,167,.2);
}
.btn:active,
.btn:focus{
background-color: #102770;
color: #ffeba7;
box-shadow: 0 8px 24px 0 rgba(16,39,112,.2);
}
.btn:hover{
background-color: #102770;
color: #ffeba7;
box-shadow: 0 8px 24px 0 rgba(16,39,112,.2);
}
.logo {
position: absolute;
top: 30px;
right: 30px;
display: block;
z-index: 100;
transition: all 250ms linear;
}
.logo img {
height: 26px;
width: auto;
display: block;
}
+323
View File
@@ -0,0 +1,323 @@
@import url('https://fonts.googleapis.com/css?family=Roboto:400,900');
* {
margin: 0;
padding: 0;
font-family: 'Roboto', sans-serif;
}
html {
scroll-behavior: smooth;
}
body {
justify-content: space-around;
max-width: 2500px;
margin: auto;
}
.fixed-navbar {
position: fixed;
top: 0;
left: 0;
background-color: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
z-index: 999;
display: flex;
justify-content: space-between;
padding: 0 50px 0 50px;
width: calc(100% - 100px);
align-items: center;
border-bottom: 1px solid rgb(83, 83, 83);
}
.fixed-navbar ul {
list-style: none;
display: flex;
align-items: center;
height: 70px;
}
.fixed-navbar li {
margin: 0 10px;
font-weight: bold;
color: rgb(83, 83, 83);
}
.fixed-navbar a {
text-decoration: none;
color: rgb(83, 83, 83);
padding: 5px 15px;
}
.fixed-navbar a:hover {
border: 1px solid rgb(83, 83, 83);
border-radius: 5px;
padding: 5px 14px;
}
.mini-nav {
display: none;
height: 70px;
position: fixed;
width: 100%;
top: 0;
left: 0;
background-color: rgba(255, 255, 255, 0.1);
backdrop-filter: blur(10px);
z-index: 999;
padding: 0 50px 0 50px;
align-items: center;
border-bottom: 1px solid rgb(83, 83, 83);
}
.mini-nav img {
width: 30px;
height: 30px;
text-align: center;
}
main,
section {
margin: 100px 100px 100px;
}
h1 {
font-size: 40px;
font-weight: 700;
margin-bottom: 30px;
}
h2 {
font-size: 28px;
font-weight: 700;
margin-bottom: 10px;
}
.barre-verticale {
border-left: 5px solid rgb(94, 94, 94);
padding-left: 15px;
margin-bottom: 10px;
}
.citation {
font-style: italic;
color: rgb(61, 61, 61);
}
.citation-auth {
color: rgb(61, 61, 61);
margin-bottom: 40px;
}
main {
display: flex;
}
.main-left {
margin-right: 40px;
}
.main-right {
margin-left: 40px;
min-width: 40%;
}
.div-lien div {
display: flex;
flex-direction: row;
align-items: center;
text-align: left;
margin: 5px 0 5px;
padding: 20px 40px;
background-color: rgb(216, 216, 216);
color: rgb(85, 85, 85);
text-decoration: none;
border-radius: 5px;
cursor: pointer;
font-weight: bold;
}
.div-lien div:hover {
background-color: rgb(177, 177, 177);
}
.div-lien a {
text-decoration: none;
}
.div-lien img {
width: 50px;
padding-right: 15px;
}
@media (max-width: 800px) {
.main-right {
display: none;
}
main,
section {
margin: 20px 20px 20px;
}
.fixed-navbar {
margin-top: 70px;
flex-direction: column;
display: none;
}
.mini-nav {
display: flex;
}
h1 {
margin-top: 80px;
}
}
@media (max-width: 940px) {
.fixed-navbar li {
margin: 0;
}
.fixed-navbar a {
padding: 5px;
}
}
.pp {
margin: auto;
width: 100%;
max-width: 500px;
border-radius: 50%;
}
.formContact {
width: 60%;
margin: 0 auto;
background-color: #ffffff28;
padding: 20px;
border: 1px solid #ddd;
border-radius: 5px;
}
.formContact label {
display: block;
margin-top: 10px;
}
.formContact input[type="text"],
.formContact input[type="email"],
.formContact textarea {
width: calc(100% - 20px);
padding: 10px;
margin-top: 5px;
border: 1px solid #ddd;
border-radius: 5px;
max-width: calc(100% - 20px);
min-width: calc(100% - 20px);
}
.formContact input[type="submit"] {
background-color: #333;
color: #fff;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
margin-top: 10px;
}
.formContact input[type="submit"]:hover {
background-color: #555;
}
.all_projects {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.all_projects div {
height: 300px;
width: 300px;
margin: 10px;
transition: transform 0.3s;
border: 2px solid black;
border-radius: 10px;
}
.all_projects div:hover {
transform: scale(1.2);
}
.all_projects img {
width: 100%;
height: 100%;
border-radius: 7px;
}
.footer{
font-family: "Montserrat", sans-serif;
min-height: 100px;
display: flex;
align-items: center;
margin-top: 50px;
justify-content: space-between;
padding: 0 100px;
flex-wrap: wrap;
background-color: rgb(50, 50, 50);
}
.copyrights{
padding-right: 20px;
color: white;
}
.copyrights,
#year {
padding-right: 20px;
color: #9aa0a6;
display: inline;
padding: 0;
}
.conditions_generale {
text-decoration: none;
font-weight: 600;
color: #9aa0a6;
}
.btn_theme {
background-color:rgba(255, 255, 255, 0);
color: rgb(83, 83, 83);
padding: 5px 15px;
cursor: pointer;
text-transform: uppercase;
display: flex;
border: none;
font-weight: bold;
}
.btn_theme:hover {
border: 1px solid rgb(83, 83, 83);
border-radius: 5px;
padding: 5px 14px;
}
#text {
margin: 0;
margin-left: 8px;
}
.dark-mode-theme {
background-color: #1c1c1e;
color: #fefefe;
}
.dark-mode-theme .fixed-navbar ul,
.dark-mode-theme .fixed-navbar li,
.dark-mode-theme .fixed-navbar a {
color: rgb(177, 177, 177);
}
+208
View File
@@ -0,0 +1,208 @@
* {
padding: 0;
margin: 0;
user-select: none;
font-family: arial, sans-serif;
}
img {
pointer-events: none;
}
body {
background: #202124;
}
a {
color: white;
text-decoration: none;
}
nav a:hover,
nav a:active {
text-decoration: underline;
}
nav {
display: flex;
justify-content: right;
width: 100%;
align-items: center;
}
.lien_nav {
padding: 5px;
margin: 10px;
}
.img_nav {
display: flex;
height: 30px;
}
.img_compte {
border-radius: 50%;
}
header {
display: flex;
align-items: center;
justify-content: center;
flex-direction: column;
height: 80vh;
}
.logo {
max-height: 400px;
max-width: 400px;
padding: 30px;
}
.bar_recherche {
align-items: center;
padding: 0px 10px 0 10px;
display: flex;
height: 44px;
border: 1px solid #5f6368;
border-radius: 50px;
width: 80%;
max-width: 600px;
margin: 0px 20px 0 20px;
box-shadow: 0 1px 6px 0 #171717;
background: #303134;
border-color: rgba(223, 225, 229, 0);
}
.bar_recherche input {
background: transparent;
flex: 1;
border: 0;
outline: none;
padding: 10px;
font-size: 16px;
color: snow;
}
::placeholder {
color: snow;
}
.bar_recherche button img {
width: 25px;
}
.bar_recherche button {
border: 0;
border-radius: 50%;
width: 30px;
height: 30px;
background: #303134;
cursor: pointer;
}
.footer {
min-height: 100px;
display: flex;
align-items: center;
margin-top: 50px;
justify-content: space-between;
padding: 0 100px;
flex-wrap: wrap;
background-color: #171717;
position: fixed;
left: 0;
bottom: 0;
right: 420px;
}
.copyrights,
#year {
padding-right: 20px;
color: #9aa0a6;
display: inline;
padding: 0;
}
.conditions_generale {
text-decoration: none;
font-weight: 600;
color: #9aa0a6;
}
main {
display: flex;
}
.section_gauche {
flex: 0 0 auto;
position: fixed;
left: 0;
top: 0;
bottom: 0;
width: calc(100% - 420px);
}
.separator {
position: fixed;
width: 2px;
height: 100%;
background-color: #303134;
margin-left: calc(100% - 420px);
}
.section_droite {
width: 420px;
margin-left: calc(100% - 420px);
}
.liste_favori {
padding-top: 50px;
display: flex;
justify-content: space-between;
}
.liste_favori a {
text-align: center;
margin: 0 10px;
}
.liste_favori a img {
width: 150px;
height: 80px;
border-radius: 15px;
}
.liste_app {
display: flex;
flex-wrap: wrap;
}
.liste_app a {
text-align: center;
margin: 0 20px 20px 20px;
}
.liste_app a img {
width: 100px;
height: 100px;
border-radius: 15px;
}
::-webkit-scrollbar {
width: 16px;
}
::-webkit-scrollbar-thumb {
background: rgb(218, 220, 224);
background-clip: padding-box;
border: 4px solid transparent;
border-radius: 8px;
box-shadow: none;
min-height: 50px;
background-color: rgb(95, 99, 104);
}
::-webkit-scrollbar-track,
::-webkit-scrollbar-track:hover {
background: none;
border: none;
}
+242
View File
@@ -0,0 +1,242 @@
/* -------------------- autre -------------------- */
@import url('https://fonts.googleapis.com/css?family=Roboto:400,900');
*{
margin: 0;
padding: 0;
scroll-behavior: smooth;
}
html {
scroll-behavior: smooth;
}
.titre_section{
position: relative;
font-family: 'Roboto', sans-serif;
font-size: 50px;
padding: 50px 0 0 60px;
}
.titre_section::before{
content: "";
position: absolute;
width: 50px;
height: 7px;
background: rgb(150, 150, 150);
bottom: 0;
box-shadow: 0 2px 2px #0000001F;
}
/* -------------------- autre -------------------- */
/* -------------------- header -------------------- */
header{
min-height: 100vh;
background: url(../../public/landing.jpg);
background-size: cover;
}
nav{
display: flex;
list-style: none;
}
nav li{
margin: 30px;
overflow: hidden;
}
nav a{
font-size: 20px;
font-weight: 600;
font-family: 'Roboto', sans-serif;
color: white;
text-decoration: none;
position: relative;
display: block;
transition: transform 0.4s;
}
.logo{
width: 60px;
}
.big_title{
color: white;
font-size: 150px;
font-family: 'Roboto', sans-serif;
position: absolute;
top: 40%;
left: 10%;
}
/* -------------------- header -------------------- */
/* -------------------- section explication -------------------- */
.explication_contenaire{
padding: 0 100px;
}
.partie_1,
.partie_2{
box-sizing: border-box;
margin: 10px auto 10px;
padding: 10px;
width: 80%; min-height: 220px;
font-family: sans-serif;
font-size: 1em;
}
.image_parragraphe_1{
width : 150px;
border: none;
float: left;
border-radius: 10%;
}
.image_parragraphe_2{
width : 200px;
border: none;
float: right;
border-radius: 10%;
}
.space{
margin: 0, padding 0;
width: 0; height: 0;
}
/* -------------------- section explication -------------------- */
/* -------------------- section download -------------------- */
.download_link{
display: flex;
align-items: center;
flex-direction: column;
}
.btn_download{
text-decoration: none;
padding: 8px;
font-family: arial;
font-size: 1em;
color: #FFFFFF;
background-color: #0070c0;
border-radius: 10px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border: 2px solid #00b0f0;
box-shadow: 3px 3px 4px #444444;
-webkit-box-shadow: 3px 3px 4px #444444;
-moz-box-shadow: 3px 3px 4px #444444;
margin-bottom: 10px;
transition: transform 0.2s ease;
width: 70%;
cursor: pointer;
}
.btn_download:active{
transform: scale(1.05);
}
.logo_download{
width: 30px;
}
/* -------------------- section download -------------------- */
/* -------------------- section version web -------------------- */
#version_web p{
font-family: sans-serif;
font-size: 1em;
padding: 0 100px;
}
.btn_version_web{
text-decoration: none;
padding: 8px;
font-family: arial;
font-size: 1em;
color: #FFFFFF;
background-color: #0070c0;
border-radius: 10px;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border: 2px solid #00b0f0;
box-shadow: 3px 3px 4px #444444;
-webkit-box-shadow: 3px 3px 4px #444444;
-moz-box-shadow: 3px 3px 4px #444444;
margin-bottom: 10px;
transition: transform 0.2s ease;
width: 40%;
cursor: pointer;
}
.btn_version_web:active{
transform: scale(1.05);
}
.btn_version_web_contenaire{
display: flex;
justify-content: center;
align-items: center;
height: 50px;
}
/* -------------------- section version web -------------------- */
/* -------------------- section autre -------------------- */
#autre p{
font-family: sans-serif;
font-size: 1em;
padding: 0 100px;
}
#autre iframe {
padding: 20px 0 0 100px;
}
/* -------------------- section autre -------------------- */
/* -------------------- footer -------------------- */
.footer{
font-family: "Montserrat", sans-serif;
min-height: 100px;
display: flex;
align-items: center;
margin-top: 50px;
justify-content: space-between;
padding: 0 100px;
flex-wrap: wrap;
background-color: rgb(50, 50, 50);
}
.copyrights,
#year{
padding-right: 20px;
color: white;
display: inline;
padding: 0;
}
.conditions_generale{
text-decoration: none;
font-weight: 600;
color: white;
}
/* -------------------- footer -------------------- */
.dark-mode-theme {
background-color: #1c1c1e;
color: #fefefe;
}
+22
View File
@@ -0,0 +1,22 @@
* {
padding: 0;
margin: 0;
font-family: arial, sans-serif;
}
main {
margin: 0 100px;
}
h1 {
padding: 50px;
}
h2 {
padding-top: 20px;
}
.dark-mode-theme {
background-color: #1c1c1e;
color: #fefefe;
}
+1
View File
@@ -0,0 +1 @@
import '../css/compte.css'
+1
View File
@@ -0,0 +1 @@
import '../css/form.css'
+37
View File
@@ -0,0 +1,37 @@
import '../css/index.css'
const toggleBtn = document.getElementById("toggle-btn");
const body = document.querySelector("body");
const text = document.getElementById("text");
let darkmode = localStorage.getItem("dark-mode");
const enableDarkMode=() =>{
body.classList.add("dark-mode-theme");
toggleBtn.classList.add("dark-mode-toggle");
toggleBtn.style.color = "rgb(177, 177, 177)";
text.innerHTML="sombre";
localStorage.setItem("dark-mode" , "enabled")
}
const disableDarkMode= () =>{
body.classList.remove("dark-mode-theme");
toggleBtn.classList.remove("dark-mode-toggle");
toggleBtn.style.color = "rgb(83, 83, 83)";
text.innerHTML="claire";
localStorage.setItem("dark-mode" , "disabled")
}
if(darkmode === "enabled"){
enableDarkMode()
}
toggleBtn.onclick = function(){
darkmode = localStorage.getItem("dark-mode");
if(darkmode === "enabled"){
disableDarkMode()
} else {
enableDarkMode()
}
}
View File
View File
+81
View File
@@ -0,0 +1,81 @@
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Login</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
<link rel="stylesheet" href="https://unicons.iconscout.com/release/v2.1.9/css/unicons.css">
@entryPointStyles('form')
@entryPointScripts('form')
</head>
<body>
<a href="{{ route('home') }}" class="logo">
<img src="/logo.png" alt="">
</a>
<div class="section">
<div class="container">
<div class="row full-height justify-content-center">
<div class="col-12 text-center align-self-center py-5">
<div class="section pb-5 pt-5 pt-sm-2 text-center">
<h6 class="mb-0 pb-3"><span>Log In </span><span>Sign Up</span></h6>
<input class="checkbox" type="checkbox" id="reg-log" name="reg-log"/>
<label for="reg-log"></label>
@!component('components/flash')
<div class="card-3d-wrap mx-auto">
<div class="card-3d-wrapper">
<div class="card-front">
<div class="center-wrap">
<div class="section text-center">
<h4 class="mb-4 pb-3">Log In</h4>
<form action="{{ route('login') }}" method="post">
<div class="form-group">
<input type="email" name="loginemail" class="form-style" placeholder="Your Email" id="logemail" autocomplete="off">
<i class="input-icon uil uil-at"></i>
</div>
<div class="form-group mt-2">
<input type="password" name="loginpassword" class="form-style" placeholder="Your Password" id="logpass" autocomplete="off">
<i class="input-icon uil uil-lock-alt"></i>
</div>
<button class="btn mt-4">submit</button>
</form>
<p class="mb-0 mt-4 text-center"><a href="#0" class="link">Forgot your password?</a></p>
</div>
</div>
</div>
<div class="card-back">
<div class="center-wrap">
<div class="section text-center">
<h4 class="mb-4 pb-3">Sign Up</h4>
<form action="{{ route('signup') }}" method="post">
<div class="form-group">
<input type="text" name="pseudo" class="form-style" placeholder="Your Full Name" id="logname" autocomplete="off">
<i class="input-icon uil uil-user"></i>
</div>
<div class="form-group mt-2">
<input type="email" name="email" class="form-style" placeholder="Your Email" id="logemail" autocomplete="off">
<i class="input-icon uil uil-at"></i>
</div>
<div class="form-group mt-2">
<input type="password" name="password" class="form-style" placeholder="Your Password" id="logpass" autocomplete="off">
<i class="input-icon uil uil-lock-alt"></i>
</div>
<div class="form-group mt-2">
<input type="password" name="password_confirmation" class="form-style" placeholder="Confirm Your Password" id="logpass" autocomplete="off">
<i class="input-icon uil uil-lock-alt"></i>
</div>
<button class="btn mt-4">submit</button>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
+71
View File
@@ -0,0 +1,71 @@
@if(flashMessages.has('success'))
<div class="flash-success">
{{ flashMessages.get('success') }}
</div>
@end
@if(flashMessages.has('error'))
<div class="flash-error">
{{ flashMessages.get('error') }}
</div>
@end
<style>
.flash-success {
color: #155724; /* Couleur du texte */
background-color: #d4edda; /* Couleur de l'arrière-plan */
border-color: #c3e6cb; /* Couleur de la bordure */
/* Style de la bordure */
border: 1px solid transparent;
border-radius: 0.25rem;
padding: 0.75rem 1.25rem; /* Espacement interne */
/* Styles supplémentaires pour le texte et les liens */
font-weight: bold;
text-align: center;
text-decoration: none;
/* Ombre légère */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
.flash-error {
color: #721c24; /* Couleur du texte */
background-color: #f8d7da; /* Couleur de l'arrière-plan */
border-color: #f5c6cb; /* Couleur de la bordure */
/* Style de la bordure */
border: 1px solid transparent;
border-radius: 0.25rem;
padding: 0.75rem 1.25rem; /* Espacement interne */
/* Styles supplémentaires pour le texte et les liens */
font-weight: bold;
text-align: center;
text-decoration: none;
/* Ombre légère */
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
}
</style>
@if(flashMessages.has('errors.pseudo'))
<div class="flash-error">
{{ flashMessages.get('errors.pseudo') }}
</div>
@end
@if(flashMessages.has('errors.email'))
<div class="flash-error">
{{ flashMessages.get('errors.email') }}
</div>
@end
@if(flashMessages.has('errors.password'))
<div class="flash-error">
{{ flashMessages.get('errors.password') }}
</div>
@end
+53
View File
@@ -0,0 +1,53 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>My account</title>
@entryPointStyles('compte')
@entryPointScripts('compte')
</head>
<body>
<h1>Welcome {{ auth.user.pseudo }}</h1>
<a href="{{ route('home') }}">return to home page</a>
@!component('components/flash')
<ul>
<h2>Here is your personal information:</h2>
<li>pseudo : {{ auth.user.pseudo }}</li>
<li>email : {{ auth.user.email }}</li>
<li>created at : {{ auth.user.createdAt }}</li>
</ul>
<ul>
<h2>You can modify your personal information:</h2>
<li>
<form action="modifpseudo" method="post">
<label for="pseudo">Pseudo</label>
<input type="text" name="pseudo" placeholder="New pseudo">
<button>Save</button>
</form>
</li>
<li>
<form action="modifemail" method="post">
<label for="email">Email</label>
<input type="email" name="email" placeholder="New email">
<button>Save</button>
</form>
</li>
</ul>
<script>
const body = document.querySelector("body");
let darkmode = localStorage.getItem("dark-mode");
if(darkmode === "enabled"){
body.classList.add("dark-mode-theme");
} else {
body.classList.remove("dark-mode-theme");
}
</script>
</body>
</html>
+1
View File
@@ -0,0 +1 @@
<p> It's a 404 </p>
+1
View File
@@ -0,0 +1 @@
<p> It's a 500 </p>
+1
View File
@@ -0,0 +1 @@
<p> It's a 403 </p>
+149
View File
@@ -0,0 +1,149 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="shortcut icon" href="/favicon.ico" />
<title>Arthur</title>
@entryPointStyles('index')
@entryPointScripts('index')
</head>
<body>
<nav id="nav" class="fixed-navbar">
<ul class="nav-lien">
<li><a href="#">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#projects">Projects</a></li>
<li><a href="#contact">Contact</a></li>
</ul>
<button class="btn_theme" id="toggle-btn">theme
<p id="text">claire</p>
</button>
<ul class="nav-compte">
@if(auth.user)
<li>Welcome {{ auth.user.pseudo }}</li>
<li><a href="{{ route('compte') }}">Compte</a></li>
<li><a href="{{ route('logout') }}">Logout</a></li>
@else
<li><a href="{{ route('auth') }}">Login</a></li>
<li><a href="{{ route('auth') }}">Signup</a></li>
@end
</ul>
</nav>
<nav class="mini-nav">
<button id="depli-nav">
<svg xmlns="http://www.w3.org/2000/svg" width="30" height="30" viewBox="0 0 30 30">
<rect width="30" height="4" rx="2" ry="2" fill="#000" />
<rect y="10" width="30" height="4" rx="2" ry="2" fill="#000" />
<rect y="20" width="30" height="4" rx="2" ry="2" fill="#000" />
</svg>
</button>
<img src="/logo.png" alt="">
</nav>
<script>
const toggleBtn = document.getElementById("depli-nav");
const nav = document.getElementById("nav");
let toggle = "False";
toggleBtn.onclick = function(){
if(toggle === "False") {
nav.style.display = "flex";
toggle = "True";
} else {
nav.style.display = "none";
toggle = "False";
}
}
</script>
<main>
<div class="main-left">
<h1>Hi! 👋🏻<br>I'm Arthur.</h1>
<h2>Founder</h2>
<div class="barre-verticale">
<p>I am a young Frenchman with a passion for development, I am a self-taught learner and my creativity knows no limits. Every pixel I edit tells a story. Passionate about transforming ideas into visually captivating experiences, I create projects that push the boundaries of design innovation.</p>
</div>
<p class="citation">"In the middle of every difficulty lies opportunity."</p>
<p class="citation-auth">Albert Einstein</p>
<ul class="div-lien">
<a href="https://www.instagram.com/arthur.pbty/" target="_blank"><div><img src="/logo insta.png" alt="Logo">Instagram</div></a>
<a href="https://github.com/Tutur33" target="_blank"><div><img src="/logo github.png" alt="Logo">Github</div></a>
<a href="https://discord.gg/HxgaA44CPh" target="_blank"><div><img src="/Logo Discord.png" alt="Logo">Discord</div></a>
<a href="http://tuturp33.000webhostapp.com" target="_blank"><div><img src="/other.png" alt="Logo">Other...</div></a>
</ul>
</div>
<div class="main-right">
<img src="/pp.jpg" alt="Profile picture" class="pp">
</div>
</main>
<section id="about">
<h2>About</h2>
<p>Good morning ! I'm Arthur, a passionate developer based in France. My journey in the world of development is an inspiring adventure. Every line of code I write is a step toward creating unique and engaging experiences. I am driven by the desire to bring ideas to life and shape them into innovative designs.</p>
<h3>My background</h3>
<p>I gained experience in web development working on various projects, ranging from front-end to back-end. I have a deep command of languages like HTML, CSS, JavaScript, and have worked with modern frameworks like Adonis with Node.js.</p>
<h3>My philosophy</h3>
<p>I firmly believe that every difficulty is an opportunity to create something new and exciting. My approach is to combine functionality and aesthetics to deliver exceptional user experiences.</p>
<h3>My skills</h3>
<p>Web development, web design, application development, project management.</p>
<h3>My interests</h3>
<p>Outside of development, I love exploring new places, photography, and reading books about technology and creativity. And go sailing!</p>
<h3>My vision</h3>
<p>My visionMy goal is to continue to learn, innovate and inspire through my projects. I want to help create a better, more engaging web for everyone.</p>
<br>
<p>Please feel free to contact me if you have any questions or would like to collaborate on an exciting project. You can reach me via [your email address] or follow me on social media using the links below.</p>
</section>
<section id="projects">
<h2>Projects</h2>
<div class="all_projects">
<div class="nups-project">
<a href="{{ route('nups') }}" target="_blank"><img src="/project-nups.png" alt=""></a>
</div>
</div>
</section>
<section id="contact">
<h2>Contact</h2>
<form class="formContact" action="envoyer.php" method="post">
<label for="nom">Nom :</label>
<input type="text" id="nom" name="nom" required>
<br>
<label for="email">E-mail :</label>
<input type="email" id="email" name="email" required>
<br>
<label for="message">Message :</label>
<textarea id="message" name="message" rows="4" required></textarea>
<br>
<input type="submit" value="Envoyer">
</form>
</section>
<footer id="footer" class="footer">
<span class="copyrights">&copy; <div id="year"></div> - Arthur Puechberty</span>
<a href="{{ route('terms') }}" class="conditions_generale" target="_blank">Terms and Conditions</a>
</footer>
<script>
var year = new Date().getFullYear();
document.getElementById("year").innerHTML = year;
document.getElementById('myForm').addEventListener('submit', function(event) {
var input = document.getElementById('myInput');
if (input.value.trim() === '') {
event.preventDefault(); // Empêche la soumission du formulaire
} else {
this.action = "https://www.google.fr/search";
}
});
</script>
</body>
</html>
+95
View File
@@ -0,0 +1,95 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Nups</title>
@entryPointStyles('nups')
</head>
<body>
<main>
<section class="section_gauche">
<header>
<div class="div_logo">
<img class="logo" alt="Nups" src="/nups.png"/>
</div>
<form action="https://google.fr/search" method="GET" class="bar_recherche" id="myForm">
<input type="text" placeholder="Recherche" name="q" id="myInput">
<button type="submit">
<img src="/loupe.png">
</button>
</form>
<div class="liste_favori">
<a href="https://nups.fr"><img src="/onedrive.svg"><p>Onedrive</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>2 favori :</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>3 favori :</p></a>
</div>
</header>
<footer id="footer" class="footer">
<span class="copyrights">&copy; <div id="year"></div> - Arthur Puechberty</span>
<a href="{{ route('terms') }}" class="conditions_generale" target="_blank">Condition générales</a>
</footer>
<script>
var year = new Date().getFullYear();
document.getElementById("year").innerHTML = year;
document.getElementById('myForm').addEventListener('submit', function(event) {
var input = document.getElementById('myInput');
if (input.value.trim() === '') {
event.preventDefault(); // Empêche la soumission du formulaire
} else {
this.action = "https://www.google.fr/search";
}
});
</script>
</section>
<div class="separator"></div>
<section class="section_droite">
<nav>
<a class="lien_nav" target="_blank" href="https://nups.fr">
Theme
</a>
<a class="lien_nav" href="https://nups.fr" target="_blank">
Paramettre
</a>
<a class="lien_nav" href="#">
<img class="img_nav" src="/app.png"/>
</a>
<a class="lien_nav" href="https://nups.fr" target="_blank">
<img class="img_nav img_compte" src="/unnamed.png"/>
</a>
</nav>
<div class="liste_app">
<a href="https://nups.fr"><img src="/unnamed.png"><p>Compte</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Recherche</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Maps</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Actualités</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Mail</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Meet</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Contacts</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Drive</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Agenda</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Traduction</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Photos</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Nups</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Finance</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Docs</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Tableurs</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Slides</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Livres</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Hangouts</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Keep</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Jamboard</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Classroom</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Earth</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Enregistré</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Arts & Culture</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Ads</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Voyages</p></a>
<a href="https://nups.fr"><img src="/unnamed.png"><p>Formulaires</p></a>
</div>
</section>
</main>
</body>
</html>
@@ -0,0 +1,130 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Nups</title>
@entryPointStyles('project-nups')
</head>
<body>
<header>
<nav>
<li>
<img src="/logo.svg" class="logo">
</li>
<li>
<a href="#" data-text="Accueil">Accueil</a>
</li>
<li>
<a href="#explication">Explication</a>
</li>
<li>
<a href="#download">Télécharger</a>
</li>
<li>
<a href="#version_web">Version web</a>
</li>
</nav>
<h1 class="big_title">Nups</h1>
</header>
<section id="explication">
<h1 class="titre_section">Explication</h1>
<div class="explication_contenaire">
<div class="partie_1">
<img src="/arthur.jpg" class="image_parragraphe_1">
<h2>Le créateur</h2>
<p>Arthur Puechberty a décidé de créer ce logiciel le 13 juin 2023 à l'âge de 16 ans !
Il a toujours rêvé de créer un logiciel regroupant tout. Le problème avec Internet
est que dès que nous voulons faire quelque chose, il faut soit aller sur un site,
soit utiliser un logiciel. De plus, en fonction de ce que vous voulez faire, il faut
souvent accéder à des sites différents, mais ces sites ne communiquent généralement
pas entre eux, ce qui peut poser des problèmes. Il fallait remédier à cela en créant
Nups.</p>
</div>
<div class="space"></div>
<div class="partie_2">
<img src="/project-nups.png" class="image_parragraphe_2">
<h2>Qu'est-ce que Nups</h2>
<p>Nups est une société spécialisée dans les services en ligne tels que la recherche sur
Internet, la messagerie (Nups mail), les cartes (Nups Maps), le partage de vidéos
(Nups vidéo), le stockage en ligne (Nups stocke) et bien d'autres. Elle est également
active dans la recherche et le développement de nouvelles technologies.</p>
</div>
</div>
</section>
<section id="download">
<h1 class="titre_section">Télécharger</h1>
<div class="download_link">
<button type="button" class="btn_download" onclick="telecharger_installer_windows()"><span>Télécharger pour Windows </span><img src="/icon windows.png" alt="" class="logo_download" /></button>
<button type="button" class="btn_download" onclick="telecharger_installer_mac_os()"><span>Télécharger pour Mac OS </span><img src="/icon mac os.png" alt="" class="logo_download" /></button>
<button type="button" class="btn_download" onclick="telecharger_installer_linux()"><span>Télécharger pour Linux </span><img src="/icon linux.png" alt="" class="logo_download" /></button>
</div>
<script>
function telecharger_installer_windows() {
var lien = document.createElement('a');
lien.href = 'chemin/vers/le/fichier';
lien.download = 'nups installer.exe';
lien.click();
}
function telecharger_installer_mac_os() {
var lien = document.createElement('a');
lien.href = 'chemin/vers/le/fichier';
lien.download = 'nups installer.exe';
lien.click();
}
function telecharger_installer_linux() {
var lien = document.createElement('a');
lien.href = 'chemin/vers/le/fichier';
lien.download = 'nups installer.exe';
lien.click();
}
</script>
</section>
<section id="version_web">
<h1 class="titre_section">Version web</h1>
<p>Si vous ne voulez pas télécharger notre logiciel, vous pouvez toujours acceder a la version web. Sur cette version il vous suffi de vous connecter comme sur le logiciel et vous pourrez acceder a nos service.</p>
<div class="btn_version_web_contenaire">
<button type="button" class="btn_version_web" onclick="window.location.href='{{ route('nups-web') }}'">Acceder a la version web</button>
</div>
</section>
<section id="autre">
<h1 class="titre_section">Autre</h1>
<p>Nous avons aussi un serveur discord !</p>
</section>
<footer class="footer">
<span class="copyrights">&copy; <div id="year"></div> - Arthur Puechberty</span>
<a href="{{ route('terms') }}" class="conditions_generale" target="_blank">Condition générales</a>
</footer>
<script>
var year = new Date().getFullYear();
document.getElementById("year").innerHTML = year;
document.getElementById('myForm').addEventListener('submit', function(event) {
var input = document.getElementById('myInput');
if (input.value.trim() === '') {
event.preventDefault(); // Empêche la soumission du formulaire
} else {
this.action = "https://www.google.fr/search";
}
});
</script>
<script>
const body = document.querySelector("body");
let darkmode = localStorage.getItem("dark-mode");
if(darkmode === "enabled"){
body.classList.add("dark-mode-theme");
} else {
body.classList.remove("dark-mode-theme");
}
</script>
</body>
</html>
+89
View File
@@ -0,0 +1,89 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Terms and Conditions</title>
@entryPointStyles('terms')
</head>
<body>
<main>
<h1>Nups Terms and Conditions</h1>
<p>Effective Date: Saturday, June 17, 2023</p>
<p>Thank you for using Nups services! These Terms and Conditions govern your use of our services. Please read them carefully.</p>
<h2>Acceptance of Terms and Conditions</h2>
<p>1.1 Acceptance of Terms. By using Nups services, you agree to be bound by these Terms and Conditions. If you do not accept these Terms, you cannot use our services.</p>
<h2>Use of Our Services</h2>
<p>2.1 User Account. To use certain Nups services, you will need to create a user account. You are responsible for the confidentiality of your login credentials and all activities related to your account.</p>
<p>2.2 Authorized Use. You agree to use Nups services in accordance with these Terms and Conditions and all applicable laws. You may not use our services in a way that could infringe on Nups' rights or the rights of others.</p>
<p>2.3 Usage Restrictions. You agree not to access Nups services in an unauthorized manner, attempt to gain unauthorized access to accounts or computer systems, and not to disrupt or harm Nups services.</p>
<h2>User Content</h2>
<p>3.1 Content Ownership. You retain ownership of any content you submit, post, or display on Nups services. By submitting, posting, or displaying content, you grant Nups a worldwide, non-exclusive, transferable, free, and royalty-free license to use, reproduce, modify, adapt, publish, translate, distribute, display, and create derivative works from that content.</p>
<p>3.2 Content Responsibility. You are responsible for the content you submit, post, or display on Nups services. You warrant that you have all necessary rights to publish this content, and it does not violate the rights of others.</p>
<p>3.3 Respect for Intellectual Property Rights. You agree not to violate the intellectual property rights of Nups or third parties when using Nups services. You may not copy, modify, distribute, or access copyrighted content or other intellectual property items without authorization.</p>
<h2>Intellectual Property</h2>
<p>4.1 Nups' Intellectual Property Rights. All intellectual property rights related to Nups services (except user content) are owned by Nups. You do not acquire any ownership rights to Nups services or the content you access.</p>
<p>4.2 Authorized Use. Subject to compliance with these Terms and Conditions, Nups grants you a limited, non-exclusive, revocable, non-transferable license to use Nups services for personal and non-commercial purposes.</p>
<h2>Privacy</h2>
<p>5.1 Data Collection. Nups collects and uses your information in accordance with its Privacy Policy. By using Nups services, you consent to the collection and use of your information as outlined in this policy.</p>
<p>5.2 Cookies. Nups services may use cookies and similar technologies to facilitate your site usage and personalize your experience.</p>
<p>5.3 Data Security. Nups implements appropriate security measures to protect your information from unauthorized access, disclosure, or misuse.</p>
<h2>Changes to Services</h2>
<p>6.1 Changes to Terms and Conditions. Nups reserves the right to modify these Terms and Conditions at any time. Changes take effect upon their publication on the Nups website. Your continued use of Nups services after such changes constitutes your acceptance of the amended Terms and Conditions.</p>
<p>6.2 Changes to Services. Nups also reserves the right to modify, suspend, or temporarily or permanently terminate any aspect of its services, including access to certain features, without notice or liability to you. You acknowledge that Nups will not be liable to you or any third party for any changes, suspensions, or interruptions of its services.</p>
<h2>Responsibilities and Limitations</h2>
<p>7.1 Disclaimer of Warranties. Nups services are provided "as is" and "as available," without any warranties, express or implied. Nups does not guarantee the accuracy, completeness, reliability, or availability of the services. You use Nups services at your own risk.</p>
<p>7.2 Limitation of Liability. To the fullest extent permitted by law, Nups will not be liable for direct, indirect, incidental, special, consequential, or punitive damages arising from your use or inability to use Nups services.</p>
<h2>Termination</h2>
<p>8.1 Termination by You. You may terminate your user account and stop using Nups services at any time.</p>
<p>8.2 Termination by Nups. Nups reserves the right to terminate your user account and terminate your use of the services, in whole or in part, if you violate these Terms and Conditions or if your use of the services is detrimental to Nups or other users.</p>
<h2>General Provisions</h2>
<p>9.1 Entire Agreement. These Terms and Conditions constitute the entire agreement between you and Nups regarding the use of Nups services and supersede all prior or contemporaneous agreements between you and Nups.</p>
<p>9.2 Applicable Law. These Terms and Conditions are governed and interpreted in accordance with the laws of the country where Nups is headquartered.</p>
<p>9.3 Dispute Resolution. Any dispute arising from these Terms and Conditions shall be subject to the exclusive jurisdiction of the courts of the country where Nups is headquartered.</p>
<p>9.4 Severability. If any provision of these Terms and Conditions is found to be invalid, illegal, or unenforceable by a competent court, such provision shall be modified to the minimum extent necessary to make it valid, legal, and enforceable, and the other provisions shall remain in full force.</p>
<h2>Communications</h2>
<p>10.1 Nups Communications. By using Nups services, you consent to receive communications from Nups, including announcements, updates, promotional offers, and service-related messages.</p>
<p>10.2 User Communications. If you choose to contact Nups, you agree that Nups may respond to you using the contact information you have provided.</p>
<h2>Indemnification</h2>
<p>11.1 Indemnification. You agree to indemnify, defend, and hold Nups, its officers, directors, employees, agents, and representatives harmless from any claim, liability, loss, damage, cost, or expense, including reasonable attorney's fees, arising from your use of Nups services or your violation of these Terms and Conditions.</p>
<h2>Copyright Infringement Notifications</h2>
<p>12.1 Copyright Infringement Notifications. Nups respects the intellectual property rights of others. If you believe that any content available on Nups services violates your copyrights, please submit a copyright infringement notification in accordance with applicable law.</p>
<h2>Severability of Provisions</h2>
<p>13.1 Severability of Provisions. If any provision of these Terms and Conditions is found invalid, illegal, or unenforceable by a competent court, such provision shall be modified to the minimum extent necessary to make it valid, legal, and enforceable, and the other provisions shall remain in full force.</p>
<h2>Language</h2>
<p>14.1 Language of the Terms. In case of any discrepancy between the language versions of these Terms and Conditions, the French version shall prevail.</p>
<h2>Contact Us</h2>
<p>15.1 Contact. If you have questions, concerns, or comments about these Terms and Conditions, please contact us at the following address:</p>
<p>Nups Inc.<br>Address: [Address]<br>Email: [Email]<br>Phone: [Phone Number]</p>
<p>Thank you for reading our Terms and Conditions! We hope you enjoy using Nups services.</p>
</main>
<script>
const body = document.querySelector("body");
let darkmode = localStorage.getItem("dark-mode");
if(darkmode === "enabled"){
body.classList.add("dark-mode-theme");
} else {
body.classList.remove("dark-mode-theme");
}
</script>
</body>
</html>
-16
View File
@@ -1,16 +0,0 @@
document.addEventListener("DOMContentLoaded", function() {
var userLanguage = navigator.language || navigator.userLanguage;
var userLanguage = userLanguage.substring(0, 2);
if (userLanguage !== "fr" && userLanguage !== "en" && userLanguage !== "zh") {
var userLanguage = "en";
}
var elementsToStyle = document.querySelectorAll("[lang]");
for (var j = 0; j < elementsToStyle.length; j++) {
var element = elementsToStyle[j];
if (userLanguage !== element.getAttribute("lang")) {
element.style.display = "none";
}
}
});
+19
View File
@@ -0,0 +1,19 @@
/*
|--------------------------------------------------------------------------
| AdonisJs Server
|--------------------------------------------------------------------------
|
| The contents in this file is meant to bootstrap the AdonisJs application
| and start the HTTP server to accept incoming connections. You must avoid
| making this file dirty and instead make use of `lifecycle hooks` provided
| by AdonisJs service providers for custom code.
|
*/
import 'reflect-metadata'
import sourceMapSupport from 'source-map-support'
import { Ignitor } from '@adonisjs/core/build/standalone'
sourceMapSupport.install({ handleUncaughtExceptions: false })
new Ignitor(__dirname).httpServer().start()
+46
View File
@@ -0,0 +1,46 @@
/*
|--------------------------------------------------------------------------
| Application middleware
|--------------------------------------------------------------------------
|
| This file is used to define middleware for HTTP requests. You can register
| middleware as a `closure` or an IoC container binding. The bindings are
| preferred, since they keep this file clean.
|
*/
import Server from '@ioc:Adonis/Core/Server'
/*
|--------------------------------------------------------------------------
| Global middleware
|--------------------------------------------------------------------------
|
| An array of global middleware, that will be executed in the order they
| are defined for every HTTP requests.
|
*/
Server.middleware.register([
() => import('@ioc:Adonis/Core/BodyParser'),
() => import('App/Middleware/SilentAuth')
])
/*
|--------------------------------------------------------------------------
| Named middleware
|--------------------------------------------------------------------------
|
| Named middleware are defined as key-value pair. The value is the namespace
| or middleware function and key is the alias. Later you can use these
| alias on individual routes. For example:
|
| { auth: () => import('App/Middleware/Auth') }
|
| and then use it as follows
|
| Route.get('dashboard', 'UserController.dashboard').middleware('auth')
|
*/
Server.middleware.registerNamed({
auth: () => import('App/Middleware/Auth')
})
+37
View File
@@ -0,0 +1,37 @@
/*
|--------------------------------------------------------------------------
| Routes
|--------------------------------------------------------------------------
|
| This file is dedicated for defining HTTP routes. A single file is enough
| for majority of projects, however you can define routes in different
| files and just make sure to import them inside this file. For example
|
| Define routes in following two files
| start/routes/cart.ts
| start/routes/customer.ts
|
| and then import them inside `start/routes.ts` as follows
|
| import './routes/cart'
| import './routes/customer''
|
*/
import Route from '@ioc:Adonis/Core/Route'
Route.get('/', 'HomeController.index').as('home')
Route.get('/auth', 'AuthController.index').as('auth')
Route.post('/login', 'AuthController.login').as('login')
Route.post('/signup', 'AuthController.signup').as('signup')
Route.get('/logout', 'AuthController.logout').as('logout')
Route.get('/compte', 'ComptesController.index').as('compte')
Route.post('/modifpseudo', 'ComptesController.modifpseudo').as('modifpseudo')
Route.post('/modifemail', 'ComptesController.modifemail').as('modifemail')
Route.get('/projects/nups', 'ProjectsController.nups').as('nups')
Route.get('/projects/nups/web', 'ProjectsController.nupsWeb').as('nups-web')
Route.get('/terms', 'TermsController.index').as('terms')
-200
View File
@@ -1,200 +0,0 @@
.lang-fr {
display: none;
}
.lang-en {
display: none;
}
* {
padding: 0;
margin: 0;
font-family: 'Roboto', sans-serif;
}
body {
justify-content: space-around;
max-width: 2500px;
margin: auto;
}
header,
main,
section {
margin: 100px 100px 100px;
}
h1 {
padding: 0 0 50px 0;
font-weight: 900;
font-size: 50px;
}
h2 {
font-size: 40px;
font-weight: 700;
margin-bottom: 30px;
}
h3 {
font-size: 28px;
font-weight: 700;
margin-bottom: 10px;
}
.barre-verticale {
border-left: 5px solid rgb(94, 94, 94);
padding-left: 15px;
margin-bottom: 10px;
}
.citation {
font-style: italic;
color: rgb(61, 61, 61);
}
.citation-auth {
color: rgb(61, 61, 61);
margin-bottom: 40px;
}
main {
display: flex;
}
.main-left {
margin-right: 40px;
}
.main-right {
margin-left: 40px;
min-width: 40%;
}
nav ul {
display: flex;
justify-content: space-between;
margin: 0 50px 0 50px;
}
nav li {
list-style: none;
margin: 0 5px 0 5px;
}
nav a {
padding: 5px 10px;
color: rgb(83, 83, 83);
text-decoration: none;
border: 2px solid rgb(83, 83, 83);
border-radius: 5px;
cursor: pointer;
font-weight: bold;
}
nav a:hover {
color: gray;
border-color: gray;
}
.div-lien div {
display: flex;
flex-direction: row;
align-items: center;
text-align: left;
margin: 5px 0 5px;
padding: 20px 40px;
background-color: rgb(216, 216, 216);
color: rgb(85, 85, 85);
text-decoration: none;
border-radius: 5px;
cursor: pointer;
font-weight: bold;
}
.div-lien div:hover {
background-color: rgb(177, 177, 177);
}
.div-lien a {
text-decoration: none;
}
.div-lien img {
width: 50px;
padding-right: 15px;
}
@media (max-width: 800px) {
.main-right {
display: none;
}
header,
main,
section {
margin: 20px 20px 20px;
}
nav ul {
margin: 0;
}
}
.pp {
margin: auto;
width: 100%;
max-width: 500px;
border-radius: 50%;
}
form {
width: 60%;
margin: 0 auto;
background-color: #fff;
padding: 20px;
border: 1px solid #ddd;
border-radius: 5px;
}
label {
display: block;
margin-top: 10px;
}
input[type="text"],
input[type="email"],
textarea {
width: 100%;
padding: 10px;
margin-top: 5px;
border: 1px solid #ddd;
border-radius: 5px;
}
input[type="submit"] {
background-color: #333;
color: #fff;
padding: 10px 20px;
border: none;
border-radius: 5px;
cursor: pointer;
margin-top: 10px;
}
input[type="submit"]:hover {
background-color: #555;
}
.all_projects {
display: flex;
flex-wrap: wrap;
justify-content: center;
}
.all_projects div {
background-color: aqua;
height: 300px;
width: 300px;
margin: 10px;
}
+45
View File
@@ -0,0 +1,45 @@
/*
|--------------------------------------------------------------------------
| Tests
|--------------------------------------------------------------------------
|
| The contents in this file boots the AdonisJS application and configures
| the Japa tests runner.
|
| For the most part you will never edit this file. The configuration
| for the tests can be controlled via ".adonisrc.json" and
| "tests/bootstrap.ts" files.
|
*/
process.env.NODE_ENV = 'test'
import 'reflect-metadata'
import sourceMapSupport from 'source-map-support'
import { Ignitor } from '@adonisjs/core/build/standalone'
import { configure, processCliArgs, run, RunnerHooksHandler } from '@japa/runner'
sourceMapSupport.install({ handleUncaughtExceptions: false })
const kernel = new Ignitor(__dirname).kernel('test')
kernel
.boot()
.then(() => import('./tests/bootstrap'))
.then(({ runnerHooks, ...config }) => {
const app: RunnerHooksHandler[] = [() => kernel.start()]
configure({
...kernel.application.rcFile.tests,
...processCliArgs(process.argv.slice(2)),
...config,
...{
importer: (filePath) => import(filePath),
setup: app.concat(runnerHooks.setup),
teardown: runnerHooks.teardown,
},
cwd: kernel.application.appRoot,
})
run()
})
+69
View File
@@ -0,0 +1,69 @@
/**
* File source: https://bit.ly/3ukaHTz
*
* Feel free to let us know via PR, if you find something broken in this contract
* file.
*/
import type { Config } from '@japa/runner'
import TestUtils from '@ioc:Adonis/Core/TestUtils'
import { assert, runFailedTests, specReporter, apiClient } from '@japa/preset-adonis'
/*
|--------------------------------------------------------------------------
| Japa Plugins
|--------------------------------------------------------------------------
|
| Japa plugins allows you to add additional features to Japa. By default
| we register the assertion plugin.
|
| Feel free to remove existing plugins or add more.
|
*/
export const plugins: Required<Config>['plugins'] = [assert(), runFailedTests(), apiClient()]
/*
|--------------------------------------------------------------------------
| Japa Reporters
|--------------------------------------------------------------------------
|
| Japa reporters displays/saves the progress of tests as they are executed.
| By default, we register the spec reporter to show a detailed report
| of tests on the terminal.
|
*/
export const reporters: Required<Config>['reporters'] = [specReporter()]
/*
|--------------------------------------------------------------------------
| Runner hooks
|--------------------------------------------------------------------------
|
| Runner hooks are executed after booting the AdonisJS app and
| before the test files are imported.
|
| You can perform actions like starting the HTTP server or running migrations
| within the runner hooks
|
*/
export const runnerHooks: Pick<Required<Config>, 'setup' | 'teardown'> = {
setup: [() => TestUtils.ace().loadCommands()],
teardown: [],
}
/*
|--------------------------------------------------------------------------
| Configure individual suites
|--------------------------------------------------------------------------
|
| The configureSuite method gets called for every test suite registered
| within ".adonisrc.json" file.
|
| You can use this method to configure suites. For example: Only start
| the HTTP server when it is a functional suite.
*/
export const configureSuite: Required<Config>['configureSuite'] = (suite) => {
if (suite.name === 'functional') {
suite.setup(() => TestUtils.httpServer().start())
}
}
+8
View File
@@ -0,0 +1,8 @@
import { test } from '@japa/runner'
test('display welcome page', async ({ client }) => {
const response = await client.get('/')
response.assertStatus(200)
response.assertTextIncludes('<h1 class="title"> It Works! </h1>')
})
+39
View File
@@ -0,0 +1,39 @@
{
"extends": "adonis-preset-ts/tsconfig.json",
"include": [
"**/*"
],
"exclude": [
"node_modules",
"build"
],
"compilerOptions": {
"outDir": "build",
"rootDir": "./",
"sourceMap": true,
"paths": {
"App/*": [
"./app/*"
],
"Config/*": [
"./config/*"
],
"Contracts/*": [
"./contracts/*"
],
"Database/*": [
"./database/*"
]
},
"types": [
"@adonisjs/core",
"@adonisjs/repl",
"@adonisjs/session",
"@adonisjs/view",
"@adonisjs/shield",
"@japa/preset-adonis/build/adonis-typings",
"@adonisjs/lucid",
"@adonisjs/auth"
]
}
}
+219
View File
@@ -0,0 +1,219 @@
const { join } = require('path')
const Encore = require('@symfony/webpack-encore')
/*
|--------------------------------------------------------------------------
| Encore runtime environment
|--------------------------------------------------------------------------
*/
if (!Encore.isRuntimeEnvironmentConfigured()) {
Encore.configureRuntimeEnvironment(process.env.NODE_ENV || 'dev')
}
/*
|--------------------------------------------------------------------------
| Output path
|--------------------------------------------------------------------------
|
| The output path for writing the compiled files. It should always
| be inside the public directory, so that AdonisJS can serve it.
|
*/
Encore.setOutputPath('./public/assets')
/*
|--------------------------------------------------------------------------
| Public URI
|--------------------------------------------------------------------------
|
| The public URI to access the static files. It should always be
| relative from the "public" directory.
|
*/
Encore.setPublicPath('/assets')
/*
|--------------------------------------------------------------------------
| Entrypoints
|--------------------------------------------------------------------------
|
| Entrypoints are script files that boots your frontend application. Ideally
| a single entrypoint is used by majority of applications. However, feel
| free to add more (if required).
|
| Also, make sure to read the docs on "Assets bundler" to learn more about
| entrypoints.
|
*/
Encore.addEntry('index', './resources/js/index.js')
Encore.addEntry('form', './resources/css/form.css')
Encore.addEntry('compte', './resources/css/compte.css')
Encore.addEntry('terms', './resources/css/terms.css')
Encore.addEntry('project-nups', './resources/css/project-nups.css')
Encore.addEntry('nups', './resources/css/nups.css')
/*
|--------------------------------------------------------------------------
| Copy assets
|--------------------------------------------------------------------------
|
| Since the edge templates are not part of the Webpack compile lifecycle, any
| images referenced by it will not be processed by Webpack automatically. Hence
| we must copy them manually.
|
*/
// Encore.copyFiles({
// from: './resources/images',
// to: 'images/[path][name].[hash:8].[ext]',
// })
/*
|--------------------------------------------------------------------------
| Split shared code
|--------------------------------------------------------------------------
|
| Instead of bundling duplicate code in all the bundles, generate a separate
| bundle for the shared code.
|
| https://symfony.com/doc/current/frontend/encore/split-chunks.html
| https://webpack.js.org/plugins/split-chunks-plugin/
|
*/
// Encore.splitEntryChunks()
/*
|--------------------------------------------------------------------------
| Isolated entrypoints
|--------------------------------------------------------------------------
|
| Treat each entry point and its dependencies as its own isolated module.
|
*/
Encore.disableSingleRuntimeChunk()
/*
|--------------------------------------------------------------------------
| Cleanup output folder
|--------------------------------------------------------------------------
|
| It is always nice to cleanup the build output before creating a build. It
| will ensure that all unused files from the previous build are removed.
|
*/
Encore.cleanupOutputBeforeBuild()
/*
|--------------------------------------------------------------------------
| Source maps
|--------------------------------------------------------------------------
|
| Enable source maps in production
|
*/
Encore.enableSourceMaps(!Encore.isProduction())
/*
|--------------------------------------------------------------------------
| Assets versioning
|--------------------------------------------------------------------------
|
| Enable assets versioning to leverage lifetime browser and CDN cache
|
*/
Encore.enableVersioning(Encore.isProduction())
/*
|--------------------------------------------------------------------------
| Configure dev server
|--------------------------------------------------------------------------
|
| Here we configure the dev server to enable live reloading for edge templates.
| Remember edge templates are not processed by Webpack and hence we need
| to watch them explicitly and livereload the browser.
|
*/
Encore.configureDevServerOptions((options) => {
/**
* Normalize "options.static" property to an array
*/
if (!options.static) {
options.static = []
} else if (!Array.isArray(options.static)) {
options.static = [options.static]
}
/**
* Enable live reload and add views directory
*/
options.liveReload = true
options.static.push({
directory: join(__dirname, './resources/views'),
watch: true,
})
})
/*
|--------------------------------------------------------------------------
| CSS precompilers support
|--------------------------------------------------------------------------
|
| Uncomment one of the following lines of code to enable support for your
| favorite CSS precompiler
|
*/
// Encore.enableSassLoader()
// Encore.enableLessLoader()
// Encore.enableStylusLoader()
/*
|--------------------------------------------------------------------------
| CSS loaders
|--------------------------------------------------------------------------
|
| Uncomment one of the following line of code to enable support for
| PostCSS or CSS.
|
*/
// Encore.enablePostCssLoader()
// Encore.configureCssLoader(() => {})
/*
|--------------------------------------------------------------------------
| Enable Vue loader
|--------------------------------------------------------------------------
|
| Uncomment the following lines of code to enable support for vue. Also make
| sure to install the required dependencies.
|
*/
// Encore.enableVueLoader(() => {}, {
// version: 3,
// runtimeCompilerBuild: false,
// useJsx: false
// })
/*
|--------------------------------------------------------------------------
| Configure logging
|--------------------------------------------------------------------------
|
| To keep the terminal clean from unnecessary info statements , we only
| log warnings and errors. If you want all the logs, you can change
| the level to "info".
|
*/
const config = Encore.getWebpackConfig()
config.infrastructureLogging = {
level: 'warn',
}
config.stats = 'errors-warnings'
/*
|--------------------------------------------------------------------------
| Export config
|--------------------------------------------------------------------------
|
| Export config for webpack to do its job
|
*/
module.exports = config