init project
This commit is contained in:
6
.dockerignore
Normal file
6
.dockerignore
Normal file
@@ -0,0 +1,6 @@
|
||||
medias/
|
||||
tmp/
|
||||
target/
|
||||
persistence-db/
|
||||
staticbuild/
|
||||
static/
|
||||
16
.gitignore
vendored
Normal file
16
.gitignore
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
www/*/
|
||||
!www/default/
|
||||
!www/static/
|
||||
!www/home/
|
||||
|
||||
/target/
|
||||
Cargo.lock
|
||||
|
||||
# These are backup files generated by rustfmt
|
||||
**/*.rs.bk
|
||||
|
||||
/medias
|
||||
persistence-db
|
||||
tmp/*
|
||||
static/sourcefiles/
|
||||
staticbuild/
|
||||
30
Cargo.toml
Normal file
30
Cargo.toml
Normal file
@@ -0,0 +1,30 @@
|
||||
[package]
|
||||
name = "pointcloud"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
actix = "0.13.0"
|
||||
actix-web = "4.2.1"
|
||||
actix-files = "0.6"
|
||||
actix-identity = "0.4"
|
||||
actix-multipart = "0.4"
|
||||
actix-form-data = "0.6.2"
|
||||
actix-web-actors = "4.1.0"
|
||||
oauth2 = "4.2.3"
|
||||
jsonwebtoken-google = "0.1.6"
|
||||
diesel = { version = "1.4.4", features = ["postgres"] }
|
||||
serde = "1.0.136"
|
||||
serde_json = "1.0.59"
|
||||
rand = "0.8.5"
|
||||
dotenv = "0.15.0"
|
||||
sha256 = "1.0.3"
|
||||
walkdir = "2.3.2"
|
||||
tera = "1.8.0"
|
||||
futures-util = { version = "0.3.7", default-features = false, features = ["std"] }
|
||||
sanitize-filename = "0.3"
|
||||
uuid = { version = "0.8", features = ["v4"] }
|
||||
tempfile = "3.3.0"
|
||||
minifier = "0.2.2"
|
||||
lettre = { version = "0.10.0-beta.2", default-features = false, features = ["smtp-transport", "tokio1-rustls-tls", "hostname", "r2d2", "builder"] }
|
||||
derive_more = "0.99.17"
|
||||
18
Dockerfile
Normal file
18
Dockerfile
Normal file
@@ -0,0 +1,18 @@
|
||||
FROM rust:latest
|
||||
|
||||
MAINTAINER Valentin SORLIN
|
||||
|
||||
USER root
|
||||
|
||||
ENV ROCKET_ADDRESS=0.0.0.0
|
||||
ENV ROCKET_PORT=80
|
||||
|
||||
WORKDIR /usr/src/myapp
|
||||
|
||||
COPY ./liblaszip.so /lib/liblaszip.so
|
||||
|
||||
RUN rustup default nightly
|
||||
RUN cargo install cargo-watch
|
||||
RUN cargo install diesel_cli --no-default-features --features postgres
|
||||
|
||||
CMD ["cargo", "watch", "-x", "run", "-i", "/usr/src/myapp/tmp", "--why"]
|
||||
71
NORME.md
Normal file
71
NORME.md
Normal file
@@ -0,0 +1,71 @@
|
||||
Nommage
|
||||
=====================
|
||||
Les variable
|
||||
--------------------
|
||||
Les variables doivent être en minuscule en [snake_case](https://www.theserverside.com/definition/Snake-case) et sans chiffre et si possible refléter le type de variable
|
||||
|
||||
exemple correct:
|
||||
```
|
||||
let nb_chat = 5; // c'est une qte alors nb
|
||||
let chats = Vec<Chat>::new(); // c'est un tableau alors "s"
|
||||
let is_chat = True; // C'est un booléen du coup is
|
||||
```
|
||||
exemple incorrect:
|
||||
```
|
||||
let 1chien = 1; // incorrect a cause du chiffre
|
||||
let mechantChien = Chien::new(); // incorrect car CamelCase
|
||||
let IS_CHIEN = False;// incorrect car majuscule
|
||||
let nb_chien = Chien::new(); //incorrect la variable s'appel nb et ne représente pas le type de variable qui est ici un instance de Chien
|
||||
```
|
||||
Les classes
|
||||
=====================
|
||||
les classe/struct doivent commencé par une majuscule et être en un mots
|
||||
exemple correct:
|
||||
```
|
||||
struct User {}
|
||||
struct Project {}
|
||||
```
|
||||
exemple incorrect:
|
||||
```
|
||||
struct user{} // incorrect a cause de la majuscule
|
||||
struct ProjectNuageDePoints // incorrect car en plusieurs mots
|
||||
```
|
||||
Structure de code
|
||||
------------------
|
||||
Les variable doivent êtres autant que possible en début de fonction
|
||||
```
|
||||
fct main() {
|
||||
let variable_correct = 22;
|
||||
println("{}", variable_correct);
|
||||
let variable_incorrect = 35; // incorrect car non déclarré avant première action
|
||||
}
|
||||
```
|
||||
Les variable doivent être type si le type c'est pas défini directement.
|
||||
```
|
||||
let tata = String::new("une chaine de caractère"); // pas besoin de spécifier le type car on voit direct que c'est une String
|
||||
let toto:String; // ici on défini le type de la varible car elle n'est pas assigné directement
|
||||
|
||||
toto = "une chaine de caractère mais plus tard";
|
||||
```
|
||||
Pour les block le premier crochet toi être sur le même ligne que l'action(if, for, struct, ...)
|
||||
```
|
||||
if toto == True {
|
||||
//correct
|
||||
}
|
||||
if toto == True
|
||||
{
|
||||
//incorrect
|
||||
}
|
||||
if toto = True
|
||||
//incorrect
|
||||
```
|
||||
Autre
|
||||
---------------
|
||||
- Le nom des fonction doivent décrire que quel fait.
|
||||
- Si un block de code revient souvent on créer une fonction.
|
||||
- La longeur des ligne doivent rentrer dans l'ecrans.
|
||||
- La hauteur des fonction doivent rentrer dans l'ecrans.
|
||||
- Les variables dise a quoi elles servent(pas de toto) sauf pour i et j dans les boucle d'intération.
|
||||
- On ne saute pas des ligne inutilement. Un saut de ligne doit séparée 2 fonctionnement ex: déclaration des variable "\n" utilisation de celle si
|
||||
- On ne garde les commentaires de code que si il a vocation a être décommenté.
|
||||
- Les commentaires peuvent être intéressant si le code être trop complexe a lire (ex: un calcul mathématique) mais il n'est pas obligatoire il faut pensé a réécrire le code pour le rendre plus simple plutôt que de faire des truc complexe avec un commentaire.
|
||||
8
README.md
Normal file
8
README.md
Normal file
@@ -0,0 +1,8 @@
|
||||
#migrate table
|
||||
`./diesel.sh migration run`
|
||||
|
||||
#Create new table
|
||||
`./diesel.sh migration generate example_name`
|
||||
|
||||
#revert migration
|
||||
`./diesel.sh migration revert`
|
||||
5
diesel.toml
Normal file
5
diesel.toml
Normal file
@@ -0,0 +1,5 @@
|
||||
# For documentation on how to configure this file,
|
||||
# see diesel.rs/guides/configuring-diesel-cli
|
||||
|
||||
[print_schema]
|
||||
file = "src/schema.rs"
|
||||
69
docker-compose.yml
Normal file
69
docker-compose.yml
Normal file
@@ -0,0 +1,69 @@
|
||||
version: "3.3"
|
||||
|
||||
services:
|
||||
maps360:
|
||||
build: "."
|
||||
ports:
|
||||
- "80:80"
|
||||
volumes:
|
||||
- .:/usr/src/myapp
|
||||
environment:
|
||||
- HOST=maps360.fr
|
||||
- PORT=80
|
||||
- DATABASE_URL=postgresql://admin:tempPassword1234@maps360-db/db
|
||||
- MODE_INSTALL=DEV # DEV, PROD
|
||||
- RUST_BACKTRACE=1
|
||||
- TMPDIR=/usr/src/myapp/tmp
|
||||
depends_on:
|
||||
- maps360-db
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.services.maps360.loadbalancer.server.port=80
|
||||
- traefik.http.routers.maps360-http.entrypoints=http
|
||||
- traefik.http.routers.maps360-http.rule=Host(`maps360.helodee.fr`)
|
||||
- traefik.http.middlewares.https-redirect.redirectscheme.scheme=https
|
||||
- traefik.http.middlewares.https-redirect.redirectscheme.permanent=true
|
||||
- traefik.http.routers.maps360-http.middlewares=https-redirect@docker
|
||||
- traefik.http.routers.maps360-https.entrypoints=https
|
||||
- traefik.http.routers.maps360-https.rule=Host(`maps360.helodee.fr`)
|
||||
- traefik.http.routers.maps360-https.tls=true
|
||||
- traefik.http.routers.maps360-https.tls.certresolver=letsencrypt
|
||||
networks:
|
||||
- traefik
|
||||
|
||||
maps360-db:
|
||||
image: postgres:latest
|
||||
environment:
|
||||
- POSTGRES_DB=db
|
||||
- POSTGRES_USER=admin
|
||||
- POSTGRES_PASSWORD=tempPassword1234
|
||||
volumes:
|
||||
- ./persistence-db:/var/lib/postgresql/data
|
||||
networks:
|
||||
- traefik
|
||||
|
||||
maps360-adminer:
|
||||
image: adminer
|
||||
ports:
|
||||
- 8080:8080
|
||||
labels:
|
||||
- traefik.enable=true
|
||||
- traefik.http.services.maps360-adminer.loadbalancer.server.port=80
|
||||
- traefik.http.routers.maps360-adminer-http.entrypoints=http
|
||||
- traefik.http.routers.maps360-adminer-http.rule=Host(`maps360admin.helodee.fr`)
|
||||
- traefik.http.middlewares.https-redirect.redirectscheme.scheme=https
|
||||
- traefik.http.middlewares.https-redirect.redirectscheme.permanent=true
|
||||
- traefik.http.routers.maps360-adminer-http.middlewares=https-redirect@docker
|
||||
- traefik.http.routers.maps360-adminer-https.entrypoints=https
|
||||
- traefik.http.routers.maps360-adminer-https.rule=Host(`maps360admin.helodee.fr`)
|
||||
- traefik.http.routers.maps360-adminer-https.tls=true
|
||||
- traefik.http.routers.maps360-adminer-https.tls.certresolver=letsencrypt
|
||||
depends_on:
|
||||
- maps360-db
|
||||
networks:
|
||||
- traefik
|
||||
|
||||
networks:
|
||||
traefik:
|
||||
# external:
|
||||
# name: web_traefik
|
||||
BIN
liblaszip.so
Executable file
BIN
liblaszip.so
Executable file
Binary file not shown.
518
rust-analyzer.json
Normal file
518
rust-analyzer.json
Normal file
@@ -0,0 +1,518 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-04/schema#",
|
||||
"description": "Setting of https://github.com/rust-analyzer/rust-analyzer",
|
||||
"properties": {
|
||||
"rust-analyzer.cargoRunner": {
|
||||
"type": [
|
||||
"null",
|
||||
"string"
|
||||
],
|
||||
"default": null,
|
||||
"description": "Custom cargo runner extension ID."
|
||||
},
|
||||
"rust-analyzer.runnableEnv": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "null"
|
||||
},
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"mask": {
|
||||
"type": "string",
|
||||
"description": "Runnable name mask"
|
||||
},
|
||||
"env": {
|
||||
"type": "object",
|
||||
"description": "Variables in form of { \"key\": \"value\"}"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"description": "Variables in form of { \"key\": \"value\"}"
|
||||
}
|
||||
],
|
||||
"default": null,
|
||||
"markdownDescription": "Environment variables passed to the runnable launched using `Test` or `Debug` lens or `rust-analyzer.run` command."
|
||||
},
|
||||
"rust-analyzer.inlayHints.enable": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Whether to show inlay hints."
|
||||
},
|
||||
"rust-analyzer.updates.channel": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"stable",
|
||||
"nightly"
|
||||
],
|
||||
"default": "stable",
|
||||
"markdownEnumDescriptions": [
|
||||
"`stable` updates are shipped weekly, they don't contain cutting-edge features from VSCode proposed APIs but have less bugs in general.",
|
||||
"`nightly` updates are shipped daily (extension updates automatically by downloading artifacts directly from GitHub), they contain cutting-edge features and latest bug fixes. These releases help us get your feedback very quickly and speed up rust-analyzer development **drastically**."
|
||||
],
|
||||
"markdownDescription": "Choose `nightly` updates to get the latest features and bug fixes every day. While `stable` releases occur weekly and don't contain cutting-edge features from VSCode proposed APIs."
|
||||
},
|
||||
"rust-analyzer.updates.askBeforeDownload": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Whether to ask for permission before downloading any files from the Internet."
|
||||
},
|
||||
"rust-analyzer.server.path": {
|
||||
"type": [
|
||||
"null",
|
||||
"string"
|
||||
],
|
||||
"default": null,
|
||||
"markdownDescription": "Path to rust-analyzer executable (points to bundled binary by default). If this is set, then `#rust-analyzer.updates.channel#` setting is not used"
|
||||
},
|
||||
"rust-analyzer.server.extraEnv": {
|
||||
"type": [
|
||||
"null",
|
||||
"object"
|
||||
],
|
||||
"default": null,
|
||||
"markdownDescription": "Extra environment variables that will be passed to the rust-analyzer executable. Useful for passing e.g. `RA_LOG` for debugging."
|
||||
},
|
||||
"rust-analyzer.trace.server": {
|
||||
"type": "string",
|
||||
"scope": "window",
|
||||
"enum": [
|
||||
"off",
|
||||
"messages",
|
||||
"verbose"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"No traces",
|
||||
"Error only",
|
||||
"Full log"
|
||||
],
|
||||
"default": "off",
|
||||
"description": "Trace requests to the rust-analyzer (this is usually overly verbose and not recommended for regular users)."
|
||||
},
|
||||
"rust-analyzer.trace.extension": {
|
||||
"description": "Enable logging of VS Code extensions itself.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"rust-analyzer.debug.engine": {
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"auto",
|
||||
"vadimcn.vscode-lldb",
|
||||
"ms-vscode.cpptools"
|
||||
],
|
||||
"default": "auto",
|
||||
"description": "Preferred debug engine.",
|
||||
"markdownEnumDescriptions": [
|
||||
"First try to use [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb), if it's not installed try to use [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools).",
|
||||
"Use [CodeLLDB](https://marketplace.visualstudio.com/items?itemName=vadimcn.vscode-lldb)",
|
||||
"Use [MS C++ tools](https://marketplace.visualstudio.com/items?itemName=ms-vscode.cpptools)"
|
||||
]
|
||||
},
|
||||
"rust-analyzer.debug.sourceFileMap": {
|
||||
"type": "object",
|
||||
"description": "Optional source file mappings passed to the debug engine.",
|
||||
"default": {
|
||||
"/rustc/<id>": "${env:USERPROFILE}/.rustup/toolchains/<toolchain-id>/lib/rustlib/src/rust"
|
||||
}
|
||||
},
|
||||
"rust-analyzer.debug.openDebugPane": {
|
||||
"markdownDescription": "Whether to open up the `Debug Panel` on debugging start.",
|
||||
"type": "boolean",
|
||||
"default": false
|
||||
},
|
||||
"rust-analyzer.debug.engineSettings": {
|
||||
"type": "object",
|
||||
"default": {},
|
||||
"markdownDescription": "Optional settings passed to the debug engine. Example: `{ \"lldb\": { \"terminal\":\"external\"} }`"
|
||||
},
|
||||
"rust-analyzer.assist.importMergeBehavior": {
|
||||
"markdownDescription": "The strategy to use when inserting new imports or merging imports.",
|
||||
"default": "full",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"none",
|
||||
"full",
|
||||
"last"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"No merging",
|
||||
"Merge all layers of the import trees",
|
||||
"Only merge the last layer of the import trees"
|
||||
]
|
||||
},
|
||||
"rust-analyzer.assist.importPrefix": {
|
||||
"markdownDescription": "The path structure for newly inserted paths to use.",
|
||||
"default": "plain",
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"plain",
|
||||
"by_self",
|
||||
"by_crate"
|
||||
],
|
||||
"enumDescriptions": [
|
||||
"Insert import paths relative to the current module, using up to one `super` prefix if the parent module contains the requested item.",
|
||||
"Prefix all import paths with `self` if they don't begin with `self`, `super`, `crate` or a crate name.",
|
||||
"Force import paths to be absolute by always starting them with `crate` or the crate name they refer to."
|
||||
]
|
||||
},
|
||||
"rust-analyzer.assist.importGroup": {
|
||||
"markdownDescription": "Group inserted imports by the [following order](https://rust-analyzer.github.io/manual.html#auto-import). Groups are separated by newlines.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.callInfo.full": {
|
||||
"markdownDescription": "Show function name and docs in parameter hints.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.cargo.autoreload": {
|
||||
"markdownDescription": "Automatically refresh project info via `cargo metadata` on\n`Cargo.toml` changes.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.cargo.allFeatures": {
|
||||
"markdownDescription": "Activate all available features (`--all-features`).",
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.cargo.features": {
|
||||
"markdownDescription": "List of features to activate.",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"rust-analyzer.cargo.runBuildScripts": {
|
||||
"markdownDescription": "Run build scripts (`build.rs`) for more precise code analysis.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.cargo.noDefaultFeatures": {
|
||||
"markdownDescription": "Do not activate the `default` feature.",
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.cargo.target": {
|
||||
"markdownDescription": "Compilation target (target triple).",
|
||||
"default": null,
|
||||
"type": [
|
||||
"null",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
"rust-analyzer.cargo.noSysroot": {
|
||||
"markdownDescription": "Internal config for debugging, disables loading of sysroot crates.",
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.checkOnSave.enable": {
|
||||
"markdownDescription": "Run specified `cargo check` command for diagnostics on save.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.checkOnSave.allFeatures": {
|
||||
"markdownDescription": "Check with all features (`--all-features`).\nDefaults to `#rust-analyzer.cargo.allFeatures#`.",
|
||||
"default": null,
|
||||
"type": [
|
||||
"null",
|
||||
"boolean"
|
||||
]
|
||||
},
|
||||
"rust-analyzer.checkOnSave.allTargets": {
|
||||
"markdownDescription": "Check all targets and tests (`--all-targets`).",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.checkOnSave.command": {
|
||||
"markdownDescription": "Cargo command to use for `cargo check`.",
|
||||
"default": "check",
|
||||
"type": "string"
|
||||
},
|
||||
"rust-analyzer.checkOnSave.noDefaultFeatures": {
|
||||
"markdownDescription": "Do not activate the `default` feature.",
|
||||
"default": null,
|
||||
"type": [
|
||||
"null",
|
||||
"boolean"
|
||||
]
|
||||
},
|
||||
"rust-analyzer.checkOnSave.target": {
|
||||
"markdownDescription": "Check for a specific target. Defaults to\n`#rust-analyzer.cargo.target#`.",
|
||||
"default": null,
|
||||
"type": [
|
||||
"null",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
"rust-analyzer.checkOnSave.extraArgs": {
|
||||
"markdownDescription": "Extra arguments for `cargo check`.",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"rust-analyzer.checkOnSave.features": {
|
||||
"markdownDescription": "List of features to activate. Defaults to\n`#rust-analyzer.cargo.features#`.",
|
||||
"default": null,
|
||||
"type": [
|
||||
"null",
|
||||
"array"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"rust-analyzer.checkOnSave.overrideCommand": {
|
||||
"markdownDescription": "Advanced option, fully override the command rust-analyzer uses for\nchecking. The command should include `--message-format=json` or\nsimilar option.",
|
||||
"default": null,
|
||||
"type": [
|
||||
"null",
|
||||
"array"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"rust-analyzer.completion.addCallArgumentSnippets": {
|
||||
"markdownDescription": "Whether to add argument snippets when completing functions.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.completion.addCallParenthesis": {
|
||||
"markdownDescription": "Whether to add parenthesis when completing functions.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.completion.postfix.enable": {
|
||||
"markdownDescription": "Whether to show postfix snippets like `dbg`, `if`, `not`, etc.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.completion.autoimport.enable": {
|
||||
"markdownDescription": "Toggles the additional completions that automatically add imports when completed.\nNote that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.diagnostics.enable": {
|
||||
"markdownDescription": "Whether to show native rust-analyzer diagnostics.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.diagnostics.enableExperimental": {
|
||||
"markdownDescription": "Whether to show experimental rust-analyzer diagnostics that might\nhave more false positives than usual.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.diagnostics.disabled": {
|
||||
"markdownDescription": "List of rust-analyzer diagnostics to disable.",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"rust-analyzer.diagnostics.warningsAsHint": {
|
||||
"markdownDescription": "List of warnings that should be displayed with info severity.\n\nThe warnings will be indicated by a blue squiggly underline in code\nand a blue icon in the `Problems Panel`.",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"rust-analyzer.diagnostics.warningsAsInfo": {
|
||||
"markdownDescription": "List of warnings that should be displayed with hint severity.\n\nThe warnings will be indicated by faded text or three dots in code\nand will not show up in the `Problems Panel`.",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"rust-analyzer.files.watcher": {
|
||||
"markdownDescription": "Controls file watching implementation.",
|
||||
"default": "client",
|
||||
"type": "string"
|
||||
},
|
||||
"rust-analyzer.files.excludeDirs": {
|
||||
"markdownDescription": "These directories will be ignored by rust-analyzer.",
|
||||
"default": ["**/medias", "**/tmp"],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"rust-analyzer.hoverActions.debug": {
|
||||
"markdownDescription": "Whether to show `Debug` action. Only applies when\n`#rust-analyzer.hoverActions.enable#` is set.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.hoverActions.enable": {
|
||||
"markdownDescription": "Whether to show HoverActions in Rust files.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.hoverActions.gotoTypeDef": {
|
||||
"markdownDescription": "Whether to show `Go to Type Definition` action. Only applies when\n`#rust-analyzer.hoverActions.enable#` is set.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.hoverActions.implementations": {
|
||||
"markdownDescription": "Whether to show `Implementations` action. Only applies when\n`#rust-analyzer.hoverActions.enable#` is set.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.hoverActions.run": {
|
||||
"markdownDescription": "Whether to show `Run` action. Only applies when\n`#rust-analyzer.hoverActions.enable#` is set.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.hoverActions.linksInHover": {
|
||||
"markdownDescription": "Use markdown syntax for links in hover.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.inlayHints.chainingHints": {
|
||||
"markdownDescription": "Whether to show inlay type hints for method chains.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.inlayHints.maxLength": {
|
||||
"markdownDescription": "Maximum length for inlay hints. Default is unlimited.",
|
||||
"default": null,
|
||||
"type": [
|
||||
"null",
|
||||
"integer"
|
||||
],
|
||||
"minimum": 0
|
||||
},
|
||||
"rust-analyzer.inlayHints.parameterHints": {
|
||||
"markdownDescription": "Whether to show function parameter name inlay hints at the call\nsite.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.inlayHints.typeHints": {
|
||||
"markdownDescription": "Whether to show inlay type hints for variables.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.lens.debug": {
|
||||
"markdownDescription": "Whether to show `Debug` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.lens.enable": {
|
||||
"markdownDescription": "Whether to show CodeLens in Rust files.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.lens.implementations": {
|
||||
"markdownDescription": "Whether to show `Implementations` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.lens.run": {
|
||||
"markdownDescription": "Whether to show `Run` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.lens.methodReferences": {
|
||||
"markdownDescription": "Whether to show `Method References` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.",
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.lens.references": {
|
||||
"markdownDescription": "Whether to show `References` lens. Only applies when\n`#rust-analyzer.lens.enable#` is set.",
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.linkedProjects": {
|
||||
"markdownDescription": "Disable project auto-discovery in favor of explicitly specified set\nof projects.\n\nElements must be paths pointing to `Cargo.toml`,\n`rust-project.json`, or JSON objects in `rust-project.json` format.",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": [
|
||||
"string",
|
||||
"object"
|
||||
]
|
||||
}
|
||||
},
|
||||
"rust-analyzer.lruCapacity": {
|
||||
"markdownDescription": "Number of syntax trees rust-analyzer keeps in memory. Defaults to 128.",
|
||||
"default": null,
|
||||
"type": [
|
||||
"null",
|
||||
"integer"
|
||||
],
|
||||
"minimum": 0
|
||||
},
|
||||
"rust-analyzer.notifications.cargoTomlNotFound": {
|
||||
"markdownDescription": "Whether to show `can't find Cargo.toml` error message.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.procMacro.enable": {
|
||||
"markdownDescription": "Enable support for procedural macros, implies `#rust-analyzer.cargo.runBuildScripts#`.",
|
||||
"default": true,
|
||||
"type": "boolean"
|
||||
},
|
||||
"rust-analyzer.procMacro.server": {
|
||||
"markdownDescription": "Internal config, path to proc-macro server executable (typically,\nthis is rust-analyzer itself, but we override this in tests).",
|
||||
"default": null,
|
||||
"type": [
|
||||
"null",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
"rust-analyzer.runnables.overrideCargo": {
|
||||
"markdownDescription": "Command to be executed instead of 'cargo' for runnables.",
|
||||
"default": null,
|
||||
"type": [
|
||||
"null",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
"rust-analyzer.runnables.cargoExtraArgs": {
|
||||
"markdownDescription": "Additional arguments to be passed to cargo for runnables such as\ntests or binaries. For example, it may be `--release`.",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"rust-analyzer.rustcSource": {
|
||||
"markdownDescription": "Path to the Cargo.toml of the rust compiler workspace, for usage in rustc_private\nprojects, or \"discover\" to try to automatically find it.\n\nAny project which uses rust-analyzer with the rustcPrivate\ncrates must set `[package.metadata.rust-analyzer] rustc_private=true` to use it.\n\nThis option is not reloaded automatically; you must restart rust-analyzer for it to take effect.",
|
||||
"default": null,
|
||||
"type": [
|
||||
"null",
|
||||
"string"
|
||||
]
|
||||
},
|
||||
"rust-analyzer.rustfmt.extraArgs": {
|
||||
"markdownDescription": "Additional arguments to `rustfmt`.",
|
||||
"default": [],
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
},
|
||||
"rust-analyzer.rustfmt.overrideCommand": {
|
||||
"markdownDescription": "Advanced option, fully override the command rust-analyzer uses for\nformatting.",
|
||||
"default": null,
|
||||
"type": [
|
||||
"null",
|
||||
"array"
|
||||
],
|
||||
"items": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
81
src/main.rs
Normal file
81
src/main.rs
Normal file
@@ -0,0 +1,81 @@
|
||||
#![allow(unused)]
|
||||
use actix::{Actor, StreamHandler};
|
||||
use actix_files::{Files, NamedFile};
|
||||
use actix_form_data::{Error, Field, Value};
|
||||
use actix_identity::Identity;
|
||||
use actix_identity::{CookieIdentityPolicy, IdentityService};
|
||||
use actix_multipart::Multipart;
|
||||
use actix_web::{
|
||||
cookie::Cookie, get, http, middleware, post, web, web::Data, web::Form, web::Path as Pathweb,
|
||||
App, HttpRequest, HttpResponse, HttpServer, Responder,
|
||||
};
|
||||
use actix_web_actors::ws;
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::collections::HashMap;
|
||||
use std::{fs::*, default};
|
||||
use std::path::*;
|
||||
use std::process::Command;
|
||||
use tera::{Context, Tera};
|
||||
|
||||
#[macro_use]
|
||||
extern crate diesel;
|
||||
use diesel::prelude::*;
|
||||
|
||||
pub mod schema;
|
||||
pub mod models;
|
||||
// use models::{User, Project, Entity};
|
||||
|
||||
use walkdir::{DirEntry, WalkDir};
|
||||
|
||||
mod response;
|
||||
mod util;
|
||||
use util::*;
|
||||
// use response::MyError;
|
||||
|
||||
use futures_util::TryStreamExt as _;
|
||||
use std::io::Write;
|
||||
use tempfile::tempfile;
|
||||
use uuid::Uuid;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{self, prelude::*, BufReader};
|
||||
|
||||
#[get("/")]
|
||||
async fn index(req: HttpRequest, tmpl: Data<Tera>, id: Identity) -> impl Responder {
|
||||
let mut context = Context::new();
|
||||
if let Some(val) = req.peer_addr() {
|
||||
println!("Address {:?}", &val.ip());
|
||||
context.insert("ip", &format!("{:?}", &val.ip()));
|
||||
};
|
||||
response::template(tmpl, "index.html.twig", &context)
|
||||
}
|
||||
|
||||
async fn not_found(req: HttpRequest, tmpl: Data<Tera>, id: Identity) -> impl Responder {
|
||||
let context = Context::new();
|
||||
response::just_404(tmpl)
|
||||
}
|
||||
|
||||
#[actix_web::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
HttpServer::new(|| {
|
||||
let tera = Tera::new(concat!(env!("CARGO_MANIFEST_DIR"), "/templates/**/*")).unwrap();
|
||||
let mut folder_static = "static/";
|
||||
App::new()
|
||||
.app_data(Data::new(tera))
|
||||
.wrap(IdentityService::new(
|
||||
CookieIdentityPolicy::new(&[0; 32])
|
||||
.name("maps360")
|
||||
.secure(true)
|
||||
.max_age_secs(60 * 60 * 24 * 7), // 1week
|
||||
))
|
||||
.wrap(middleware::Logger::default())
|
||||
.service(index)
|
||||
.service(Files::new("/static", folder_static))
|
||||
.default_service(web::route().to(not_found))
|
||||
})
|
||||
.workers(8)
|
||||
.bind(("0.0.0.0", 80))?
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
741
src/models.rs
Normal file
741
src/models.rs
Normal file
@@ -0,0 +1,741 @@
|
||||
use super::util::*;
|
||||
use crate::schema::*;
|
||||
use diesel::pg::*;
|
||||
use diesel::prelude::*;
|
||||
use rand::prelude::*;
|
||||
use serde_json::{json, Serializer, Value};
|
||||
use std::path::Path;
|
||||
use std::time::*;
|
||||
use uuid::Uuid;
|
||||
|
||||
pub fn db() -> PgConnection {
|
||||
let database_url = std::env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
||||
PgConnection::establish(&database_url).expect(&format!("Error connecting to {}", database_url))
|
||||
}
|
||||
|
||||
// #[derive(Debug, Queryable, Identifiable, Insertable, serde::Serialize)]
|
||||
// pub struct User {
|
||||
// pub id: i32,
|
||||
// pub username: String,
|
||||
// pub password: String,
|
||||
// pub salt: String,
|
||||
// pub image: String,
|
||||
// pub email: String,
|
||||
// pub google: String,
|
||||
// pub email_valid: String,
|
||||
// }
|
||||
|
||||
// impl User {
|
||||
// pub fn create(username: String, email: String, pass_not_hashed: String) -> Result<Self, String> {
|
||||
// let mut rng = rand::thread_rng();
|
||||
// let y: f64 = rng.gen();
|
||||
// let salt = sha256::digest(y.to_string());
|
||||
|
||||
// let pass_hashed = sha256::digest(format!("{}{}", &salt, &pass_not_hashed));
|
||||
// let uuid = Uuid::new_v4().to_string();
|
||||
// let result = diesel::insert_into(users::table)
|
||||
// .values((
|
||||
// users::dsl::username.eq(username),
|
||||
// users::dsl::password.eq(pass_hashed),
|
||||
// users::dsl::salt.eq(salt),
|
||||
// users::dsl::image.eq("/static/img/default_user.svg".to_string()),
|
||||
// users::dsl::email_valid.eq(uuid),
|
||||
// users::dsl::email.eq(email),
|
||||
// users::dsl::google.eq("".to_string()),
|
||||
// ))
|
||||
// .get_result(&db());
|
||||
// if !result.is_err() {
|
||||
// let user_session = result.unwrap();
|
||||
// return Ok(user_session);
|
||||
// }
|
||||
// match result.err() {
|
||||
// Some(x) => {
|
||||
// if format!("{}", x).contains("email") {
|
||||
// return Err("Un compte est déjà associé à cet Email".to_string());
|
||||
// } else if format!("{}", x).contains("username") {
|
||||
// return Err("Ce nom d'utilisateur est déja utilisé".to_string());
|
||||
// }
|
||||
// return Err("Could not create user".to_string());
|
||||
// },
|
||||
// None => return Err("Could not create user".to_string())
|
||||
// }
|
||||
// Err("Could not create user".to_string())
|
||||
// }
|
||||
|
||||
// pub fn find_all() -> Result<Vec<Self>, String> {
|
||||
// let result = users::dsl::users.get_results::<User>(&db());
|
||||
// if !result.is_err() {
|
||||
// let users = result.unwrap();
|
||||
// return Ok(users);
|
||||
// }
|
||||
// Err(format!("Users not found"))
|
||||
// }
|
||||
|
||||
// pub fn find(id: i32) -> Result<Self, String> {
|
||||
// let result = users::dsl::users
|
||||
// .filter(users::dsl::id.eq(id))
|
||||
// .get_result::<Self>(&db());
|
||||
// if !result.is_err() {
|
||||
// let user_session = result.unwrap();
|
||||
// return Ok(user_session);
|
||||
// }
|
||||
// Err(format!("User {} not found", id))
|
||||
// }
|
||||
|
||||
// pub fn update(self) -> Result<Self, String> {
|
||||
// let filter = users::dsl::users.filter(users::dsl::id.eq(self.id));
|
||||
// let result = diesel::update(filter)
|
||||
// .set((
|
||||
// users::dsl::username.eq(self.username),
|
||||
// users::dsl::password.eq(self.password),
|
||||
// users::dsl::salt.eq(self.salt),
|
||||
// users::dsl::image.eq(self.image),
|
||||
// users::dsl::email.eq(self.email),
|
||||
// users::dsl::email_valid.eq(self.email_valid),
|
||||
// users::dsl::google.eq(self.google),
|
||||
// ))
|
||||
// .get_result::<Self>(&db());
|
||||
// if !result.is_err() {
|
||||
// let user_session = result.unwrap();
|
||||
// return Ok(user_session);
|
||||
// }
|
||||
// Err(format!("User {} not update", self.id))
|
||||
// }
|
||||
|
||||
// pub fn find_by_username(username: &str) -> Result<Self, String> {
|
||||
// let result = users::dsl::users
|
||||
// .filter(users::dsl::username.eq(&username))
|
||||
// .get_result::<Self>(&db());
|
||||
// if !result.is_err() {
|
||||
// let user = result.unwrap();
|
||||
// return Ok(user);
|
||||
// }
|
||||
// Err(format!("User {} not find", &username))
|
||||
// }
|
||||
|
||||
// pub fn find_by_changepass(changepass: &str) -> Result<Self, String> {
|
||||
// let result = users::dsl::users
|
||||
// .filter(users::dsl::password.eq(&changepass))
|
||||
// .get_result::<Self>(&db());
|
||||
// if !result.is_err() {
|
||||
// let user = result.unwrap();
|
||||
// return Ok(user);
|
||||
// }
|
||||
// Err(format!("User {} not find", &changepass))
|
||||
// }
|
||||
|
||||
// pub fn find_by_email(email: &str) -> Result<Self, String> {
|
||||
// let result = users::dsl::users
|
||||
// .filter(users::dsl::email.eq(&email))
|
||||
// .get_result::<Self>(&db());
|
||||
// if !result.is_err() {
|
||||
// let user = result.unwrap();
|
||||
// return Ok(user);
|
||||
// }
|
||||
// Err(format!("User {} not find", &email))
|
||||
// }
|
||||
|
||||
// pub fn find_by_key(key: &str) -> Result<Self, String> {
|
||||
// let result = users::dsl::users
|
||||
// .filter(users::dsl::username.eq(&key))
|
||||
// .filter(users::dsl::password.eq(""))
|
||||
// .get_result::<Self>(&db());
|
||||
// if !result.is_err() {
|
||||
// let user = result.unwrap();
|
||||
// return Ok(user);
|
||||
// }
|
||||
// Err(format!("User {} not find", &key))
|
||||
// }
|
||||
|
||||
// pub fn find_by_google(google: &str) -> Result<Self, String> {
|
||||
// let result = users::dsl::users
|
||||
// .filter(users::dsl::google.eq(&google))
|
||||
// .get_result::<Self>(&db());
|
||||
// if !result.is_err() {
|
||||
// let user = result.unwrap();
|
||||
// return Ok(user);
|
||||
// }
|
||||
// Err(format!("User by google {} not find", &google))
|
||||
// }
|
||||
|
||||
// pub fn find_by_email_valid(email_valid: &str) -> Result<Self, String> {
|
||||
// let result = users::dsl::users
|
||||
// .filter(users::dsl::email_valid.eq(&email_valid))
|
||||
// .get_result::<Self>(&db());
|
||||
// if !result.is_err() {
|
||||
// let user = result.unwrap();
|
||||
// return Ok(user);
|
||||
// }
|
||||
// Err(format!("User by email_valid {} not find", &email_valid))
|
||||
// }
|
||||
|
||||
// pub fn generate_salt(&mut self) {
|
||||
// let mut rng = rand::thread_rng();
|
||||
// let y: f64 = rng.gen(); // generates a float between 0 and 1
|
||||
// self.salt = sha256::digest(y.to_string())
|
||||
// }
|
||||
|
||||
// pub fn get_projects(&self) -> Result<Vec<Project>, String> {
|
||||
// let result = projects::dsl::projects
|
||||
// .filter(projects::dsl::creator_id.eq(&self.id))
|
||||
// .get_results::<Project>(&db());
|
||||
// if !result.is_err() {
|
||||
// let projects = result.unwrap();
|
||||
// return Ok(projects);
|
||||
// }
|
||||
// Err(format!("Project {} not fetched", self.id))
|
||||
// }
|
||||
|
||||
// pub fn get_project_accesss(&self) -> Result<Vec<ProjectAccess>, String> {
|
||||
// let result = project_accesss::dsl::project_accesss
|
||||
// .filter(project_accesss::dsl::user_id.eq(&self.id))
|
||||
// .get_results::<ProjectAccess>(&db());
|
||||
// if !result.is_err() {
|
||||
// let project_accesss = result.unwrap();
|
||||
// return Ok(project_accesss);
|
||||
// }
|
||||
// Err(format!("ProjectAccesss {} not fetched", self.id))
|
||||
// }
|
||||
|
||||
// pub fn delete(self) -> Result<String, String> {
|
||||
// let id = self.id.clone();
|
||||
// let name = self.username.clone();
|
||||
// let result_projects = self.get_projects();
|
||||
// let projects = result_projects.unwrap();
|
||||
// for project in projects {
|
||||
// project.delete();
|
||||
// }
|
||||
// let filter_user = users::dsl::users.filter(users::dsl::id.eq(&id));
|
||||
// let result_del_user = diesel::delete(filter_user)
|
||||
// .returning(users::dsl::username)
|
||||
// .get_result::<String>(&db());
|
||||
// if result_del_user.is_err() {
|
||||
// return Err(format!("User cannot be deleted in db()"));
|
||||
// }
|
||||
// return Ok("User was deleted".to_string());
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[derive(Debug, Queryable, Identifiable, Insertable, serde::Serialize)]
|
||||
// pub struct Project {
|
||||
// pub id: i32,
|
||||
// pub creator_id: i32,
|
||||
// pub uuid: String,
|
||||
// pub name: String,
|
||||
// pub password: String,
|
||||
// pub time_limit: SystemTime,
|
||||
// pub premium: i32,
|
||||
// pub is_public: bool,
|
||||
// pub image: String,
|
||||
// pub origin_filename: String,
|
||||
// pub description: String,
|
||||
// pub data: String,
|
||||
// }
|
||||
// impl Project {
|
||||
// const FREE: i32 = 0;
|
||||
// const PAID: i32 = 1;
|
||||
|
||||
// pub fn create(
|
||||
// name: String,
|
||||
// origin_filename: String,
|
||||
// password: String,
|
||||
// user: &User,
|
||||
// ) -> Result<Self, String> {
|
||||
// let result = diesel::insert_into(projects::table)
|
||||
// .values((
|
||||
// projects::dsl::origin_filename.eq(origin_filename),
|
||||
// projects::dsl::creator_id.eq(user.id),
|
||||
// projects::dsl::uuid.eq(Uuid::new_v4().to_string()),
|
||||
// projects::dsl::name.eq(name),
|
||||
// projects::dsl::password.eq(password),
|
||||
// projects::dsl::time_limit
|
||||
// .eq(SystemTime::now() + Duration::new(60 * 60 * 24 * 5, 0)), // calcul pour 5 jour en seconde
|
||||
// projects::dsl::premium.eq(Project::FREE),
|
||||
// projects::dsl::is_public.eq(true),
|
||||
// projects::dsl::description.eq("".to_string()),
|
||||
// projects::dsl::data.eq("{}".to_string()),
|
||||
// ))
|
||||
// .get_result(&db());
|
||||
// if !result.is_err() {
|
||||
// let project = result.unwrap();
|
||||
// return Ok(project);
|
||||
// }
|
||||
// Err(format!("Project not created"))
|
||||
// }
|
||||
|
||||
// pub fn find(id: i32) -> Result<Self, String> {
|
||||
// let result = projects::dsl::projects
|
||||
// .filter(projects::dsl::id.eq(id))
|
||||
// .get_result::<Self>(&db());
|
||||
// if !result.is_err() {
|
||||
// let project = result.unwrap();
|
||||
// return Ok(project);
|
||||
// }
|
||||
// Err(format!("User {} not found", id))
|
||||
// }
|
||||
|
||||
// pub fn find_by_uuid(uuid: &str) -> Result<Self, String> {
|
||||
// let result = projects::dsl::projects
|
||||
// .filter(projects::dsl::uuid.eq(&uuid))
|
||||
// .get_result::<Self>(&db());
|
||||
// if !result.is_err() {
|
||||
// let project = result.unwrap();
|
||||
// return Ok(project);
|
||||
// }
|
||||
// Err(format!("Project {} not find", &uuid))
|
||||
// }
|
||||
|
||||
// pub fn find_by_public(is_public: bool) -> Result<Vec<Self>, String> {
|
||||
// let result = projects::dsl::projects
|
||||
// .filter(projects::dsl::is_public.eq(&is_public))
|
||||
// .get_results::<Project>(&db());
|
||||
// if !result.is_err() {
|
||||
// let projects = result.unwrap();
|
||||
// return Ok(projects);
|
||||
// }
|
||||
// Err(format!("User {} not found", &is_public))
|
||||
// }
|
||||
|
||||
// pub fn update(self) -> Result<Self, String> {
|
||||
// let filter = projects::dsl::projects.filter(projects::dsl::id.eq(self.id));
|
||||
// let result = diesel::update(filter)
|
||||
// .set((
|
||||
// projects::dsl::image.eq(self.image),
|
||||
// projects::dsl::origin_filename.eq(self.origin_filename),
|
||||
// projects::dsl::creator_id.eq(self.creator_id),
|
||||
// projects::dsl::uuid.eq(self.uuid),
|
||||
// projects::dsl::name.eq(self.name),
|
||||
// projects::dsl::password.eq(self.password),
|
||||
// projects::dsl::time_limit.eq(self.time_limit),
|
||||
// projects::dsl::premium.eq(self.premium),
|
||||
// projects::dsl::is_public.eq(self.is_public),
|
||||
// projects::dsl::data.eq(self.data),
|
||||
// projects::dsl::description.eq(self.description),
|
||||
// ))
|
||||
// .get_result::<Self>(&db());
|
||||
// if !result.is_err() {
|
||||
// let project = result.unwrap();
|
||||
// return Ok(project);
|
||||
// }
|
||||
// Err(format!("Project {} not update", self.id))
|
||||
// }
|
||||
|
||||
// pub fn get_entitys(&self) -> Result<Vec<Entity>, String> {
|
||||
// let result = entitys::dsl::entitys
|
||||
// .filter(entitys::dsl::project_id.eq(&self.id))
|
||||
// .get_results::<Entity>(&db());
|
||||
// if !result.is_err() {
|
||||
// let entitys = result.unwrap();
|
||||
// return Ok(entitys);
|
||||
// }
|
||||
// Err(format!("Project entitys {} not fetched", self.id))
|
||||
// }
|
||||
|
||||
// pub fn get_creator(&self) -> Result<User, String> {
|
||||
// User::find(self.creator_id)
|
||||
// }
|
||||
|
||||
// pub fn get_project_accesss(&self) -> Result<Vec<ProjectAccess>, String> {
|
||||
// let result = project_accesss::dsl::project_accesss
|
||||
// .filter(project_accesss::dsl::project_id.eq(&self.id))
|
||||
// .get_results::<ProjectAccess>(&db());
|
||||
// if !result.is_err() {
|
||||
// let project_accesss = result.unwrap();
|
||||
// return Ok(project_accesss);
|
||||
// }
|
||||
// Err(format!("ProjectAccesss {} not fetched", self.id))
|
||||
// }
|
||||
|
||||
// pub fn delete(self) -> Result<String, String> {
|
||||
// let result_file = std::fs::remove_dir_all(Path::new("medias").join(self.uuid));
|
||||
// let filter_entity = entitys::dsl::entitys.filter(entitys::dsl::project_id.eq(&self.id));
|
||||
// let result_del_entity = diesel::delete(filter_entity)
|
||||
// .returning(entitys::dsl::name)
|
||||
// .get_results::<String>(&db());
|
||||
// if result_del_entity.is_err() {
|
||||
// return Err(format!("Project delete could not remove entity in db()"));
|
||||
// }
|
||||
// let filter_project = projects::dsl::projects.filter(projects::dsl::id.eq(&self.id));
|
||||
// let result_del_project = diesel::delete(filter_project)
|
||||
// .returning(projects::dsl::name)
|
||||
// .get_result::<String>(&db());
|
||||
// if result_del_project.is_err() {
|
||||
// return Err(format!("Project delete could not remove project in db()"));
|
||||
// }
|
||||
// return Ok("Project was deleted".to_string());
|
||||
// }
|
||||
|
||||
// pub fn get_logs(&self) -> String {
|
||||
// let path = Path::new("./medias")
|
||||
// .join(self.uuid.clone())
|
||||
// .join("cmd_logs.txt");
|
||||
// if path.exists() {
|
||||
// return String::from_utf8_lossy(&std::fs::read(&path).unwrap()).to_string();
|
||||
// }
|
||||
// "".to_string()
|
||||
// }
|
||||
|
||||
// const CONVERTION: i32 = 0;
|
||||
// const COMPLETE: i32 = 1;
|
||||
// const CRASHED: i32 = 2;
|
||||
|
||||
// pub fn get_status(&self) -> i32 {
|
||||
// let path = Path::new("./medias")
|
||||
// .join(self.uuid.clone())
|
||||
// .join("cmd_logs.txt");
|
||||
// if path.exists() {
|
||||
// let metadata = std::fs::metadata(path).unwrap();
|
||||
// let modified_time = metadata.modified().unwrap().elapsed().unwrap().as_secs();
|
||||
// // println!("{} > 10", modified_time);
|
||||
// if modified_time > 300 {
|
||||
// return Project::CRASHED;
|
||||
// }
|
||||
// return Project::CONVERTION;
|
||||
// }
|
||||
// Project::COMPLETE
|
||||
// }
|
||||
|
||||
// pub const ACCESSREAD: i32 = 0;
|
||||
// pub const ACCESSWRITE: i32 = 1;
|
||||
|
||||
// pub fn test_access(&self, result_user: &Result<User, String>, access_type: i32) -> bool {
|
||||
// if access_type == Project::ACCESSREAD && self.is_public {
|
||||
// return true;
|
||||
// } else if access_type == Project::ACCESSREAD && !result_user.is_err() {
|
||||
// let user = result_user.as_ref().unwrap();
|
||||
// if user.id == self.creator_id {
|
||||
// return true;
|
||||
// }
|
||||
// let result_pa = ProjectAccess::find(user.id,self.id);
|
||||
// if(!result_pa.is_err()){
|
||||
// let pa = result_pa.unwrap();
|
||||
// if(pa.access_type == Project::ACCESSREAD || pa.access_type == Project::ACCESSWRITE){
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// } else if access_type == Project::ACCESSWRITE && !result_user.is_err() {
|
||||
// let user = result_user.as_ref().unwrap();
|
||||
// if user.id == self.creator_id {
|
||||
// return true;
|
||||
// }
|
||||
// let result_pa = ProjectAccess::find(user.id,self.id);
|
||||
// if(!result_pa.is_err()){
|
||||
// let pa = result_pa.unwrap();
|
||||
// if(pa.access_type == Project::ACCESSWRITE){
|
||||
// return true;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// return false;
|
||||
// }
|
||||
|
||||
// pub fn to_json(&self) -> Value {
|
||||
// let mut project_value = json!(self);
|
||||
// project_value["entitys"] = json!(self.get_entitys().unwrap());
|
||||
// project_value["creator"] = json!(self.get_creator().unwrap());
|
||||
// project_value["cmd_logs"] = json!(self.get_logs());
|
||||
// project_value["status"] = json!(self.get_status());
|
||||
// project_value["data"] = self.get_data();
|
||||
// let project_accesss = self.get_project_accesss().unwrap();
|
||||
// let mut project_accesss_json = Vec::new();
|
||||
// for project_access in project_accesss {
|
||||
// project_accesss_json.push(project_access.to_json());
|
||||
// }
|
||||
// project_value["project_accesss"] = json!(project_accesss_json);
|
||||
// project_value
|
||||
// }
|
||||
|
||||
// pub fn duplicate(&self) -> Result<Self, String> {
|
||||
// let user = User::find(self.creator_id)?;
|
||||
// let mut project = Project::create(self.name.clone()+"_copy", self.origin_filename.clone(), self.password.clone(), &user)?;
|
||||
// project.description = self.description.clone();
|
||||
// project.is_public = self.is_public.clone();
|
||||
// project = project.update().unwrap();
|
||||
// let copy_result = copy_dir_all(Path::new("./medias").join(self.uuid.clone()), Path::new("./medias").join(project.uuid.clone()));
|
||||
// if copy_result.is_err() {
|
||||
// return Err(format!("You cannot copy {} in {}",self.uuid,project.uuid));
|
||||
// }
|
||||
// copy_result.unwrap();
|
||||
// let entitys = self.get_entitys()?;
|
||||
// for e in entitys {
|
||||
// let entity = e.duplicate(&project);
|
||||
// }
|
||||
// return Ok(project);
|
||||
// }
|
||||
|
||||
// pub fn set_data(&mut self, object: &Value) {
|
||||
// self.data = object.to_string();
|
||||
// }
|
||||
|
||||
// pub fn get_data(&self) -> Value {
|
||||
// serde_json::from_str(self.data.as_str()).unwrap()
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[derive(Debug, Queryable, Identifiable, Insertable, serde::Serialize)]
|
||||
// pub struct Entity {
|
||||
// pub id: i32,
|
||||
// pub project_id: i32,
|
||||
// pub name: String,
|
||||
// pub type_entity: i32,
|
||||
// pub data: String,
|
||||
// pub parent_id: Option<i32>,
|
||||
// }
|
||||
// impl Entity {
|
||||
// pub const POTREE: i32 = 0;
|
||||
// pub const MODELE: i32 = 1;
|
||||
// pub const IMAGE360: i32 = 2;
|
||||
// pub const POTREEITEM: i32 = 3;
|
||||
// pub const GROUP: i32 = 3;
|
||||
|
||||
// pub fn create(name: String, type_entity: i32, project: &Project) -> Result<Self, String> {
|
||||
// let result = diesel::insert_into(entitys::table)
|
||||
// .values((
|
||||
// entitys::dsl::project_id.eq(project.id),
|
||||
// entitys::dsl::name.eq(name),
|
||||
// entitys::dsl::type_entity.eq(type_entity),
|
||||
// entitys::dsl::data.eq(json!({}).to_string()),
|
||||
// entitys::dsl::parent_id.eq(None::<i32>),
|
||||
// ))
|
||||
// .get_result(&db());
|
||||
// if !result.is_err() {
|
||||
// let entity = result.unwrap();
|
||||
// return Ok(entity);
|
||||
// }
|
||||
// Err(format!("Entity not created"))
|
||||
// }
|
||||
|
||||
// pub fn duplicate(&self , project: &Project) -> Result<Self, String> {
|
||||
// let result = diesel::insert_into(entitys::table)
|
||||
// .values((
|
||||
// entitys::dsl::project_id.eq(project.id),
|
||||
// entitys::dsl::name.eq(self.name.clone()),
|
||||
// entitys::dsl::type_entity.eq(self.type_entity),
|
||||
// entitys::dsl::data.eq(self.data.clone()),
|
||||
// entitys::dsl::parent_id.eq(None::<i32>),
|
||||
// ))
|
||||
// .get_result(&db());
|
||||
// if !result.is_err() {
|
||||
// let entity = result.unwrap();
|
||||
// return Ok(entity);
|
||||
// }
|
||||
// Err(format!("Entity not created"))
|
||||
// }
|
||||
|
||||
// pub fn find(id: i32) -> Result<Self, String> {
|
||||
// let result = entitys::dsl::entitys
|
||||
// .filter(entitys::dsl::id.eq(id))
|
||||
// .get_result::<Self>(&db());
|
||||
// if !result.is_err() {
|
||||
// let entity = result.unwrap();
|
||||
// return Ok(entity);
|
||||
// }
|
||||
// Err(format!("User {} not found", id))
|
||||
// }
|
||||
|
||||
// pub fn update(self) -> Result<Self, String> {
|
||||
// let filter = entitys::dsl::entitys.filter(entitys::dsl::id.eq(self.id));
|
||||
// let result = diesel::update(filter)
|
||||
// .set((
|
||||
// entitys::dsl::project_id.eq(self.project_id),
|
||||
// entitys::dsl::name.eq(self.name),
|
||||
// entitys::dsl::type_entity.eq(self.type_entity),
|
||||
// entitys::dsl::data.eq(self.data),
|
||||
// entitys::dsl::parent_id.eq(self.parent_id),
|
||||
// ))
|
||||
// .get_result::<Self>(&db());
|
||||
// if !result.is_err() {
|
||||
// let entity = result.unwrap();
|
||||
// return Ok(entity);
|
||||
// }
|
||||
// Err(format!("Project {} not update", self.id))
|
||||
// }
|
||||
|
||||
// pub fn set_data(&mut self, object: &Value) {
|
||||
// self.data = object.to_string();
|
||||
// }
|
||||
|
||||
// pub fn get_data(&self) -> Value {
|
||||
// serde_json::from_str(self.data.as_str()).unwrap()
|
||||
// }
|
||||
|
||||
// pub fn get_project(&self) -> Result<Project, String> {
|
||||
// let result = projects::dsl::projects
|
||||
// .filter(projects::dsl::id.eq(self.project_id))
|
||||
// .get_result::<Project>(&db());
|
||||
// if !result.is_err() {
|
||||
// let project = result.unwrap();
|
||||
// return Ok(project);
|
||||
// }
|
||||
// Err(format!("User {} not found", self.project_id))
|
||||
// }
|
||||
|
||||
// pub fn find_by_name_and_project(name: String, project_id: i32) -> Vec<Entity> {
|
||||
// let result = entitys::dsl::entitys
|
||||
// .filter(entitys::dsl::name.eq(&name))
|
||||
// .filter(entitys::dsl::project_id.eq(&project_id))
|
||||
// .get_results::<Entity>(&db());
|
||||
// if !result.is_err() {
|
||||
// let entitys = result.unwrap();
|
||||
// return entitys;
|
||||
// }
|
||||
// Vec::<Entity>::new()
|
||||
// }
|
||||
|
||||
// pub fn delete(self) -> Result<String, String> {
|
||||
// let id = self.id.clone();
|
||||
// let name = self.name.clone();
|
||||
// let result_project = self.get_project();
|
||||
// if result_project.is_err() {
|
||||
// return Err(format!("Entity delete could not find project"));
|
||||
// }
|
||||
// let project = result_project.unwrap();
|
||||
// let entity_with_same_file = Entity::find_by_name_and_project(self.name, self.project_id);
|
||||
|
||||
// if self.type_entity != Entity::POTREEITEM && entity_with_same_file.len() <= 1 {
|
||||
// let entity_path = Path::new("medias").join(project.uuid).join(&name);
|
||||
// if entity_path.exists() && entity_path.is_dir() {
|
||||
// let result_file = std::fs::remove_dir_all(entity_path);
|
||||
// if result_file.is_err() {
|
||||
// return Err(format!("Entity delete could not remove folder"));
|
||||
// }
|
||||
// } else if entity_path.exists() {
|
||||
// let result_file = std::fs::remove_file(entity_path);
|
||||
// if result_file.is_err() {
|
||||
// return Err(format!("Entity delete could not remove file"));
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// let filter_entity = entitys::dsl::entitys.filter(entitys::dsl::id.eq(&id));
|
||||
// let result_del_entity = diesel::delete(filter_entity)
|
||||
// .returning(entitys::dsl::name)
|
||||
// .get_result::<String>(&db());
|
||||
// if result_del_entity.is_err() {
|
||||
// return Err(format!("Entity delete could not remove project in db()"));
|
||||
// }
|
||||
// return Ok("Entity was deleted".to_string());
|
||||
// }
|
||||
// }
|
||||
|
||||
// #[derive(Debug, Queryable, Identifiable, Insertable, serde::Serialize)]
|
||||
// pub struct ProjectAccess {
|
||||
// pub id: i32,
|
||||
// pub user_id: i32,
|
||||
// pub project_id: i32,
|
||||
// pub access_type: i32,
|
||||
// }
|
||||
// impl ProjectAccess {
|
||||
|
||||
// pub fn create(
|
||||
// user: &User,
|
||||
// project: &Project,
|
||||
// access: i32,
|
||||
// ) -> Result<Self, String> {
|
||||
// let project_access_result = ProjectAccess::find(user.id, project.id);
|
||||
// if !project_access_result.is_err(){
|
||||
// let mut project_access = project_access_result.unwrap();
|
||||
// project_access.access_type = access;
|
||||
// project_access = project_access.update().unwrap();
|
||||
// return Ok(project_access);
|
||||
// }
|
||||
// if ProjectAccess::find(user.id, project.id).is_err() {
|
||||
// let result = diesel::insert_into(project_accesss::table)
|
||||
// .values((
|
||||
// project_accesss::dsl::user_id.eq(user.id),
|
||||
// project_accesss::dsl::project_id.eq(project.id),
|
||||
// project_accesss::dsl::access_type.eq(access),
|
||||
// ))
|
||||
// .get_result(&db());
|
||||
// let pa_project = project_accesss::dsl::project_accesss
|
||||
// .filter(project_accesss::dsl::project_id.eq(project.id))
|
||||
// .get_results::<ProjectAccess>(&db())
|
||||
// .unwrap();
|
||||
// if !result.is_err() {
|
||||
// let project_access = result.unwrap();
|
||||
// return Ok(project_access);
|
||||
// }
|
||||
// }
|
||||
// Err(format!("Project_Access not created"))
|
||||
// }
|
||||
|
||||
// pub fn get_user(&self) -> Result<User, String> {
|
||||
// let result = users::dsl::users
|
||||
// .filter(users::dsl::id.eq(&self.user_id))
|
||||
// .get_result::<User>(&db());
|
||||
// if !result.is_err() {
|
||||
// let user = result.unwrap();
|
||||
// return Ok(user);
|
||||
// }
|
||||
// Err(format!("User {} not found", self.user_id))
|
||||
// }
|
||||
|
||||
// pub fn get_project(&self) -> Result<Project, String> {
|
||||
// let result = projects::dsl::projects
|
||||
// .filter(projects::dsl::id.eq(&self.project_id))
|
||||
// .get_result::<Project>(&db());
|
||||
// if !result.is_err() {
|
||||
// let project = result.unwrap();
|
||||
// return Ok(project);
|
||||
// }
|
||||
// Err(format!("Project {} not found", self.project_id))
|
||||
// }
|
||||
|
||||
// pub fn find(user_id: i32, project_id: i32) -> Result<Self, String> {
|
||||
// let result = project_accesss::dsl::project_accesss
|
||||
// .filter(project_accesss::dsl::user_id.eq(user_id))
|
||||
// .filter(project_accesss::dsl::project_id.eq(project_id))
|
||||
// .get_result::<Self>(&db());
|
||||
// if !result.is_err() {
|
||||
// let project_access = result.unwrap();
|
||||
// return Ok(project_access);
|
||||
// }
|
||||
// Err(format!("Project Access with project_id{} and user_id{} not found", project_id, user_id))
|
||||
// }
|
||||
|
||||
// pub fn find_id(id: i32) -> Result<Self, String> {
|
||||
// let result = project_accesss::dsl::project_accesss
|
||||
// .filter(project_accesss::dsl::id.eq(id))
|
||||
// .get_result::<Self>(&db());
|
||||
// if !result.is_err() {
|
||||
// let project_access = result.unwrap();
|
||||
// return Ok(project_access);
|
||||
// }
|
||||
// Err(format!("ProjectAccess {} not found", id))
|
||||
// }
|
||||
|
||||
// pub fn update(self) -> Result<Self, String> {
|
||||
// let filter = project_accesss::dsl::project_accesss.filter(project_accesss::dsl::id.eq(self.id));
|
||||
// let result = diesel::update(filter)
|
||||
// .set((
|
||||
// project_accesss::dsl::user_id.eq(self.user_id),
|
||||
// project_accesss::dsl::project_id.eq(self.project_id),
|
||||
// project_accesss::dsl::access_type.eq(self.access_type),
|
||||
// ))
|
||||
// .get_result::<Self>(&db());
|
||||
// if !result.is_err() {
|
||||
// let project_access = result.unwrap();
|
||||
// return Ok(project_access);
|
||||
// }
|
||||
// Err(format!("ProjectAccess {} not update", self.id))
|
||||
// }
|
||||
|
||||
// pub fn delete(self) -> Result<String, String> {
|
||||
// let id = self.id.clone();
|
||||
// let filter_pa = project_accesss::dsl::project_accesss.filter(project_accesss::dsl::id.eq(&id));
|
||||
// let result_del_pa = diesel::delete(filter_pa)
|
||||
// .returning(project_accesss::dsl::id)
|
||||
// .get_result::<i32>(&db());
|
||||
// if result_del_pa.is_err() {
|
||||
// return Err(format!("ProjectAccess cannot be deleted in db()"));
|
||||
// }
|
||||
// return Ok("ProjectAccess was deleted".to_string());
|
||||
// }
|
||||
|
||||
// pub fn to_json(self) -> Value {
|
||||
// let mut project_access_value = json!(self);
|
||||
// project_access_value["user"] = json!(self.get_user().unwrap());
|
||||
// project_access_value["project"] = json!(self.get_project().unwrap());
|
||||
// project_access_value
|
||||
// }
|
||||
// }
|
||||
79
src/response.rs
Normal file
79
src/response.rs
Normal file
@@ -0,0 +1,79 @@
|
||||
use actix_files::{Files, NamedFile};
|
||||
use actix_identity::Identity;
|
||||
use actix_identity::{CookieIdentityPolicy, IdentityService};
|
||||
use actix_web::{
|
||||
cookie::Cookie, get, http, middleware, post, web, web::Data, web::Form, App, HttpRequest,
|
||||
HttpResponse, HttpServer, Responder,
|
||||
http::{header::ContentType, StatusCode}, error::ResponseError
|
||||
};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::path::PathBuf;
|
||||
use tera::{Context, Tera};
|
||||
|
||||
use serde_json::{json, Value};
|
||||
use derive_more::{Display, Error};
|
||||
|
||||
// #[derive(Debug, Display)]
|
||||
// pub struct MyError {
|
||||
// tmpl: Tera,
|
||||
// message_erreur: String,
|
||||
// }
|
||||
// impl MyError {
|
||||
// pub fn new(_tmpl: Tera, message: &String) -> Self {
|
||||
// MyError {
|
||||
// tmpl: _tmpl,
|
||||
// message_erreur: message.to_string(),
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// impl ResponseError for MyError {
|
||||
|
||||
// fn error_response(&self) -> HttpResponse {
|
||||
// let context = Context::new();
|
||||
// context.insert("message_erreur", &self.message_erreur);
|
||||
// let result_tmpl = self.tmpl.render("catch/500.html.twig", &context);
|
||||
// let body = "internal error".to_string();
|
||||
// if !result_tmpl.is_err() {
|
||||
// body = result_tmpl.unwrap();
|
||||
// }
|
||||
// HttpResponse::build(StatusCode::INTERNAL_SERVER_ERROR)
|
||||
// .insert_header(ContentType::html())
|
||||
// .body(body)
|
||||
// }
|
||||
|
||||
// // fn status_code(&self) -> StatusCode {
|
||||
// // match *self {
|
||||
// // MyError::InternalError => StatusCode::INTERNAL_SERVER_ERROR,
|
||||
// // MyError::BadClientData => StatusCode::BAD_REQUEST,
|
||||
// // MyError::Timeout => StatusCode::GATEWAY_TIMEOUT,
|
||||
// // }
|
||||
// // }
|
||||
// }
|
||||
|
||||
pub fn json(obj: Value) -> HttpResponse {
|
||||
HttpResponse::Ok().insert_header(ContentType::json()).body(obj.to_string())
|
||||
}
|
||||
|
||||
pub fn text(s: String) -> HttpResponse {
|
||||
HttpResponse::Ok().body(s)
|
||||
}
|
||||
|
||||
pub fn template(tmpl: Data<Tera>, name: &'static str, context: &Context) -> HttpResponse {
|
||||
HttpResponse::Ok().body(tmpl.render(name, context).unwrap())
|
||||
}
|
||||
|
||||
pub fn redirect(uri: &str) -> HttpResponse {
|
||||
HttpResponse::Found()
|
||||
.append_header((http::header::LOCATION, uri))
|
||||
.finish()
|
||||
}
|
||||
|
||||
pub fn just_404(tmpl: Data<Tera>) -> HttpResponse {
|
||||
let context = Context::new();
|
||||
HttpResponse::NotFound().body(tmpl.render("catch/404.html.twig", &context).unwrap())
|
||||
// HttpResponse::NotFound().finish()
|
||||
}
|
||||
|
||||
pub fn file(req: HttpRequest, path: PathBuf) -> HttpResponse {
|
||||
NamedFile::open(path).unwrap().into_response(&req)
|
||||
}
|
||||
0
src/schema.rs
Normal file
0
src/schema.rs
Normal file
333
src/util.rs
Normal file
333
src/util.rs
Normal file
@@ -0,0 +1,333 @@
|
||||
#![allow(unused)]
|
||||
// #[macro_use]
|
||||
// extern crate diesel;
|
||||
extern crate dotenv;
|
||||
|
||||
use diesel::pg::PgConnection;
|
||||
use diesel::prelude::*;
|
||||
use dotenv::dotenv;
|
||||
use std::collections::HashMap;
|
||||
use std::io::{self, Read, Seek, Write};
|
||||
use std::path::Path;
|
||||
use std::process::Command;
|
||||
|
||||
use actix_identity::Identity;
|
||||
use actix_multipart::Multipart;
|
||||
use futures_util::TryStreamExt as _;
|
||||
use serde_json::{json, Value};
|
||||
use std::fs::File;
|
||||
use std::process::*;
|
||||
use tempfile::NamedTempFile;
|
||||
use uuid::Uuid;
|
||||
use actix_web::web::Data;
|
||||
|
||||
use std::io::prelude::*;
|
||||
use std::iter::Iterator;
|
||||
// use zip::result::ZipError;
|
||||
// use zip::write::FileOptions;
|
||||
|
||||
use walkdir::{DirEntry, WalkDir};
|
||||
// use reqwest::blocking::Client;
|
||||
|
||||
use tera::{Context, Tera};
|
||||
|
||||
#[derive(Debug, Clone, serde::Serialize)]
|
||||
pub struct FormData {
|
||||
pub name: String,
|
||||
pub content_type: String,
|
||||
pub value: String,
|
||||
pub filename: String,
|
||||
pub path: String,
|
||||
}
|
||||
|
||||
impl FormData {
|
||||
pub fn new(_name: String, _content_type: String) -> Self {
|
||||
FormData {
|
||||
name: _name,
|
||||
content_type: _content_type,
|
||||
value: "".to_string(),
|
||||
filename: "".to_string(),
|
||||
path: "".to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn save_file<P: AsRef<Path>>(self, path: P) {
|
||||
let content = String::from_utf8_lossy(&std::fs::read(&self.path).unwrap()).to_string();
|
||||
|
||||
if content != "" {
|
||||
std::fs::create_dir_all(&path.as_ref().parent().unwrap()).unwrap();
|
||||
std::fs::rename(self.path, &path.as_ref());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// enum FormDataVec {
|
||||
// FormData(FormData),
|
||||
// FormDataVec(Vec<FormData>),
|
||||
// }
|
||||
|
||||
pub async fn get_form_data(mut payload: Multipart) -> HashMap<String, FormData> {
|
||||
let mut form_datas: HashMap<String, FormData> = HashMap::new();
|
||||
let mut is_finish = false;
|
||||
while !is_finish {
|
||||
let mut field_result = &mut payload.try_next().await;
|
||||
if field_result.is_ok() {
|
||||
if let Some(field) = field_result.as_mut().unwrap() {
|
||||
let mut form_data =
|
||||
FormData::new(field.name().to_string(), field.content_type().to_string());
|
||||
let content_disposition = field.content_disposition();
|
||||
let filename_option = content_disposition.get_filename();
|
||||
if filename_option.is_some() {
|
||||
form_data.filename = filename_option.unwrap().to_string();
|
||||
let mut f = NamedTempFile::new().unwrap();
|
||||
form_data.path = f.into_temp_path().to_str().unwrap().to_string();
|
||||
let mut file = std::fs::File::create(form_data.path.clone()).unwrap();
|
||||
while let Some(chunk) = field.try_next().await.unwrap() {
|
||||
file.write_all(&chunk);
|
||||
}
|
||||
} else {
|
||||
let mut value = String::new();
|
||||
while let Some(chunk) = field.try_next().await.unwrap() {
|
||||
let str_chunk = std::str::from_utf8(&chunk).unwrap();
|
||||
value.push_str(str_chunk);
|
||||
}
|
||||
form_data.value = value;
|
||||
// field.get_result()
|
||||
}
|
||||
form_datas.insert(form_data.name.clone(), form_data);
|
||||
} else {
|
||||
is_finish = true;
|
||||
}
|
||||
} else {
|
||||
is_finish = true;
|
||||
println!("{:?}", "this form is not enctype=multipart/form-data");
|
||||
}
|
||||
}
|
||||
return form_datas;
|
||||
}
|
||||
|
||||
pub fn generate_key() -> String {
|
||||
use rand::Rng;
|
||||
const CHARSET: &[u8] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZ\
|
||||
abcdefghijklmnopqrstuvwxyz\
|
||||
0123456789";
|
||||
const PASSWORD_LEN: usize = 10;
|
||||
let mut rng = rand::thread_rng();
|
||||
|
||||
let password: String = (0..PASSWORD_LEN)
|
||||
.map(|_| {
|
||||
let idx = rng.gen_range(0..CHARSET.len());
|
||||
CHARSET[idx] as char
|
||||
})
|
||||
.collect();
|
||||
return password;
|
||||
}
|
||||
|
||||
// pub fn get_user_session(id: &Identity) -> Result<User, String> {
|
||||
// if let Some(user_id) = id.identity() {
|
||||
// let result = User::find(user_id.parse::<i32>().unwrap());
|
||||
// return result;
|
||||
// }
|
||||
// Err("Not cookie found".to_string())
|
||||
// }
|
||||
|
||||
pub async fn convert_video<P: AsRef<Path>, Q: AsRef<Path>>(
|
||||
from: P,
|
||||
to: Q,
|
||||
data: &Value,
|
||||
quality: &'static str,
|
||||
) {
|
||||
let mut buffer: String;
|
||||
let mut to_folder = to.as_ref().parent().unwrap();
|
||||
let stdout_path = to_folder.join(format!(
|
||||
"{}{}",
|
||||
to.as_ref().file_name().unwrap().to_str().unwrap(),
|
||||
"_stdout.txt"
|
||||
));
|
||||
let data_path = to_folder.join(format!(
|
||||
"{}{}",
|
||||
to.as_ref().file_name().unwrap().to_str().unwrap(),
|
||||
"_data.json"
|
||||
));
|
||||
std::fs::write(&data_path, data.to_string());
|
||||
let mut final_name = to.as_ref().as_os_str().to_str().unwrap();
|
||||
// let mut str = final_name.to_string();
|
||||
// str = str.replace(".mp4", format!("{}.mp4", quality).as_str());
|
||||
// final_name = str.as_str();
|
||||
|
||||
println!(
|
||||
"converting {:?} to {:?}",
|
||||
from.as_ref().as_os_str().to_str().unwrap(),
|
||||
&final_name
|
||||
);
|
||||
let mut cmd = Command::new("./src/soft/ffmpeg");
|
||||
cmd.stdout(Stdio::from(File::create(&stdout_path).unwrap()))
|
||||
.stderr(Stdio::null())
|
||||
.stdin(Stdio::null())
|
||||
.args([
|
||||
"-y",
|
||||
"-progress",
|
||||
"-",
|
||||
"-i",
|
||||
from.as_ref().as_os_str().to_str().unwrap(),
|
||||
"-vcodec",
|
||||
"libx264",
|
||||
"-acodec",
|
||||
"aac",
|
||||
"-scodec",
|
||||
"mov_text",
|
||||
"-map",
|
||||
"V",
|
||||
"-map",
|
||||
"a?",
|
||||
"-map",
|
||||
"s?",
|
||||
]);
|
||||
if quality != "copy" {
|
||||
cmd.args(["-s", &quality]);
|
||||
}
|
||||
cmd.arg(final_name);
|
||||
let mut ffmpeg = cmd.spawn().expect("failed to execute child");
|
||||
ffmpeg.wait();
|
||||
std::fs::remove_file(&stdout_path);
|
||||
std::fs::write(&data_path, get_video_data(&to).unwrap().to_string());
|
||||
println!(
|
||||
"converting end {:?} to {:?}",
|
||||
from.as_ref().as_os_str().to_str().unwrap(),
|
||||
to.as_ref().as_os_str().to_str().unwrap()
|
||||
);
|
||||
}
|
||||
|
||||
pub fn convert_e57_las<P: AsRef<Path>>(path: P) -> Result<String, String> {
|
||||
let stdout_path = path.as_ref().parent().unwrap().join("cmd_logs.txt");
|
||||
let mut cmd = Command::new("wine"); // wine ./src/soft/e572las.exe -v -i \"{e57filepath}\" -o \"{e57filepath}.las\
|
||||
cmd.stdout(Stdio::null())
|
||||
.stderr(Stdio::from(File::create(&stdout_path).unwrap()))
|
||||
.stdin(Stdio::null())
|
||||
.args([
|
||||
"./src/soft/e572las.exe",
|
||||
"-v",
|
||||
"-i",
|
||||
format!("{}", path.as_ref().as_os_str().to_str().unwrap()).as_str(),
|
||||
"-o",
|
||||
format!("{}.las", path.as_ref().as_os_str().to_str().unwrap()).as_str(),
|
||||
]);
|
||||
println!("{:?}", cmd);
|
||||
|
||||
let mut ffmpeg = cmd.spawn().expect("failed to execute wine e572las");
|
||||
ffmpeg.wait();
|
||||
std::fs::remove_file(&stdout_path);
|
||||
// let mut output = cmd.output().expect("failed to execute wine e572las");
|
||||
// let result = String::from_utf8_lossy(&output.stderr).to_string();
|
||||
println!("convert_e57_las");
|
||||
Ok("result".to_string())
|
||||
}
|
||||
|
||||
pub fn convert_las_potree<P: AsRef<Path>>(path: P) -> Result<String, String> {
|
||||
let stdout_path = path.as_ref().parent().unwrap().join("cmd_logs.txt");
|
||||
let mut cmd = Command::new("./src/e57extractor/PotreeConverter"); // wine ./src/soft/e572las.exe -v -i \"{e57filepath}\" -o \"{e57filepath}.las\
|
||||
cmd.stdout(Stdio::from(File::create(&stdout_path).unwrap()))
|
||||
.stderr(Stdio::null())
|
||||
.stdin(Stdio::null())
|
||||
.args([
|
||||
// "./src/e57extractor/PotreeConverter.exe",
|
||||
format!("{}", path.as_ref().as_os_str().to_str().unwrap()).as_str(),
|
||||
]);
|
||||
println!("{:?}", cmd);
|
||||
|
||||
let mut output = cmd.output().expect("failed to execute PotreeConverter");
|
||||
let fs = std::fs::File::create(
|
||||
format!(
|
||||
"{}_converted/sources.json",
|
||||
path.as_ref().as_os_str().to_str().unwrap()
|
||||
)
|
||||
.as_str(),
|
||||
);
|
||||
let mut ffmpeg = cmd.spawn().expect("failed to execute PotreeConverter");
|
||||
ffmpeg.wait();
|
||||
std::fs::remove_file(&stdout_path);
|
||||
// let mut output = cmd.output().expect("failed to execute PotreeConverter");
|
||||
// let result = String::from_utf8_lossy(&output.stdout).to_string();
|
||||
println!("convert_las_potree");
|
||||
Ok("result".to_string())
|
||||
}
|
||||
|
||||
pub fn convert_e57_images<P: AsRef<Path>>(path: P) -> Result<String, String> {
|
||||
let stdout_path = path.as_ref().parent().unwrap().join("cmd_logs.txt");
|
||||
let mut cmd = Command::new("python3"); // wine ./src/soft/e572las.exe -v -i \"{e57filepath}\" -o \"{e57filepath}.las\
|
||||
cmd.stdout(Stdio::from(File::create(&stdout_path).unwrap()))
|
||||
.stderr(Stdio::from(File::create(&stdout_path).unwrap()))
|
||||
.stdin(Stdio::null())
|
||||
.args([
|
||||
"./src/e57extractor/",
|
||||
format!("{}", path.as_ref().as_os_str().to_str().unwrap()).as_str(),
|
||||
"--only-images",
|
||||
]);
|
||||
println!("{:?}", cmd);
|
||||
|
||||
let mut ffmpeg = cmd.spawn().expect("failed to execute PotreeConverter");
|
||||
ffmpeg.wait();
|
||||
|
||||
let output = String::from_utf8_lossy(&std::fs::read(&stdout_path).unwrap()).to_string();
|
||||
std::fs::remove_file(&stdout_path);
|
||||
if output.contains("File contains no 2D images. Exiting...") || output.contains("E57_ERROR") {
|
||||
println!("No image found");
|
||||
return Err("No image found".to_string());
|
||||
}
|
||||
println!("convert_e57_images");
|
||||
println!("{}", output);
|
||||
Ok("result".to_string())
|
||||
}
|
||||
|
||||
pub fn get_video_data<P: AsRef<Path>>(path: P) -> Result<Value, serde_json::Error> {
|
||||
let mut output = Command::new("./src/soft/ffprobe")
|
||||
.args([
|
||||
"-print_format",
|
||||
"json",
|
||||
"-show_format",
|
||||
"-show_streams",
|
||||
"-show_chapters",
|
||||
path.as_ref().as_os_str().to_str().unwrap(),
|
||||
])
|
||||
.output()
|
||||
.expect("failed to execute ffprobe");
|
||||
let str = String::from_utf8_lossy(&output.stdout).to_string();
|
||||
let result: Result<Value, serde_json::Error> = serde_json::from_str(&str);
|
||||
result
|
||||
}
|
||||
|
||||
pub fn save_file_field(field: &FormData) -> String {
|
||||
let extension = Path::new(&field.filename)
|
||||
.extension()
|
||||
.unwrap()
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.to_string();
|
||||
let uuid = Uuid::new_v4().to_string();
|
||||
let final_path_local =
|
||||
Path::new("./static/sourcefiles").join(format!("{}.{}", uuid, extension));
|
||||
let final_path = Path::new("/static/sourcefiles")
|
||||
.join(format!("{}.{}", uuid, extension))
|
||||
.to_str()
|
||||
.unwrap()
|
||||
.to_string();
|
||||
|
||||
std::fs::create_dir_all("./static/sourcefiles");
|
||||
std::fs::rename(&field.path, &final_path_local);
|
||||
|
||||
return final_path;
|
||||
}
|
||||
|
||||
pub fn copy_dir_all(src: impl AsRef<Path>, dst: impl AsRef<Path>) -> io::Result<()> {
|
||||
std::fs::create_dir_all(&dst)?;
|
||||
for entry in std::fs::read_dir(src)? {
|
||||
let entry = entry?;
|
||||
let ty = entry.file_type()?;
|
||||
if ty.is_dir() {
|
||||
copy_dir_all(entry.path(), dst.as_ref().join(entry.file_name()))?;
|
||||
} else {
|
||||
std::fs::copy(entry.path(), dst.as_ref().join(entry.file_name()))?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
BIN
static/favicon.png
Normal file
BIN
static/favicon.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
BIN
static/img/404.png
Normal file
BIN
static/img/404.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 4.4 KiB |
BIN
static/img/logo.png
Normal file
BIN
static/img/logo.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 27 KiB |
6812
static/scripts/bootstrap.bundle.js
vendored
Executable file
6812
static/scripts/bootstrap.bundle.js
vendored
Executable file
File diff suppressed because it is too large
Load Diff
1
static/scripts/bootstrap.bundle.js.map
Executable file
1
static/scripts/bootstrap.bundle.js.map
Executable file
File diff suppressed because one or more lines are too long
7
static/scripts/bootstrap.bundle.min.js
vendored
Executable file
7
static/scripts/bootstrap.bundle.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
1
static/scripts/bootstrap.bundle.min.js.map
Executable file
1
static/scripts/bootstrap.bundle.min.js.map
Executable file
File diff suppressed because one or more lines are too long
4999
static/scripts/bootstrap.esm.js
vendored
Executable file
4999
static/scripts/bootstrap.esm.js
vendored
Executable file
File diff suppressed because it is too large
Load Diff
1
static/scripts/bootstrap.esm.js.map
Executable file
1
static/scripts/bootstrap.esm.js.map
Executable file
File diff suppressed because one or more lines are too long
7
static/scripts/bootstrap.esm.min.js
vendored
Executable file
7
static/scripts/bootstrap.esm.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
1
static/scripts/bootstrap.esm.min.js.map
Executable file
1
static/scripts/bootstrap.esm.min.js.map
Executable file
File diff suppressed because one or more lines are too long
5048
static/scripts/bootstrap.js
vendored
Executable file
5048
static/scripts/bootstrap.js
vendored
Executable file
File diff suppressed because it is too large
Load Diff
1
static/scripts/bootstrap.js.map
Executable file
1
static/scripts/bootstrap.js.map
Executable file
File diff suppressed because one or more lines are too long
7
static/scripts/bootstrap.min.js
vendored
Executable file
7
static/scripts/bootstrap.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
1
static/scripts/bootstrap.min.js.map
Executable file
1
static/scripts/bootstrap.min.js.map
Executable file
File diff suppressed because one or more lines are too long
4
static/scripts/jquery-3.2.1.slim.min.js
vendored
Normal file
4
static/scripts/jquery-3.2.1.slim.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
static/scripts/popper.min.js
vendored
Executable file
6
static/scripts/popper.min.js
vendored
Executable file
File diff suppressed because one or more lines are too long
0
static/scripts/specific.js
Normal file
0
static/scripts/specific.js
Normal file
5051
static/styles/bootstrap-grid.css
vendored
Executable file
5051
static/styles/bootstrap-grid.css
vendored
Executable file
File diff suppressed because it is too large
Load Diff
1
static/styles/bootstrap-grid.css.map
Executable file
1
static/styles/bootstrap-grid.css.map
Executable file
File diff suppressed because one or more lines are too long
7
static/styles/bootstrap-grid.min.css
vendored
Executable file
7
static/styles/bootstrap-grid.min.css
vendored
Executable file
File diff suppressed because one or more lines are too long
1
static/styles/bootstrap-grid.min.css.map
Executable file
1
static/styles/bootstrap-grid.min.css.map
Executable file
File diff suppressed because one or more lines are too long
5050
static/styles/bootstrap-grid.rtl.css
vendored
Executable file
5050
static/styles/bootstrap-grid.rtl.css
vendored
Executable file
File diff suppressed because it is too large
Load Diff
1
static/styles/bootstrap-grid.rtl.css.map
Executable file
1
static/styles/bootstrap-grid.rtl.css.map
Executable file
File diff suppressed because one or more lines are too long
7
static/styles/bootstrap-grid.rtl.min.css
vendored
Executable file
7
static/styles/bootstrap-grid.rtl.min.css
vendored
Executable file
File diff suppressed because one or more lines are too long
1
static/styles/bootstrap-grid.rtl.min.css.map
Executable file
1
static/styles/bootstrap-grid.rtl.min.css.map
Executable file
File diff suppressed because one or more lines are too long
481
static/styles/bootstrap-reboot.css
vendored
Executable file
481
static/styles/bootstrap-reboot.css
vendored
Executable file
@@ -0,0 +1,481 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v5.1.1 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/
|
||||
:root {
|
||||
--bs-blue: #0d6efd;
|
||||
--bs-indigo: #6610f2;
|
||||
--bs-purple: #6f42c1;
|
||||
--bs-pink: #d63384;
|
||||
--bs-red: #dc3545;
|
||||
--bs-orange: #fd7e14;
|
||||
--bs-yellow: #ffc107;
|
||||
--bs-green: #198754;
|
||||
--bs-teal: #20c997;
|
||||
--bs-cyan: #0dcaf0;
|
||||
--bs-white: #fff;
|
||||
--bs-gray: #6c757d;
|
||||
--bs-gray-dark: #343a40;
|
||||
--bs-gray-100: #f8f9fa;
|
||||
--bs-gray-200: #e9ecef;
|
||||
--bs-gray-300: #dee2e6;
|
||||
--bs-gray-400: #ced4da;
|
||||
--bs-gray-500: #adb5bd;
|
||||
--bs-gray-600: #6c757d;
|
||||
--bs-gray-700: #495057;
|
||||
--bs-gray-800: #343a40;
|
||||
--bs-gray-900: #212529;
|
||||
--bs-primary: #0d6efd;
|
||||
--bs-secondary: #6c757d;
|
||||
--bs-success: #198754;
|
||||
--bs-info: #0dcaf0;
|
||||
--bs-warning: #ffc107;
|
||||
--bs-danger: #dc3545;
|
||||
--bs-light: #f8f9fa;
|
||||
--bs-dark: #212529;
|
||||
--bs-primary-rgb: 13, 110, 253;
|
||||
--bs-secondary-rgb: 108, 117, 125;
|
||||
--bs-success-rgb: 25, 135, 84;
|
||||
--bs-info-rgb: 13, 202, 240;
|
||||
--bs-warning-rgb: 255, 193, 7;
|
||||
--bs-danger-rgb: 220, 53, 69;
|
||||
--bs-light-rgb: 248, 249, 250;
|
||||
--bs-dark-rgb: 33, 37, 41;
|
||||
--bs-white-rgb: 255, 255, 255;
|
||||
--bs-black-rgb: 0, 0, 0;
|
||||
--bs-body-color-rgb: 33, 37, 41;
|
||||
--bs-body-bg-rgb: 255, 255, 255;
|
||||
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
||||
--bs-body-font-family: var(--bs-font-sans-serif);
|
||||
--bs-body-font-size: 1rem;
|
||||
--bs-body-font-weight: 400;
|
||||
--bs-body-line-height: 1.5;
|
||||
--bs-body-color: #212529;
|
||||
--bs-body-bg: #fff;
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
:root {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: var(--bs-body-font-family);
|
||||
font-size: var(--bs-body-font-size);
|
||||
font-weight: var(--bs-body-font-weight);
|
||||
line-height: var(--bs-body-line-height);
|
||||
color: var(--bs-body-color);
|
||||
text-align: var(--bs-body-text-align);
|
||||
background-color: var(--bs-body-bg);
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 1rem 0;
|
||||
color: inherit;
|
||||
background-color: currentColor;
|
||||
border: 0;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
hr:not([size]) {
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
h6, h5, h4, h3, h2, h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: calc(1.375rem + 1.5vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: calc(1.325rem + 0.9vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: calc(1.3rem + 0.6vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
abbr[title],
|
||||
abbr[data-bs-original-title] {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
padding-left: 2rem;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5rem;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0.2em;
|
||||
background-color: #fcf8e3;
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 0.75em;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0d6efd;
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:hover {
|
||||
color: #0a58ca;
|
||||
}
|
||||
|
||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: var(--bs-font-monospace);
|
||||
font-size: 1em;
|
||||
direction: ltr /* rtl:ignore */;
|
||||
unicode-bidi: bidi-override;
|
||||
}
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
pre code {
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 0.875em;
|
||||
color: #d63384;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
a > code {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
kbd {
|
||||
padding: 0.2rem 0.4rem;
|
||||
font-size: 0.875em;
|
||||
color: #fff;
|
||||
background-color: #212529;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
kbd kbd {
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
img,
|
||||
svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table {
|
||||
caption-side: bottom;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
color: #6c757d;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: inherit;
|
||||
text-align: -webkit-match-parent;
|
||||
}
|
||||
|
||||
thead,
|
||||
tbody,
|
||||
tfoot,
|
||||
tr,
|
||||
td,
|
||||
th {
|
||||
border-color: inherit;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus:not(:focus-visible) {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
[role=button] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
select {
|
||||
word-wrap: normal;
|
||||
}
|
||||
select:disabled {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
[list]::-webkit-calendar-picker-indicator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
button,
|
||||
[type=button],
|
||||
[type=reset],
|
||||
[type=submit] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
button:not(:disabled),
|
||||
[type=button]:not(:disabled),
|
||||
[type=reset]:not(:disabled),
|
||||
[type=submit]:not(:disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
float: left;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
line-height: inherit;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
legend {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
legend + * {
|
||||
clear: left;
|
||||
}
|
||||
|
||||
::-webkit-datetime-edit-fields-wrapper,
|
||||
::-webkit-datetime-edit-text,
|
||||
::-webkit-datetime-edit-minute,
|
||||
::-webkit-datetime-edit-hour-field,
|
||||
::-webkit-datetime-edit-day-field,
|
||||
::-webkit-datetime-edit-month-field,
|
||||
::-webkit-datetime-edit-year-field {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-inner-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type=search] {
|
||||
outline-offset: -2px;
|
||||
-webkit-appearance: textfield;
|
||||
}
|
||||
|
||||
/* rtl:raw:
|
||||
[type="tel"],
|
||||
[type="url"],
|
||||
[type="email"],
|
||||
[type="number"] {
|
||||
direction: ltr;
|
||||
}
|
||||
*/
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
::-webkit-color-swatch-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::file-selector-button {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
iframe {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/*# sourceMappingURL=bootstrap-reboot.css.map */
|
||||
1
static/styles/bootstrap-reboot.css.map
Executable file
1
static/styles/bootstrap-reboot.css.map
Executable file
File diff suppressed because one or more lines are too long
8
static/styles/bootstrap-reboot.min.css
vendored
Executable file
8
static/styles/bootstrap-reboot.min.css
vendored
Executable file
File diff suppressed because one or more lines are too long
1
static/styles/bootstrap-reboot.min.css.map
Executable file
1
static/styles/bootstrap-reboot.min.css.map
Executable file
File diff suppressed because one or more lines are too long
478
static/styles/bootstrap-reboot.rtl.css
vendored
Executable file
478
static/styles/bootstrap-reboot.rtl.css
vendored
Executable file
@@ -0,0 +1,478 @@
|
||||
/*!
|
||||
* Bootstrap Reboot v5.1.1 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors
|
||||
* Copyright 2011-2021 Twitter, Inc.
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
* Forked from Normalize.css, licensed MIT (https://github.com/necolas/normalize.css/blob/master/LICENSE.md)
|
||||
*/
|
||||
:root {
|
||||
--bs-blue: #0d6efd;
|
||||
--bs-indigo: #6610f2;
|
||||
--bs-purple: #6f42c1;
|
||||
--bs-pink: #d63384;
|
||||
--bs-red: #dc3545;
|
||||
--bs-orange: #fd7e14;
|
||||
--bs-yellow: #ffc107;
|
||||
--bs-green: #198754;
|
||||
--bs-teal: #20c997;
|
||||
--bs-cyan: #0dcaf0;
|
||||
--bs-white: #fff;
|
||||
--bs-gray: #6c757d;
|
||||
--bs-gray-dark: #343a40;
|
||||
--bs-gray-100: #f8f9fa;
|
||||
--bs-gray-200: #e9ecef;
|
||||
--bs-gray-300: #dee2e6;
|
||||
--bs-gray-400: #ced4da;
|
||||
--bs-gray-500: #adb5bd;
|
||||
--bs-gray-600: #6c757d;
|
||||
--bs-gray-700: #495057;
|
||||
--bs-gray-800: #343a40;
|
||||
--bs-gray-900: #212529;
|
||||
--bs-primary: #0d6efd;
|
||||
--bs-secondary: #6c757d;
|
||||
--bs-success: #198754;
|
||||
--bs-info: #0dcaf0;
|
||||
--bs-warning: #ffc107;
|
||||
--bs-danger: #dc3545;
|
||||
--bs-light: #f8f9fa;
|
||||
--bs-dark: #212529;
|
||||
--bs-primary-rgb: 13, 110, 253;
|
||||
--bs-secondary-rgb: 108, 117, 125;
|
||||
--bs-success-rgb: 25, 135, 84;
|
||||
--bs-info-rgb: 13, 202, 240;
|
||||
--bs-warning-rgb: 255, 193, 7;
|
||||
--bs-danger-rgb: 220, 53, 69;
|
||||
--bs-light-rgb: 248, 249, 250;
|
||||
--bs-dark-rgb: 33, 37, 41;
|
||||
--bs-white-rgb: 255, 255, 255;
|
||||
--bs-black-rgb: 0, 0, 0;
|
||||
--bs-body-color-rgb: 33, 37, 41;
|
||||
--bs-body-bg-rgb: 255, 255, 255;
|
||||
--bs-font-sans-serif: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", "Liberation Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
||||
--bs-font-monospace: SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
||||
--bs-gradient: linear-gradient(180deg, rgba(255, 255, 255, 0.15), rgba(255, 255, 255, 0));
|
||||
--bs-body-font-family: var(--bs-font-sans-serif);
|
||||
--bs-body-font-size: 1rem;
|
||||
--bs-body-font-weight: 400;
|
||||
--bs-body-line-height: 1.5;
|
||||
--bs-body-color: #212529;
|
||||
--bs-body-bg: #fff;
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
@media (prefers-reduced-motion: no-preference) {
|
||||
:root {
|
||||
scroll-behavior: smooth;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
font-family: var(--bs-body-font-family);
|
||||
font-size: var(--bs-body-font-size);
|
||||
font-weight: var(--bs-body-font-weight);
|
||||
line-height: var(--bs-body-line-height);
|
||||
color: var(--bs-body-color);
|
||||
text-align: var(--bs-body-text-align);
|
||||
background-color: var(--bs-body-bg);
|
||||
-webkit-text-size-adjust: 100%;
|
||||
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
hr {
|
||||
margin: 1rem 0;
|
||||
color: inherit;
|
||||
background-color: currentColor;
|
||||
border: 0;
|
||||
opacity: 0.25;
|
||||
}
|
||||
|
||||
hr:not([size]) {
|
||||
height: 1px;
|
||||
}
|
||||
|
||||
h6, h5, h4, h3, h2, h1 {
|
||||
margin-top: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-weight: 500;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: calc(1.375rem + 1.5vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h1 {
|
||||
font-size: 2.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: calc(1.325rem + 0.9vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h2 {
|
||||
font-size: 2rem;
|
||||
}
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: calc(1.3rem + 0.6vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h3 {
|
||||
font-size: 1.75rem;
|
||||
}
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
h4 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-size: 1.25rem;
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
abbr[title],
|
||||
abbr[data-bs-original-title] {
|
||||
-webkit-text-decoration: underline dotted;
|
||||
text-decoration: underline dotted;
|
||||
cursor: help;
|
||||
-webkit-text-decoration-skip-ink: none;
|
||||
text-decoration-skip-ink: none;
|
||||
}
|
||||
|
||||
address {
|
||||
margin-bottom: 1rem;
|
||||
font-style: normal;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul {
|
||||
padding-right: 2rem;
|
||||
}
|
||||
|
||||
ol,
|
||||
ul,
|
||||
dl {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
ol ol,
|
||||
ul ul,
|
||||
ol ul,
|
||||
ul ol {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
dt {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
dd {
|
||||
margin-bottom: 0.5rem;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
blockquote {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
b,
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
small {
|
||||
font-size: 0.875em;
|
||||
}
|
||||
|
||||
mark {
|
||||
padding: 0.2em;
|
||||
background-color: #fcf8e3;
|
||||
}
|
||||
|
||||
sub,
|
||||
sup {
|
||||
position: relative;
|
||||
font-size: 0.75em;
|
||||
line-height: 0;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sub {
|
||||
bottom: -0.25em;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #0d6efd;
|
||||
text-decoration: underline;
|
||||
}
|
||||
a:hover {
|
||||
color: #0a58ca;
|
||||
}
|
||||
|
||||
a:not([href]):not([class]), a:not([href]):not([class]):hover {
|
||||
color: inherit;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
pre,
|
||||
code,
|
||||
kbd,
|
||||
samp {
|
||||
font-family: var(--bs-font-monospace);
|
||||
font-size: 1em;
|
||||
direction: ltr ;
|
||||
unicode-bidi: bidi-override;
|
||||
}
|
||||
|
||||
pre {
|
||||
display: block;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
overflow: auto;
|
||||
font-size: 0.875em;
|
||||
}
|
||||
pre code {
|
||||
font-size: inherit;
|
||||
color: inherit;
|
||||
word-break: normal;
|
||||
}
|
||||
|
||||
code {
|
||||
font-size: 0.875em;
|
||||
color: #d63384;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
a > code {
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
kbd {
|
||||
padding: 0.2rem 0.4rem;
|
||||
font-size: 0.875em;
|
||||
color: #fff;
|
||||
background-color: #212529;
|
||||
border-radius: 0.2rem;
|
||||
}
|
||||
kbd kbd {
|
||||
padding: 0;
|
||||
font-size: 1em;
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
figure {
|
||||
margin: 0 0 1rem;
|
||||
}
|
||||
|
||||
img,
|
||||
svg {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
table {
|
||||
caption-side: bottom;
|
||||
border-collapse: collapse;
|
||||
}
|
||||
|
||||
caption {
|
||||
padding-top: 0.5rem;
|
||||
padding-bottom: 0.5rem;
|
||||
color: #6c757d;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
th {
|
||||
text-align: inherit;
|
||||
text-align: -webkit-match-parent;
|
||||
}
|
||||
|
||||
thead,
|
||||
tbody,
|
||||
tfoot,
|
||||
tr,
|
||||
td,
|
||||
th {
|
||||
border-color: inherit;
|
||||
border-style: solid;
|
||||
border-width: 0;
|
||||
}
|
||||
|
||||
label {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
button {
|
||||
border-radius: 0;
|
||||
}
|
||||
|
||||
button:focus:not(:focus-visible) {
|
||||
outline: 0;
|
||||
}
|
||||
|
||||
input,
|
||||
button,
|
||||
select,
|
||||
optgroup,
|
||||
textarea {
|
||||
margin: 0;
|
||||
font-family: inherit;
|
||||
font-size: inherit;
|
||||
line-height: inherit;
|
||||
}
|
||||
|
||||
button,
|
||||
select {
|
||||
text-transform: none;
|
||||
}
|
||||
|
||||
[role=button] {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
select {
|
||||
word-wrap: normal;
|
||||
}
|
||||
select:disabled {
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
[list]::-webkit-calendar-picker-indicator {
|
||||
display: none;
|
||||
}
|
||||
|
||||
button,
|
||||
[type=button],
|
||||
[type=reset],
|
||||
[type=submit] {
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
button:not(:disabled),
|
||||
[type=button]:not(:disabled),
|
||||
[type=reset]:not(:disabled),
|
||||
[type=submit]:not(:disabled) {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
::-moz-focus-inner {
|
||||
padding: 0;
|
||||
border-style: none;
|
||||
}
|
||||
|
||||
textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
fieldset {
|
||||
min-width: 0;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
border: 0;
|
||||
}
|
||||
|
||||
legend {
|
||||
float: right;
|
||||
width: 100%;
|
||||
padding: 0;
|
||||
margin-bottom: 0.5rem;
|
||||
font-size: calc(1.275rem + 0.3vw);
|
||||
line-height: inherit;
|
||||
}
|
||||
@media (min-width: 1200px) {
|
||||
legend {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
}
|
||||
legend + * {
|
||||
clear: right;
|
||||
}
|
||||
|
||||
::-webkit-datetime-edit-fields-wrapper,
|
||||
::-webkit-datetime-edit-text,
|
||||
::-webkit-datetime-edit-minute,
|
||||
::-webkit-datetime-edit-hour-field,
|
||||
::-webkit-datetime-edit-day-field,
|
||||
::-webkit-datetime-edit-month-field,
|
||||
::-webkit-datetime-edit-year-field {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::-webkit-inner-spin-button {
|
||||
height: auto;
|
||||
}
|
||||
|
||||
[type=search] {
|
||||
outline-offset: -2px;
|
||||
-webkit-appearance: textfield;
|
||||
}
|
||||
|
||||
[type="tel"],
|
||||
[type="url"],
|
||||
[type="email"],
|
||||
[type="number"] {
|
||||
direction: ltr;
|
||||
}
|
||||
::-webkit-search-decoration {
|
||||
-webkit-appearance: none;
|
||||
}
|
||||
|
||||
::-webkit-color-swatch-wrapper {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
::file-selector-button {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
}
|
||||
|
||||
output {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
iframe {
|
||||
border: 0;
|
||||
}
|
||||
|
||||
summary {
|
||||
display: list-item;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
progress {
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
[hidden] {
|
||||
display: none !important;
|
||||
}
|
||||
/*# sourceMappingURL=bootstrap-reboot.rtl.css.map */
|
||||
1
static/styles/bootstrap-reboot.rtl.css.map
Executable file
1
static/styles/bootstrap-reboot.rtl.css.map
Executable file
File diff suppressed because one or more lines are too long
8
static/styles/bootstrap-reboot.rtl.min.css
vendored
Executable file
8
static/styles/bootstrap-reboot.rtl.min.css
vendored
Executable file
File diff suppressed because one or more lines are too long
1
static/styles/bootstrap-reboot.rtl.min.css.map
Executable file
1
static/styles/bootstrap-reboot.rtl.min.css.map
Executable file
File diff suppressed because one or more lines are too long
4866
static/styles/bootstrap-utilities.css
vendored
Executable file
4866
static/styles/bootstrap-utilities.css
vendored
Executable file
File diff suppressed because it is too large
Load Diff
1
static/styles/bootstrap-utilities.css.map
Executable file
1
static/styles/bootstrap-utilities.css.map
Executable file
File diff suppressed because one or more lines are too long
7
static/styles/bootstrap-utilities.min.css
vendored
Executable file
7
static/styles/bootstrap-utilities.min.css
vendored
Executable file
File diff suppressed because one or more lines are too long
1
static/styles/bootstrap-utilities.min.css.map
Executable file
1
static/styles/bootstrap-utilities.min.css.map
Executable file
File diff suppressed because one or more lines are too long
4857
static/styles/bootstrap-utilities.rtl.css
vendored
Executable file
4857
static/styles/bootstrap-utilities.rtl.css
vendored
Executable file
File diff suppressed because it is too large
Load Diff
1
static/styles/bootstrap-utilities.rtl.css.map
Executable file
1
static/styles/bootstrap-utilities.rtl.css.map
Executable file
File diff suppressed because one or more lines are too long
7
static/styles/bootstrap-utilities.rtl.min.css
vendored
Executable file
7
static/styles/bootstrap-utilities.rtl.min.css
vendored
Executable file
File diff suppressed because one or more lines are too long
1
static/styles/bootstrap-utilities.rtl.min.css.map
Executable file
1
static/styles/bootstrap-utilities.rtl.min.css.map
Executable file
File diff suppressed because one or more lines are too long
11222
static/styles/bootstrap.css
vendored
Executable file
11222
static/styles/bootstrap.css
vendored
Executable file
File diff suppressed because it is too large
Load Diff
1
static/styles/bootstrap.css.map
Executable file
1
static/styles/bootstrap.css.map
Executable file
File diff suppressed because one or more lines are too long
7
static/styles/bootstrap.min.css
vendored
Executable file
7
static/styles/bootstrap.min.css
vendored
Executable file
File diff suppressed because one or more lines are too long
1
static/styles/bootstrap.min.css.map
Executable file
1
static/styles/bootstrap.min.css.map
Executable file
File diff suppressed because one or more lines are too long
11198
static/styles/bootstrap.rtl.css
vendored
Executable file
11198
static/styles/bootstrap.rtl.css
vendored
Executable file
File diff suppressed because it is too large
Load Diff
1
static/styles/bootstrap.rtl.css.map
Executable file
1
static/styles/bootstrap.rtl.css.map
Executable file
File diff suppressed because one or more lines are too long
7
static/styles/bootstrap.rtl.min.css
vendored
Executable file
7
static/styles/bootstrap.rtl.min.css
vendored
Executable file
File diff suppressed because one or more lines are too long
1
static/styles/bootstrap.rtl.min.css.map
Executable file
1
static/styles/bootstrap.rtl.min.css.map
Executable file
File diff suppressed because one or more lines are too long
53
static/styles/specific.css
Normal file
53
static/styles/specific.css
Normal file
@@ -0,0 +1,53 @@
|
||||
.bg-darker {
|
||||
background: #111111 !important;
|
||||
}
|
||||
|
||||
.text-shadow {
|
||||
color: white;
|
||||
text-shadow: 1px 1px 1px black, -1px -1px 1px black, 1px -1px 1px black, -1px 1px 1px black;
|
||||
}
|
||||
|
||||
.border-intern {
|
||||
outline: 3px solid var(--bs-success);
|
||||
outline-offset: -4px;
|
||||
box-shadow: 2px 2px 0 var(--bs-success) inset, -2px -2px 0 var(--bs-success) inset !important;
|
||||
}
|
||||
|
||||
.border-intern::after {
|
||||
content: "";
|
||||
outline: 3px solid var(--bs-success);
|
||||
outline-offset: -4px;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
box-shadow: 2px 2px 0 var(--bs-success) inset, -2px -2px 0 var(--bs-success) inset !important;
|
||||
pointer-events:none;
|
||||
}
|
||||
|
||||
/* @media (prefers-color-scheme: dark) {
|
||||
body, .card {
|
||||
background: var(--bs-dark);
|
||||
color: var(--bs-light);
|
||||
}
|
||||
|
||||
* {
|
||||
color: var(--bs-light);
|
||||
}
|
||||
|
||||
.navbar {
|
||||
background: black;
|
||||
}
|
||||
|
||||
#logo {
|
||||
filter: invert(1);
|
||||
}
|
||||
} */
|
||||
|
||||
.color-hover{
|
||||
color:#8A8787
|
||||
}
|
||||
.color-hover:hover {
|
||||
color:#545050
|
||||
}
|
||||
15
templates/base.html.twig
Executable file
15
templates/base.html.twig
Executable file
@@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>{% block title %}{% endblock title %} - MAPS360</title>
|
||||
|
||||
{% block head %}
|
||||
{% include 'includecss.html.twig' %}
|
||||
{% endblock head %}
|
||||
</head>
|
||||
<body>
|
||||
{% block body %}{% endblock body %}
|
||||
{% block footer %}{% include 'includescript.html.twig' %}{% endblock footer %}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
28
templates/catch/404.html.twig
Executable file
28
templates/catch/404.html.twig
Executable file
@@ -0,0 +1,28 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
{% block title %}Erreur 404{% endblock %}
|
||||
{% block body %}
|
||||
|
||||
<div class="text-center pt-5" style="height:100vh;">
|
||||
|
||||
<img src="/static/img/404.png" alt="404" class="zoom-hover" style="max-width:100vw;">
|
||||
|
||||
<i class="h5 d-block pb-4"> La page que vous essayez d'atteindre n'existe pas ou vous n'êtes pas autorisé à la voir.</i>
|
||||
|
||||
<hr class="mx-5 mb-4">
|
||||
|
||||
<a href="/" class="btn btn-primary mdi mdi-arrow-left me-2"> Page d'accueil</a>
|
||||
|
||||
<a href="/login" class="btn btn-outline-primary ms-2"> Login <span class="mdi mdi-arrow-right"></span> <a/>
|
||||
|
||||
</div>
|
||||
|
||||
<style media="screen">
|
||||
.zoom-hover {
|
||||
transition: transform .5s ease;
|
||||
}
|
||||
.zoom-hover:hover {
|
||||
transform: scale(1.2);
|
||||
}
|
||||
</style>
|
||||
|
||||
{% endblock %}
|
||||
22
templates/includecss.html.twig
Normal file
22
templates/includecss.html.twig
Normal file
@@ -0,0 +1,22 @@
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="Pointcloud viewer">
|
||||
<meta name="author" content="https://pradierh.fr/, https://sorlinv.fr/">
|
||||
|
||||
|
||||
<!-- Favicons -->
|
||||
<link rel="apple-touch-icon" href="/static/favicon.png" sizes="180x180">
|
||||
<link rel="icon" href="/static/favicon.png" type="image/png">
|
||||
<link rel="mask-icon" href="/static/favicon.png" color="#7952b3">
|
||||
<meta name="theme-color" content="#333333">
|
||||
|
||||
<link href="https://vjs.zencdn.net/7.17.0/video-js.css" rel="stylesheet" />
|
||||
<link href="https://unpkg.com/@videojs/themes@1/dist/fantasy/index.css" rel="stylesheet">
|
||||
|
||||
<link rel="stylesheet" href="/static/styles/bootstrap.css">
|
||||
<link rel="stylesheet" href="/static/styles/specific.css">
|
||||
|
||||
<link rel="stylesheet" href="//cdn.materialdesignicons.com/5.3.45/css/materialdesignicons.min.css">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@mdi/font@6.6.96/css/materialdesignicons.min.css">
|
||||
|
||||
<script src="https://accounts.google.com/gsi/client" async defer></script>
|
||||
14
templates/includescript.html.twig
Normal file
14
templates/includescript.html.twig
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
|
||||
<script src="/static/scripts/jquery-3.2.1.slim.min.js"></script>
|
||||
<script src="/static/scripts/popper.min.js"></script>
|
||||
<script src="/static/scripts/bootstrap.min.js"></script>
|
||||
<script src="https://unpkg.com/petite-vue"></script>
|
||||
|
||||
<script src="https://unpkg.com/@popperjs/core@2"></script>
|
||||
<script src="https://unpkg.com/tippy.js@6"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.bundle.min.js" integrity="sha384-A3rJD856KowSb7dwlZdYEkO39Gagi7vIsF0jrRAoQmDKKtQBHUuLZ9AsSv4jD4Xa" crossorigin="anonymous"></script>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.11.5/dist/umd/popper.min.js" integrity="sha384-Xe+8cL9oJa6tN/veChSP7q+mnSPaj5Bcu9mPX5F5xIGE0DVittaqT5lorf0EI7Vk" crossorigin="anonymous"></script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0/dist/js/bootstrap.min.js" integrity="sha384-ODmDIVzN+pFdexxHEHFBQH3/9/vQ9uori45z4JjnFsRydbmQbmL5t1tQ0culUzyK" crossorigin="anonymous"></script>
|
||||
<script type="module" src="/static/scripts/specific.js"></script>
|
||||
4
templates/index.html.twig
Executable file
4
templates/index.html.twig
Executable file
@@ -0,0 +1,4 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
{% block title %}Acceuil{% endblock %}
|
||||
{% block body %}
|
||||
{% endblock %}
|
||||
Reference in New Issue
Block a user