Enforce ESLint and Prettier
continuous-integration/drone/push Build is passing Details

error-extensions-editor
Clément FRÉVILLE 10 months ago
parent e4fa38e9ce
commit 74a68d9743

@ -0,0 +1,41 @@
{
"root": true,
"ignorePatterns": ["projects/**/*"],
"overrides": [
{
"files": ["*.ts"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:@angular-eslint/recommended",
"plugin:@angular-eslint/template/process-inline-templates"
],
"rules": {
"@angular-eslint/directive-selector": [
"error",
{
"type": "attribute",
"prefix": "app",
"style": "camelCase"
}
],
"@angular-eslint/component-selector": [
"error",
{
"type": "element",
"prefix": "app",
"style": "kebab-case"
}
]
}
},
{
"files": ["*.html"],
"extends": [
"plugin:@angular-eslint/template/recommended",
"plugin:@angular-eslint/template/accessibility"
],
"rules": {}
}
]
}

@ -0,0 +1,12 @@
{
"tabWidth": 2,
"useTabs": false,
"singleQuote": true,
"semi": true,
"bracketSpacing": true,
"arrowParens": "always",
"trailingComma": "es5",
"bracketSameLine": true,
"printWidth": 80,
"endOfLine": "auto"
}

@ -16,17 +16,10 @@
"outputPath": "dist/sandkasten",
"index": "src/index.html",
"browser": "src/main.ts",
"polyfills": [
"zone.js"
],
"polyfills": ["zone.js"],
"tsConfig": "tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.scss"],
"scripts": []
},
"configurations": {
@ -74,25 +67,24 @@
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"polyfills": [
"zone.js",
"zone.js/testing"
],
"polyfills": ["zone.js", "zone.js/testing"],
"tsConfig": "tsconfig.spec.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.scss"
],
"assets": ["src/favicon.ico", "src/assets"],
"styles": ["src/styles.scss"],
"scripts": []
}
},
"lint": {
"builder": "@angular-eslint/builder:lint",
"options": {
"lintFilePatterns": ["src/**/*.ts", "src/**/*.html"]
}
}
}
}
},
"cli": {
"analytics": false
"analytics": false,
"schematicCollections": ["@angular-eslint/schematics"]
}
}

3107
package-lock.json generated

File diff suppressed because it is too large Load Diff

@ -6,23 +6,25 @@
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
"test": "ng test",
"fmt": "prettier --write src",
"lint": "ng lint"
},
"private": true,
"dependencies": {
"@angular/animations": "^17.1.0",
"@angular/cdk": "^17.1.0",
"@angular/common": "^17.1.0",
"@angular/compiler": "^17.1.0",
"@angular/core": "^17.1.0",
"@angular/forms": "^17.1.0",
"@angular/platform-browser": "^17.1.0",
"@angular/platform-browser-dynamic": "^17.1.0",
"@angular/router": "^17.1.0",
"@angular/animations": "^17.1.1",
"@angular/cdk": "^17.1.1",
"@angular/common": "^17.1.1",
"@angular/compiler": "^17.1.1",
"@angular/core": "^17.1.1",
"@angular/forms": "^17.1.1",
"@angular/platform-browser": "^17.1.1",
"@angular/platform-browser-dynamic": "^17.1.1",
"@angular/router": "^17.1.1",
"@codemirror/lang-cpp": "^6.0.2",
"@codemirror/lang-javascript": "^6.2.1",
"@codemirror/state": "^6.4.0",
"@codemirror/view": "^6.23.0",
"@codemirror/view": "^6.23.1",
"@emailjs/browser": "^3.12.1",
"@ngx-translate/core": "^15.0.0",
"@ngx-translate/http-loader": "^8.0.0",
@ -35,16 +37,25 @@
"zone.js": "~0.14.3"
},
"devDependencies": {
"@angular-devkit/build-angular": "^17.1.0",
"@angular/cli": "~17.1.0",
"@angular/compiler-cli": "^17.1.0",
"@angular-devkit/build-angular": "^17.1.1",
"@angular-eslint/builder": "17.2.1",
"@angular-eslint/eslint-plugin": "17.2.1",
"@angular-eslint/eslint-plugin-template": "17.2.1",
"@angular-eslint/schematics": "17.2.1",
"@angular-eslint/template-parser": "17.2.1",
"@angular/cli": "~17.1.1",
"@angular/compiler-cli": "^17.1.1",
"@types/jasmine": "~5.1.4",
"@typescript-eslint/eslint-plugin": "^6.20.0",
"@typescript-eslint/parser": "^6.20.0",
"eslint": "^8.56.0",
"jasmine-core": "~5.1.1",
"karma": "~6.4.2",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.1",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"prettier": "^3.2.4",
"typescript": "~5.3.3"
}
}

@ -2,8 +2,8 @@ import { NgModule } from '@angular/core';
import { RouterModule, Routes } from '@angular/router';
import { EditorComponent } from './components/editor/editor.component';
import { LandingPageComponent } from './components/landing-page/landing-page.component';
import { DocumentationComponent } from "./components/documentation/documentation.component";
import { FormComponent } from "./components/form/form.component";
import { DocumentationComponent } from './components/documentation/documentation.component';
import { FormComponent } from './components/form/form.component';
import { TermsOfServiceComponent } from './components/terms-of-service/terms-of-service.component';
import { OurStoryComponent } from './components/our-story/our-story.component';
import { PrivacyPolicyComponent } from './components/privacy-policy/privacy-policy.component';
@ -16,11 +16,11 @@ const routes: Routes = [
{ path: 'contact', component: FormComponent },
{ path: 'our-story', component: OurStoryComponent },
{ path: 'terms-of-service', component: TermsOfServiceComponent },
{ path: 'privacy-policy', component: PrivacyPolicyComponent }
{ path: 'privacy-policy', component: PrivacyPolicyComponent },
];
@NgModule({
imports: [RouterModule.forRoot(routes)],
exports: [RouterModule]
exports: [RouterModule],
})
export class AppRoutingModule { }
export class AppRoutingModule {}

@ -1,16 +1,18 @@
<body [ngClass]="themeClass">
<div [ngClass]="themeClass" class="app">
<header>
<app-header [ngClass]="themeClass" [themeClass]="themeClass" [themeService]="themeService"></app-header>
</header>
<div [ngClass]="themeClass" class="app">
<header>
<app-header
[ngClass]="themeClass"
[themeClass]="themeClass"
[themeService]="themeService"></app-header>
</header>
<main>
<router-outlet></router-outlet>
</main>
<main>
<router-outlet></router-outlet>
</main>
<footer>
<app-footer></app-footer>
</footer>
</div>
<footer>
<app-footer></app-footer>
</footer>
</div>
</body>

@ -2,10 +2,11 @@
body {
overflow: hidden;
transition: background-color .3s ease-in-out, color .3s ease-in-out;
transition:
background-color 0.3s ease-in-out,
color 0.3s ease-in-out;
}
body.light-theme {
background-color: #ffffff;
color: #000000;

@ -3,9 +3,11 @@ import { RouterTestingModule } from '@angular/router/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(() => TestBed.configureTestingModule({
imports: [RouterTestingModule, AppComponent]
}));
beforeEach(() =>
TestBed.configureTestingModule({
imports: [RouterTestingModule, AppComponent],
})
);
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
@ -17,6 +19,8 @@ describe('AppComponent', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('.content span')?.textContent).toContain('sandkasten app is running!');
expect(compiled.querySelector('.content span')?.textContent).toContain(
'sandkasten app is running!'
);
});
});

@ -9,9 +9,8 @@ import { NgClass } from '@angular/common';
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
standalone: true,
imports: [NgClass, HeaderComponent, RouterOutlet, FooterComponent]
imports: [NgClass, HeaderComponent, RouterOutlet, FooterComponent],
})
export class AppComponent implements OnInit {
themeClass = 'light-theme';
@ -27,4 +26,4 @@ export class AppComponent implements OnInit {
toggleTheme() {
this.themeService.toggleDarkTheme();
}
}
}

@ -2,5 +2,5 @@ import { HttpClient } from '@angular/common/http';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}

@ -1,15 +1,36 @@
<div class="documentation">
<h1 class="title">Documentation</h1>
<div class="how_it_works">
<h2 class="question">Comment fonctionne Sandkasten ?</h2>
<span class="text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce in sagittis quam. Suspendisse eget posuere ligula, ut pretium sapien. Nulla vitae aliquam risus. Nulla facilisi. Cras sodales placerat elit, at ultricies dolor fringilla eget. Nullam sodales eros eget nisl dignissim, vel accumsan ligula euismod. Praesent congue placerat ullamcorper. Mauris at ante porttitor, maximus magna at, convallis velit.</span>
</div>
<div class="code_execution">
<h2 class="question">Exécution du code :</h2>
<span class="text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce in sagittis quam. Suspendisse eget posuere ligula, ut pretium sapien. Nulla vitae aliquam risus. Nulla facilisi. Cras sodales placerat elit, at ultricies dolor fringilla eget. Nullam sodales eros eget nisl dignissim, vel accumsan ligula euismod. Praesent congue placerat ullamcorper. Mauris at ante porttitor, maximus magna at, convallis velit.</span>
</div>
<div class="code_transfert">
<h2 class="question">Transmission du code :</h2>
<span class="text">Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce in sagittis quam. Suspendisse eget posuere ligula, ut pretium sapien. Nulla vitae aliquam risus. Nulla facilisi. Cras sodales placerat elit, at ultricies dolor fringilla eget. Nullam sodales eros eget nisl dignissim, vel accumsan ligula euismod. Praesent congue placerat ullamcorper. Mauris at ante porttitor, maximus magna at, convallis velit.</span>
</div>
<h1 class="title">Documentation</h1>
<div class="how_it_works">
<h2 class="question">Comment fonctionne Sandkasten ?</h2>
<span class="text"
>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce in
sagittis quam. Suspendisse eget posuere ligula, ut pretium sapien. Nulla
vitae aliquam risus. Nulla facilisi. Cras sodales placerat elit, at
ultricies dolor fringilla eget. Nullam sodales eros eget nisl dignissim,
vel accumsan ligula euismod. Praesent congue placerat ullamcorper. Mauris
at ante porttitor, maximus magna at, convallis velit.</span
>
</div>
<div class="code_execution">
<h2 class="question">Exécution du code :</h2>
<span class="text"
>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce in
sagittis quam. Suspendisse eget posuere ligula, ut pretium sapien. Nulla
vitae aliquam risus. Nulla facilisi. Cras sodales placerat elit, at
ultricies dolor fringilla eget. Nullam sodales eros eget nisl dignissim,
vel accumsan ligula euismod. Praesent congue placerat ullamcorper. Mauris
at ante porttitor, maximus magna at, convallis velit.</span
>
</div>
<div class="code_transfert">
<h2 class="question">Transmission du code :</h2>
<span class="text"
>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce in
sagittis quam. Suspendisse eget posuere ligula, ut pretium sapien. Nulla
vitae aliquam risus. Nulla facilisi. Cras sodales placerat elit, at
ultricies dolor fringilla eget. Nullam sodales eros eget nisl dignissim,
vel accumsan ligula euismod. Praesent congue placerat ullamcorper. Mauris
at ante porttitor, maximus magna at, convallis velit.</span
>
</div>
</div>

@ -1,23 +1,25 @@
.documentation {
display: flex;
flex-direction: column;
padding: 4rem 8rem;
.title {
font-size: 3rem;
text-align: center;
}
.how_it_works,
.code_execution,
.code_transfert {
display: flex;
flex-direction: column;
padding: 4rem 8rem;
.title {
font-size: 3rem;
text-align: center;
.question {
font-size: 2rem;
}
.how_it_works, .code_execution, .code_transfert {
display: flex;
flex-direction: column;
.question {
font-size: 2rem;
}
.text {
font-size: 1.25rem;
}
.text {
font-size: 1.25rem;
}
}
}
}

@ -8,7 +8,7 @@ describe('DocumentationComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [DocumentationComponent]
imports: [DocumentationComponent],
});
fixture = TestBed.createComponent(DocumentationComponent);
component = fixture.componentInstance;

@ -4,8 +4,6 @@ import { Component } from '@angular/core';
selector: 'app-documentation',
templateUrl: './documentation.component.html',
styleUrls: ['./documentation.component.scss'],
standalone: true
standalone: true,
})
export class DocumentationComponent {
}
export class DocumentationComponent {}

@ -2,8 +2,7 @@
<div>
<codemirror6-editor
[(ngModel)]="editorContent"
[extensions]="extensions"
></codemirror6-editor>
[extensions]="extensions"></codemirror6-editor>
</div>
<pre [innerHTML]="resultContent | safeHTML"></pre>

@ -8,8 +8,8 @@ describe('EditorComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [EditorComponent]
});
imports: [EditorComponent],
});
fixture = TestBed.createComponent(EditorComponent);
component = fixture.componentInstance;
fixture.detectChanges();

@ -9,68 +9,72 @@ import { SafeHTMLPipe } from '../../safe-html.pipe';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
@Component({
selector: "app-editor",
templateUrl: "./editor.component.html",
styleUrls: ["./editor.component.scss"],
standalone: true,
imports: [
CodeMirrorComponent,
ReactiveFormsModule,
FormsModule,
SafeHTMLPipe,
],
selector: 'app-editor',
templateUrl: './editor.component.html',
styleUrls: ['./editor.component.scss'],
standalone: true,
imports: [
CodeMirrorComponent,
ReactiveFormsModule,
FormsModule,
SafeHTMLPipe,
],
})
export class EditorComponent {
isLoaded: boolean = false; // Pour vérifier si le chargement est terminé
readonly languages: LanguageDescription[] = LANGUAGES;
// Mode par défaut
private _selectedLanguage = this.languages.find((lang) => lang.name === "JavaScript")!;
private _selectedLanguage = this.languages.find(
(lang) => lang.name === 'JavaScript'
)!;
get selectedLanguage(): LanguageDescription {
return this._selectedLanguage;
}
set selectedLanguage(value: LanguageDescription) {
this._selectedLanguage = value;
if (value.name in CODE_DEFAULTS) {
this.editorContent = CODE_DEFAULTS[value.name as keyof typeof CODE_DEFAULTS];
this.editorContent =
CODE_DEFAULTS[value.name as keyof typeof CODE_DEFAULTS];
}
this.selectedLanguage.load().then((language) => {
this.codemirror.editor?.dispatch({
effects: this.languageCompartment.reconfigure(language)
effects: this.languageCompartment.reconfigure(language),
});
});
}
// Contenu de l'éditeur que l'on passera au serveur
editorContent: string = CODE_DEFAULTS[this.selectedLanguage.name as keyof typeof CODE_DEFAULTS];
resultContent: string = "";
editorContent: string =
CODE_DEFAULTS[this.selectedLanguage.name as keyof typeof CODE_DEFAULTS];
resultContent: string = '';
// Message d'erreur
errorMessage: string = "";
errorMessage: string = '';
@ViewChild(CodeMirrorComponent) private codemirror!: CodeMirrorComponent;
private readonly languageCompartment = new Compartment();
protected readonly extensions: Extension[] = [
basicSetup,
this.languageCompartment.of(this.selectedLanguage.support!)
this.languageCompartment.of(this.selectedLanguage.support!),
];
constructor(
private codeExecutionService: CodeExecutionService
) {
}
constructor(private codeExecutionService: CodeExecutionService) {}
// Efface le contenu de l'éditeur
clear(): void {
this.editorContent = "";
this.editorContent = '';
}
onRunButtonClicked() {
// Le code à exécuter est le contenu de l'éditeur
const codeToExecute = this.editorContent;
this.codeExecutionService.executeCode(codeToExecute, this.selectedLanguage.name);
this.codeExecutionService.executeCode(
codeToExecute,
this.selectedLanguage.name
);
this.resultContent = '';
}
@ -78,7 +82,7 @@ export class EditorComponent {
loadFromFile(event: Event) {
const file = (event.target as HTMLInputElement).files![0];
for (const language of this.languages) {
if (language.extensions.some(ext => file.name.endsWith(`.${ext}`))) {
if (language.extensions.some((ext) => file.name.endsWith(`.${ext}`))) {
this.selectedLanguage = language;
const reader = new FileReader();
reader.onload = (event) => {
@ -89,9 +93,8 @@ export class EditorComponent {
return;
}
}
const extensions = this.languages.flatMap(lang => lang.extensions);
this.errorMessage =
`Unsupported language. Please select one of the following languages: ${extensions.join(', ')}.`;
const extensions = this.languages.flatMap((lang) => lang.extensions);
this.errorMessage = `Unsupported language. Please select one of the following languages: ${extensions.join(', ')}.`;
console.error(this.errorMessage);
}

@ -1,56 +1,96 @@
<head>
<link href="https://fonts.googleapis.com/css2?family=Podkova:wght@400;700&display=swap" rel="stylesheet">
<link
href="https://fonts.googleapis.com/css2?family=Podkova:wght@400;700&display=swap"
rel="stylesheet" />
</head>
<div class="footer">
<!--Logo and copyrights-->
<div class="rights">
<img class="sandkasten-logo" routerLink="" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }"
[src]="sandkasten_logo" alt="Logo-Sandkasten" />
<div class="title">Sandkasten</div>
<div class="copyright">{{ 'FooterPage.Rights' | translate}}</div>
</div>
<!--Navigation-->
<div class="navigation">
<div class="about">
<span class="title">{{ 'FooterPage.About' | translate}}</span>
<div class="links">
<!-- TODO - Add the router links -->
<a routerLink="our-story" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">{{
'FooterPage.Story' | translate}}</a>
<a routerLink="" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">{{
'FooterPage.Contact' | translate}}</a>
</div>
</div>
<!--Logo and copyrights-->
<div class="rights">
<img
class="sandkasten-logo"
routerLink=""
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
[src]="sandkasten_logo"
alt="Logo-Sandkasten" />
<div class="title">Sandkasten</div>
<div class="copyright">{{ 'FooterPage.Rights' | translate }}</div>
</div>
<div class="legals">
<span class="title">{{ 'FooterPage.Legal' | translate}}</span>
<div class="links">
<a routerLink="terms-of-service" routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }">{{ 'FooterPage.Terms' | translate}}</a>
<a routerLink="privacy-policy" routerLinkActive="active" [routerLinkActiveOptions]="{ exact: true }">{{
'FooterPage.Privacy' | translate}}</a>
</div>
</div>
<!--Navigation-->
<div class="navigation">
<div class="about">
<span class="title">{{ 'FooterPage.About' | translate }}</span>
<div class="links">
<!-- TODO - Add the router links -->
<a
routerLink="our-story"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>{{ 'FooterPage.Story' | translate }}</a
>
<a
routerLink=""
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>{{ 'FooterPage.Contact' | translate }}</a
>
</div>
</div>
<!--Socials-->
<div class="socials">
<a href="https://twitter.com/Sandkasten3a">
<img class="tiwtter-logo" class="image" routerLink="" routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }" [src]="twitter_logo" alt="Logo-Twitter" />
</a>
<div class="legals">
<span class="title">{{ 'FooterPage.Legal' | translate }}</span>
<div class="links">
<a
routerLink="terms-of-service"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>{{ 'FooterPage.Terms' | translate }}</a
>
<a
routerLink="privacy-policy"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>{{ 'FooterPage.Privacy' | translate }}</a
>
</div>
</div>
</div>
<a href="https://instagram.com">
<img class="instagram-logo" class="image" routerLink="" routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }" [src]="instagram_logo" alt="Logo-Instagram" />
</a>
<!--Socials-->
<div class="socials">
<a href="https://twitter.com/Sandkasten3a">
<img
class="tiwtter-logo"
class="image"
routerLink=""
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
[src]="twitter_logo"
alt="Logo-Twitter" />
</a>
<a href="https://www.facebook.com/profile.php?id=61555217444337">
<img class="facebook-logo" class="image" routerLink="" routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }" [src]="facebook_logo" alt="Logo-Facebook" />
</a>
</div>
<a href="https://instagram.com">
<img
class="instagram-logo"
class="image"
routerLink=""
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
[src]="instagram_logo"
alt="Logo-Instagram" />
</a>
</div>
<a href="https://www.facebook.com/profile.php?id=61555217444337">
<img
class="facebook-logo"
class="image"
routerLink=""
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
[src]="facebook_logo"
alt="Logo-Facebook" />
</a>
</div>
</div>

@ -1,6 +1,6 @@
.footer {
background-color: #494b92;
padding: .5rem 1rem;
padding: 0.5rem 1rem;
display: flex;
flex-direction: row;
justify-content: space-between;
@ -10,8 +10,8 @@
.rights {
display: grid;
grid: 'logo title' auto 'copyright copyright' / auto 1fr;
gap: .5rem;
color: #FFFFFF;
gap: 0.5rem;
color: #ffffff;
.sandkasten-logo {
grid-area: logo;
@ -48,27 +48,26 @@
.legals {
display: flex;
flex-direction: column;
gap: .5rem;
gap: 0.5rem;
.title {
color: #FFFFFF;
color: #ffffff;
text-shadow: 0 4px 4px rgba(0, 0, 0, 0.25);
}
.links {
display: flex;
flex-direction: column;
gap: .25rem;
gap: 0.25rem;
>a {
> a {
color: #818181;
text-decoration: none;
transition: color .3s ease;
transition: color 0.3s ease;
}
:hover {
color: #FFFFFF;
color: #ffffff;
}
}
}
@ -82,4 +81,4 @@
aspect-ratio: 1;
padding-right: 10px;
}
}
}

@ -8,8 +8,8 @@ describe('FooterComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [FooterComponent]
});
imports: [FooterComponent],
});
fixture = TestBed.createComponent(FooterComponent);
component = fixture.componentInstance;
fixture.detectChanges();

@ -1,4 +1,4 @@
import { Component, OnInit } from '@angular/core';
import { Component } from '@angular/core';
import { TranslateModule } from '@ngx-translate/core';
import { RouterLink, RouterLinkActive } from '@angular/router';
@ -7,12 +7,11 @@ import { RouterLink, RouterLinkActive } from '@angular/router';
templateUrl: './footer.component.html',
styleUrls: ['./footer.component.scss'],
standalone: true,
imports: [RouterLink, RouterLinkActive, TranslateModule]
imports: [RouterLink, RouterLinkActive, TranslateModule],
})
export class FooterComponent {
sandkasten_logo: string = 'assets/img/logo.png';
twitter_logo: string = 'assets/img/twitter.svg';
instagram_logo: string = 'assets/img/instagram.svg';
facebook_logo: string = 'assets/img/facebook.svg';
}

@ -1,31 +1,58 @@
<div class="contact">
<h1 class="title">Nous contacter</h1>
<h1 class="title">Nous contacter</h1>
<div [formGroup]="form" class="form">
<div>
<!-- <label for="name">Nom</label>-->
<input type="text" id="name" name="name" placeholder="Votre nom" required formControlName="from_name">
</div>
<div>
<!-- <label for="email">Email</label>-->
<input type="email" id="email" name="email" placeholder="Votre email" required formControlName="from_email">
</div>
<div [formGroup]="form" class="form">
<div>
<!-- <label for="name">Nom</label>-->
<input
type="text"
id="name"
name="name"
placeholder="Votre nom"
required
formControlName="from_name" />
</div>
<div>
<!-- <label for="subject">Sujet</label>-->
<input type="text" id="subject" name="subject" placeholder="Sujet" required formControlName="subject">
</div>
<div>
<!-- <label for="email">Email</label>-->
<input
type="email"
id="email"
name="email"
placeholder="Votre email"
required
formControlName="from_email" />
</div>
<div>
<!-- <label for="message">Message</label>-->
<textarea id="message" name="message" placeholder="Votre message" required formControlName="message"></textarea>
</div>
<div>
<!-- <label for="subject">Sujet</label>-->
<input
type="text"
id="subject"
name="subject"
placeholder="Sujet"
required
formControlName="subject" />
</div>
<div class="submit_button">
<button class="submit_btn" type="submit" (click)="send()" [disabled]="!form.valid">Envoyer</button>
</div>
<div>
<!-- <label for="message">Message</label>-->
<textarea
id="message"
name="message"
placeholder="Votre message"
required
formControlName="message"></textarea>
</div>
<div class="submit_button">
<button
class="submit_btn"
type="submit"
(click)="send()"
[disabled]="!form.valid">
Envoyer
</button>
</div>
</div>
</div>

@ -1,53 +1,53 @@
.contact {
display: flex;
flex-direction: column;
align-items: center;
padding: 2rem 8rem;
.title {
font-size: 2rem;
text-align: center;
}
.form {
display: flex;
flex-direction: column;
align-items: center;
padding: 2rem 8rem;
.title {
font-size: 2rem;
text-align: center;
gap: 2rem;
width: 100%;
max-width: 600px;
& input,
& textarea {
width: 100%;
min-height: 2rem;
}
.form {
display: flex;
flex-direction: column;
gap: 2rem;
width: 100%;
max-width: 600px;
& input, & textarea {
width: 100%;
min-height: 2rem;
}
& textarea {
resize: none;
height: 10rem;
}
.submit_button {
display: flex;
justify-content: center;
& textarea {
resize: none;
height: 10rem;
}
& button {
border: none;
background-color: #1976D2;
color: white;
border-radius: 10px;
width: 80%;
height: 2.5rem;
.submit_button {
display: flex;
justify-content: center;
text-transform: uppercase;
cursor: pointer;
& button {
border: none;
background-color: #1976d2;
color: white;
border-radius: 10px;
width: 80%;
height: 2.5rem;
transition: scale .3s ease-in-out;
text-transform: uppercase;
cursor: pointer;
&:hover {
scale: 1.05;
}
}
transition: scale 0.3s ease-in-out;
&:hover {
scale: 1.05;
}
}
}
}
}

@ -8,8 +8,8 @@ describe('FormComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [FormComponent]
});
imports: [FormComponent],
});
fixture = TestBed.createComponent(FormComponent);
component = fixture.componentInstance;
fixture.detectChanges();
@ -19,4 +19,3 @@ describe('FormComponent', () => {
expect(component).toBeTruthy();
});
});

@ -8,7 +8,7 @@ import emailjs from '@emailjs/browser';
templateUrl: './form.component.html',
styleUrls: ['./form.component.scss'],
standalone: true,
imports: [ReactiveFormsModule]
imports: [ReactiveFormsModule],
})
export class FormComponent {
form: FormGroup;
@ -19,24 +19,28 @@ export class FormComponent {
to_name: ['Sandkasten'],
from_email: [''],
subject: [''],
message: ['']
message: [''],
});
}
async send() {
emailjs.init('cLIr6GuwhkrH1JFio');
try {
let response = await emailjs.send("service_rvmwu94", "template_q0spe61", {
from_name: this.form.value.from_name,
to_name: this.form.value.to_name,
message: this.form.value.message,
from_email: this.form.value.from_email,
subject: this.form.value.subject,
});
const response = await emailjs.send(
'service_rvmwu94',
'template_q0spe61',
{
from_name: this.form.value.from_name,
to_name: this.form.value.to_name,
message: this.form.value.message,
from_email: this.form.value.from_email,
subject: this.form.value.subject,
}
);
console.log("Envoi du message:", response);
console.log('Envoi du message:', response);
alert("Message envoyé avec succès !");
alert('Message envoyé avec succès !');
this.form.reset();
} catch (error) {
console.error("Erreur lors de l'envoi du message:", error);

@ -1,138 +1,172 @@
<div class="header" role="banner" [ngClass]="themeClass">
<div class="left_part">
<div class="left_part__logo--container">
<img class="left_part__logo--sandkasten"
routerLink=""
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
[src]="sandkasten_logo" alt="Logo-Sandkasten" />
</div>
</div>
<div class="left_part">
<div class="left_part__logo--container">
<a routerLink="/" routerLinkActive="active">
<img
class="left_part__logo--sandkasten"
ngSrc="assets/img/logo.png"
width="64"
height="64"
alt="Logo Sandkasten" />
</a>
</div>
</div>
<div class="right_part">
<div class="right_part--menu_mobile" (click)="openCloseMenu(); $event.stopPropagation();">
Menu
</div>
<div class="right_part">
<div
class="right_part--menu_mobile"
(click)="openCloseMenu()"
(keydown)="openCloseMenu()"
tabindex="0">
Menu
</div>
<nav class="right_part--menu">
<a
routerLink="editor"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>{{ 'HeaderPage.Editor' | translate }}</a>
<nav class="right_part--menu">
<a
routerLink="editor"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>{{ 'HeaderPage.Editor' | translate }}</a
>
<a
routerLink="documentation"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>{{ 'HeaderPage.Documentation' | translate }}</a>
<a
routerLink="documentation"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>{{ 'HeaderPage.Documentation' | translate }}</a
>
<a
routerLink="contact"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>{{ 'HeaderPage.Contact' | translate }}</a>
</nav>
<a
routerLink="contact"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>{{ 'HeaderPage.Contact' | translate }}</a
>
</nav>
<div class="right_part--bottom">
<div class="right_part--toggles">
<div class="wrapper">
<div class="toggle">
<input class="toggle-input" type="checkbox" (click)="toggleTheme()" [checked]="isCheck"/>
<div class="toggle-bg"></div>
<div class="toggle-switch">
<div class="toggle-switch-figure"></div>
<div class="toggle-switch-figureAlt"></div>
</div>
</div>
</div>
<div class="right_part--bottom">
<div class="right_part--toggles">
<div class="wrapper">
<div class="toggle">
<input
class="toggle-input"
type="checkbox"
(click)="toggleTheme()"
[checked]="isCheck" />
<div class="toggle-bg"></div>
<div class="toggle-switch">
<div class="toggle-switch-figure"></div>
<div class="toggle-switch-figureAlt"></div>
</div>
</div>
</div>
<select class="right_part__lang" (change)="onLanguageChange($event)">
<option value="fr">🇫🇷 Français</option>
<option value="en">🇬🇧 English</option>
</select>
</div>
<select class="right_part__lang" (change)="onLanguageChange($event)">
<option value="fr">🇫🇷 Français</option>
<option value="en">🇬🇧 English</option>
</select>
</div>
<div class="right_part__connexion">
<!--Login-->
<div class="right_part__connexion--login">
<span>Log In</span>
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_67_222)">
<path d="M15 28.8462C11.4456 28.8462 8.214 27.495 5.7624 25.2936C7.1148 22.0764 10.2576 20.3334 14.9862 20.3334C19.7196 20.3334 22.8696 22.1598 24.231 25.3842C21.7806 27.5796 18.5484 28.8462 15 28.8462ZM15.1668 7.6662C18.123 7.6662 20.3334 9.9534 20.3334 12.993C20.3334 16.119 18.0084 18.6666 15.1668 18.6666C12.3252 18.6666 10.0002 16.119 10.0002 12.993C10.0002 9.9534 12.2106 7.6662 15.1668 7.6662ZM15 0C6.7158 0 0 6.7158 0 15C0 15.549 0.0336 16.0896 0.0912 16.623C0.1104 16.8 0.1458 16.9716 0.171 17.1468C0.222 17.5002 0.2748 17.8524 0.3498 18.1974C0.3936 18.4002 0.4512 18.5964 0.5034 18.7956C0.5844 19.1046 0.6672 19.4118 0.7668 19.713C0.8352 19.9182 0.9126 20.118 0.9888 20.319C1.0968 20.6046 1.2102 20.886 1.335 21.1626C1.4244 21.3612 1.5198 21.5568 1.6182 21.7506C1.7532 22.0182 1.896 22.2804 2.0466 22.5384C2.1558 22.7256 2.2656 22.9098 2.3826 23.0916C2.5458 23.3454 2.7186 23.5908 2.8962 23.8338C3.0204 24.0042 3.1422 24.1746 3.2736 24.3384C3.4686 24.5832 3.6762 24.816 3.8856 25.0476C4.0176 25.194 4.1448 25.344 4.2828 25.4844C4.5258 25.7334 4.7826 25.965 5.0418 26.196C5.1456 26.2884 5.2392 26.391 5.346 26.481L5.3484 26.4744C8.04719 28.7544 11.467 30.0036 15 30C18.5284 30.004 21.9442 28.7581 24.6414 26.4834C24.6421 26.4854 24.6427 26.4874 24.6432 26.4894C24.7464 26.403 24.8376 26.304 24.9372 26.2146C25.2024 25.9794 25.4652 25.7424 25.713 25.4892C25.8498 25.35 25.9752 25.2018 26.106 25.0572C26.3172 24.8238 26.5266 24.5892 26.7228 24.3426C26.8536 24.1794 26.9754 24.009 27.099 23.8398C27.2772 23.5968 27.4512 23.3502 27.6144 23.0958C28.0087 22.4779 28.3592 21.8331 28.6632 21.1662C28.788 20.8896 28.902 20.6082 29.0106 20.3226C29.0868 20.121 29.1642 19.9212 29.232 19.7154C29.3322 19.4142 29.415 19.107 29.496 18.7974C29.5482 18.5982 29.6058 18.402 29.6496 18.1998C29.7252 17.8542 29.778 17.5014 29.829 17.1474C29.8542 16.9722 29.8896 16.8012 29.9088 16.6242C29.9658 16.0902 30 15.5496 30 15C30 6.7158 23.2842 0 15 0Z" fill="#605FFC"/>
</g>
<defs>
<clipPath id="clip0_67_222">
<rect width="30" height="30" fill="white"/>
</clipPath>
</defs>
</svg>
</div>
<!--Register-->
<div class="right_part__connexion--register">
<span>Register Now</span>
</div>
</div>
</div>
</div>
<div class="mobile_menu" [ngClass]="{'opened': isMenuOpen}" #menuRef>
<div class="mobile_menu--wrapper">
<div class="mobile_menu--toggles">
<div class="wrapper">
<div class="toggle">
<input class="toggle-input" type="checkbox" (click)="toggleTheme()" [checked]="isCheck"/>
<div class="toggle-bg"></div>
<div class="toggle-switch">
<div class="toggle-switch-figure"></div>
<div class="toggle-switch-figureAlt"></div>
</div>
</div>
</div>
<select class="right_part__lang" (change)="onLanguageChange($event)">
<option value="fr">🇫🇷 Français</option>
<option value="en">🇬🇧 English</option>
</select>
</div>
<nav class="mobile_menu--menu">
<a
routerLink="editor"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>{{ 'HeaderPage.Editor' | translate }}</a>
<div class="right_part__connexion">
<!--Login-->
<div class="right_part__connexion--login">
<span>Log In</span>
<svg
width="30"
height="30"
viewBox="0 0 30 30"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_67_222)">
<path
d="M15 28.8462C11.4456 28.8462 8.214 27.495 5.7624 25.2936C7.1148 22.0764 10.2576 20.3334 14.9862 20.3334C19.7196 20.3334 22.8696 22.1598 24.231 25.3842C21.7806 27.5796 18.5484 28.8462 15 28.8462ZM15.1668 7.6662C18.123 7.6662 20.3334 9.9534 20.3334 12.993C20.3334 16.119 18.0084 18.6666 15.1668 18.6666C12.3252 18.6666 10.0002 16.119 10.0002 12.993C10.0002 9.9534 12.2106 7.6662 15.1668 7.6662ZM15 0C6.7158 0 0 6.7158 0 15C0 15.549 0.0336 16.0896 0.0912 16.623C0.1104 16.8 0.1458 16.9716 0.171 17.1468C0.222 17.5002 0.2748 17.8524 0.3498 18.1974C0.3936 18.4002 0.4512 18.5964 0.5034 18.7956C0.5844 19.1046 0.6672 19.4118 0.7668 19.713C0.8352 19.9182 0.9126 20.118 0.9888 20.319C1.0968 20.6046 1.2102 20.886 1.335 21.1626C1.4244 21.3612 1.5198 21.5568 1.6182 21.7506C1.7532 22.0182 1.896 22.2804 2.0466 22.5384C2.1558 22.7256 2.2656 22.9098 2.3826 23.0916C2.5458 23.3454 2.7186 23.5908 2.8962 23.8338C3.0204 24.0042 3.1422 24.1746 3.2736 24.3384C3.4686 24.5832 3.6762 24.816 3.8856 25.0476C4.0176 25.194 4.1448 25.344 4.2828 25.4844C4.5258 25.7334 4.7826 25.965 5.0418 26.196C5.1456 26.2884 5.2392 26.391 5.346 26.481L5.3484 26.4744C8.04719 28.7544 11.467 30.0036 15 30C18.5284 30.004 21.9442 28.7581 24.6414 26.4834C24.6421 26.4854 24.6427 26.4874 24.6432 26.4894C24.7464 26.403 24.8376 26.304 24.9372 26.2146C25.2024 25.9794 25.4652 25.7424 25.713 25.4892C25.8498 25.35 25.9752 25.2018 26.106 25.0572C26.3172 24.8238 26.5266 24.5892 26.7228 24.3426C26.8536 24.1794 26.9754 24.009 27.099 23.8398C27.2772 23.5968 27.4512 23.3502 27.6144 23.0958C28.0087 22.4779 28.3592 21.8331 28.6632 21.1662C28.788 20.8896 28.902 20.6082 29.0106 20.3226C29.0868 20.121 29.1642 19.9212 29.232 19.7154C29.3322 19.4142 29.415 19.107 29.496 18.7974C29.5482 18.5982 29.6058 18.402 29.6496 18.1998C29.7252 17.8542 29.778 17.5014 29.829 17.1474C29.8542 16.9722 29.8896 16.8012 29.9088 16.6242C29.9658 16.0902 30 15.5496 30 15C30 6.7158 23.2842 0 15 0Z"
fill="#605FFC" />
</g>
<defs>
<clipPath id="clip0_67_222">
<rect width="30" height="30" fill="white" />
</clipPath>
</defs>
</svg>
</div>
<!--Register-->
<div class="right_part__connexion--register">
<span>Register Now</span>
</div>
</div>
</div>
</div>
<div class="mobile_menu" [ngClass]="{ opened: isMenuOpen }" #menuRef>
<div class="mobile_menu--wrapper">
<div class="mobile_menu--toggles">
<div class="wrapper">
<div class="toggle">
<input
class="toggle-input"
type="checkbox"
(click)="toggleTheme()"
[checked]="isCheck" />
<div class="toggle-bg"></div>
<div class="toggle-switch">
<div class="toggle-switch-figure"></div>
<div class="toggle-switch-figureAlt"></div>
</div>
</div>
</div>
<select class="right_part__lang" (change)="onLanguageChange($event)">
<option value="fr">🇫🇷 Français</option>
<option value="en">🇬🇧 English</option>
</select>
</div>
<nav class="mobile_menu--menu">
<a
routerLink="editor"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>{{ 'HeaderPage.Editor' | translate }}</a
>
<a
routerLink="documentation"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>{{ 'HeaderPage.Documentation' | translate }}</a>
<a
routerLink="documentation"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>{{ 'HeaderPage.Documentation' | translate }}</a
>
<a
routerLink="contact"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>{{ 'HeaderPage.Contact' | translate }}</a>
</nav>
<div class="mobile_menu__connexion">
<!--Login-->
<div class="right_part__connexion--login">
<span>Log In</span>
<svg width="30" height="30" viewBox="0 0 30 30" fill="none" xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_67_222)">
<path d="M15 28.8462C11.4456 28.8462 8.214 27.495 5.7624 25.2936C7.1148 22.0764 10.2576 20.3334 14.9862 20.3334C19.7196 20.3334 22.8696 22.1598 24.231 25.3842C21.7806 27.5796 18.5484 28.8462 15 28.8462ZM15.1668 7.6662C18.123 7.6662 20.3334 9.9534 20.3334 12.993C20.3334 16.119 18.0084 18.6666 15.1668 18.6666C12.3252 18.6666 10.0002 16.119 10.0002 12.993C10.0002 9.9534 12.2106 7.6662 15.1668 7.6662ZM15 0C6.7158 0 0 6.7158 0 15C0 15.549 0.0336 16.0896 0.0912 16.623C0.1104 16.8 0.1458 16.9716 0.171 17.1468C0.222 17.5002 0.2748 17.8524 0.3498 18.1974C0.3936 18.4002 0.4512 18.5964 0.5034 18.7956C0.5844 19.1046 0.6672 19.4118 0.7668 19.713C0.8352 19.9182 0.9126 20.118 0.9888 20.319C1.0968 20.6046 1.2102 20.886 1.335 21.1626C1.4244 21.3612 1.5198 21.5568 1.6182 21.7506C1.7532 22.0182 1.896 22.2804 2.0466 22.5384C2.1558 22.7256 2.2656 22.9098 2.3826 23.0916C2.5458 23.3454 2.7186 23.5908 2.8962 23.8338C3.0204 24.0042 3.1422 24.1746 3.2736 24.3384C3.4686 24.5832 3.6762 24.816 3.8856 25.0476C4.0176 25.194 4.1448 25.344 4.2828 25.4844C4.5258 25.7334 4.7826 25.965 5.0418 26.196C5.1456 26.2884 5.2392 26.391 5.346 26.481L5.3484 26.4744C8.04719 28.7544 11.467 30.0036 15 30C18.5284 30.004 21.9442 28.7581 24.6414 26.4834C24.6421 26.4854 24.6427 26.4874 24.6432 26.4894C24.7464 26.403 24.8376 26.304 24.9372 26.2146C25.2024 25.9794 25.4652 25.7424 25.713 25.4892C25.8498 25.35 25.9752 25.2018 26.106 25.0572C26.3172 24.8238 26.5266 24.5892 26.7228 24.3426C26.8536 24.1794 26.9754 24.009 27.099 23.8398C27.2772 23.5968 27.4512 23.3502 27.6144 23.0958C28.0087 22.4779 28.3592 21.8331 28.6632 21.1662C28.788 20.8896 28.902 20.6082 29.0106 20.3226C29.0868 20.121 29.1642 19.9212 29.232 19.7154C29.3322 19.4142 29.415 19.107 29.496 18.7974C29.5482 18.5982 29.6058 18.402 29.6496 18.1998C29.7252 17.8542 29.778 17.5014 29.829 17.1474C29.8542 16.9722 29.8896 16.8012 29.9088 16.6242C29.9658 16.0902 30 15.5496 30 15C30 6.7158 23.2842 0 15 0Z" fill="#605FFC"/>
</g>
<defs>
<clipPath id="clip0_67_222">
<rect width="30" height="30" fill="white"/>
</clipPath>
</defs>
</svg>
</div>
<!--Register-->
<div class="right_part__connexion--register">
<span>Register Now</span>
</div>
</div>
</div>
</div>
<a
routerLink="contact"
routerLinkActive="active"
[routerLinkActiveOptions]="{ exact: true }"
>{{ 'HeaderPage.Contact' | translate }}</a
>
</nav>
<div class="mobile_menu__connexion">
<!--Login-->
<div class="right_part__connexion--login">
<span>Log In</span>
<svg
width="30"
height="30"
viewBox="0 0 30 30"
fill="none"
xmlns="http://www.w3.org/2000/svg">
<g clip-path="url(#clip0_67_222)">
<path
d="M15 28.8462C11.4456 28.8462 8.214 27.495 5.7624 25.2936C7.1148 22.0764 10.2576 20.3334 14.9862 20.3334C19.7196 20.3334 22.8696 22.1598 24.231 25.3842C21.7806 27.5796 18.5484 28.8462 15 28.8462ZM15.1668 7.6662C18.123 7.6662 20.3334 9.9534 20.3334 12.993C20.3334 16.119 18.0084 18.6666 15.1668 18.6666C12.3252 18.6666 10.0002 16.119 10.0002 12.993C10.0002 9.9534 12.2106 7.6662 15.1668 7.6662ZM15 0C6.7158 0 0 6.7158 0 15C0 15.549 0.0336 16.0896 0.0912 16.623C0.1104 16.8 0.1458 16.9716 0.171 17.1468C0.222 17.5002 0.2748 17.8524 0.3498 18.1974C0.3936 18.4002 0.4512 18.5964 0.5034 18.7956C0.5844 19.1046 0.6672 19.4118 0.7668 19.713C0.8352 19.9182 0.9126 20.118 0.9888 20.319C1.0968 20.6046 1.2102 20.886 1.335 21.1626C1.4244 21.3612 1.5198 21.5568 1.6182 21.7506C1.7532 22.0182 1.896 22.2804 2.0466 22.5384C2.1558 22.7256 2.2656 22.9098 2.3826 23.0916C2.5458 23.3454 2.7186 23.5908 2.8962 23.8338C3.0204 24.0042 3.1422 24.1746 3.2736 24.3384C3.4686 24.5832 3.6762 24.816 3.8856 25.0476C4.0176 25.194 4.1448 25.344 4.2828 25.4844C4.5258 25.7334 4.7826 25.965 5.0418 26.196C5.1456 26.2884 5.2392 26.391 5.346 26.481L5.3484 26.4744C8.04719 28.7544 11.467 30.0036 15 30C18.5284 30.004 21.9442 28.7581 24.6414 26.4834C24.6421 26.4854 24.6427 26.4874 24.6432 26.4894C24.7464 26.403 24.8376 26.304 24.9372 26.2146C25.2024 25.9794 25.4652 25.7424 25.713 25.4892C25.8498 25.35 25.9752 25.2018 26.106 25.0572C26.3172 24.8238 26.5266 24.5892 26.7228 24.3426C26.8536 24.1794 26.9754 24.009 27.099 23.8398C27.2772 23.5968 27.4512 23.3502 27.6144 23.0958C28.0087 22.4779 28.3592 21.8331 28.6632 21.1662C28.788 20.8896 28.902 20.6082 29.0106 20.3226C29.0868 20.121 29.1642 19.9212 29.232 19.7154C29.3322 19.4142 29.415 19.107 29.496 18.7974C29.5482 18.5982 29.6058 18.402 29.6496 18.1998C29.7252 17.8542 29.778 17.5014 29.829 17.1474C29.8542 16.9722 29.8896 16.8012 29.9088 16.6242C29.9658 16.0902 30 15.5496 30 15C30 6.7158 23.2842 0 15 0Z"
fill="#605FFC" />
</g>
<defs>
<clipPath id="clip0_67_222">
<rect width="30" height="30" fill="white" />
</clipPath>
</defs>
</svg>
</div>
<!--Register-->
<div class="right_part__connexion--register">
<span>Register Now</span>
</div>
</div>
</div>
</div>
</div>

@ -1,14 +1,14 @@
@import '../../../styles';
//region Colors
$color-sun: #E4C74D;
$color-cloud-inner: #FFFFFF;
$color-cloud-outer: #D4D4D2;
$color-parent-outer: #81C0D5;
$color-parent-inner: #C0E6F6;
$color-moon-inner: #FFFDF2;
$color-moon-outer: #DEE1C5;
$color-stars: #FCFCFC;
$color-sun: #e4c74d;
$color-cloud-inner: #ffffff;
$color-cloud-outer: #d4d4d2;
$color-parent-outer: #81c0d5;
$color-parent-inner: #c0e6f6;
$color-moon-inner: #fffdf2;
$color-moon-outer: #dee1c5;
$color-stars: #fcfcfc;
// endregion
//region Mixins
@ -19,7 +19,7 @@ $color-stars: #FCFCFC;
left: $left;
width: $size;
height: $size;
background-color: #EFEEDA;
background-color: #efeeda;
border-radius: 100%;
border: 4px solid $color-moon-outer;
}
@ -41,7 +41,7 @@ $color-stars: #FCFCFC;
}
//endregion
$theme-transition: all .3s ease-in-out;
$theme-transition: all 0.3s ease-in-out;
.header {
position: relative;
@ -58,13 +58,13 @@ $theme-transition: all .3s ease-in-out;
flex-direction: row;
&__logo {
&--container{
&--container {
display: flex;
flex-direction: row;
gap: 2rem;
}
&--sandkasten{
&--sandkasten {
width: 4rem;
height: auto;
aspect-ratio: 1;
@ -72,7 +72,8 @@ $theme-transition: all .3s ease-in-out;
}
}
.right_part, .mobile_menu {
.right_part,
.mobile_menu {
// Dark mode button
.wrapper {
text-align: center;
@ -85,7 +86,8 @@ $theme-transition: all .3s ease-in-out;
border-radius: 40px;
}
&:before, &:after {
&:before,
&:after {
content: '';
display: table;
}
@ -103,7 +105,7 @@ $theme-transition: all .3s ease-in-out;
background-color: $color-parent-inner;
border-radius: 40px;
border: 4px solid $color-parent-outer;
transition: all .1s cubic-bezier(0.250, 0.460, 0.450, 0.940);
transition: all 0.1s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}
.toggle-input {
@ -144,10 +146,10 @@ $theme-transition: all .3s ease-in-out;
width: 30px;
height: 30px;
margin-left: 60px;
background-color: #F5EB42;
background-color: #f5eb42;
border: 4px solid $color-sun;
border-radius: 50%;
transition: all .1s cubic-bezier(0.250, 0.460, 0.450, 0.940);
transition: all 0.1s cubic-bezier(0.25, 0.46, 0.45, 0.94);
.toggle-switch-figure {
position: absolute;
@ -160,7 +162,7 @@ $theme-transition: all .3s ease-in-out;
border-radius: 20px;
background-color: #fff;
transform: scale(0.4);
transition: all .12s cubic-bezier(0.250, 0.460, 0.450, 0.940);
transition: all 0.12s cubic-bezier(0.25, 0.46, 0.45, 0.94);
&:after {
@include cloudBubble(-65px, -42px, 15px, 15px, 70deg);
}
@ -173,15 +175,15 @@ $theme-transition: all .3s ease-in-out;
@include crater(5px, 2px, 2px);
box-shadow:
42px -7px 0 -3px $color-stars,
75px -10px 0 -3px $color-stars,
54px 4px 0 -4px $color-stars,
83px 7px 0 -2px $color-stars,
63px 18px 0 -4px $color-stars,
44px 23px 0 -2px $color-stars,
78px 21px 0 -3px $color-stars;
transition: all .12s cubic-bezier(0.250, 0.460, 0.450, 0.940);
42px -7px 0 -3px $color-stars,
75px -10px 0 -3px $color-stars,
54px 4px 0 -4px $color-stars,
83px 7px 0 -2px $color-stars,
63px 18px 0 -4px $color-stars,
44px 23px 0 -2px $color-stars,
78px 21px 0 -3px $color-stars;
transition: all 0.12s cubic-bezier(0.25, 0.46, 0.45, 0.94);
transform: scale(0);
&:before {
@ -250,7 +252,7 @@ $theme-transition: all .3s ease-in-out;
cursor: pointer;
display: flex;
align-items: center;
gap: .5rem;
gap: 0.5rem;
color: $color-purple;
white-space: nowrap;
@ -260,10 +262,10 @@ $theme-transition: all .3s ease-in-out;
cursor: pointer;
border: 1px solid $color-black;
border-radius: 10px;
padding: .75rem 2rem;
padding: 0.75rem 2rem;
white-space: nowrap;
transition: border .3s ease-in-out;
transition: border 0.3s ease-in-out;
}
}
}
@ -278,7 +280,10 @@ $theme-transition: all .3s ease-in-out;
transform: translateX(100%);
z-index: 99;
transition: transform .3s ease-in-out, box-shadow .3s ease-in-out, background .3s ease-in-out;
transition:
transform 0.3s ease-in-out,
box-shadow 0.3s ease-in-out,
background 0.3s ease-in-out;
&.opened {
transform: translateX(0);
@ -361,7 +366,6 @@ $theme-transition: all .3s ease-in-out;
}
}
@media (max-width: 1024px) {
.header {
.right_part {
@ -386,12 +390,10 @@ $theme-transition: all .3s ease-in-out;
}
}
@media(max-width: 767px) {
@media (max-width: 767px) {
.header {
.mobile_menu {
width: 75%;
}
}
}

@ -8,8 +8,8 @@ describe('HeaderComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [HeaderComponent]
});
imports: [HeaderComponent],
});
fixture = TestBed.createComponent(HeaderComponent);
component = fixture.componentInstance;
fixture.detectChanges();

@ -1,53 +1,66 @@
import {Component, ElementRef, HostListener, Input, OnInit, ViewChild} from '@angular/core';
import {TranslationService} from '../../services/translation.service';
import {ThemeService} from "../../services/theme.service";
import {
Component,
ElementRef,
HostListener,
Input,
ViewChild,
} from '@angular/core';
import { TranslationService } from '../../services/translation.service';
import { ThemeService } from '../../services/theme.service';
import { TranslateModule } from '@ngx-translate/core';
import { ReactiveFormsModule } from '@angular/forms';
import { RouterLink, RouterLinkActive } from '@angular/router';
import { NgClass } from '@angular/common';
import { NgClass, NgOptimizedImage } from '@angular/common';
@Component({
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss'],
standalone: true,
imports: [NgClass, RouterLink, RouterLinkActive, ReactiveFormsModule, TranslateModule]
selector: 'app-header',
templateUrl: './header.component.html',
styleUrls: ['./header.component.scss'],
standalone: true,
imports: [
NgClass,
RouterLink,
RouterLinkActive,
ReactiveFormsModule,
TranslateModule,
NgOptimizedImage,
],
})
export class HeaderComponent {
title: string = 'Sandkasten';
version: string = '1.0';
sandkasten_logo: string = 'assets/img/logo.png';
isMenuOpen: boolean = false;
isCheck: boolean = false;
@ViewChild('menuRef') menuRef!: ElementRef;
@Input() themeClass!: string;
@Input() themeService!: ThemeService;
title: string = 'Sandkasten';
version: string = '1.0';
isMenuOpen: boolean = false;
isCheck: boolean = false;
@ViewChild('menuRef') menuRef!: ElementRef;
@Input() themeClass!: string;
@Input() themeService!: ThemeService;
// Instanciation du service pour les actions de traduction
constructor(private translationService: TranslationService) {
}
// Instanciation du service pour les actions de traduction
constructor(private translationService: TranslationService) {}
// Méthode pour changer la langue
onLanguageChange(event: any) {
this.translationService.onLanguageChange(event);
}
// Méthode pour changer la langue
onLanguageChange(event: Event) {
this.translationService.onLanguageChange(
(event.target as HTMLSelectElement).value as 'fr' | 'en'
);
}
toggleTheme() {
this.themeService.toggleDarkTheme();
this.themeService.isDarkTheme.subscribe(value => {
this.isCheck = value;
})
}
toggleTheme() {
this.themeService.toggleDarkTheme();
this.themeService.isDarkTheme.subscribe((value) => {
this.isCheck = value;
});
}
openCloseMenu() {
this.isMenuOpen = !this.isMenuOpen;
}
openCloseMenu() {
this.isMenuOpen = !this.isMenuOpen;
}
@HostListener('document:click', ['$event'])
clickout(event: any) {
// If the menu is open and click is outside the menu, we close it
if (this.isMenuOpen && !this.menuRef.nativeElement.contains(event.target)) {
this.isMenuOpen = false;
}
@HostListener('document:click', ['$event'])
clickout(event: MouseEvent) {
// If the menu is open and click is outside the menu, we close it
if (this.isMenuOpen && !this.menuRef.nativeElement.contains(event.target)) {
this.isMenuOpen = false;
}
}
}
}

@ -1,9 +1,13 @@
<div class="landing-page" [ngClass]="themeClass">
<div class="landing-page--container">
<h2 class="landing-page--title">{{ 'LandingPage.Welcome' | translate}}</h2>
<span class="landing-page--subtitle">{{ 'LandingPage.Description' | translate}}</span>
<div class="landing-page__button">
<a class="landing-page__button--link" (click)="onContinue()">{{ 'LandingPage.Try' | translate}}</a>
</div>
</div>
<div class="landing-page--container">
<h2 class="landing-page--title">{{ 'LandingPage.Welcome' | translate }}</h2>
<span class="landing-page--subtitle">{{
'LandingPage.Description' | translate
}}</span>
<div class="landing-page__button">
<a class="landing-page__button--link" routerLink="/editor">{{
'LandingPage.Try' | translate
}}</a>
</div>
</div>
</div>

@ -1,63 +1,61 @@
@import '../../../styles';
.landing-page {
padding: 6rem;
display: flex;
flex-direction: row;
gap: 2rem;
color: $color-black;
transition: color .3s ease-in-out;
padding: 6rem;
display: flex;
flex-direction: row;
gap: 2rem;
color: $color-black;
transition: color 0.3s ease-in-out;
&--container {
display: flex;
flex-direction: column;
gap: 1rem;
}
&--container {
display: flex;
flex-direction: column;
gap: 1rem;
}
&--title {
font-size: 5rem;
font-weight: 700;
margin: 0;
}
&--subtitle {
font-size: 1rem;
font-weight: 400;
margin: 0;
}
&__button {
padding: 0.75rem 2rem;
background: $color-purple;
border-radius: 10px;
width: fit-content;
white-space: nowrap;
color: $color-white;
}
@media (max-width: 1024px) {
padding: 4rem;
flex-direction: column;
gap: 1rem;
&--title {
font-size: 5rem;
font-weight: 700;
margin: 0;
font-size: 4rem;
}
}
&--subtitle {
font-size: 1rem;
font-weight: 400;
margin: 0;
}
&__button {
padding: .75rem 2rem;
background: $color-purple;
border-radius: 10px;
width: fit-content;
white-space: nowrap;
color: $color-white;
}
@media (max-width: 767px) {
padding: 2rem;
@media(max-width: 1024px) {
padding: 4rem;
flex-direction: column;
gap: 1rem;
&--title {
font-size: 4rem;
}
}
@media(max-width: 767px) {
padding: 2rem;
&--title {
font-size: 2.5rem;
}
&--title {
font-size: 2.5rem;
}
}
&.dark-theme {
color: $color-white;
}
&.dark-theme {
color: $color-white;
}
}

@ -8,8 +8,8 @@ describe('LandingPageComponent', () => {
beforeEach(() => {
TestBed.configureTestingModule({
imports: [LandingPageComponent]
});
imports: [LandingPageComponent],
});
fixture = TestBed.createComponent(LandingPageComponent);
component = fixture.componentInstance;
fixture.detectChanges();

@ -1,6 +1,6 @@
import {Component, OnInit} from '@angular/core';
import { Router } from '@angular/router';
import {ThemeService} from "../../services/theme.service";
import { Component, OnInit } from '@angular/core';
import { Router, RouterLink } from '@angular/router';
import { ThemeService } from '../../services/theme.service';
import { TranslateModule } from '@ngx-translate/core';
import { NgClass } from '@angular/common';
@ -9,20 +9,25 @@ import { NgClass } from '@angular/common';
templateUrl: './landing-page.component.html',
styleUrls: ['./landing-page.component.scss'],
standalone: true,
imports: [NgClass, TranslateModule]
imports: [NgClass, TranslateModule, RouterLink],
})
export class LandingPageComponent implements OnInit {
themeClass!: string;
constructor(private router: Router, private themeService: ThemeService){}
constructor(
private router: Router,
private themeService: ThemeService
) {}
ngOnInit() {
this.themeService.isDarkTheme.subscribe(value => {
value ? this.themeClass = 'dark-theme' : this.themeClass = 'light-theme';
})
this.themeService.isDarkTheme.subscribe((value) => {
value
? (this.themeClass = 'dark-theme')
: (this.themeClass = 'light-theme');
});
}
// Si click sur "Run", on redirige vers la page d'édition
onContinue():void{
this.router.navigateByUrl('/editor');
onContinue(): void {
this.router.navigateByUrl('/editor');
}
}

@ -1,8 +1,8 @@
import {LanguageDescription} from "@codemirror/language";
import {javascript} from "@codemirror/lang-javascript";
import { LanguageDescription } from '@codemirror/language';
import { javascript } from '@codemirror/lang-javascript';
export const CODE_DEFAULTS = {
'C': /** @lang C */ `#include <stdio.h>
C: /** @lang C */ `#include <stdio.h>
int main() {
printf("Hello, World!\\n");
return 0;
@ -12,8 +12,8 @@ int main() {
std::cout << "Hello, World!\\n";
return 0;
}`,
'JavaScript': /** @lang JS */ `console.log("Hello, World!");`,
'TypeScript': /** @lang TS */ `console.log("Hello, World!");`
JavaScript: /** @lang JS */ `console.log("Hello, World!");`,
TypeScript: /** @lang TS */ `console.log("Hello, World!");`,
};
export const LANGUAGES = [
@ -21,16 +21,16 @@ export const LANGUAGES = [
name: 'C',
extensions: ['c', 'h', 'ino'],
load() {
return import("@codemirror/lang-cpp").then(m => m.cpp())
}
return import('@codemirror/lang-cpp').then((m) => m.cpp());
},
}),
LanguageDescription.of({
name: "C++",
name: 'C++',
alias: ['cpp'],
extensions: ['cpp', "c++", 'cc', 'cxx', 'hpp', "h++", 'hh', 'hxx'],
extensions: ['cpp', 'c++', 'cc', 'cxx', 'hpp', 'h++', 'hh', 'hxx'],
load() {
return import("@codemirror/lang-cpp").then(m => m.cpp())
}
return import('@codemirror/lang-cpp').then((m) => m.cpp());
},
}),
LanguageDescription.of({
name: 'JavaScript',
@ -43,7 +43,9 @@ export const LANGUAGES = [
alias: ['ts'],
extensions: ['ts'],
load() {
return import("@codemirror/lang-javascript").then(m => m.javascript({typescript: true}))
}
return import('@codemirror/lang-javascript').then((m) =>
m.javascript({ typescript: true })
);
},
}),
];

@ -1,31 +1,36 @@
<body>
<main>
<div>
<img class="colin"
[src]="colin" alt="Photo-Colin" />
<h1>COLIN FRIZOT</h1>
<p>Bonjour, je suis Colin, un poisson développeur. (fraude)</p>
<main>
<div>
<img class="colin" [src]="colin" alt="Photo-Colin" />
<h1>COLIN FRIZOT</h1>
<p>Bonjour, je suis Colin, un poisson développeur. (fraude)</p>
<img class="hugo"
[src]="hugo" alt="Photo-Hugo" />
<h1>HUGO PRADIER</h1>
<p>Bonjour, je suis Hugo, un développeur bientôt chauve. (suit tous les tutos en ligne, mais ça marche jamais)</p>
<img class="hugo" [src]="hugo" alt="Photo-Hugo" />
<h1>HUGO PRADIER</h1>
<p>
Bonjour, je suis Hugo, un développeur bientôt chauve. (suit tous les
tutos en ligne, mais ça marche jamais)
</p>
<img class="bastien"
[src]="bastien" alt="Photo-Bastien" />
<h1>BASTIEN OLLIER</h1>
<p>Bonjour, je suis Bastien, un développeur visuellement parlant, très puant. (connaît l'adresse de la grand-mère de Colin)</p>
<img class="bastien" [src]="bastien" alt="Photo-Bastien" />
<h1>BASTIEN OLLIER</h1>
<p>
Bonjour, je suis Bastien, un développeur visuellement parlant, très
puant. (connaît l'adresse de la grand-mère de Colin)
</p>
<img class="clement"
[src]="clement" alt="Photo-Clement" />
<h1>CLÉMENT FRÉVILLE</h1>
<p>Bonjour, je suis Clément, un développeur meilleur que tes profs. (dieu)</p>
<img class="clement" [src]="clement" alt="Photo-Clement" />
<h1>CLÉMENT FRÉVILLE</h1>
<p>
Bonjour, je suis Clément, un développeur meilleur que tes profs. (dieu)
</p>
<img class="matis"
[src]="matis" alt="Photo-Matis" />
<h1>MATIS MAZINGUE</h1>
<p>Bonjour, je suis Matis, un "développeur". (est là que pour l'argent, mais il est nul)</p>
</div>
</main>
</body>
<img class="matis" [src]="matis" alt="Photo-Matis" />
<h1>MATIS MAZINGUE</h1>
<p>
Bonjour, je suis Matis, un "développeur". (est là que pour l'argent,
mais il est nul)
</p>
</div>
</main>
</body>

@ -8,10 +8,9 @@ describe('OurStoryComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [OurStoryComponent]
})
.compileComponents();
imports: [OurStoryComponent],
}).compileComponents();
fixture = TestBed.createComponent(OurStoryComponent);
component = fixture.componentInstance;
fixture.detectChanges();

@ -1,14 +1,14 @@
import { Component, OnInit } from '@angular/core';
import { Component } from '@angular/core';
import { Router } from '@angular/router';
@Component({
selector: 'app-our-story',
templateUrl: './our-story.component.html',
styleUrl: './our-story.component.scss',
standalone: true
standalone: true,
})
export class OurStoryComponent {
constructor(private router: Router) { }
constructor(private router: Router) {}
colin: string = 'assets/img/colin.png';
hugo: string = 'assets/img/hugo.png';
bastien: string = 'assets/img/bastien.png';

@ -1,122 +1,182 @@
<body>
<h1>{{ 'PrivacyPolicyPage.PrivacyPolicy' | translate }}</h1>
<p>
{{ 'PrivacyPolicyPage.Promise' | translate
}}<a href="https://www.sandkasten.fr">sandkasten.fr</a>
{{ 'PrivacyPolicyPage.PromisePart2' | translate }}
</p>
<p>{{ 'PrivacyPolicyPage.Policy' | translate }}</p>
<div class="wpembed-toc">
<h3>{{ 'PrivacyPolicyPage.TableContents' | translate }}</h3>
<ol class="wpembed-toc">
<li>
<a href="#collection-of-personal-information">{{
'PrivacyPolicyPage.PersonalInformation.Title' | translate
}}</a>
</li>
<li>
<a href="#privacy-of-children">{{
'PrivacyPolicyPage.PrivacyChildren.Title' | translate
}}</a>
</li>
<li>
<a href="#use-and-processing-of-collected-information">{{
'PrivacyPolicyPage.UseProcInformation.Title' | translate
}}</a>
</li>
<li>
<a href="#managing-information">{{
'PrivacyPolicyPage.ManagingInformation.Title' | translate
}}</a>
</li>
<li>
<a href="#disclosure-of-information">{{
'PrivacyPolicyPage.DisclosureInformation.Title' | translate
}}</a>
</li>
<li>
<a href="#retention-of-information">{{
'PrivacyPolicyPage.RetentionInformation.Title' | translate
}}</a>
</li>
<li>
<a href="#do-not-track-signals">{{
'PrivacyPolicyPage.DoNotTrack.Title' | translate
}}</a>
</li>
<li>
<a href="#links-to-other-resources">{{
'PrivacyPolicyPage.LinksResources.Title' | translate
}}</a>
</li>
<li>
<a href="#information-security">{{
'PrivacyPolicyPage.InformationSecurity.Title' | translate
}}</a>
</li>
<li>
<a href="#data-breach">{{
'PrivacyPolicyPage.DataBreach.Title' | translate
}}</a>
</li>
<li>
<a href="#changes-and-amendments">{{
'PrivacyPolicyPage.Amendments.Title' | translate
}}</a>
</li>
<li>
<a href="#acceptance-of-this-policy">{{
'PrivacyPolicyPage.Acceptance.Title' | translate
}}</a>
</li>
<li>
<a href="#contacting-us">{{
'PrivacyPolicyPage.ContactingUs.Title' | translate
}}</a>
</li>
</ol>
</div>
<h2 id="collection-of-personal-information">
{{ 'PrivacyPolicyPage.PersonalInformation.Title' | translate }}
</h2>
<p>{{ 'PrivacyPolicyPage.PersonalInformation.Text1' | translate }}</p>
<p>{{ 'PrivacyPolicyPage.PersonalInformation.Text2' | translate }}</p>
<ul>
<li>{{ 'PrivacyPolicyPage.PersonalInformation.Text3' | translate }}</li>
<li>{{ 'PrivacyPolicyPage.PersonalInformation.Text4' | translate }}</li>
</ul>
<p>{{ 'PrivacyPolicyPage.PersonalInformation.Text5' | translate }}</p>
<h1>{{ 'PrivacyPolicyPage.PrivacyPolicy' | translate }}</h1>
<p>{{ 'PrivacyPolicyPage.Promise' | translate}}<a href="https://www.sandkasten.fr">sandkasten.fr</a>
{{ 'PrivacyPolicyPage.PromisePart2' | translate}}</p>
<p>{{ 'PrivacyPolicyPage.Policy' | translate }}</p>
<div class="wpembed-toc">
<h3>{{ 'PrivacyPolicyPage.TableContents' | translate}}</h3>
<ol class="wpembed-toc">
<li>
<a href="#collection-of-personal-information">{{ 'PrivacyPolicyPage.PersonalInformation.Title' |
translate}}</a>
</li>
<li>
<a href="#privacy-of-children">{{ 'PrivacyPolicyPage.PrivacyChildren.Title' | translate}}</a>
</li>
<li>
<a href="#use-and-processing-of-collected-information">{{ 'PrivacyPolicyPage.UseProcInformation.Title' |
translate}}</a>
</li>
<li>
<a href="#managing-information">{{ 'PrivacyPolicyPage.ManagingInformation.Title' | translate }}</a>
</li>
<li>
<a href="#disclosure-of-information">{{ 'PrivacyPolicyPage.DisclosureInformation.Title' | translate
}}</a>
</li>
<li>
<a href="#retention-of-information">{{ 'PrivacyPolicyPage.RetentionInformation.Title' | translate }}</a>
</li>
<li>
<a href="#do-not-track-signals">{{ 'PrivacyPolicyPage.DoNotTrack.Title' | translate}}</a>
</li>
<li>
<a href="#links-to-other-resources">{{ 'PrivacyPolicyPage.LinksResources.Title' | translate}}</a>
</li>
<li>
<a href="#information-security">{{ 'PrivacyPolicyPage.InformationSecurity.Title' | translate}}</a>
</li>
<li>
<a href="#data-breach">{{ 'PrivacyPolicyPage.DataBreach.Title' | translate}}</a>
</li>
<li>
<a href="#changes-and-amendments">{{ 'PrivacyPolicyPage.Amendments.Title' | translate}}</a>
</li>
<li>
<a href="#acceptance-of-this-policy">{{ 'PrivacyPolicyPage.Acceptance.Title' | translate}}</a>
</li>
<li>
<a href="#contacting-us">{{ 'PrivacyPolicyPage.ContactingUs.Title' | translate}}</a>
</li>
</ol>
</div>
<h2 id="collection-of-personal-information">{{ 'PrivacyPolicyPage.PersonalInformation.Title' | translate}}</h2>
<p>{{ 'PrivacyPolicyPage.PersonalInformation.Text1' | translate }}</p>
<p>{{ 'PrivacyPolicyPage.PersonalInformation.Text2' | translate}}</p>
<ul>
<li>{{ 'PrivacyPolicyPage.PersonalInformation.Text3' | translate}}</li>
<li>{{ 'PrivacyPolicyPage.PersonalInformation.Text4' | translate}}</li>
</ul>
<p>{{ 'PrivacyPolicyPage.PersonalInformation.Text5' | translate}}</p>
<h2 id="privacy-of-children">
{{ 'PrivacyPolicyPage.PrivacyChildren.Title' | translate }}
</h2>
<p>{{ 'PrivacyPolicyPage.PrivacyChildren.Text1' | translate }}</p>
<p>{{ 'PrivacyPolicyPage.PrivacyChildren.Text2' | translate }}</p>
<h2 id="use-and-processing-of-collected-information">
{{ 'PrivacyPolicyPage.UseProcInformation.Title' | translate }}
</h2>
<p>{{ 'PrivacyPolicyPage.UseProcInformation.Text1' | translate }}</p>
<p>{{ 'PrivacyPolicyPage.UseProcInformation.Text2' | translate }}</p>
<p>{{ 'PrivacyPolicyPage.UseProcInformation.Text3' | translate }}</p>
<p>{{ 'PrivacyPolicyPage.UseProcInformation.Text4' | translate }}</p>
<ul>
<li>{{ 'PrivacyPolicyPage.UseProcInformation.List1' | translate }}</li>
<li>{{ 'PrivacyPolicyPage.UseProcInformation.List2' | translate }}</li>
<li>{{ 'PrivacyPolicyPage.UseProcInformation.List3' | translate }}</li>
<li>{{ 'PrivacyPolicyPage.UseProcInformation.List4' | translate }}</li>
</ul>
<p>{{ 'PrivacyPolicyPage.UseProcInformation.Text5' | translate }}</p>
<p>{{ 'PrivacyPolicyPage.UseProcInformation.Text6' | translate }}</p>
<h2 id="privacy-of-children">{{ 'PrivacyPolicyPage.PrivacyChildren.Title' | translate}}</h2>
<p>{{ 'PrivacyPolicyPage.PrivacyChildren.Text1' | translate}}</p>
<p>{{ 'PrivacyPolicyPage.PrivacyChildren.Text2' | translate}}</p>
<h2 id="use-and-processing-of-collected-information">{{ 'PrivacyPolicyPage.UseProcInformation.Title' | translate}}
</h2>
<p>{{ 'PrivacyPolicyPage.UseProcInformation.Text1' | translate}}</p>
<p>{{ 'PrivacyPolicyPage.UseProcInformation.Text2' | translate}}</p>
<p>{{ 'PrivacyPolicyPage.UseProcInformation.Text3' | translate}}</p>
<p>{{ 'PrivacyPolicyPage.UseProcInformation.Text4' | translate}}</p>
<ul>
<li>{{ 'PrivacyPolicyPage.UseProcInformation.List1' | translate}}</li>
<li>{{ 'PrivacyPolicyPage.UseProcInformation.List2' | translate}}</li>
<li>{{ 'PrivacyPolicyPage.UseProcInformation.List3' | translate}}</li>
<li>{{ 'PrivacyPolicyPage.UseProcInformation.List4' | translate}}</li>
</ul>
<p>{{ 'PrivacyPolicyPage.UseProcInformation.Text5' | translate}}</p>
<p>{{ 'PrivacyPolicyPage.UseProcInformation.Text6' | translate}}</p>
<h2 id="managing-information">
{{ 'PrivacyPolicyPage.ManagingInformation.Title' | translate }}
</h2>
<p>{{ 'PrivacyPolicyPage.ManagingInformation.Text1' | translate }}</p>
<h2 id="managing-information">{{ 'PrivacyPolicyPage.ManagingInformation.Title' | translate}}</h2>
<p>{{ 'PrivacyPolicyPage.ManagingInformation.Text1' | translate}}</p>
<h2 id="disclosure-of-information">
{{ 'PrivacyPolicyPage.DisclosureInformation.Title' | translate }}
</h2>
<p>{{ 'PrivacyPolicyPage.DisclosureInformation.Text1' | translate }}</p>
<p>{{ 'PrivacyPolicyPage.DisclosureInformation.Text2' | translate }}</p>
<h2 id="disclosure-of-information">{{ 'PrivacyPolicyPage.DisclosureInformation.Title' | translate}}</h2>
<p>{{ 'PrivacyPolicyPage.DisclosureInformation.Text1' | translate}}</p>
<p>{{ 'PrivacyPolicyPage.DisclosureInformation.Text2' | translate}}</p>
<h2 id="retention-of-information">
{{ 'PrivacyPolicyPage.RetentionInformation.Title' | translate }}
</h2>
<p>{{ 'PrivacyPolicyPage.RetentionInformation.Text1' | translate }}</p>
<p>{{ 'PrivacyPolicyPage.RetentionInformation.Text2' | translate }}</p>
<h2 id="retention-of-information">{{ 'PrivacyPolicyPage.RetentionInformation.Title' | translate }}</h2>
<p>{{ 'PrivacyPolicyPage.RetentionInformation.Text1' | translate }}</p>
<p>{{ 'PrivacyPolicyPage.RetentionInformation.Text2' | translate }}</p>
<h2 id="do-not-track-signals">
{{ 'PrivacyPolicyPage.DoNotTrack.Title' | translate }}
</h2>
<p>
{{ 'PrivacyPolicyPage.DoNotTrack.Text1' | translate
}}<a
href="https://www.internetcookies.com"
target="_blank"
ref="nofollow noreferrer noopener external"
>internetcookies.com</a
>
</p>
<h2 id="do-not-track-signals">{{ 'PrivacyPolicyPage.DoNotTrack.Title' | translate}}</h2>
<p>{{ 'PrivacyPolicyPage.DoNotTrack.Text1' | translate}}<a href="https://www.internetcookies.com" target="_blank"
ref="nofollow noreferrer noopener external">internetcookies.com</a></p>
<h2 id="links-to-other-resources">
{{ 'PrivacyPolicyPage.LinksResources.Title' | translate }}
</h2>
<p>{{ 'PrivacyPolicyPage.LinksResources.Text1' | translate }}</p>
<h2 id="links-to-other-resources">{{ 'PrivacyPolicyPage.LinksResources.Title' | translate}}</h2>
<p>{{ 'PrivacyPolicyPage.LinksResources.Text1' | translate}}</p>
<h2 id="information-security">
{{ 'PrivacyPolicyPage.InformationSecurity.Title' | translate }}
</h2>
<p>{{ 'PrivacyPolicyPage.InformationSecurity.Text1' | translate }}</p>
<p>{{ 'PrivacyPolicyPage.InformationSecurity.Text2' | translate }}/p></p>
<p>{{ 'PrivacyPolicyPage.InformationSecurity.Text3' | translate }}</p>
<h2 id="information-security">{{ 'PrivacyPolicyPage.InformationSecurity.Title' | translate}}</h2>
<p>{{ 'PrivacyPolicyPage.InformationSecurity.Text1' | translate}}</p>
<p>{{ 'PrivacyPolicyPage.InformationSecurity.Text2' | translate}}/p>
<p>{{ 'PrivacyPolicyPage.InformationSecurity.Text3' | translate}}</p>
<h2 id="data-breach">
{{ 'PrivacyPolicyPage.DataBreach.Title' | translate }}
</h2>
<p>{{ 'PrivacyPolicyPage.DataBreach.Text1' | translate }}</p>
<h2 id="data-breach">{{ 'PrivacyPolicyPage.DataBreach.Title' | translate}}</h2>
<p>{{ 'PrivacyPolicyPage.DataBreach.Text1' | translate}}</p>
<h2 id="changes-and-amendments">
{{ 'PrivacyPolicyPage.Amendments.Title' | translate }}
</h2>
<p>{{ 'PrivacyPolicyPage.Amendments.Text1' | translate }}</p>
<p>{{ 'PrivacyPolicyPage.Amendments.Text2' | translate }}</p>
<h2 id="changes-and-amendments">{{ 'PrivacyPolicyPage.Amendments.Title' | translate}}</h2>
<p>{{ 'PrivacyPolicyPage.Amendments.Text1' | translate}}</p>
<p>{{ 'PrivacyPolicyPage.Amendments.Text2' | translate}}</p>
<h2 id="acceptance-of-this-policy">
{{ 'PrivacyPolicyPage.Acceptance.Title' | translate }}
</h2>
<p>{{ 'PrivacyPolicyPage.Acceptance.Text1' | translate }}</p>
<h2 id="acceptance-of-this-policy">{{ 'PrivacyPolicyPage.Acceptance.Title' | translate}}</h2>
<p>{{ 'PrivacyPolicyPage.Acceptance.Text1' | translate}}
<h2 id="contacting-us">
{{ 'PrivacyPolicyPage.ContactingUs.Title' | translate }}
</h2>
<p>{{ 'PrivacyPolicyPage.ContactingUs.Text1' | translate }}</p>
<p>
<a
href="&#109;&#097;&#105;&#108;&#116;&#111;&#058;s&#97;n&#100;ka&#115;&#116;e&#110;3a&#64;&#103;&#109;a&#105;&#108;.&#99;&#111;m"
>sa&#110;&#100;&#107;&#97;&#115;te&#110;&#51;&#97;&#64;&#103;m&#97;il.&#99;&#111;m</a
>
</p>
<p>{{ 'PrivacyPolicyPage.ContactingUs.Text2' | translate }}</p>
<h2 id="contacting-us">{{ 'PrivacyPolicyPage.ContactingUs.Title' | translate}}</h2>
<p>{{ 'PrivacyPolicyPage.ContactingUs.Text1' | translate}}</p>
<p><a
href="&#109;&#097;&#105;&#108;&#116;&#111;&#058;s&#97;n&#100;ka&#115;&#116;e&#110;3a&#64;&#103;&#109;a&#105;&#108;.&#99;&#111;m">sa&#110;&#100;&#107;&#97;&#115;te&#110;&#51;&#97;&#64;&#103;m&#97;il.&#99;&#111;m</a>
</p>
<p>{{ 'PrivacyPolicyPage.ContactingUs.Text2' | translate}}</p>
<p>{{ 'PrivacyPolicyPage.Date' | translate}}</p>
</body>
<p>{{ 'PrivacyPolicyPage.Date' | translate }}</p>
</body>

@ -8,10 +8,9 @@ describe('PrivacyPolicyComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [PrivacyPolicyComponent]
})
.compileComponents();
imports: [PrivacyPolicyComponent],
}).compileComponents();
fixture = TestBed.createComponent(PrivacyPolicyComponent);
component = fixture.componentInstance;
fixture.detectChanges();

@ -2,16 +2,15 @@ import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
@Component({
selector: 'app-privacy-policy',
templateUrl: './privacy-policy.component.html',
styleUrl: './privacy-policy.component.scss',
standalone: true,
imports: [TranslateModule]
imports: [TranslateModule],
})
export class PrivacyPolicyComponent {
constructor(private router: Router) { }
constructor(private router: Router) {}
// Si click sur "Run", on redirige vers la page de politique de confidentialité
onContinue(): void {

@ -1,23 +1,30 @@
<body>
<h1>{{ 'TermsOfServicePage.Mentions' | translate }}</h1>
<h1>{{ 'TermsOfServicePage.Mentions' | translate }}</h1>
<p>{{ 'TermsOfServicePage.Law' | translate }}</p>
<h2>{{ 'TermsOfServicePage.Edition' | translate }}</h2>
<p>{{ 'TermsOfServicePage.URL' | translate }} <a href="www.sandkasten.fr">www.sandkasten.fr</a> {{
'TermsOfServicePage.Site' | translate}}</p>
<p>{{ 'TermsOfServicePage.Address' | translate }}</p>
<h2>{{ 'TermsOfServicePage.Hosting' | translate }}</h2>
<p>{{ 'TermsOfServicePage.Host' | translate }}<a
href="https://www.hostinger.fr/contact">https://www.hostinger.fr/contact</a>).</p>
<p>{{ 'TermsOfServicePage.Law' | translate }}</p>
<h2>{{ 'TermsOfServicePage.Edition' | translate }}</h2>
<p>
{{ 'TermsOfServicePage.URL' | translate }}
<a href="www.sandkasten.fr">www.sandkasten.fr</a>
{{ 'TermsOfServicePage.Site' | translate }}
</p>
<p>{{ 'TermsOfServicePage.Address' | translate }}</p>
<h2>{{ 'TermsOfServicePage.Hosting' | translate }}</h2>
<p>
{{ 'TermsOfServicePage.Host' | translate
}}<a href="https://www.hostinger.fr/contact"
>https://www.hostinger.fr/contact</a
>).
</p>
<h2>{{ 'TermsOfServicePage.Publishing' | translate }}</h2>
<p>{{ 'TermsOfServicePage.DirectorPublish' | translate }}</p>
<h2>{{ 'TermsOfServicePage.Publishing' | translate }}</h2>
<p>{{ 'TermsOfServicePage.DirectorPublish' | translate }}</p>
<h2>{{ 'TermsOfServicePage.ContactUs' | translate }}</h2>
<p>{{ 'TermsOfServicePage.Phone' | translate }}</p>
<p>{{ 'TermsOfServicePage.Mail' | translate }}</p>
<p>{{ 'TermsOfServicePage.Post' | translate }}</p>
<h2>{{ 'TermsOfServicePage.ContactUs' | translate }}</h2>
<p>{{ 'TermsOfServicePage.Phone' | translate }}</p>
<p>{{ 'TermsOfServicePage.Mail' | translate }}</p>
<p>{{ 'TermsOfServicePage.Post' | translate }}</p>
<h2>{{ 'TermsOfServicePage.Data' | translate }}</h2>
<p>{{ 'TermsOfServicePage.GDPR' | translate }}</p>
</body>
<h2>{{ 'TermsOfServicePage.Data' | translate }}</h2>
<p>{{ 'TermsOfServicePage.GDPR' | translate }}</p>
</body>

@ -8,10 +8,9 @@ describe('TermsOfServiceComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [TermsOfServiceComponent]
})
.compileComponents();
imports: [TermsOfServiceComponent],
}).compileComponents();
fixture = TestBed.createComponent(TermsOfServiceComponent);
component = fixture.componentInstance;
fixture.detectChanges();

@ -2,16 +2,15 @@ import { Component } from '@angular/core';
import { Router } from '@angular/router';
import { TranslateModule } from '@ngx-translate/core';
@Component({
selector: 'app-terms-of-service',
templateUrl: './terms-of-service.component.html',
styleUrl: './terms-of-service.component.scss',
standalone: true,
imports: [TranslateModule]
imports: [TranslateModule],
})
export class TermsOfServiceComponent {
constructor(private router: Router) { }
constructor(private router: Router) {}
// Si click sur "Run", on redirige vers la page de termes de service
onContinue(): void {

@ -3,8 +3,11 @@ import { inject } from '@angular/core/testing';
import { DomSanitizer } from '@angular/platform-browser';
describe('SafeHTMLPipe', () => {
it('create an instance', inject([DomSanitizer], (domSanitizer: DomSanitizer) => {
const pipe = new SafeHTMLPipe(domSanitizer);
expect(pipe).toBeTruthy();
}));
it('create an instance', inject(
[DomSanitizer],
(domSanitizer: DomSanitizer) => {
const pipe = new SafeHTMLPipe(domSanitizer);
expect(pipe).toBeTruthy();
}
));
});

@ -6,11 +6,9 @@ import { DomSanitizer } from '@angular/platform-browser';
standalone: true,
})
export class SafeHTMLPipe implements PipeTransform {
constructor(protected sanitizer: DomSanitizer) {}
transform(value: unknown, ...args: unknown[]): unknown {
transform(value: unknown): unknown {
return this.sanitizer.bypassSecurityTrustHtml(value as string);
}
}

@ -3,8 +3,8 @@ import { SSE } from 'sse.js';
import { Observable, Subject } from 'rxjs';
export type ExecutionMessage = {
type: 'stdout' | 'stderr' | 'exit',
text: string
type: 'stdout' | 'stderr' | 'exit';
text: string;
};
@Injectable({
@ -28,8 +28,8 @@ export class CodeExecutionService {
sse.addEventListener('message', (event: MessageEvent<string>) => {
const result = event.data;
// @ts-ignore
// @ts-expect-error The type is not declared although present
const type = event.id;
const text = decodeURIComponent(result.replace(/%00/g, ''));
if (type === 'end') {

@ -12,4 +12,4 @@ export class ThemeService {
this._darkTheme.next(!this._darkTheme.value);
console.log('Theme toggled');
}
}
}

@ -5,13 +5,13 @@ import { TranslateService } from '@ngx-translate/core';
providedIn: 'root',
})
export class TranslationService {
language: string = 'fr'; // Par défaut, français
get language() {
return this.translate.currentLang;
}
constructor(private translate: TranslateService) {}
onLanguageChange(event: any) {
this.language = event.target.value;
this.translate.use(this.language);
console.log(this.language);
}
}
constructor(private translate: TranslateService) {}
onLanguageChange(language: 'fr' | 'en') {
this.translate.use(language);
}
}

@ -1,119 +1,119 @@
{
"LandingPage": {
"Welcome": "Welcome to Sandkasten",
"Description": "You've arrived at the best code testing sandbox site! We let you test all your programs in your favorite languages. Thanks to the Code Mirror editor and our personalized management of execution on containers, your code becomes completely harmless, so you can have as much fun as you like!",
"Try": "Try it now !"
"LandingPage": {
"Welcome": "Welcome to Sandkasten",
"Description": "You've arrived at the best code testing sandbox site! We let you test all your programs in your favorite languages. Thanks to the Code Mirror editor and our personalized management of execution on containers, your code becomes completely harmless, so you can have as much fun as you like!",
"Try": "Try it now !"
},
"HeaderPage": {
"Editor": "Editor",
"Documentation": "Documentation",
"Contact": "Contact us"
},
"FooterPage": {
"About": "About Sandkasten",
"Contact": "Contact us",
"Story": "Our story",
"Legal": "Legal mentions",
"Terms": "Terms of use",
"Privacy": "Privacy policy",
"Rights": "©2024 Sandkasten, Inc. All rights reserved."
},
"TermsOfServicePage": {
"Mentions": "LEGALS MENTIONS",
"Law": "In accordance with the provisions of Law No. 2004-575 of June 21, 2004, relating to confidence in the digital economy, the identity of the various contributors involved in the creation and monitoring of the Sandkasten website is specified to users.",
"Edition": "Website editing.",
"URL": "The present website, accessible at the URL",
"Site": "(the « Site »), is edited by:",
"Address": "Sandkasten, a company with capital of 100 euros, registered with the R.C.S. of CLERMONT-FERRAND under the number RCS CLERMONT-FERRAND B 123 456 789, whose registered office is located at 7 Av. Blaise Pascal 63170 Aubière, represented by Jul Lamiff, duly authorized.",
"Hosting": "Hosting",
"Host": "The Site is hosted by Hostinger International LTD, located in , (telephone contact or email :",
"Publishing": "Publishing Director",
"DirectorPublish": "The Site's Publishing Director is Jul Lamiff.",
"ContactUs": "Contact us",
"Phone": "By phone: +33651107802",
"Mail": "By email: sandkasten3a@gmail.com",
"Post": "By post: 7 Av. Blaise Pascal 63170 Aubière",
"Data": "Personal data",
"GDPR": "The processing of your personal data is governed by our Privacy Charter, available from the « Personal Data Protection Charter » section, in accordance with the General Data Protection Regulation 2016/679 of April 27, 2016 («GDPR»)."
},
"PrivacyPolicyPage": {
"PrivacyPolicy": "Privacy Policy",
"Promise": "We respect your privacy and are committed to protecting it through our compliance with this privacy policy (« Policy »). This Policy describes the types of information we may collect from you or that you may provide (« Personal Information ») on the ",
"PromisePart2": "website (« Website » or « Service ») and any of its related products and services (collectively, « Services »), and our practices for collecting, using, maintaining, protecting, and disclosing that Personal Information. It also describes the choices available to you regarding our use of your Personal Information and how you can access and update it.",
"Policy": "This Policy is a legally binding agreement between you (« User », « you » or « your ») and Sandkasten Inc. (« Sandkasten Inc. », « we », « us » or « our »). If you are entering into this Policy on behalf of a business or other legal entity, you represent that you have the authority to bind such entity to this Policy, in which case the terms « User », « you » or « your » shall refer to such entity. If you do not have such authority, or if you do not agree with the terms of this Policy, you must not accept this Policy and may not access and use the Website and Services. By accessing and using the Website and Services, you acknowledge that you have read, understood, and agree to be bound by the terms of this Policy. This Policy does not apply to the practices of companies that we do not own or control, or to individuals that we do not employ or manage.",
"TableContents": "Table of contents",
"PersonalInformation": {
"Title": "Collection of personal information",
"Text1": "You can access and use the Website and Services without telling us who you are or revealing any information by which someone could identify you as a specific, identifiable individual. If, however, you wish to use some of the features offered on the Website, you may be asked to provide certain Personal Information (for example, your name and e-mail address).",
"Text2": "We receive and store any information you knowingly provide to us when you create an account, or fill any forms on the Website. When required, this information may include the following: ",
"Text3": "Account details (such as user name, unique user ID, password, etc)",
"Text4": "Contact information (such as email address, phone number, etc)",
"Text5": "You can choose not to provide us with your Personal Information, but then you may not be able to take advantage of some of the features on the Website. Users who are uncertain about what information is mandatory are welcome to contact us."
},
"HeaderPage": {
"Editor": "Editor",
"Documentation": "Documentation",
"Contact": "Contact us"
"PrivacyChildren": {
"Title": "Privacy of children",
"Text1": "We do not knowingly collect any Personal Information from children under the age of 13. If you are under the age of 13, please do not submit any Personal Information through the Website and Services. If you have reason to believe that a child under the age of 13 has provided Personal Information to us through the Website and Services, please contact us to request that we delete that child's Personal Information from our Services.",
"Text2": "We encourage parents and legal guardians to monitor their children's Internet usage and to help enforce this Policy by instructing their children never to provide Personal Information through the Website and Services without their permission. We also ask that all parents and legal guardians overseeing the care of children take the necessary precautions to ensure that their children are instructed to never give out Personal Information when online without their permission."
},
"FooterPage": {
"About": "About Sandkasten",
"Contact": "Contact us",
"Story": "Our story",
"Legal": "Legal mentions",
"Terms": "Terms of use",
"Privacy": "Privacy policy",
"Rights": "©2024 Sandkasten, Inc. All rights reserved."
"UseProcInformation": {
"Title": "Use and processing of collected information",
"Text1": "We act as a data controller and a data processor when handling Personal Information, unless we have entered into a data processing agreement with you in which case you would be the data controller and we would be the data processor.",
"Text2": "Our role may also differ depending on the specific situation involving Personal Information. We act in the capacity of a data controller when we ask you to submit your Personal Information that is necessary to ensure your access and use of the Website and Services. In such instances, we are a data controller because we determine the purposes and means of the processing of Personal Information.",
"Text3": "We act in the capacity of a data processor in situations when you submit Personal Information through the Website and Services. We do not own, control, or make decisions about the submitted Personal Information, and such Personal Information is processed only in accordance with your instructions. In such instances, the User providing Personal Information acts as a data controller.",
"Text4": "In order to make the Website and Services available to you, or to meet a legal obligation, we may need to collect and use certain Personal Information. If you do not provide the information that we request, we may not be able to provide you with the requested products or services. Any of the information we collect from you may be used for the following purposes:",
"List1": "Create and manage user accounts",
"List2": "Request user feedback",
"List3": "Respond to legal requests and prevent harm",
"List4": "Run and operate the Website and Services",
"Text5": "Processing your Personal Information depends on how you interact with the Website and Services, where you are located in the world and if one of the following applies: (i) you have given your consent for one or more specific purposes; (ii) provision of information is necessary for the performance of this Policy with you and/or for any pre-contractual obligations thereof; (iii) processing is necessary for compliance with a legal obligation to which you are subject; (iv) processing is related to a task that is carried out in the public interest or in the exercise of official authority vested in us; (v) processing is necessary for the purposes of the legitimate interests pursued by us or by a third party.",
"Text6": "Note that under some legislations we may be allowed to process information until you object to such processing by opting out, without having to rely on consent or any other of the legal bases. In any case, we will be happy to clarify the specific legal basis that applies to the processing, and in particular whether the provision of Personal Information is a statutory or contractual requirement, or a requirement necessary to enter into a contract. « ManagingInformation »: « Managing information »"
},
"TermsOfServicePage": {
"Mentions": "LEGALS MENTIONS",
"Law": "In accordance with the provisions of Law No. 2004-575 of June 21, 2004, relating to confidence in the digital economy, the identity of the various contributors involved in the creation and monitoring of the Sandkasten website is specified to users.",
"Edition": "Website editing.",
"URL": "The present website, accessible at the URL",
"Site": "(the « Site »), is edited by:",
"Address": "Sandkasten, a company with capital of 100 euros, registered with the R.C.S. of CLERMONT-FERRAND under the number RCS CLERMONT-FERRAND B 123 456 789, whose registered office is located at 7 Av. Blaise Pascal 63170 Aubière, represented by Jul Lamiff, duly authorized.",
"Hosting": "Hosting",
"Host": "The Site is hosted by Hostinger International LTD, located in , (telephone contact or email :",
"Publishing": "Publishing Director",
"DirectorPublish": "The Site's Publishing Director is Jul Lamiff.",
"ContactUs": "Contact us",
"Phone": "By phone: +33651107802",
"Mail": "By email: sandkasten3a@gmail.com",
"Post": "By post: 7 Av. Blaise Pascal 63170 Aubière",
"Data": "Personal data",
"GDPR": "The processing of your personal data is governed by our Privacy Charter, available from the « Personal Data Protection Charter » section, in accordance with the General Data Protection Regulation 2016/679 of April 27, 2016 («GDPR»)."
"ManagingInformation": {
"Title": "Managing information",
"Text1": "You are able to delete certain Personal Information we have about you. The Personal Information you can delete may change as the Website and Services change. When you delete Personal Information, however, we may maintain a copy of the unrevised Personal Information in our records for the duration necessary to comply with our obligations to our affiliates and partners, and for the purposes described below."
},
"PrivacyPolicyPage": {
"PrivacyPolicy": "Privacy Policy",
"Promise": "We respect your privacy and are committed to protecting it through our compliance with this privacy policy (« Policy »). This Policy describes the types of information we may collect from you or that you may provide (« Personal Information ») on the ",
"PromisePart2": "website (« Website » or « Service ») and any of its related products and services (collectively, « Services »), and our practices for collecting, using, maintaining, protecting, and disclosing that Personal Information. It also describes the choices available to you regarding our use of your Personal Information and how you can access and update it.",
"Policy": "This Policy is a legally binding agreement between you (« User », « you » or « your ») and Sandkasten Inc. (« Sandkasten Inc. », « we », « us » or « our »). If you are entering into this Policy on behalf of a business or other legal entity, you represent that you have the authority to bind such entity to this Policy, in which case the terms « User », « you » or « your » shall refer to such entity. If you do not have such authority, or if you do not agree with the terms of this Policy, you must not accept this Policy and may not access and use the Website and Services. By accessing and using the Website and Services, you acknowledge that you have read, understood, and agree to be bound by the terms of this Policy. This Policy does not apply to the practices of companies that we do not own or control, or to individuals that we do not employ or manage.",
"TableContents": "Table of contents",
"PersonalInformation": {
"Title": "Collection of personal information",
"Text1": "You can access and use the Website and Services without telling us who you are or revealing any information by which someone could identify you as a specific, identifiable individual. If, however, you wish to use some of the features offered on the Website, you may be asked to provide certain Personal Information (for example, your name and e-mail address).",
"Text2": "We receive and store any information you knowingly provide to us when you create an account, or fill any forms on the Website. When required, this information may include the following: ",
"Text3": "Account details (such as user name, unique user ID, password, etc)",
"Text4": "Contact information (such as email address, phone number, etc)",
"Text5": "You can choose not to provide us with your Personal Information, but then you may not be able to take advantage of some of the features on the Website. Users who are uncertain about what information is mandatory are welcome to contact us."
},
"PrivacyChildren": {
"Title": "Privacy of children",
"Text1": "We do not knowingly collect any Personal Information from children under the age of 13. If you are under the age of 13, please do not submit any Personal Information through the Website and Services. If you have reason to believe that a child under the age of 13 has provided Personal Information to us through the Website and Services, please contact us to request that we delete that child's Personal Information from our Services.",
"Text2": "We encourage parents and legal guardians to monitor their children's Internet usage and to help enforce this Policy by instructing their children never to provide Personal Information through the Website and Services without their permission. We also ask that all parents and legal guardians overseeing the care of children take the necessary precautions to ensure that their children are instructed to never give out Personal Information when online without their permission."
},
"UseProcInformation": {
"Title": "Use and processing of collected information",
"Text1": "We act as a data controller and a data processor when handling Personal Information, unless we have entered into a data processing agreement with you in which case you would be the data controller and we would be the data processor.",
"Text2": "Our role may also differ depending on the specific situation involving Personal Information. We act in the capacity of a data controller when we ask you to submit your Personal Information that is necessary to ensure your access and use of the Website and Services. In such instances, we are a data controller because we determine the purposes and means of the processing of Personal Information.",
"Text3": "We act in the capacity of a data processor in situations when you submit Personal Information through the Website and Services. We do not own, control, or make decisions about the submitted Personal Information, and such Personal Information is processed only in accordance with your instructions. In such instances, the User providing Personal Information acts as a data controller.",
"Text4": "In order to make the Website and Services available to you, or to meet a legal obligation, we may need to collect and use certain Personal Information. If you do not provide the information that we request, we may not be able to provide you with the requested products or services. Any of the information we collect from you may be used for the following purposes:",
"List1": "Create and manage user accounts",
"List2": "Request user feedback",
"List3": "Respond to legal requests and prevent harm",
"List4": "Run and operate the Website and Services",
"Text5": "Processing your Personal Information depends on how you interact with the Website and Services, where you are located in the world and if one of the following applies: (i) you have given your consent for one or more specific purposes; (ii) provision of information is necessary for the performance of this Policy with you and/or for any pre-contractual obligations thereof; (iii) processing is necessary for compliance with a legal obligation to which you are subject; (iv) processing is related to a task that is carried out in the public interest or in the exercise of official authority vested in us; (v) processing is necessary for the purposes of the legitimate interests pursued by us or by a third party.",
"Text6": "Note that under some legislations we may be allowed to process information until you object to such processing by opting out, without having to rely on consent or any other of the legal bases. In any case, we will be happy to clarify the specific legal basis that applies to the processing, and in particular whether the provision of Personal Information is a statutory or contractual requirement, or a requirement necessary to enter into a contract. « ManagingInformation »: « Managing information »"
},
"ManagingInformation": {
"Title": "Managing information",
"Text1": "You are able to delete certain Personal Information we have about you. The Personal Information you can delete may change as the Website and Services change. When you delete Personal Information, however, we may maintain a copy of the unrevised Personal Information in our records for the duration necessary to comply with our obligations to our affiliates and partners, and for the purposes described below."
},
"DisclosureInformation": {
"Title": "Disclosure of information",
"Text1": "To maintain the highest level of privacy and to protect your Personal Information to the full extent, we do not share your Personal Information with any third parties.",
"Text2": "However, we may also disclose any Personal Information we collect, use or receive if required or permitted by law, such as to comply with a subpoena or similar legal process, and when we believe in good faith that disclosure is necessary to protect our rights, protect your safety or the safety of others, investigate fraud, or respond to a government request."
},
"RetentionInformation": {
"Title": "Retention of information",
"Text1": "We will retain and use your Personal Information for the period necessary as long as your user account remains active, to enforce our Policy, resolve disputes, and unless a longer retention period is required or permitted by law.",
"Text2": "We may use any aggregated data derived from or incorporating your Personal Information after you update or delete it, but not in a manner that would identify you personally. Once the retention period expires, Personal Information shall be deleted. Therefore, the right to access, the right to erasure, the right to rectification, and the right to data portability cannot be enforced after the expiration of the retention period."
},
"DoNotTrack": {
"Title": "Do Not Track signals",
"Text1": "Some browsers incorporate a Do Not Track feature that signals to websites you visit that you do not want to have your online activity tracked. Tracking is not the same as using or collecting information in connection with a website. For these purposes, tracking refers to collecting personally identifiable information from consumers who use or visit a website or online service as they move across different websites over time. How browsers communicate the Do Not Track signal is not yet uniform. As a result, the Website and Services are not yet set up to interpret or respond to Do Not Track signals communicated by your browser. Even so, as described in more detail throughout this Policy, we limit our use and collection of your Personal Information. For a description of Do Not Track protocols for browsers and mobile devices or to learn more about the choices available to you, visit "
},
"LinksResources": {
"Title": "Links to other resources",
"Text1": "The Website and Services contain links to other resources that are not owned or controlled by us. Please be aware that we are not responsible for the privacy practices of such other resources or third parties. We encourage you to be aware when you leave the Website and Services and to read the privacy statements of each and every resource that may collect Personal Information."
},
"InformationSecurity": {
"Title": "Information security",
"Text1": "We secure information you provide on computer servers in a controlled, secure environment, protected from unauthorized access, use, or disclosure. We maintain reasonable administrative, technical, and physical safeguards in an effort to protect against unauthorized access, use, modification, and disclosure of Personal Information in our control and custody. However, no data transmission over the Internet or wireless network can be guaranteed.",
"Text2": "Therefore, while we strive to protect your Personal Information, you acknowledge that (i) there are security and privacy limitations of the Internet which are beyond our control; (ii) the security, integrity, and privacy of any and all information and data exchanged between you and the Website and Services cannot be guaranteed; and (iii) any such information and data may be viewed or tampered with in transit by a third party, despite best efforts.",
"Text3": "As the security of Personal Information depends in part on the security of the device you use to communicate with us and the security you use to protect your credentials, please take appropriate measures to protect this information."
},
"DataBreach": {
"Title": "Data breach",
"Text1": "In the event we become aware that the security of the Website and Services has been compromised or Users' Personal Information has been disclosed to unrelated third parties as a result of external activity, including, but not limited to, security attacks or fraud, we reserve the right to take reasonably appropriate measures, including, but not limited to, investigation and reporting, as well as notification to and cooperation with law enforcement authorities. In the event of a data breach, we will make reasonable efforts to notify affected individuals if we believe that there is a reasonable risk of harm to the User as a result of the breach or if notice is otherwise required by law. When we do, we will send you an email."
},
"Amendments": {
"Title": "Changes and amendments",
"Text1": "We reserve the right to modify this Policy or its terms related to the Website and Services at any time at our discretion. When we do, we will revise the updated date at the bottom of this page. We may also provide notice to you in other ways at our discretion, such as through the contact information you have provided.",
"Text2": "An updated version of this Policy will be effective immediately upon the posting of the revised Policy unless otherwise specified. Your continued use of the Website and Services after the effective date of the revised Policy (or such other act specified at that time) will constitute your consent to those changes. However, we will not, without your consent, use your Personal Information in a manner materially different than what was stated at the time your Personal Information was collected."
},
"Acceptance": {
"Title": "Acceptance of this policy",
"Text1": "You acknowledge that you have read this Policy and agree to all its terms and conditions. By accessing and using the Website and Services and submitting your information you agree to be bound by this Policy. If you do not agree to abide by the terms of this Policy, you are not authorized to access or use the Website and Services."
},
"ContactingUs": {
"Title": "Contacting us",
"Text1": "If you have any questions, concerns, or complaints regarding this Policy, the information we hold about you, or if you wish to exercise your rights, we encourage you to contact us using the details below:",
"Text2": "We will attempt to resolve complaints and disputes and make every reasonable effort to honor your wish to exercise your rights as quickly as possible and in any event, within the timescales provided by applicable data protection laws."
},
"Date": "This document was last updated on January 10, 2024"
}
}
"DisclosureInformation": {
"Title": "Disclosure of information",
"Text1": "To maintain the highest level of privacy and to protect your Personal Information to the full extent, we do not share your Personal Information with any third parties.",
"Text2": "However, we may also disclose any Personal Information we collect, use or receive if required or permitted by law, such as to comply with a subpoena or similar legal process, and when we believe in good faith that disclosure is necessary to protect our rights, protect your safety or the safety of others, investigate fraud, or respond to a government request."
},
"RetentionInformation": {
"Title": "Retention of information",
"Text1": "We will retain and use your Personal Information for the period necessary as long as your user account remains active, to enforce our Policy, resolve disputes, and unless a longer retention period is required or permitted by law.",
"Text2": "We may use any aggregated data derived from or incorporating your Personal Information after you update or delete it, but not in a manner that would identify you personally. Once the retention period expires, Personal Information shall be deleted. Therefore, the right to access, the right to erasure, the right to rectification, and the right to data portability cannot be enforced after the expiration of the retention period."
},
"DoNotTrack": {
"Title": "Do Not Track signals",
"Text1": "Some browsers incorporate a Do Not Track feature that signals to websites you visit that you do not want to have your online activity tracked. Tracking is not the same as using or collecting information in connection with a website. For these purposes, tracking refers to collecting personally identifiable information from consumers who use or visit a website or online service as they move across different websites over time. How browsers communicate the Do Not Track signal is not yet uniform. As a result, the Website and Services are not yet set up to interpret or respond to Do Not Track signals communicated by your browser. Even so, as described in more detail throughout this Policy, we limit our use and collection of your Personal Information. For a description of Do Not Track protocols for browsers and mobile devices or to learn more about the choices available to you, visit "
},
"LinksResources": {
"Title": "Links to other resources",
"Text1": "The Website and Services contain links to other resources that are not owned or controlled by us. Please be aware that we are not responsible for the privacy practices of such other resources or third parties. We encourage you to be aware when you leave the Website and Services and to read the privacy statements of each and every resource that may collect Personal Information."
},
"InformationSecurity": {
"Title": "Information security",
"Text1": "We secure information you provide on computer servers in a controlled, secure environment, protected from unauthorized access, use, or disclosure. We maintain reasonable administrative, technical, and physical safeguards in an effort to protect against unauthorized access, use, modification, and disclosure of Personal Information in our control and custody. However, no data transmission over the Internet or wireless network can be guaranteed.",
"Text2": "Therefore, while we strive to protect your Personal Information, you acknowledge that (i) there are security and privacy limitations of the Internet which are beyond our control; (ii) the security, integrity, and privacy of any and all information and data exchanged between you and the Website and Services cannot be guaranteed; and (iii) any such information and data may be viewed or tampered with in transit by a third party, despite best efforts.",
"Text3": "As the security of Personal Information depends in part on the security of the device you use to communicate with us and the security you use to protect your credentials, please take appropriate measures to protect this information."
},
"DataBreach": {
"Title": "Data breach",
"Text1": "In the event we become aware that the security of the Website and Services has been compromised or Users' Personal Information has been disclosed to unrelated third parties as a result of external activity, including, but not limited to, security attacks or fraud, we reserve the right to take reasonably appropriate measures, including, but not limited to, investigation and reporting, as well as notification to and cooperation with law enforcement authorities. In the event of a data breach, we will make reasonable efforts to notify affected individuals if we believe that there is a reasonable risk of harm to the User as a result of the breach or if notice is otherwise required by law. When we do, we will send you an email."
},
"Amendments": {
"Title": "Changes and amendments",
"Text1": "We reserve the right to modify this Policy or its terms related to the Website and Services at any time at our discretion. When we do, we will revise the updated date at the bottom of this page. We may also provide notice to you in other ways at our discretion, such as through the contact information you have provided.",
"Text2": "An updated version of this Policy will be effective immediately upon the posting of the revised Policy unless otherwise specified. Your continued use of the Website and Services after the effective date of the revised Policy (or such other act specified at that time) will constitute your consent to those changes. However, we will not, without your consent, use your Personal Information in a manner materially different than what was stated at the time your Personal Information was collected."
},
"Acceptance": {
"Title": "Acceptance of this policy",
"Text1": "You acknowledge that you have read this Policy and agree to all its terms and conditions. By accessing and using the Website and Services and submitting your information you agree to be bound by this Policy. If you do not agree to abide by the terms of this Policy, you are not authorized to access or use the Website and Services."
},
"ContactingUs": {
"Title": "Contacting us",
"Text1": "If you have any questions, concerns, or complaints regarding this Policy, the information we hold about you, or if you wish to exercise your rights, we encourage you to contact us using the details below:",
"Text2": "We will attempt to resolve complaints and disputes and make every reasonable effort to honor your wish to exercise your rights as quickly as possible and in any event, within the timescales provided by applicable data protection laws."
},
"Date": "This document was last updated on January 10, 2024"
}
}

@ -1,119 +1,119 @@
{
"LandingPage": {
"Welcome" : "Bienvenue sur Sandkasten",
"Description": "Vous voici arrivé sur le meilleur site bac à sable de test de code ! Nous vous permettons de tester tous vos programmes sur vos langages préférés. Grâce à léditeur Code Mirror et à notre gestion personalisée de lexécution sur des conteneurs, votre code devient complétement inoffensif et vous pouvez donc vous amusez autant que vous le souhaitez !",
"Try": "Essayez maintenant !"
"LandingPage": {
"Welcome": "Bienvenue sur Sandkasten",
"Description": "Vous voici arrivé sur le meilleur site bac à sable de test de code ! Nous vous permettons de tester tous vos programmes sur vos langages préférés. Grâce à léditeur Code Mirror et à notre gestion personalisée de lexécution sur des conteneurs, votre code devient complétement inoffensif et vous pouvez donc vous amusez autant que vous le souhaitez !",
"Try": "Essayez maintenant !"
},
"HeaderPage": {
"Editor": "Éditeur",
"Documentation": "Documentation",
"Contact": "Nous contacter"
},
"FooterPage": {
"About": "À propos de Sandkasten",
"Contact": "Nous contacter",
"Story": "Notre histoire",
"Legal": "Mentions légales",
"Terms": "Conditions d'utilisation",
"Privacy": "Politique de confidentialité",
"Rights": "©2024 Sandkasten, Inc. Tous droits réservés"
},
"TermsOfServicePage": {
"Mentions": "MENTIONS LÉGALES",
"Law": "Conformément aux dispositions de la loi n° 2004-575 du 21 juin 2004 pour la confiance en l'économie numérique, il est précisé aux utilisateurs du site Sandkasten l'identité des différents intervenants dans le cadre de sa réalisation et de son suivi.",
"Edition": "Édition du site",
"URL": "Le présent site, accessible à l'URL",
"Site": "(le « Site »), est édité par :",
"Address": "Sandkasten, société au capital de 100 euros, inscrite au R.C.S. de CLERMONT-FERRAND sous le numéro RCS CLERMONT-FERRAND B 123 456 789, dont le siège social est situé au 7 Av. Blaise Pascal 63170 Aubière, représenté(e) par Jul Lamiff dûment habilité(e)",
"Hosting": "Hébergement",
"Host": "Le Site est hébergé par la société Hostinger International LTD, situé , (contact téléphonique ou email :",
"Publishing": "Directeur de publication",
"DirectorPublish": "Le Directeur de la publication du Site est Jul Lamiff.",
"ContactUs": "Nous contacter",
"Phone": "Par téléphone : +33651107802",
"Mail": "Par email : sandkasten3a@gmail.com",
"Post": "Par courrier : 7 Av. Blaise Pascal 63170 Aubière",
"Data": "Données personnelles",
"GDPR": "Le traitement de vos données à caractère personnel est régi par notre Charte du respect de la vie privée, disponible depuis la section « Charte de Protection des Données Personnelles », conformément au Règlement Général sur la Protection des Données 2016/679 du 27 avril 2016 («RGPD»)."
},
"PrivacyPolicyPage": {
"PrivacyPolicy": "Politique de confidentialité",
"Promise": "Nous respectons votre vie privée et nous nous engageons à la protéger en nous conformant à la présente politique de protection de la vie privée (« politique »). La présente politique décrit les types d'informations que nous pouvons recueillir auprès de vous ou que vous pouvez fournir (« informations personnelles ») sur le site web de la ",
"PromisePart2": "site web (« Site web » ou « Service ») et de ses produits et services connexes (collectivement « Services »), ainsi que nos pratiques en matière de collecte, d'utilisation, de maintien, de protection et de (collectivement, les « services »), ainsi que nos pratiques en matière de collecte, d'utilisation, de conservation, de protection et de divulgation de ces informations personnelles. protéger et de divulguer ces informations personnelles. Elle décrit également les choix qui s'offrent à vous en ce qui concerne l'utilisation de vos Il décrit également les choix qui vous sont offerts concernant l'utilisation de vos informations personnelles et la manière dont vous pouvez y accéder et les mettre à jour.",
"Policy": "La présente politique constitue une entente ayant force obligatoire entre vous (« Utilisateur », « vous » ou « votre ») et Sandkasten Inc. (« Sandkasten Inc. », « nous », « notre » ou « nos »). Si vous adhérez à la présente politique au nom d'une entreprise ou d'une autre entité juridique, vous déclarez que vous avez le pouvoir de lier cette entité à la présente politique, auquel cas les termes « Utilisateur », « vous » ou « votre » feront référence à cette entité. Si vous ne disposez pas d'une telle autorité ou si vous n'acceptez pas les termes de la présente politique, vous ne devez pas accepter la présente politique et ne pouvez pas accéder au site web et aux services ni les utiliser. En accédant au site web et aux services et en les utilisant, vous reconnaissez avoir lu, compris et accepté d'être lié par les termes de la présente politique. La présente politique ne s'applique pas aux pratiques des entreprises que nous ne possédons pas ou ne contrôlons pas, ni aux personnes que nous n'employons pas ou ne gérons pas.",
"TableContents": "Table de matières",
"PersonalInformation": {
"Title": "Collecte d'informations personnelles",
"Text1": "Vous pouvez accéder au site web et aux services et les utiliser sans nous dire qui vous êtes ni révéler d'informations permettant de vous identifier en tant qu'individu spécifique et identifiable. Toutefois, si vous souhaitez utiliser certaines des fonctions offertes sur le site web, il se peut que l'on vous demande de fournir certaines informations personnelles (par exemple, votre nom et votre adresse électronique).",
"Text2": "Nous recevons et conservons toutes les informations que vous nous fournissez sciemment lorsque vous créez un compte ou remplissez des formulaires sur le sur le site web. Lorsque cela est nécessaire, ces informations peuvent inclure les éléments suivants : ",
"Text3": "Détails du compte (nom d'utilisateur, identifiant unique, mot de passe, etc.)",
"Text4": "Informations de contact (telles que l'adresse électronique, le numéro de téléphone, etc.)",
"Text5": "Vous pouvez choisir de ne pas nous fournir vos informations personnelles, mais il se peut alors que vous ne puissiez pas profiter de certaines fonctions du site web. de certaines fonctionnalités du site web. Les utilisateurs qui ne savent pas quelles informations sont obligatoires sont invités à nous contacter. à nous contacter."
},
"HeaderPage": {
"Editor": "Éditeur",
"Documentation": "Documentation",
"Contact": "Nous contacter"
"PrivacyChildren": {
"Title": "Vie privée des enfants",
"Text1": "Nous ne collectons pas sciemment d'informations personnelles auprès d'enfants de moins de 13 ans. Si vous avez moins de 13 ans, veuillez ne pas soumettre d'informations personnelles par l'intermédiaire du site web et des services. Si vous avez des raisons de croire qu'un enfant de moins de 13 ans nous a fourni des informations personnelles par l'intermédiaire du site web et des services, veuillez nous contacter pour nous demander de supprimer les informations personnelles de cet enfant de nos services.",
"Text2": "Nous encourageons les parents et les tuteurs légaux à surveiller l'utilisation d'Internet par leurs enfants et à contribuer à l'application de la présente politique en demandant à leurs enfants de ne jamais fournir d'informations personnelles par l'intermédiaire du site web et des services sans leur autorisation. Nous demandons également à tous les parents et tuteurs légaux qui s'occupent d'enfants de prendre les précautions nécessaires pour s'assurer que leurs enfants sont informés qu'ils ne doivent jamais communiquer d'informations personnelles en ligne sans leur autorisation."
},
"FooterPage": {
"About": "À propos de Sandkasten",
"Contact": "Nous contacter",
"Story": "Notre histoire",
"Legal": "Mentions légales",
"Terms": "Conditions d'utilisation",
"Privacy": "Politique de confidentialité",
"Rights": "©2024 Sandkasten, Inc. Tous droits réservés"
"UseProcInformation": {
"Title": "Utilisation et traitement des informations collectées",
"Text1": "Nous agissons en tant que responsable du traitement des données et en tant que sous-traitant des données lorsque nous traitons des informations personnelles, à moins que nous ayons conclu un accord de traitement des données avec vous, auquel cas vous seriez le contrôleur des données et nous serions le le responsable du traitement des données.",
"Text2": "Notre rôle peut également varier en fonction de la situation spécifique impliquant des informations personnelles. Nous agissons en qualité de responsable du traitement des données lorsque nous vous demandons de soumettre vos informations personnelles qui sont nécessaires pour assurer votre accès et votre utilisation du site web et des services. Dans ce cas, nous sommes un contrôleur de données parce que nous déterminons les objectifs et les moyens du traitement des informations personnelles.",
"Text3": "Nous agissons en qualité de responsable du traitement des données lorsque vous soumettez des informations personnelles par l'intermédiaire du site web et des services. Nous ne possédons pas, ne contrôlons pas et ne prenons pas de décisions concernant les informations personnelles soumises, et ces informations personnelles ne sont traitées que conformément à vos instructions. Dans ce cas, l'utilisateur qui fournit les informations personnelles agit en tant que responsable du traitement des données.",
"Text4": "Afin de mettre le site web et les services à votre disposition, ou pour répondre à une obligation légale, nous pouvons avoir besoin de collecter et d'utiliser certaines informations personnelles. Si vous ne fournissez pas les informations que nous demandons, il se peut que nous ne soyons pas en mesure de vous fournir les produits ou services demandés. Les informations que nous recueillons auprès de vous peuvent être utilisées aux fins suivantes :",
"List1": "Créer et gérer des comptes d'utilisateurs",
"List2": "Demander l'avis des utilisateurs",
"List3": "Répondre aux demandes légales et prévenir les dommages",
"List4": "Gérer et exploiter le site web et les services",
"Text5": "Le traitement de vos informations personnelles dépend de la manière dont vous interagissez avec le site web et les services, de l'endroit où vous vous trouvez dans le monde et de l'application de l'une des conditions suivantes : (i) vous avez donné votre consentement pour une ou plusieurs finalités spécifiques ; (ii) la fourniture d'informations est nécessaire à l'exécution de la présente politique avec vous et/ou de ses obligations précontractuelles ; (iii) le traitement est nécessaire au respect d'une obligation légale à laquelle vous êtes soumis ; (iv) le traitement est lié à une tâche effectuée dans l'intérêt public ou dans l'exercice de l'autorité officielle dont nous sommes investis ; (v) le traitement est nécessaire aux fins des intérêts légitimes poursuivis par nous ou par un tiers.",
"Text6": "Notez qu'en vertu de certaines législations, nous pouvons être autorisés à traiter des informations jusqu'à ce que vous vous opposiez à ce traitement en vous désinscrivant, sans avoir à nous appuyer sur le consentement ou toute autre base juridique. Dans tous les cas, nous serons heureux de clarifier la base juridique spécifique qui s'applique au traitement, et en particulier si la fourniture d'informations personnelles est une exigence légale ou contractuelle, ou une exigence nécessaire à la conclusion d'un contrat."
},
"TermsOfServicePage": {
"Mentions": "MENTIONS LÉGALES",
"Law": "Conformément aux dispositions de la loi n° 2004-575 du 21 juin 2004 pour la confiance en l'économie numérique, il est précisé aux utilisateurs du site Sandkasten l'identité des différents intervenants dans le cadre de sa réalisation et de son suivi.",
"Edition": "Édition du site",
"URL": "Le présent site, accessible à l'URL",
"Site": "(le « Site »), est édité par :",
"Address": "Sandkasten, société au capital de 100 euros, inscrite au R.C.S. de CLERMONT-FERRAND sous le numéro RCS CLERMONT-FERRAND B 123 456 789, dont le siège social est situé au 7 Av. Blaise Pascal 63170 Aubière, représenté(e) par Jul Lamiff dûment habilité(e)",
"Hosting": "Hébergement",
"Host": "Le Site est hébergé par la société Hostinger International LTD, situé , (contact téléphonique ou email :",
"Publishing": "Directeur de publication",
"DirectorPublish": "Le Directeur de la publication du Site est Jul Lamiff.",
"ContactUs": "Nous contacter",
"Phone": "Par téléphone : +33651107802",
"Mail": "Par email : sandkasten3a@gmail.com",
"Post": "Par courrier : 7 Av. Blaise Pascal 63170 Aubière",
"Data": "Données personnelles",
"GDPR": "Le traitement de vos données à caractère personnel est régi par notre Charte du respect de la vie privée, disponible depuis la section « Charte de Protection des Données Personnelles », conformément au Règlement Général sur la Protection des Données 2016/679 du 27 avril 2016 («RGPD»)."
"ManagingInformation": {
"Title": "Gestion de l'information",
"Text1": "Vous pouvez supprimer certaines informations personnelles que nous détenons à votre sujet. Les informations personnelles que vous pouvez supprimer peuvent changer au fur et à mesure que le site web et les services évoluent. Lorsque vous supprimez des informations personnelles, nous pouvons toutefois conserver une copie des informations personnelles non révisées dans nos dossiers pendant la durée nécessaire au respect de nos obligations à l'égard de nos affiliés et partenaires, et aux fins décrites ci-dessous."
},
"PrivacyPolicyPage": {
"PrivacyPolicy": "Politique de confidentialité",
"Promise": "Nous respectons votre vie privée et nous nous engageons à la protéger en nous conformant à la présente politique de protection de la vie privée (« politique »). La présente politique décrit les types d'informations que nous pouvons recueillir auprès de vous ou que vous pouvez fournir (« informations personnelles ») sur le site web de la ",
"PromisePart2": "site web (« Site web » ou « Service ») et de ses produits et services connexes (collectivement « Services »), ainsi que nos pratiques en matière de collecte, d'utilisation, de maintien, de protection et de (collectivement, les « services »), ainsi que nos pratiques en matière de collecte, d'utilisation, de conservation, de protection et de divulgation de ces informations personnelles. protéger et de divulguer ces informations personnelles. Elle décrit également les choix qui s'offrent à vous en ce qui concerne l'utilisation de vos Il décrit également les choix qui vous sont offerts concernant l'utilisation de vos informations personnelles et la manière dont vous pouvez y accéder et les mettre à jour.",
"Policy": "La présente politique constitue une entente ayant force obligatoire entre vous (« Utilisateur », « vous » ou « votre ») et Sandkasten Inc. (« Sandkasten Inc. », « nous », « notre » ou « nos »). Si vous adhérez à la présente politique au nom d'une entreprise ou d'une autre entité juridique, vous déclarez que vous avez le pouvoir de lier cette entité à la présente politique, auquel cas les termes « Utilisateur », « vous » ou « votre » feront référence à cette entité. Si vous ne disposez pas d'une telle autorité ou si vous n'acceptez pas les termes de la présente politique, vous ne devez pas accepter la présente politique et ne pouvez pas accéder au site web et aux services ni les utiliser. En accédant au site web et aux services et en les utilisant, vous reconnaissez avoir lu, compris et accepté d'être lié par les termes de la présente politique. La présente politique ne s'applique pas aux pratiques des entreprises que nous ne possédons pas ou ne contrôlons pas, ni aux personnes que nous n'employons pas ou ne gérons pas.",
"TableContents": "Table de matières",
"PersonalInformation": {
"Title": "Collecte d'informations personnelles",
"Text1": "Vous pouvez accéder au site web et aux services et les utiliser sans nous dire qui vous êtes ni révéler d'informations permettant de vous identifier en tant qu'individu spécifique et identifiable. Toutefois, si vous souhaitez utiliser certaines des fonctions offertes sur le site web, il se peut que l'on vous demande de fournir certaines informations personnelles (par exemple, votre nom et votre adresse électronique).",
"Text2": "Nous recevons et conservons toutes les informations que vous nous fournissez sciemment lorsque vous créez un compte ou remplissez des formulaires sur le sur le site web. Lorsque cela est nécessaire, ces informations peuvent inclure les éléments suivants : ",
"Text3": "Détails du compte (nom d'utilisateur, identifiant unique, mot de passe, etc.)",
"Text4": "Informations de contact (telles que l'adresse électronique, le numéro de téléphone, etc.)",
"Text5": "Vous pouvez choisir de ne pas nous fournir vos informations personnelles, mais il se peut alors que vous ne puissiez pas profiter de certaines fonctions du site web. de certaines fonctionnalités du site web. Les utilisateurs qui ne savent pas quelles informations sont obligatoires sont invités à nous contacter. à nous contacter."
},
"PrivacyChildren": {
"Title": "Vie privée des enfants",
"Text1": "Nous ne collectons pas sciemment d'informations personnelles auprès d'enfants de moins de 13 ans. Si vous avez moins de 13 ans, veuillez ne pas soumettre d'informations personnelles par l'intermédiaire du site web et des services. Si vous avez des raisons de croire qu'un enfant de moins de 13 ans nous a fourni des informations personnelles par l'intermédiaire du site web et des services, veuillez nous contacter pour nous demander de supprimer les informations personnelles de cet enfant de nos services.",
"Text2": "Nous encourageons les parents et les tuteurs légaux à surveiller l'utilisation d'Internet par leurs enfants et à contribuer à l'application de la présente politique en demandant à leurs enfants de ne jamais fournir d'informations personnelles par l'intermédiaire du site web et des services sans leur autorisation. Nous demandons également à tous les parents et tuteurs légaux qui s'occupent d'enfants de prendre les précautions nécessaires pour s'assurer que leurs enfants sont informés qu'ils ne doivent jamais communiquer d'informations personnelles en ligne sans leur autorisation."
},
"UseProcInformation": {
"Title": "Utilisation et traitement des informations collectées",
"Text1": "Nous agissons en tant que responsable du traitement des données et en tant que sous-traitant des données lorsque nous traitons des informations personnelles, à moins que nous ayons conclu un accord de traitement des données avec vous, auquel cas vous seriez le contrôleur des données et nous serions le le responsable du traitement des données.",
"Text2": "Notre rôle peut également varier en fonction de la situation spécifique impliquant des informations personnelles. Nous agissons en qualité de responsable du traitement des données lorsque nous vous demandons de soumettre vos informations personnelles qui sont nécessaires pour assurer votre accès et votre utilisation du site web et des services. Dans ce cas, nous sommes un contrôleur de données parce que nous déterminons les objectifs et les moyens du traitement des informations personnelles.",
"Text3": "Nous agissons en qualité de responsable du traitement des données lorsque vous soumettez des informations personnelles par l'intermédiaire du site web et des services. Nous ne possédons pas, ne contrôlons pas et ne prenons pas de décisions concernant les informations personnelles soumises, et ces informations personnelles ne sont traitées que conformément à vos instructions. Dans ce cas, l'utilisateur qui fournit les informations personnelles agit en tant que responsable du traitement des données.",
"Text4": "Afin de mettre le site web et les services à votre disposition, ou pour répondre à une obligation légale, nous pouvons avoir besoin de collecter et d'utiliser certaines informations personnelles. Si vous ne fournissez pas les informations que nous demandons, il se peut que nous ne soyons pas en mesure de vous fournir les produits ou services demandés. Les informations que nous recueillons auprès de vous peuvent être utilisées aux fins suivantes :",
"List1": "Créer et gérer des comptes d'utilisateurs",
"List2": "Demander l'avis des utilisateurs",
"List3": "Répondre aux demandes légales et prévenir les dommages",
"List4": "Gérer et exploiter le site web et les services",
"Text5": "Le traitement de vos informations personnelles dépend de la manière dont vous interagissez avec le site web et les services, de l'endroit où vous vous trouvez dans le monde et de l'application de l'une des conditions suivantes : (i) vous avez donné votre consentement pour une ou plusieurs finalités spécifiques ; (ii) la fourniture d'informations est nécessaire à l'exécution de la présente politique avec vous et/ou de ses obligations précontractuelles ; (iii) le traitement est nécessaire au respect d'une obligation légale à laquelle vous êtes soumis ; (iv) le traitement est lié à une tâche effectuée dans l'intérêt public ou dans l'exercice de l'autorité officielle dont nous sommes investis ; (v) le traitement est nécessaire aux fins des intérêts légitimes poursuivis par nous ou par un tiers.",
"Text6": "Notez qu'en vertu de certaines législations, nous pouvons être autorisés à traiter des informations jusqu'à ce que vous vous opposiez à ce traitement en vous désinscrivant, sans avoir à nous appuyer sur le consentement ou toute autre base juridique. Dans tous les cas, nous serons heureux de clarifier la base juridique spécifique qui s'applique au traitement, et en particulier si la fourniture d'informations personnelles est une exigence légale ou contractuelle, ou une exigence nécessaire à la conclusion d'un contrat."
},
"ManagingInformation": {
"Title": "Gestion de l'information",
"Text1": "Vous pouvez supprimer certaines informations personnelles que nous détenons à votre sujet. Les informations personnelles que vous pouvez supprimer peuvent changer au fur et à mesure que le site web et les services évoluent. Lorsque vous supprimez des informations personnelles, nous pouvons toutefois conserver une copie des informations personnelles non révisées dans nos dossiers pendant la durée nécessaire au respect de nos obligations à l'égard de nos affiliés et partenaires, et aux fins décrites ci-dessous."
},
"DisclosureInformation": {
"Title": "Divulgation d'informations",
"Text1": "Afin de maintenir le plus haut niveau de confidentialité et de protéger au maximum vos informations personnelles, nous ne partageons pas vos informations personnelles avec des tiers.",
"Text2": "Toutefois, nous pouvons également divulguer toute information personnelle que nous recueillons, utilisons ou recevons si la loi l'exige ou l'autorise, par exemple pour nous conformer à une citation à comparaître ou à une procédure judiciaire similaire, et lorsque nous estimons de bonne foi que la divulgation est nécessaire pour protéger nos droits, votre sécurité ou celle d'autrui, enquêter sur des fraudes ou répondre à une demande du gouvernement."
},
"RetentionInformation": {
"Title": "Rétention de l'information",
"Text1": "Nous conserverons et utiliserons vos informations personnelles pendant la période nécessaire tant que votre compte d'utilisateur restera actif, pour appliquer notre politique, résoudre les litiges et à moins qu'une période de conservation plus longue ne soit requise ou autorisée par la loi.",
"Text2": "Nous pouvons utiliser toute donnée agrégée dérivée de vos informations personnelles ou les incorporant après que vous les avez mises à jour ou supprimées, mais pas d'une manière qui permettrait de vous identifier personnellement. À l'expiration de la période de conservation, les informations personnelles sont supprimées. Par conséquent, le droit d'accès, le droit d'effacement, le droit de rectification et le droit à la portabilité des données ne peuvent être appliqués après l'expiration de la période de conservation."
},
"DoNotTrack": {
"Title": "Signaux Ne Pas Suivre",
"Text1": "Certains navigateurs intègrent une fonction Ne Pas Suivre qui signale aux sites web que vous visitez que vous ne souhaitez pas que votre activité en ligne soit suivie. Le suivi n'est pas la même chose que l'utilisation ou la collecte d'informations en rapport avec un site web. À cette fin, le suivi fait référence à la collecte d'informations personnellement identifiables auprès des consommateurs qui utilisent ou visitent un site web ou un service en ligne lorsqu'ils se déplacent sur différents sites web au fil du temps. La manière dont les navigateurs communiquent le signal Do Not Track n'est pas encore uniforme. Par conséquent, le site web et les services ne sont pas encore configurés pour interpréter ou répondre aux signaux Do Not Track communiqués par votre navigateur. Malgré cela, comme décrit plus en détail dans la présente politique, nous limitons l'utilisation et la collecte de vos informations personnelles. Pour obtenir une description des protocoles Do Not Track pour les navigateurs et les appareils mobiles ou pour en savoir plus sur les choix qui s'offrent à vous, consultez le site suivant "
},
"LinksResources": {
"Title": "Liens vers d'autres ressources",
"Text1": "Le site web et les services contiennent des liens vers d'autres ressources qui ne sont pas détenues ou contrôlées par nous. Sachez que nous ne sommes pas responsables des pratiques en matière de protection de la vie privée de ces autres ressources ou tiers. Nous vous encourageons à être vigilant lorsque vous quittez le site web et les services et à lire les déclarations de confidentialité de chaque ressource susceptible de collecter des informations personnelles."
},
"InformationSecurity": {
"Title": "Sécurité de l'information",
"Text1": "Nous sécurisons les informations que vous fournissez sur des serveurs informatiques dans un environnement contrôlé et sécurisé, à l'abri de tout accès, utilisation ou divulgation non autorisés. Nous maintenons des mesures de protection administratives, techniques et physiques raisonnables afin d'empêcher l'accès, l'utilisation, la modification et la divulgation non autorisés des informations personnelles dont nous avons le contrôle et la garde. Toutefois, aucune transmission de données sur Internet ou sur un réseau sans fil ne peut être garantie.",
"Text2": "Par conséquent, bien que nous nous efforcions de protéger vos informations personnelles, vous reconnaissez que (i) il existe des limites à la sécurité et à la confidentialité de l'internet qui échappent à notre contrôle ; (ii) la sécurité, l'intégrité et la confidentialité de toutes les informations et données échangées entre vous et le site web et les services ne peuvent être garanties ; et (iii) ces informations et données peuvent être consultées ou falsifiées en cours de route par un tiers, malgré tous les efforts déployés.",
"Text3": "Étant donné que la sécurité des informations personnelles dépend en partie de la sécurité de l'appareil que vous utilisez pour communiquer avec nous et de la sécurité que vous utilisez pour protéger vos informations d'identification, veuillez prendre les mesures appropriées pour protéger ces informations."
},
"DataBreach": {
"Title": "Violation de données",
"Text1": "Si nous apprenons que la sécurité du site web et des services a été compromise ou que les informations personnelles des utilisateurs ont été divulguées à des tiers non liés à la suite d'une activité externe, y compris, mais sans s'y limiter, des attaques de sécurité ou des fraudes, nous nous réservons le droit de prendre des mesures raisonnablement appropriées, y compris, mais sans s'y limiter, une enquête et un rapport, ainsi qu'une notification aux autorités chargées de l'application de la loi et une coopération avec celles-ci. En cas de violation des données, nous ferons des efforts raisonnables pour notifier les personnes concernées si nous estimons qu'il existe un risque raisonnable de préjudice pour l'utilisateur à la suite de la violation ou si la notification est autrement requise par la loi. Dans ce cas, nous vous enverrons un courrier électronique."
},
"Amendments": {
"Title": "Changements et amendements",
"Text1": "Nous nous réservons le droit de modifier la présente politique ou les conditions relatives au site web et aux services à tout moment et à notre discrétion. Le cas échéant, nous indiquerons la date de mise à jour au bas de cette page. Nous pouvons également vous informer par d'autres moyens, à notre discrétion, tels que les coordonnées que vous nous avez fournies.",
"Text2": "Une version mise à jour de la présente politique entrera en vigueur immédiatement après la publication de la politique révisée, sauf indication contraire. En continuant à utiliser le site web et les services après la date d'entrée en vigueur de la politique révisée (ou de tout autre acte spécifié à ce moment-là), vous consentez à ces changements. Toutefois, nous n'utiliserons pas, sans votre consentement, vos informations personnelles d'une manière matériellement différente de ce qui était indiqué au moment où vos informations personnelles ont été collectées."
},
"Acceptance": {
"Title": "Acceptation de cette politiques",
"Text1": "Vous reconnaissez avoir lu la présente politique et en accepter tous les termes et conditions. En accédant au site web et aux services, en les utilisant et en soumettant vos informations, vous acceptez d'être lié par la présente politique. Si vous n'acceptez pas de respecter les conditions de la présente politique, vous n'êtes pas autorisé à accéder au site web et aux services ou à les utiliser."
},
"ContactingUs": {
"Title": "Nous contacter",
"Text1": "Si vous avez des questions, des préoccupations ou des plaintes concernant la présente politique ou les informations que nous détenons à votre sujet, ou si vous souhaitez exercer vos droits, nous vous encourageons à nous contacter en utilisant les coordonnées ci-dessous :",
"Text2": "Nous nous efforcerons de résoudre les plaintes et les litiges et ferons tous les efforts raisonnables pour répondre à votre souhait d'exercer vos droits le plus rapidement possible et, en tout état de cause, dans les délais prévus par les lois applicables en matière de protection des données."
},
"Date": "Ce document a été mis à jour pour la dernière fois le 10 janvier 2024."
}
}
"DisclosureInformation": {
"Title": "Divulgation d'informations",
"Text1": "Afin de maintenir le plus haut niveau de confidentialité et de protéger au maximum vos informations personnelles, nous ne partageons pas vos informations personnelles avec des tiers.",
"Text2": "Toutefois, nous pouvons également divulguer toute information personnelle que nous recueillons, utilisons ou recevons si la loi l'exige ou l'autorise, par exemple pour nous conformer à une citation à comparaître ou à une procédure judiciaire similaire, et lorsque nous estimons de bonne foi que la divulgation est nécessaire pour protéger nos droits, votre sécurité ou celle d'autrui, enquêter sur des fraudes ou répondre à une demande du gouvernement."
},
"RetentionInformation": {
"Title": "Rétention de l'information",
"Text1": "Nous conserverons et utiliserons vos informations personnelles pendant la période nécessaire tant que votre compte d'utilisateur restera actif, pour appliquer notre politique, résoudre les litiges et à moins qu'une période de conservation plus longue ne soit requise ou autorisée par la loi.",
"Text2": "Nous pouvons utiliser toute donnée agrégée dérivée de vos informations personnelles ou les incorporant après que vous les avez mises à jour ou supprimées, mais pas d'une manière qui permettrait de vous identifier personnellement. À l'expiration de la période de conservation, les informations personnelles sont supprimées. Par conséquent, le droit d'accès, le droit d'effacement, le droit de rectification et le droit à la portabilité des données ne peuvent être appliqués après l'expiration de la période de conservation."
},
"DoNotTrack": {
"Title": "Signaux Ne Pas Suivre",
"Text1": "Certains navigateurs intègrent une fonction Ne Pas Suivre qui signale aux sites web que vous visitez que vous ne souhaitez pas que votre activité en ligne soit suivie. Le suivi n'est pas la même chose que l'utilisation ou la collecte d'informations en rapport avec un site web. À cette fin, le suivi fait référence à la collecte d'informations personnellement identifiables auprès des consommateurs qui utilisent ou visitent un site web ou un service en ligne lorsqu'ils se déplacent sur différents sites web au fil du temps. La manière dont les navigateurs communiquent le signal Do Not Track n'est pas encore uniforme. Par conséquent, le site web et les services ne sont pas encore configurés pour interpréter ou répondre aux signaux Do Not Track communiqués par votre navigateur. Malgré cela, comme décrit plus en détail dans la présente politique, nous limitons l'utilisation et la collecte de vos informations personnelles. Pour obtenir une description des protocoles Do Not Track pour les navigateurs et les appareils mobiles ou pour en savoir plus sur les choix qui s'offrent à vous, consultez le site suivant "
},
"LinksResources": {
"Title": "Liens vers d'autres ressources",
"Text1": "Le site web et les services contiennent des liens vers d'autres ressources qui ne sont pas détenues ou contrôlées par nous. Sachez que nous ne sommes pas responsables des pratiques en matière de protection de la vie privée de ces autres ressources ou tiers. Nous vous encourageons à être vigilant lorsque vous quittez le site web et les services et à lire les déclarations de confidentialité de chaque ressource susceptible de collecter des informations personnelles."
},
"InformationSecurity": {
"Title": "Sécurité de l'information",
"Text1": "Nous sécurisons les informations que vous fournissez sur des serveurs informatiques dans un environnement contrôlé et sécurisé, à l'abri de tout accès, utilisation ou divulgation non autorisés. Nous maintenons des mesures de protection administratives, techniques et physiques raisonnables afin d'empêcher l'accès, l'utilisation, la modification et la divulgation non autorisés des informations personnelles dont nous avons le contrôle et la garde. Toutefois, aucune transmission de données sur Internet ou sur un réseau sans fil ne peut être garantie.",
"Text2": "Par conséquent, bien que nous nous efforcions de protéger vos informations personnelles, vous reconnaissez que (i) il existe des limites à la sécurité et à la confidentialité de l'internet qui échappent à notre contrôle ; (ii) la sécurité, l'intégrité et la confidentialité de toutes les informations et données échangées entre vous et le site web et les services ne peuvent être garanties ; et (iii) ces informations et données peuvent être consultées ou falsifiées en cours de route par un tiers, malgré tous les efforts déployés.",
"Text3": "Étant donné que la sécurité des informations personnelles dépend en partie de la sécurité de l'appareil que vous utilisez pour communiquer avec nous et de la sécurité que vous utilisez pour protéger vos informations d'identification, veuillez prendre les mesures appropriées pour protéger ces informations."
},
"DataBreach": {
"Title": "Violation de données",
"Text1": "Si nous apprenons que la sécurité du site web et des services a été compromise ou que les informations personnelles des utilisateurs ont été divulguées à des tiers non liés à la suite d'une activité externe, y compris, mais sans s'y limiter, des attaques de sécurité ou des fraudes, nous nous réservons le droit de prendre des mesures raisonnablement appropriées, y compris, mais sans s'y limiter, une enquête et un rapport, ainsi qu'une notification aux autorités chargées de l'application de la loi et une coopération avec celles-ci. En cas de violation des données, nous ferons des efforts raisonnables pour notifier les personnes concernées si nous estimons qu'il existe un risque raisonnable de préjudice pour l'utilisateur à la suite de la violation ou si la notification est autrement requise par la loi. Dans ce cas, nous vous enverrons un courrier électronique."
},
"Amendments": {
"Title": "Changements et amendements",
"Text1": "Nous nous réservons le droit de modifier la présente politique ou les conditions relatives au site web et aux services à tout moment et à notre discrétion. Le cas échéant, nous indiquerons la date de mise à jour au bas de cette page. Nous pouvons également vous informer par d'autres moyens, à notre discrétion, tels que les coordonnées que vous nous avez fournies.",
"Text2": "Une version mise à jour de la présente politique entrera en vigueur immédiatement après la publication de la politique révisée, sauf indication contraire. En continuant à utiliser le site web et les services après la date d'entrée en vigueur de la politique révisée (ou de tout autre acte spécifié à ce moment-là), vous consentez à ces changements. Toutefois, nous n'utiliserons pas, sans votre consentement, vos informations personnelles d'une manière matériellement différente de ce qui était indiqué au moment où vos informations personnelles ont été collectées."
},
"Acceptance": {
"Title": "Acceptation de cette politiques",
"Text1": "Vous reconnaissez avoir lu la présente politique et en accepter tous les termes et conditions. En accédant au site web et aux services, en les utilisant et en soumettant vos informations, vous acceptez d'être lié par la présente politique. Si vous n'acceptez pas de respecter les conditions de la présente politique, vous n'êtes pas autorisé à accéder au site web et aux services ou à les utiliser."
},
"ContactingUs": {
"Title": "Nous contacter",
"Text1": "Si vous avez des questions, des préoccupations ou des plaintes concernant la présente politique ou les informations que nous détenons à votre sujet, ou si vous souhaitez exercer vos droits, nous vous encourageons à nous contacter en utilisant les coordonnées ci-dessous :",
"Text2": "Nous nous efforcerons de résoudre les plaintes et les litiges et ferons tous les efforts raisonnables pour répondre à votre souhait d'exercer vos droits le plus rapidement possible et, en tout état de cause, dans les délais prévus par les lois applicables en matière de protection des données."
},
"Date": "Ce document a été mis à jour pour la dernière fois le 10 janvier 2024."
}
}

@ -1,4 +1,4 @@
<!DOCTYPE html>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
@ -10,8 +10,7 @@
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;500&display=swap"
rel="stylesheet"
/>
rel="stylesheet" />
</head>
<body>
<app-root></app-root>

@ -2,7 +2,11 @@ import { createTranslateLoader } from './app/app.module';
import { importProvidersFrom } from '@angular/core';
import { AppComponent } from './app/app.component';
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { withInterceptorsFromDi, provideHttpClient, HttpClient } from '@angular/common/http';
import {
withInterceptorsFromDi,
provideHttpClient,
HttpClient,
} from '@angular/common/http';
import { ReactiveFormsModule, FormsModule } from '@angular/forms';
import { AppRoutingModule } from './app/app-routing.module';
import { BrowserModule, bootstrapApplication } from '@angular/platform-browser';
@ -10,16 +14,21 @@ import { TranslationService } from './app/services/translation.service';
bootstrapApplication(AppComponent, {
providers: [
importProvidersFrom(BrowserModule, AppRoutingModule, ReactiveFormsModule, FormsModule,
importProvidersFrom(
BrowserModule,
AppRoutingModule,
ReactiveFormsModule,
FormsModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: (createTranslateLoader),
deps: [HttpClient]
},
defaultLanguage: 'fr'
})),
loader: {
provide: TranslateLoader,
useFactory: createTranslateLoader,
deps: [HttpClient],
},
defaultLanguage: 'fr',
})
),
TranslationService,
provideHttpClient(withInterceptorsFromDi())
]
provideHttpClient(withInterceptorsFromDi()),
],
}).catch(console.error);

@ -1,6 +1,6 @@
//region Colors
$color-purple: #605FFC;
$color-white: #FFFFFF;
$color-purple: #605ffc;
$color-white: #ffffff;
$color-black: #000000;
$color-light-black: #333333;
//endregion
@ -12,4 +12,3 @@ $color-light-black: #333333;
body {
margin: 0;
}

@ -5,10 +5,6 @@
"outDir": "./out-tsc/app",
"types": []
},
"files": [
"src/main.ts"
],
"include": [
"src/**/*.d.ts"
]
"files": ["src/main.ts"],
"include": ["src/**/*.d.ts"]
}

@ -20,15 +20,12 @@
"module": "ES2022",
"useDefineForClassFields": false,
"allowSyntheticDefaultImports": true,
"lib": [
"ES2022",
"dom"
]
"lib": ["ES2022", "dom"],
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true
}
"strictTemplates": true,
},
}

@ -3,12 +3,7 @@
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jasmine"
]
"types": ["jasmine"]
},
"include": [
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
"include": ["src/**/*.spec.ts", "src/**/*.d.ts"]
}

Loading…
Cancel
Save