Photothèque sans album

beta
anulax1225 ago%!(EXTRA string=3 months)
parent 4f17a9135b
commit 248483d8c5
  1. 55
      app/Http/Controllers/PhotoController.php
  2. 105
      app/Http/Controllers/S3Controller.php
  3. 21
      app/Models/Photo.php
  4. 11
      app/Models/User.php
  5. 25
      app/Utils/S3.php
  6. 2
      composer.json
  7. 275
      composer.lock
  8. 28
      database/migrations/2025_01_19_150608_add_column_uuid_to_table_photo.php
  9. 32
      database/migrations/2025_01_19_205249_add_columns_users.php
  10. 27
      database/migrations/2025_01_19_205325_add_relation_user_photo.php
  11. 2
      public/icons/account.svg
  12. 0
      public/icons/add-image.svg
  13. 7
      public/icons/add.svg
  14. 4
      public/icons/admin.svg
  15. 5
      public/icons/archive.svg
  16. 4
      public/icons/block-content.svg
  17. 0
      public/icons/block-quote.svg
  18. 2
      public/icons/block-relance.svg
  19. 0
      public/icons/bold.svg
  20. 6
      public/icons/cancel.svg
  21. BIN
      public/icons/chats-notif.png
  22. BIN
      public/icons/chats.png
  23. 15
      public/icons/communications.svg
  24. 4
      public/icons/cross.svg
  25. BIN
      public/icons/dark-messagerie-notif.png
  26. 5
      public/icons/darkmode.svg
  27. BIN
      public/icons/delete.png
  28. 2
      public/icons/done.svg
  29. BIN
      public/icons/download.png
  30. 4
      public/icons/dropdown-arrow.svg
  31. BIN
      public/icons/dwg.png
  32. 2
      public/icons/entreprise.svg
  33. 16
      public/icons/error.svg
  34. BIN
      public/icons/excel.png
  35. 0
      public/icons/facebook.svg
  36. BIN
      public/icons/fichier.png
  37. 7
      public/icons/file-upload.svg
  38. 2
      public/icons/filter.svg
  39. 7
      public/icons/full-screen.svg
  40. 13
      public/icons/hide.svg
  41. BIN
      public/icons/historique.png
  42. 4
      public/icons/home.svg
  43. 0
      public/icons/instagram.svg
  44. 0
      public/icons/italic.svg
  45. 0
      public/icons/list.svg
  46. 19
      public/icons/loaded.svg
  47. 2
      public/icons/loading.svg
  48. 4
      public/icons/logout.svg
  49. 0
      public/icons/mail.svg
  50. 4
      public/icons/menu.svg
  51. BIN
      public/icons/messagerie-notif.png
  52. BIN
      public/icons/messagerie.png
  53. 2
      public/icons/model.svg
  54. 5
      public/icons/modify.svg
  55. 4
      public/icons/more.svg
  56. 13
      public/icons/next.svg
  57. BIN
      public/icons/pdf.png
  58. BIN
      public/icons/pdf_download.png
  59. 4
      public/icons/photo.svg
  60. 12
      public/icons/project.svg
  61. 12
      public/icons/projects.svg
  62. BIN
      public/icons/projet.png
  63. 12
      public/icons/relance.svg
  64. 4
      public/icons/reopen.svg
  65. 14
      public/icons/reset-password.svg
  66. 4
      public/icons/search.svg
  67. 12
      public/icons/sections.svg
  68. 6
      public/icons/send.svg
  69. 8
      public/icons/settings.svg
  70. 10
      public/icons/show.svg
  71. 15
      public/icons/slider.svg
  72. BIN
      public/icons/step.png
  73. 2
      public/icons/success.svg
  74. 0
      public/icons/title.svg
  75. 15
      public/icons/type.svg
  76. 6
      public/icons/unity.svg
  77. BIN
      public/icons/utilisateurs.png
  78. BIN
      public/icons/word.png
  79. BIN
      public/icons/zip.png
  80. 1
      public/img/background.svg
  81. BIN
      public/img/sarasin.jpg
  82. BIN
      public/img/sarasin.png
  83. 51
      resources/css/app.css
  84. 142
      resources/js/Components/Dropzone.vue
  85. 29
      resources/js/Layouts/GuestLayout.vue
  86. 26
      resources/js/Pages/Home.vue
  87. 0
      resources/js/Pages/Photo/Create.vue
  88. 81
      resources/js/Pages/Photo/Index.vue
  89. 81
      resources/js/Pages/Photo/Partials/Create.vue
  90. 40
      resources/js/Pages/Photo/Partials/Edit.vue
  91. 81
      resources/js/Pages/Photo/Partials/Modal.vue
  92. 75
      resources/js/Pages/Photo/Partials/Show.vue
  93. 0
      resources/js/Pages/Photo/Show.vue
  94. 50
      resources/js/file.js
  95. 106
      resources/js/storageS3.js
  96. 6
      resources/js/utils.js
  97. 1
      resources/views/app.blade.php
  98. 30
      routes/web.php

@ -4,7 +4,10 @@
use App\Models\Photo;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Inertia\Inertia;
use Illuminate\Support\Str;
class PhotoController extends Controller
{
@ -14,7 +17,7 @@ class PhotoController extends Controller
public function index()
{
return Inertia::render('Photo/Index', [
"photos" => Photo::all()
"photos" => Photo::all()->jsonSerialize(),
]);
}
@ -23,7 +26,7 @@ public function index()
*/
public function create()
{
//
return Inertia::render('Photo/Create');
}
/**
@ -31,23 +34,24 @@ public function create()
*/
public function store(Request $request)
{
//
}
/**
* Display the specified resource.
*/
public function show(string $id)
{
//
}
$request->validate([
"name" => "required|string|max:255",
"path" => "required|string",
]);
if(!Storage::disk("s3")->exists($request->path))
return redirect()->back()->withErrors(["path" => "Probleme with the file transfert"]);
/**
* Show the form for editing the specified resource.
*/
public function edit(string $id)
{
//
$uuid = Str::uuid();
$path = "photos/" . $uuid . "-" . $request->name . "." . pathinfo($request->path, PATHINFO_EXTENSION);
Storage::disk("s3")->move($request->path, $path);
Photo::create([
"uuid" => $uuid,
"name" => $request->name,
"path" => $path,
"user_id" => Auth::user()->id
]);
return redirect(route("photo.index"))->with(["message" => "Photo ajouté avec success"]);
}
/**
@ -55,7 +59,15 @@ public function edit(string $id)
*/
public function update(Request $request, string $id)
{
//
$request->validate([
"name" => "required|string|max:255",
]);
$photo = Photo::where("uuid", $request->id)->first();
if(!$photo) redirect()->back()->withErrors(["uuid" => "Photo introuvable" ]);
$photo->update([
"name" => $request->name
]);
return redirect(route("photo.index"))->with(["message" => "Nom de la photo modifié avec success"]);
}
/**
@ -63,6 +75,9 @@ public function update(Request $request, string $id)
*/
public function destroy(string $id)
{
//
$photo = Photo::where("uuid", $id)->first();
if(!$photo) redirect()->back()->withErrors(["uuid" => "Photo introuvable" ]);
$photo->delete();
return redirect(route("photo.index"))->with(["message" => "Photo supprimée avec success"]);
}
}

@ -0,0 +1,105 @@
<?php
namespace App\Http\Controllers;
use App\Utils\S3;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\Storage;
use Normalizer;
class S3Controller extends Controller
{
private $bucket;
public function __construct() {
$this->bucket = config("filesystems.disks.s3.bucket");
}
private static function NormalizeName($name) {
// Normalize the filename according to the NFC convention
// Requires php-intl module
// More info: https://www.php.net/manual/en/class.normalizer.php
if (class_exists('Normalizer')) {
$normalized_filename = Normalizer::normalize($name, Normalizer::FORM_C);
if ($normalized_filename !== false) {
return $normalized_filename;
}
} else {
// If Normalizer is not installed, we transform the text into an
// ASCII representation without diacritics.
return iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $name);
}
return $name;
}
public function GeneratePresignedUrl(Request $request)
{
return response()->json([ "url" => S3::signUrl($request->key) ]);
}
public function StartMultipartUpload(Request $request)
{
$filename = "tmp/" . Str::random(10) . "_" . Str::replace(" ", "_", $request->filename);
$client = ((object)Storage::disk("s3"))->getClient();
$result = $client->createMultipartUpload([
"Bucket" => $this->bucket,
"Key" => $filename,
'ContentDisposition' => 'inline',
]);
return response()->json([
"uploadId" => $result["UploadId"],
"key" => $filename,
]);
}
public function GeneratePresignedMultipartUrl(Request $request)
{
$client = ((object)Storage::disk("s3"))->getClient();
$command = $client->getCommand('UploadPart', [
"Bucket" => $this->bucket,
"Key" => $request->key,
"UploadId" => $request->uploadId,
"ContentLength" => $request->partLength,
"PartNumber" => $request->partNumber,
]);
$preSignedUrl = $client->createPresignedRequest($command, Carbon::tomorrow());
return response()->json([ "url" => (string)$preSignedUrl->getUri() ]);
}
public function CompleteMultipartUpload(Request $request)
{
$client = ((object)Storage::disk("s3"))->getClient();
$result = $client->completeMultipartUpload([
"Bucket" => $this->bucket,
"Key" => $request->key,
"UploadId" => $request->uploadId,
"MultipartUpload" => [
"Parts" => $request->parts
]
]);
return response()->json([ "message" => "Upload completed", "Location" => $result["Location"] ]);
}
public function ProxyS3(Request $request)
{
$response = Http::withBody($request->getContent(), "binary/octet-stream")->withHeaders([ "Content-Length" => $request->header("Content-Length") ])->put($request->header("X-SignedUrl"));
$ETag = $response->getHeader("ETag") ? $response->getHeader("ETag")[0] : dd($response);
return response(json_encode([
"ETag" => $ETag
]), $response->status());
}
public function Download(Request $request)
{
$url = S3::signUrl($request->key);
return redirect($url);
}
}

@ -2,6 +2,8 @@
namespace App\Models;
use App\Utils\S3;
use Illuminate\Database\Eloquent\Model;
class Photo extends Model
@ -9,5 +11,24 @@ class Photo extends Model
protected $fillable = [
'name',
'path',
'uuid',
'user_id'
];
public function user()
{
return $this->belongsTo(User::class);
}
public function jsonSerialize():array
{
return [
'id' => $this->id,
'uuid' => $this->uuid,
'name' => $this->name,
'path' => S3::signUrl($this->path),
'user' => $this->user,
];
}
}

@ -21,7 +21,11 @@ class User extends Authenticatable
'name',
'email',
'password',
'email_verified_at'
'email_verified_at',
'totem',
'tel',
'contactable',
'role',
];
/**
@ -46,4 +50,9 @@ protected function casts(): array
'password' => 'hashed',
];
}
public function photos()
{
return $this->hasMany(Photo::class);
}
}

@ -0,0 +1,25 @@
<?php
namespace App\Utils;
use Carbon\Carbon;
use Illuminate\Support\Facades\Storage;
class S3
{
public static function encodeURI($str)
{
$revert = ['%21'=>'!', '%2A'=>'*', '%27'=>"'", '%28'=>'(', '%29'=>')', '%2F'=>'/'];
return strtr(rawurlencode($str), $revert);
}
public static function signUrl($key){
$client = ((object)Storage::disk("s3"))->getClient();
$bucket = config("filesystems.disks.s3.bucket");
$command = $client->getCommand('GetObject', [
"Bucket" => $bucket,
"Key" => $key
]);
return (string)$client->createPresignedRequest($command, Carbon::tomorrow())->getUri();
}
}

@ -12,6 +12,8 @@
"laravel/framework": "^11.31",
"laravel/sanctum": "^4.0",
"laravel/tinker": "^2.9",
"league/flysystem": "^3.29",
"league/flysystem-aws-s3-v3": "^3.29",
"tightenco/ziggy": "^2.0"
},
"require-dev": {

275
composer.lock generated

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "00eb55bee5045608ccbc5fe1b47ebac8",
"content-hash": "52a54306259a78af065842cfdf574e84",
"packages": [
{
"name": "archtechx/enums",
@ -52,6 +52,158 @@
},
"time": "2024-10-29T15:38:32+00:00"
},
{
"name": "aws/aws-crt-php",
"version": "v1.2.7",
"source": {
"type": "git",
"url": "https://github.com/awslabs/aws-crt-php.git",
"reference": "d71d9906c7bb63a28295447ba12e74723bd3730e"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/awslabs/aws-crt-php/zipball/d71d9906c7bb63a28295447ba12e74723bd3730e",
"reference": "d71d9906c7bb63a28295447ba12e74723bd3730e",
"shasum": ""
},
"require": {
"php": ">=5.5"
},
"require-dev": {
"phpunit/phpunit": "^4.8.35||^5.6.3||^9.5",
"yoast/phpunit-polyfills": "^1.0"
},
"suggest": {
"ext-awscrt": "Make sure you install awscrt native extension to use any of the functionality."
},
"type": "library",
"autoload": {
"classmap": [
"src/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "AWS SDK Common Runtime Team",
"email": "aws-sdk-common-runtime@amazon.com"
}
],
"description": "AWS Common Runtime for PHP",
"homepage": "https://github.com/awslabs/aws-crt-php",
"keywords": [
"amazon",
"aws",
"crt",
"sdk"
],
"support": {
"issues": "https://github.com/awslabs/aws-crt-php/issues",
"source": "https://github.com/awslabs/aws-crt-php/tree/v1.2.7"
},
"time": "2024-10-18T22:15:13+00:00"
},
{
"name": "aws/aws-sdk-php",
"version": "3.337.2",
"source": {
"type": "git",
"url": "https://github.com/aws/aws-sdk-php.git",
"reference": "f885dd803a257da9d54e72a4750bba73e1196aee"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/aws/aws-sdk-php/zipball/f885dd803a257da9d54e72a4750bba73e1196aee",
"reference": "f885dd803a257da9d54e72a4750bba73e1196aee",
"shasum": ""
},
"require": {
"aws/aws-crt-php": "^1.2.3",
"ext-json": "*",
"ext-pcre": "*",
"ext-simplexml": "*",
"guzzlehttp/guzzle": "^6.5.8 || ^7.4.5",
"guzzlehttp/promises": "^1.4.0 || ^2.0",
"guzzlehttp/psr7": "^1.9.1 || ^2.4.5",
"mtdowling/jmespath.php": "^2.6",
"php": ">=7.2.5",
"psr/http-message": "^1.0 || ^2.0"
},
"require-dev": {
"andrewsville/php-token-reflection": "^1.4",
"aws/aws-php-sns-message-validator": "~1.0",
"behat/behat": "~3.0",
"composer/composer": "^1.10.22",
"dms/phpunit-arraysubset-asserts": "^0.4.0",
"doctrine/cache": "~1.4",
"ext-dom": "*",
"ext-openssl": "*",
"ext-pcntl": "*",
"ext-sockets": "*",
"nette/neon": "^2.3",
"paragonie/random_compat": ">= 2",
"phpunit/phpunit": "^5.6.3 || ^8.5 || ^9.5",
"psr/cache": "^1.0 || ^2.0 || ^3.0",
"psr/simple-cache": "^1.0 || ^2.0 || ^3.0",
"sebastian/comparator": "^1.2.3 || ^4.0",
"yoast/phpunit-polyfills": "^1.0"
},
"suggest": {
"aws/aws-php-sns-message-validator": "To validate incoming SNS notifications",
"doctrine/cache": "To use the DoctrineCacheAdapter",
"ext-curl": "To send requests using cURL",
"ext-openssl": "Allows working with CloudFront private distributions and verifying received SNS messages",
"ext-sockets": "To use client-side monitoring"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.0-dev"
}
},
"autoload": {
"files": [
"src/functions.php"
],
"psr-4": {
"Aws\\": "src/"
},
"exclude-from-classmap": [
"src/data/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Apache-2.0"
],
"authors": [
{
"name": "Amazon Web Services",
"homepage": "http://aws.amazon.com"
}
],
"description": "AWS SDK for PHP - Use Amazon Web Services in your PHP project",
"homepage": "http://aws.amazon.com/sdkforphp",
"keywords": [
"amazon",
"aws",
"cloud",
"dynamodb",
"ec2",
"glacier",
"s3",
"sdk"
],
"support": {
"forum": "https://forums.aws.amazon.com/forum.jspa?forumID=80",
"issues": "https://github.com/aws/aws-sdk-php/issues",
"source": "https://github.com/aws/aws-sdk-php/tree/3.337.2"
},
"time": "2025-01-17T19:10:04+00:00"
},
{
"name": "brick/math",
"version": "0.12.1",
@ -3452,6 +3604,61 @@
},
"time": "2024-10-08T08:58:34+00:00"
},
{
"name": "league/flysystem-aws-s3-v3",
"version": "3.29.0",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/flysystem-aws-s3-v3.git",
"reference": "c6ff6d4606e48249b63f269eba7fabdb584e76a9"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/flysystem-aws-s3-v3/zipball/c6ff6d4606e48249b63f269eba7fabdb584e76a9",
"reference": "c6ff6d4606e48249b63f269eba7fabdb584e76a9",
"shasum": ""
},
"require": {
"aws/aws-sdk-php": "^3.295.10",
"league/flysystem": "^3.10.0",
"league/mime-type-detection": "^1.0.0",
"php": "^8.0.2"
},
"conflict": {
"guzzlehttp/guzzle": "<7.0",
"guzzlehttp/ringphp": "<1.1.1"
},
"type": "library",
"autoload": {
"psr-4": {
"League\\Flysystem\\AwsS3V3\\": ""
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Frank de Jonge",
"email": "info@frankdejonge.nl"
}
],
"description": "AWS S3 filesystem adapter for Flysystem.",
"keywords": [
"Flysystem",
"aws",
"file",
"files",
"filesystem",
"s3",
"storage"
],
"support": {
"source": "https://github.com/thephpleague/flysystem-aws-s3-v3/tree/3.29.0"
},
"time": "2024-08-17T13:10:48+00:00"
},
{
"name": "league/flysystem-local",
"version": "3.29.0",
@ -3660,6 +3867,72 @@
],
"time": "2024-11-12T13:57:08+00:00"
},
{
"name": "mtdowling/jmespath.php",
"version": "2.8.0",
"source": {
"type": "git",
"url": "https://github.com/jmespath/jmespath.php.git",
"reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/jmespath/jmespath.php/zipball/a2a865e05d5f420b50cc2f85bb78d565db12a6bc",
"reference": "a2a865e05d5f420b50cc2f85bb78d565db12a6bc",
"shasum": ""
},
"require": {
"php": "^7.2.5 || ^8.0",
"symfony/polyfill-mbstring": "^1.17"
},
"require-dev": {
"composer/xdebug-handler": "^3.0.3",
"phpunit/phpunit": "^8.5.33"
},
"bin": [
"bin/jp.php"
],
"type": "library",
"extra": {
"branch-alias": {
"dev-master": "2.8-dev"
}
},
"autoload": {
"files": [
"src/JmesPath.php"
],
"psr-4": {
"JmesPath\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Graham Campbell",
"email": "hello@gjcampbell.co.uk",
"homepage": "https://github.com/GrahamCampbell"
},
{
"name": "Michael Dowling",
"email": "mtdowling@gmail.com",
"homepage": "https://github.com/mtdowling"
}
],
"description": "Declaratively specify how to extract elements from a JSON document",
"keywords": [
"json",
"jsonpath"
],
"support": {
"issues": "https://github.com/jmespath/jmespath.php/issues",
"source": "https://github.com/jmespath/jmespath.php/tree/2.8.0"
},
"time": "2024-09-04T18:46:31+00:00"
},
{
"name": "nesbot/carbon",
"version": "3.8.2",

@ -0,0 +1,28 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table('photos', function (Blueprint $table) {
$table->uuid('uuid')->unique()->after('id');
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('photos', function (Blueprint $table) {
$table->dropColumn("uuid");
});
}
};

@ -0,0 +1,32 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table("users", function (Blueprint $table) {
$table->string("totem", 100)->default("");
$table->string("tel", 25)->default("");
$table->string("role", 255)->default("");
$table->tinyInteger("contactable")->default(0);
$table->string("path")->default("profiles/none.png");
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table("users", function (Blueprint $table) {
$table->dropColumns(["totem", "tel", "role"]);
});
}
};

@ -0,0 +1,27 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
Schema::table("photos", function (Blueprint $table) {
$table->unsignedBigInteger("user_id");
$table->foreign("user_id")->references("id")->on("users");
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
//
}
};

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><title>Account Settings</title><path d="M9.6,3.32a3.86,3.86,0,1,0,3.86,3.85A3.85,3.85,0,0,0,9.6,3.32M16.35,11a.26.26,0,0,0-.25.21l-.18,1.27a4.63,4.63,0,0,0-.82.45l-1.2-.48a.3.3,0,0,0-.3.13l-1,1.66a.24.24,0,0,0,.06.31l1,.79a3.94,3.94,0,0,0,0,1l-1,.79a.23.23,0,0,0-.06.3l1,1.67c.06.13.19.13.3.13l1.2-.49a3.85,3.85,0,0,0,.82.46l.18,1.27a.24.24,0,0,0,.25.2h1.93a.24.24,0,0,0,.23-.2l.18-1.27a5,5,0,0,0,.81-.46l1.19.49c.12,0,.25,0,.32-.13l1-1.67a.23.23,0,0,0-.06-.3l-1-.79a4,4,0,0,0,0-.49,2.67,2.67,0,0,0,0-.48l1-.79a.25.25,0,0,0,.06-.31l-1-1.66c-.06-.13-.19-.13-.31-.13L19.5,13a4.07,4.07,0,0,0-.82-.45l-.18-1.27a.23.23,0,0,0-.22-.21H16.46M9.71,13C5.45,13,2,14.7,2,16.83v1.92h9.33a6.65,6.65,0,0,1,0-5.69A13.56,13.56,0,0,0,9.71,13m7.6,1.43a1.45,1.45,0,1,1,0,2.89,1.45,1.45,0,0,1,0-2.89Z"/></svg>

After

Width:  |  Height:  |  Size: 1011 B

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="Edit / Add_Plus_Circle">
<path id="Vector" d="M8 12H12M12 12H16M12 12V16M12 12V8M12 21C7.02944 21 3 16.9706 3 12C3 7.02944 7.02944 3 12 3C16.9706 3 21 7.02944 21 12C21 16.9706 16.9706 21 12 21Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 524 B

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 14.5V16.5M7 10.0288C7.47142 10 8.05259 10 8.8 10H15.2C15.9474 10 16.5286 10 17 10.0288M7 10.0288C6.41168 10.0647 5.99429 10.1455 5.63803 10.327C5.07354 10.6146 4.6146 11.0735 4.32698 11.638C4 12.2798 4 13.1198 4 14.8V16.2C4 17.8802 4 18.7202 4.32698 19.362C4.6146 19.9265 5.07354 20.3854 5.63803 20.673C6.27976 21 7.11984 21 8.8 21H15.2C16.8802 21 17.7202 21 18.362 20.673C18.9265 20.3854 19.3854 19.9265 19.673 19.362C20 18.7202 20 17.8802 20 16.2V14.8C20 13.1198 20 12.2798 19.673 11.638C19.3854 11.0735 18.9265 10.6146 18.362 10.327C18.0057 10.1455 17.5883 10.0647 17 10.0288M7 10.0288V8C7 5.23858 9.23858 3 12 3C14.7614 3 17 5.23858 17 8V10.0288" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 974 B

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M8 10C7.44772 10 7 10.4477 7 11C7 11.5523 7.44772 12 8 12H16C16.5523 12 17 11.5523 17 11C17 10.4477 16.5523 10 16 10H8Z" fill="#0F0F0F"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M23 4C23 2.34315 21.6569 1 20 1H4C2.34315 1 1 2.34315 1 4V5C1 6.30622 1.83481 7.41746 3 7.82929V20C3 21.6569 4.34315 23 6 23H18C19.6569 23 21 21.6569 21 20V7.82929C22.1652 7.41746 23 6.30622 23 5V4ZM20 6H4C3.44772 6 3 5.55228 3 5V4C3 3.44772 3.44772 3 4 3H20C20.5523 3 21 3.44772 21 4V5C21 5.55228 20.5523 6 20 6ZM5 20V8H19V20C19 20.5523 18.5523 21 18 21H6C5.44772 21 5 20.5523 5 20Z" fill="#0F0F0F"/>
</svg>

After

Width:  |  Height:  |  Size: 825 B

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 256 256" id="Flat" xmlns="http://www.w3.org/2000/svg">
<path d="M120,48v64a7.9954,7.9954,0,0,1-8,8H48a7.99539,7.99539,0,0,1-8-8V48a7.99539,7.99539,0,0,1,8-8h64A7.9954,7.9954,0,0,1,120,48Zm88-8H144a7.99539,7.99539,0,0,0-8,8v64a7.99539,7.99539,0,0,0,8,8h64a7.9954,7.9954,0,0,0,8-8V48A7.9954,7.9954,0,0,0,208,40Zm-96,96H48a7.99539,7.99539,0,0,0-8,8v64a7.99539,7.99539,0,0,0,8,8h64a7.9954,7.9954,0,0,0,8-8V144A7.9954,7.9954,0,0,0,112,136Zm96,0H144a7.99539,7.99539,0,0,0-8,8v64a7.99539,7.99539,0,0,0,8,8h64a7.9954,7.9954,0,0,0,8-8V144A7.9954,7.9954,0,0,0,208,136Z"/>
</svg>

After

Width:  |  Height:  |  Size: 751 B

Before

Width:  |  Height:  |  Size: 580 B

After

Width:  |  Height:  |  Size: 580 B

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg"><defs><style>.cls-1{fill:none;stroke:#020202;stroke-miterlimit:10;stroke-width:1.91px;}</style></defs><circle class="cls-1" cx="12" cy="5.32" r="3.82"/><line class="cls-1" x1="14.55" y1="2.77" x2="9.45" y2="7.86"/><polyline class="cls-1" points="18.59 7.23 22.5 7.23 22.5 22.5 1.5 22.5 1.5 7.23 5.41 7.23"/><polyline class="cls-1" points="1.5 7.23 12 17.73 22.5 7.23"/><line class="cls-1" x1="9.14" y1="14.86" x2="1.5" y2="22.5"/><line class="cls-1" x1="22.5" y1="22.5" x2="14.86" y2="14.86"/><polyline class="cls-1" points="18.59 7.23 22.5 7.23 22.5 22.5 1.5 22.5 1.5 7.23 5.41 7.23"/></svg>

After

Width:  |  Height:  |  Size: 833 B

Before

Width:  |  Height:  |  Size: 645 B

After

Width:  |  Height:  |  Size: 645 B

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg">
<title>cancel2</title>
<path d="M19.587 16.001l6.096 6.096c0.396 0.396 0.396 1.039 0 1.435l-2.151 2.151c-0.396 0.396-1.038 0.396-1.435 0l-6.097-6.096-6.097 6.096c-0.396 0.396-1.038 0.396-1.434 0l-2.152-2.151c-0.396-0.396-0.396-1.038 0-1.435l6.097-6.096-6.097-6.097c-0.396-0.396-0.396-1.039 0-1.435l2.153-2.151c0.396-0.396 1.038-0.396 1.434 0l6.096 6.097 6.097-6.097c0.396-0.396 1.038-0.396 1.435 0l2.151 2.152c0.396 0.396 0.396 1.038 0 1.435l-6.096 6.096z"></path>
</svg>

After

Width:  |  Height:  |  Size: 710 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 -2 20 20" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>communication / 2 - communication, email, envelope, mail, message icon</title>
<g id="Free-Icons" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" stroke-linecap="round" stroke-linejoin="round">
<g transform="translate(-821.000000, -84.000000)" id="Group" stroke="#000000" stroke-width="2">
<g transform="translate(819.000000, 80.000000)" id="Shape">
<polyline points="3.99663853 6 12 11 19.995112 6">
</polyline>
<path d="M4.39663853,19 C3.62343988,19 2.99663853,18.4428432 2.99663853,17.7555556 L2.99663853,6.24444444 C2.99663853,5.55715676 3.62343988,5 4.39663853,5 L19.595112,5 C20.3683106,5 20.995112,5.55715676 20.995112,6.24444444 L20.995112,17.7555556 C20.995112,18.4428432 20.3683106,19 19.595112,19 L4.39663853,19 Z">
</path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16 8L8 16M8.00001 8L16 16" stroke="#000000" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 349 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M12 16C14.2091 16 16 14.2091 16 12C16 9.79086 14.2091 8 12 8V16Z" fill="#000000"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M12 2C6.47715 2 2 6.47715 2 12C2 17.5228 6.47715 22 12 22C17.5228 22 22 17.5228 22 12C22 6.47715 17.5228 2 12 2ZM12 4V8C9.79086 8 8 9.79086 8 12C8 14.2091 9.79086 16 12 16V20C16.4183 20 20 16.4183 20 12C20 7.58172 16.4183 4 12 4Z" fill="#000000"/>
</svg>

After

Width:  |  Height:  |  Size: 616 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

@ -0,0 +1,2 @@
<?xml version="1.0" ?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M16.5163 8.93451L11.0597 14.7023L8.0959 11.8984" stroke="#000000" stroke-width="2"/><path d="M12 21C16.9706 21 21 16.9706 21 12C21 7.02944 16.9706 3 12 3C7.02944 3 3 7.02944 3 12C3 16.9706 7.02944 21 12 21Z" stroke="#000000" stroke-width="2"/></svg>

After

Width:  |  Height:  |  Size: 462 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.8 KiB

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.7071 14.7071C12.3166 15.0976 11.6834 15.0976 11.2929 14.7071L6.29289 9.70711C5.90237 9.31658 5.90237 8.68342 6.29289 8.29289C6.68342 7.90237 7.31658 7.90237 7.70711 8.29289L12 12.5858L16.2929 8.29289C16.6834 7.90237 17.3166 7.90237 17.7071 8.29289C18.0976 8.68342 18.0976 9.31658 17.7071 9.70711L12.7071 14.7071Z" fill="#000000"/>
</svg>

After

Width:  |  Height:  |  Size: 611 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 858 B

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 32 32" id="icon" xmlns="http://www.w3.org/2000/svg"><defs><style>.cls-1{fill:none;}</style></defs><title>enterprise</title><rect x="8" y="8" width="2" height="4"/><rect x="8" y="14" width="2" height="4"/><rect x="14" y="8" width="2" height="4"/><rect x="14" y="14" width="2" height="4"/><rect x="8" y="20" width="2" height="4"/><rect x="14" y="20" width="2" height="4"/><path d="M30,14a2,2,0,0,0-2-2H22V4a2,2,0,0,0-2-2H4A2,2,0,0,0,2,4V30H30ZM4,4H20V28H4ZM22,28V14h6V28Z"/><rect id="_Transparent_Rectangle_" data-name="&lt;Transparent Rectangle&gt;" class="cls-1" width="32" height="32"/></svg>

After

Width:  |  Height:  |  Size: 774 B

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#FF0000" height="800px" width="800px" version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 511.76 511.76" xml:space="preserve">
<g>
<g>
<path d="M436.896,74.869c-99.84-99.819-262.208-99.819-362.048,0c-99.797,99.819-99.797,262.229,0,362.048
c49.92,49.899,115.477,74.837,181.035,74.837s131.093-24.939,181.013-74.837C536.715,337.099,536.715,174.688,436.896,74.869z
M361.461,331.317c8.341,8.341,8.341,21.824,0,30.165c-4.16,4.16-9.621,6.251-15.083,6.251c-5.461,0-10.923-2.091-15.083-6.251
l-75.413-75.435l-75.392,75.413c-4.181,4.16-9.643,6.251-15.083,6.251c-5.461,0-10.923-2.091-15.083-6.251
c-8.341-8.341-8.341-21.845,0-30.165l75.392-75.413l-75.413-75.413c-8.341-8.341-8.341-21.845,0-30.165
c8.32-8.341,21.824-8.341,30.165,0l75.413,75.413l75.413-75.413c8.341-8.341,21.824-8.341,30.165,0
c8.341,8.32,8.341,21.824,0,30.165l-75.413,75.413L361.461,331.317z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 811 B

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 409 B

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g id="File / File_Add">
<path id="Vector" d="M12 18V15M12 15V12M12 15H9M12 15H15M13 3.00087C12.9045 3 12.7973 3 12.6747 3H8.2002C7.08009 3 6.51962 3 6.0918 3.21799C5.71547 3.40973 5.40973 3.71547 5.21799 4.0918C5 4.51962 5 5.08009 5 6.2002V17.8002C5 18.9203 5 19.4801 5.21799 19.9079C5.40973 20.2842 5.71547 20.5905 6.0918 20.7822C6.51921 21 7.079 21 8.19694 21L15.8031 21C16.921 21 17.48 21 17.9074 20.7822C18.2837 20.5905 18.5905 20.2842 18.7822 19.9079C19 19.4805 19 18.9215 19 17.8036V9.32568C19 9.20296 19 9.09561 18.9991 9M13 3.00087C13.2856 3.00347 13.4663 3.01385 13.6388 3.05526C13.8429 3.10425 14.0379 3.18526 14.2168 3.29492C14.4186 3.41857 14.5918 3.59182 14.9375 3.9375L18.063 7.06298C18.4089 7.40889 18.5809 7.58136 18.7046 7.78319C18.8142 7.96214 18.8953 8.15726 18.9443 8.36133C18.9857 8.53376 18.9963 8.71451 18.9991 9M13 3.00087V5.8C13 6.9201 13 7.47977 13.218 7.90759C13.4097 8.28392 13.7155 8.59048 14.0918 8.78223C14.5192 9 15.079 9 16.1969 9H18.9991M18.9991 9H19.0002" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" clip-rule="evenodd" d="M15 10.5A3.502 3.502 0 0 0 18.355 8H21a1 1 0 1 0 0-2h-2.645a3.502 3.502 0 0 0-6.71 0H3a1 1 0 0 0 0 2h8.645A3.502 3.502 0 0 0 15 10.5zM3 16a1 1 0 1 0 0 2h2.145a3.502 3.502 0 0 0 6.71 0H21a1 1 0 1 0 0-2h-9.145a3.502 3.502 0 0 0-6.71 0H3z" fill="#000000"/></svg>

After

Width:  |  Height:  |  Size: 528 B

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M23 4C23 2.34315 21.6569 1 20 1H16C15.4477 1 15 1.44772 15 2C15 2.55228 15.4477 3 16 3H20C20.5523 3 21 3.44772 21 4V8C21 8.55228 21.4477 9 22 9C22.5523 9 23 8.55228 23 8V4Z" fill="#0F0F0F"/>
<path d="M23 16C23 15.4477 22.5523 15 22 15C21.4477 15 21 15.4477 21 16V20C21 20.5523 20.5523 21 20 21H16C15.4477 21 15 21.4477 15 22C15 22.5523 15.4477 23 16 23H20C21.6569 23 23 21.6569 23 20V16Z" fill="#0F0F0F"/>
<path d="M4 21H8C8.55228 21 9 21.4477 9 22C9 22.5523 8.55228 23 8 23H4C2.34315 23 1 21.6569 1 20V16C1 15.4477 1.44772 15 2 15C2.55228 15 3 15.4477 3 16V20C3 20.5523 3.44772 21 4 21Z" fill="#0F0F0F"/>
<path d="M1 8C1 8.55228 1.44772 9 2 9C2.55228 9 3 8.55228 3 8L3 4C3 3.44772 3.44772 3 4 3H8C8.55228 3 9 2.55228 9 2C9 1.44772 8.55228 1 8 1H4C2.34315 1 1 2.34315 1 4V8Z" fill="#0F0F0F"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" >
<path d="M0 0h48v48H0z" fill="none"/>
<g id="Shopicon">
<path d="M11.957,33.214L7.171,38L10,40.828l5.305-5.305C17.867,36.992,20.788,38,24,38c12,0,20-14,20-14s-2.953-5.159-7.957-9.214
L40.829,10L38,7.172l-5.305,5.305C30.133,11.008,27.212,10,24,10C12,10,4,24,4,24S6.953,29.159,11.957,33.214z M16,24
c0-4.418,3.582-8,8-8c1.483,0,2.867,0.411,4.058,1.114l-3.035,3.035C24.694,20.062,24.356,20,24,20c-2.206,0-4,1.794-4,4
c0,0.356,0.062,0.694,0.149,1.023l-3.035,3.035C16.411,26.867,16,25.483,16,24z M32,24c0,4.418-3.582,8-8,8
c-1.483,0-2.867-0.411-4.058-1.114l3.035-3.035C23.306,27.938,23.644,28,24,28c2.206,0,4-1.794,4-4
c0-0.356-0.062-0.694-0.149-1.023l3.035-3.035C31.589,21.133,32,22.517,32,24z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 937 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 6V15H6V11C6 9.89543 6.89543 9 8 9C9.10457 9 10 9.89543 10 11V15H15V6L8 0L1 6Z" fill="#000000"/>
</svg>

After

Width:  |  Height:  |  Size: 335 B

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.1 KiB

Before

Width:  |  Height:  |  Size: 347 B

After

Width:  |  Height:  |  Size: 347 B

Before

Width:  |  Height:  |  Size: 788 B

After

Width:  |  Height:  |  Size: 788 B

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 22 22" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>file_done [#1705]</title>
<desc>Created with Sketch.</desc>
<defs>
</defs>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Dribbble-Light-Preview" transform="translate(-298.000000, -1479.000000)" fill="#000000">
<g id="icons" transform="translate(56.000000, 160.000000)">
<path d="M245.329132,1332.84581 C245.316153,1332.84581 245.302175,1332.84482 245.288198,1332.84482 C245.282208,1332.84482 245.279212,1332.84581 245.273222,1332.84581 L245.329132,1332.84581 Z M263.893198,1324.84886 L258.711553,1319.4401 C258.524854,1319.25615 258.271263,1319 258.007688,1319 L246.439342,1319 L246.41538,1319 C245.325138,1319 244.218922,1320.02756 244.218922,1321.10654 L243.996281,1321.25884 L243.996281,1332.16143 C243.996281,1332.69449 244.740082,1332.8379 245.288198,1332.84482 C245.825332,1332.84185 245.993061,1332.70142 245.993061,1332.16143 L245.993061,1322.27157 C245.993061,1321.72466 246.885622,1320.97797 247.437732,1320.97797 L255.976963,1320.97797 L255.976963,1325.26226 C255.976963,1326.34125 257.30582,1326.91189 258.396062,1326.91189 L261.967303,1326.91189 L261.967303,1336.11737 C261.967303,1336.6633 261.966305,1336.80175 261.415194,1336.80175 L251.431292,1336.80175 C250.892162,1336.80175 250.034545,1337.36844 249.994609,1337.90447 C250.034545,1338.42864 250.892162,1338.77973 251.431292,1338.77973 L262.413584,1338.77973 L262.437545,1338.77973 C263.526789,1338.77973 263.964084,1338.20908 263.964084,1337.1301 L263.964084,1337.08263 L263.964084,1325.62522 C263.964084,1325.36215 264.080895,1325.03381 263.893198,1324.84886 L263.893198,1324.84886 Z M249.986622,1337.94304 C249.986622,1337.93019 249.993611,1337.91733 249.994609,1337.90447 C249.993611,1337.89162 249.986622,1337.87975 249.986622,1337.86689 L249.986622,1337.94304 Z M248.5739,1335.45574 C248.96427,1335.84244 248.96427,1336.46846 248.5739,1336.85417 L244.388648,1341 L244.303785,1340.91495 L244.303785,1340.91495 L242.292029,1338.92214 C241.902657,1338.53644 241.902657,1337.91041 242.292029,1337.52371 C242.6824,1337.13801 243.314381,1337.13801 243.703753,1337.52371 L244.388648,1338.20216 L247.162176,1335.45574 C247.551548,1335.07004 248.183529,1335.07004 248.5739,1335.45574 L248.5739,1335.45574 Z" id="file_done-[#1705]">
</path>
</g>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M7.706 0.290 C 7.484 0.362,7.356 0.490,7.294 0.699 C 7.259 0.816,7.253 1.088,7.253 2.508 C 7.253 4.389,7.251 4.365,7.443 4.557 C 7.700 4.813,8.300 4.813,8.557 4.557 C 8.749 4.365,8.747 4.389,8.747 2.508 C 8.747 0.688,8.744 0.656,8.596 0.480 C 8.472 0.333,8.339 0.284,8.040 0.276 C 7.893 0.272,7.743 0.278,7.706 0.290 M2.753 2.266 C 2.595 2.338,2.362 2.566,2.281 2.728 C 2.197 2.897,2.193 3.085,2.269 3.253 C 2.343 3.418,4.667 5.750,4.850 5.843 C 5.109 5.976,5.375 5.911,5.643 5.649 C 5.907 5.391,5.977 5.111,5.843 4.850 C 5.750 4.667,3.418 2.343,3.253 2.269 C 3.101 2.200,2.901 2.199,2.753 2.266 M12.853 2.282 C 12.730 2.339,12.520 2.536,11.518 3.541 C 10.597 4.464,10.316 4.762,10.271 4.860 C 10.195 5.025,10.196 5.216,10.272 5.378 C 10.342 5.528,10.572 5.764,10.727 5.845 C 10.884 5.927,11.117 5.926,11.280 5.843 C 11.447 5.757,13.757 3.447,13.843 3.280 C 13.926 3.118,13.927 2.884,13.846 2.729 C 13.764 2.572,13.552 2.364,13.392 2.283 C 13.213 2.192,13.048 2.192,12.853 2.282 M0.699 7.292 C 0.404 7.385,0.258 7.620,0.258 7.999 C 0.259 8.386,0.403 8.618,0.698 8.706 C 0.816 8.741,1.079 8.747,2.508 8.747 C 3.997 8.747,4.196 8.742,4.318 8.702 C 4.498 8.644,4.644 8.498,4.702 8.318 C 4.788 8.053,4.745 7.677,4.608 7.491 C 4.578 7.451,4.492 7.384,4.417 7.343 L 4.280 7.267 2.547 7.261 C 1.152 7.257,0.791 7.263,0.699 7.292 M11.745 7.278 C 11.622 7.308,11.452 7.411,11.392 7.492 C 11.255 7.677,11.212 8.053,11.298 8.318 C 11.356 8.498,11.502 8.644,11.682 8.702 C 11.804 8.742,12.003 8.747,13.492 8.747 C 14.921 8.747,15.184 8.741,15.302 8.706 C 15.597 8.618,15.741 8.386,15.742 7.999 C 15.742 7.614,15.595 7.383,15.290 7.291 C 15.187 7.260,14.864 7.254,13.496 7.256 C 12.578 7.258,11.790 7.268,11.745 7.278 M4.853 10.282 C 4.730 10.339,4.520 10.536,3.518 11.541 C 2.597 12.464,2.316 12.762,2.271 12.860 C 2.195 13.025,2.196 13.216,2.272 13.378 C 2.342 13.528,2.572 13.764,2.727 13.845 C 2.884 13.927,3.117 13.926,3.280 13.843 C 3.447 13.757,5.757 11.447,5.843 11.280 C 5.926 11.118,5.927 10.884,5.846 10.729 C 5.764 10.572,5.552 10.364,5.392 10.283 C 5.213 10.192,5.048 10.192,4.853 10.282 M10.753 10.266 C 10.595 10.338,10.362 10.566,10.281 10.728 C 10.197 10.897,10.193 11.085,10.269 11.253 C 10.343 11.418,12.667 13.750,12.850 13.843 C 13.109 13.976,13.375 13.911,13.643 13.649 C 13.907 13.391,13.977 13.111,13.843 12.850 C 13.750 12.667,11.418 10.343,11.253 10.269 C 11.101 10.200,10.901 10.199,10.753 10.266 M7.745 11.277 C 7.620 11.309,7.451 11.412,7.392 11.492 C 7.254 11.678,7.253 11.691,7.253 13.489 C 7.253 14.921,7.259 15.184,7.294 15.302 C 7.382 15.597,7.615 15.741,8.000 15.741 C 8.385 15.741,8.618 15.597,8.706 15.302 C 8.768 15.090,8.767 11.875,8.704 11.690 C 8.644 11.514,8.575 11.430,8.420 11.346 C 8.310 11.286,8.246 11.271,8.057 11.264 C 7.930 11.259,7.790 11.265,7.745 11.277 " stroke="none" fill-rule="evenodd" fill="#000000"></path></svg>

After

Width:  |  Height:  |  Size: 3.0 KiB

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg" fill="none">
<path stroke="#000000" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M20 12h-9.5m7.5 3l3-3-3-3m-5-2V6a2 2 0 00-2-2H6a2 2 0 00-2 2v12a2 2 0 002 2h5a2 2 0 002-2v-1"/>
</svg>

After

Width:  |  Height:  |  Size: 415 B

Before

Width:  |  Height:  |  Size: 558 B

After

Width:  |  Height:  |  Size: 558 B

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M4 6H20M4 12H20M4 18H20" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 344 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.9 KiB

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" id="Layer_1" data-name="Layer 1" xmlns="http://www.w3.org/2000/svg"><defs><style>.cls-1{fill:none;stroke:#020202;stroke-miterlimit:10;stroke-width:1.91px;}</style></defs><path class="cls-1" d="M10.09,13A1.91,1.91,0,0,1,12,11.05h0A1.91,1.91,0,0,1,13.91,13v.17a1.92,1.92,0,0,1-.56,1.35l-.79.79A1.9,1.9,0,0,0,12,16.61v.16"/><path class="cls-1" d="M12,3.41,10.09,1.5H1.5V20.59A1.9,1.9,0,0,0,3.41,22.5H20.59a1.9,1.9,0,0,0,1.91-1.91V3.41Z"/><line class="cls-1" x1="1.5" y1="7.23" x2="22.5" y2="7.23"/><line class="cls-1" x1="11.05" y1="18.68" x2="12.95" y2="18.68"/></svg>

After

Width:  |  Height:  |  Size: 739 B

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M1 22C1 21.4477 1.44772 21 2 21H22C22.5523 21 23 21.4477 23 22C23 22.5523 22.5523 23 22 23H2C1.44772 23 1 22.5523 1 22Z" fill="#0F0F0F"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M18.3056 1.87868C17.1341 0.707107 15.2346 0.707107 14.063 1.87868L3.38904 12.5526C2.9856 12.9561 2.70557 13.4662 2.5818 14.0232L2.04903 16.4206C1.73147 17.8496 3.00627 19.1244 4.43526 18.8069L6.83272 18.2741C7.38969 18.1503 7.89981 17.8703 8.30325 17.4669L18.9772 6.79289C20.1488 5.62132 20.1488 3.72183 18.9772 2.55025L18.3056 1.87868ZM15.4772 3.29289C15.8677 2.90237 16.5009 2.90237 16.8914 3.29289L17.563 3.96447C17.9535 4.35499 17.9535 4.98816 17.563 5.37868L15.6414 7.30026L13.5556 5.21448L15.4772 3.29289ZM12.1414 6.62869L4.80325 13.9669C4.66877 14.1013 4.57543 14.2714 4.53417 14.457L4.0014 16.8545L6.39886 16.3217C6.58452 16.2805 6.75456 16.1871 6.88904 16.0526L14.2272 8.71448L12.1414 6.62869Z" fill="#0F0F0F"/>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.75 5C13.75 5.9665 12.9665 6.75 12 6.75C11.0335 6.75 10.25 5.9665 10.25 5C10.25 4.0335 11.0335 3.25 12 3.25C12.9665 3.25 13.75 4.0335 13.75 5ZM13.75 19C13.75 19.9665 12.9665 20.75 12 20.75C11.0335 20.75 10.25 19.9665 10.25 19C10.25 18.0335 11.0335 17.25 12 17.25C12.9665 17.25 13.75 18.0335 13.75 19ZM12 13.75C12.9665 13.75 13.75 12.9665 13.75 12C13.75 11.0335 12.9665 10.25 12 10.25C11.0335 10.25 10.25 11.0335 10.25 12C10.25 12.9665 11.0335 13.75 12 13.75Z" fill="#000000"/>
</svg>

After

Width:  |  Height:  |  Size: 756 B

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 32 32" id="icon" xmlns="http://www.w3.org/2000/svg">
<defs>
<style>
.cls-1 {
fill: none;
}
</style>
</defs>
<path d="M2,16A14,14,0,1,0,16,2,14,14,0,0,0,2,16Zm6-1H20.15L14.57,9.3926,16,8l8,8-8,8-1.43-1.4272L20.15,17H8Z"/>
<polygon id="inner-path" class="cls-1" points="16 8 14.57 9.393 20.15 15 8 15 8 17 20.15 17 14.57 22.573 16 24 24 16 16 8"/>
<rect id="_Transparent_Rectangle_" data-name="&lt;Transparent Rectangle&gt;" class="cls-1" width="32" height="32"/>
</svg>

After

Width:  |  Height:  |  Size: 687 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 645 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M9.29289 1.29289C9.48043 1.10536 9.73478 1 10 1H18C19.6569 1 21 2.34315 21 4V20C21 21.6569 19.6569 23 18 23H6C4.34315 23 3 21.6569 3 20V8C3 7.73478 3.10536 7.48043 3.29289 7.29289L9.29289 1.29289ZM18 3H11V8C11 8.55228 10.5523 9 10 9H5V14.5858L7.79289 11.7929C8.18342 11.4024 8.81658 11.4024 9.20711 11.7929L13 15.5858L14.2929 14.2929C14.6834 13.9024 15.3166 13.9024 15.7071 14.2929L19 17.5858V4C19 3.44772 18.5523 3 18 3ZM5 20V17.4142L8.5 13.9142L12.2929 17.7071C12.6834 18.0976 13.3166 18.0976 13.7071 17.7071L15 16.4142L18.9269 20.3411L18.9367 20.3508C18.7946 20.7301 18.4288 21 18 21H6C5.44772 21 5 20.5523 5 20ZM6.41421 7H9V4.41421L6.41421 7ZM14.5 13C15.3284 13 16 12.3284 16 11.5C16 10.6716 15.3284 10 14.5 10C13.6716 10 13 10.6716 13 11.5C13 12.3284 13.6716 13 14.5 13Z" fill="#000000"/>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>project</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="Combined-Shape" fill="#000000" transform="translate(64.000000, 34.346667)">
<path d="M192,7.10542736e-15 L384,110.851252 L384,332.553755 L192,443.405007 L1.42108547e-14,332.553755 L1.42108547e-14,110.851252 L192,7.10542736e-15 Z M42.666,157.654 L42.6666667,307.920144 L170.666,381.82 L170.666,231.555 L42.666,157.654 Z M341.333,157.655 L213.333,231.555 L213.333,381.82 L341.333333,307.920144 L341.333,157.655 Z M192,49.267223 L66.1333333,121.936377 L192,194.605531 L317.866667,121.936377 L192,49.267223 Z">
</path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 950 B

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" height="800px" width="800px" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 24 24" xml:space="preserve">
<g id="cubes">
<path d="M17,23.1l-5-2.5l-5,2.5l-6-3v-7.2l5-2.8V3.9l6-3l6,3v6.5l5,2.5v7.2L17,23.1z M18,16.6v3.8l3-1.5v-3.8L18,16.6z M13,18.9
l3,1.5v-3.8l-3-1.5V18.9z M8,16.6v3.8l3-1.5v-3.8L8,16.6z M3,18.9l3,1.5v-3.8l-3-1.5V18.9z M14.2,13.5l2.8,1.4l2.8-1.4L17,12.1
L14.2,13.5z M4.1,13.4L7,14.9l2.9-1.4L7,11.8L4.1,13.4z M13,7.6v4.3l3-1.5V6.1L13,7.6z M8,10.1l3,1.7V7.6L8,6.1V10.1z M9.2,4.5
L12,5.9l2.8-1.4L12,3.1L9.2,4.5z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 746 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg version="1.1" id="Uploaded to svgrepo.com" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
width="800px" height="800px" viewBox="0 0 32 32" xml:space="preserve">
<style type="text/css">
.puchipuchi_een{fill:#111918;}
</style>
<path class="puchipuchi_een" d="M30.291,2.87l-9.581,25.26c-0.39,1.029-1.346,1.234-2.123,0.456c0,0-6.036-6.036-6.586-6.586
s-0.359-1.631,0.425-2.403l13.316-13.11c0.784-0.772,0.711-0.856-0.163-0.187L10.588,17.784c-0.873,0.669-2.224,0.58-3.002-0.198
l-4.172-4.172c-0.778-0.778-0.573-1.733,0.456-2.124l25.26-9.581C30.159,1.319,30.681,1.841,30.291,2.87z M8.707,20.121
C8.318,19.732,8,19.864,8,20.414V25c0,0.55,0.386,0.768,0.857,0.485l2.401-1.441c0.472-0.283,0.539-0.833,0.15-1.222L8.707,20.121z"
/>
</svg>

After

Width:  |  Height:  |  Size: 888 B

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M20 19C20 19.5523 19.5523 20 19 20H5C4.44772 20 4 19.5523 4 19V11.2268L10.0069 16.5663C11.1436 17.5767 12.8564 17.5767 13.9931 16.5663L20 11.2268V19ZM4.56205 8.99999H19.438L12.6402 3.33519C12.2693 3.02615 11.7307 3.02615 11.3598 3.33519L4.56205 8.99999ZM6.7552 11L11.3356 15.0715C11.7145 15.4083 12.2855 15.4083 12.6644 15.0715L17.2448 11H6.7552ZM19 22C20.6569 22 22 20.6568 22 19V8.99999C22 8.70321 21.8682 8.42177 21.6402 8.23177L13.9206 1.79875C12.808 0.871631 11.192 0.871633 10.0794 1.79875L2.35982 8.23177C2.13182 8.42177 2 8.70321 2 8.99999V19C2 20.6568 3.34315 22 5 22H19Z" fill="#000000"/>
</svg>

After

Width:  |  Height:  |  Size: 875 B

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" xmlns="http://www.w3.org/2000/svg"
width="800px" height="800px" viewBox="0 0 52 52" enable-background="new 0 0 52 52" xml:space="preserve">
<g>
<path d="M42,23H10c-2.2,0-4,1.8-4,4v19c0,2.2,1.8,4,4,4h32c2.2,0,4-1.8,4-4V27C46,24.8,44.2,23,42,23z M31,44.5
c-1.5,1-3.2,1.5-5,1.5c-0.6,0-1.2-0.1-1.8-0.2c-2.4-0.5-4.4-1.8-5.7-3.8l3.3-2.2c0.7,1.1,1.9,1.9,3.2,2.1c1.3,0.3,2.6,0,3.8-0.8
c2.3-1.5,2.9-4.7,1.4-6.9c-0.7-1.1-1.9-1.9-3.2-2.1c-1.3-0.3-2.6,0-3.8,0.8c-0.3,0.2-0.5,0.4-0.7,0.6L26,37h-9v-9l2.6,2.6
c0.4-0.4,0.9-0.8,1.3-1.1c2-1.3,4.4-1.8,6.8-1.4c2.4,0.5,4.4,1.8,5.7,3.8C36.2,36.1,35.1,41.7,31,44.5z"/>
<path d="M10,18.1v0.4C10,18.4,10,18.3,10,18.1C10,18.1,10,18.1,10,18.1z"/>
<path d="M11,19h4c0.6,0,1-0.3,1-0.9V18c0-5.7,4.9-10.4,10.7-10C32,8.4,36,13,36,18.4v-0.3c0,0.6,0.4,0.9,1,0.9h4
c0.6,0,1-0.3,1-0.9V18c0-9.1-7.6-16.4-16.8-16c-8.5,0.4-15,7.6-15.2,16.1C10.1,18.6,10.5,19,11,19z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.0 KiB

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M16.6725 16.6412L21 21M19 11C19 15.4183 15.4183 19 11 19C6.58172 19 3 15.4183 3 11C3 6.58172 6.58172 3 11 3C15.4183 3 19 6.58172 19 11Z" stroke="#000000" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 456 B

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 512 512" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
<title>group</title>
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g id="icon" fill="#000000" transform="translate(64.000000, 64.000000)">
<path d="M106.666667,1.42108547e-14 L106.666667,42.6666667 L42.6666667,42.6666667 L42.6666667,341.333333 L106.666667,341.333333 L106.666667,384 L1.42108547e-14,384 L1.42108547e-14,1.42108547e-14 L106.666667,1.42108547e-14 Z M384,1.42108547e-14 L384,384 L277.333333,384 L277.333333,341.333333 L341.333333,341.333333 L341.333333,42.6666667 L277.333333,42.6666667 L277.333333,1.42108547e-14 L384,1.42108547e-14 Z M298.666667,256 L298.666667,298.666667 L85.3333333,298.666667 L85.3333333,256 L298.666667,256 Z M298.666667,170.666667 L298.666667,213.333333 L85.3333333,213.333333 L85.3333333,170.666667 L298.666667,170.666667 Z M298.666667,85.3333333 L298.666667,128 L85.3333333,128 L85.3333333,85.3333333 L298.666667,85.3333333 Z" id="Combined-Shape">
</path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.2 KiB

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M48 0H0V48H48V0Z" fill="white" fill-opacity="0.01"/>
<path d="M43 5L29.7 43L22.1 25.9L5 18.3L43 5Z" stroke="#000000" stroke-width="4" stroke-linejoin="round"/>
<path d="M43.0001 5L22.1001 25.9" stroke="#000000" stroke-width="4" stroke-linecap="round" stroke-linejoin="round"/>
</svg>

After

Width:  |  Height:  |  Size: 513 B

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
<rect x="0" fill="none" width="20" height="20"/>
<g>
<path d="M18 12h-2.18c-.17.7-.44 1.35-.81 1.93l1.54 1.54-2.1 2.1-1.54-1.54c-.58.36-1.23.63-1.91.79V19H8v-2.18c-.68-.16-1.33-.43-1.91-.79l-1.54 1.54-2.12-2.12 1.54-1.54c-.36-.58-.63-1.23-.79-1.91H1V9.03h2.17c.16-.7.44-1.35.8-1.94L2.43 5.55l2.1-2.1 1.54 1.54c.58-.37 1.24-.64 1.93-.81V2h3v2.18c.68.16 1.33.43 1.91.79l1.54-1.54 2.12 2.12-1.54 1.54c.36.59.64 1.24.8 1.94H18V12zm-8.5 1.5c1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3 1.34 3 3 3z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 719 B

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg" >
<path d="M0 0h48v48H0z" fill="none"/>
<g id="Shopicon">
<circle cx="24" cy="24" r="4"/>
<path d="M24,38c12,0,20-14,20-14s-8-14-20-14S4,24,4,24S12,38,24,38z M24,16c4.418,0,8,3.582,8,8s-3.582,8-8,8s-8-3.582-8-8
S19.582,16,24,16z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 464 B

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 16 16" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="si-glyph si-glyph-slide-show">
<title>Slide-show</title>
<defs>
</defs>
<g stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
<g fill="#434343">
<rect x="7" y="0" width="1.906" height="2.219" class="si-glyph-fill">
</rect>
<path d="M15.993,2.621 C15.993,2.287 15.674,2.016 15.281,2.016 L0.781,2.016 C0.387,2.016 0.069,2.287 0.069,2.621 L0.069,3.937 L1.031,3.937 L1.031,11.986 L5.465,11.986 L3.17,14.724 C3.009,14.886 3.069,15.209 3.306,15.446 L3.736,15.875 L7.063,12.105 L7.063,15.968 L8.914,15.968 L8.914,12.002 L12.333,15.874 L12.762,15.445 C12.999,15.209 13.06,14.885 12.898,14.723 L10.533,11.985 L14.939,11.985 L14.939,3.936 L15.995,3.936 L15.995,2.621 L15.993,2.621 Z M14.031,11.106 L1.959,11.106 L1.959,3.937 L14.031,3.937 L14.031,11.106 L14.031,11.106 Z" class="si-glyph-fill">
</path>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

@ -0,0 +1,2 @@
<?xml version="1.0" encoding="utf-8"?><!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg"><path fill="#00B100" d="M512 64a448 448 0 1 1 0 896 448 448 0 0 1 0-896zm-55.808 536.384-99.52-99.584a38.4 38.4 0 1 0-54.336 54.336l126.72 126.72a38.272 38.272 0 0 0 54.336 0l262.4-262.464a38.4 38.4 0 1 0-54.272-54.336L456.192 600.384z"/></svg>

After

Width:  |  Height:  |  Size: 456 B

Before

Width:  |  Height:  |  Size: 620 B

After

Width:  |  Height:  |  Size: 620 B

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg width="800px" height="800px" viewBox="0 0 48 48" xmlns="http://www.w3.org/2000/svg">
<title>category</title>
<g id="Layer_2" data-name="Layer 2">
<g id="invisible_box" data-name="invisible box">
<rect width="48" height="48" fill="none"/>
</g>
<g id="icons_Q2" data-name="icons Q2">
<path d="M24,7.7,29.3,16H18.6L24,7.7M24,2a2.1,2.1,0,0,0-1.7,1L13.2,17a2.3,2.3,0,0,0,0,2,1.9,1.9,0,0,0,1.7,1H33a2.1,2.1,0,0,0,1.7-1,1.8,1.8,0,0,0,0-2l-9-14A1.9,1.9,0,0,0,24,2Z"/>
<path d="M43,43H29a2,2,0,0,1-2-2V27a2,2,0,0,1,2-2H43a2,2,0,0,1,2,2V41A2,2,0,0,1,43,43ZM31,39H41V29H31Z"/>
<path d="M13,28a6,6,0,1,1-6,6,6,6,0,0,1,6-6m0-4A10,10,0,1,0,23,34,10,10,0,0,0,13,24Z"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 854 B

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Uploaded to: SVG Repo, www.svgrepo.com, Generator: SVG Repo Mixer Tools -->
<svg fill="#000000" width="800px" height="800px" viewBox="0 0 32 32" version="1.1" xmlns="http://www.w3.org/2000/svg">
<title>unity</title>
<path d="M25.94 25.061l-5.382-9.060 5.382-9.064 2.598 9.062-2.599 9.060zM13.946 24.191l-6.768-6.717h10.759l5.38 9.061-9.372-2.342zM13.946 7.809l9.371-2.342-5.379 9.061h-10.761zM30.996 12.917l-3.282-11.913-12.251 3.193-1.812 3.112-3.68-0.027-8.966 8.719 8.967 8.72 3.678-0.029 1.817 3.112 12.246 3.192 3.283-11.908-1.864-3.087z"></path>
</svg>

After

Width:  |  Height:  |  Size: 602 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 808 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 747 B

@ -1 +0,0 @@
<svg xmlns='http://www.w3.org/2000/svg' width='100%' height='100%' viewBox='0 0 1600 800'><rect fill='#0F172A' width='1600' height='800'/><g fill-opacity='1'><path fill='#0f182b' d='M486 705.8c-109.3-21.8-223.4-32.2-335.3-19.4C99.5 692.1 49 703 0 719.8V800h843.8c-115.9-33.2-230.8-68.1-347.6-92.2C492.8 707.1 489.4 706.5 486 705.8z'/><path fill='#10182c' d='M1600 0H0v719.8c49-16.8 99.5-27.8 150.7-33.5c111.9-12.7 226-2.4 335.3 19.4c3.4 0.7 6.8 1.4 10.2 2c116.8 24 231.7 59 347.6 92.2H1600V0z'/><path fill='#10192e' d='M478.4 581c3.2 0.8 6.4 1.7 9.5 2.5c196.2 52.5 388.7 133.5 593.5 176.6c174.2 36.6 349.5 29.2 518.6-10.2V0H0v574.9c52.3-17.6 106.5-27.7 161.1-30.9C268.4 537.4 375.7 554.2 478.4 581z'/><path fill='#11192f' d='M0 0v429.4c55.6-18.4 113.5-27.3 171.4-27.7c102.8-0.8 203.2 22.7 299.3 54.5c3 1 5.9 2 8.9 3c183.6 62 365.7 146.1 562.4 192.1c186.7 43.7 376.3 34.4 557.9-12.6V0H0z'/><path fill='#111A30' d='M181.8 259.4c98.2 6 191.9 35.2 281.3 72.1c2.8 1.1 5.5 2.3 8.3 3.4c171 71.6 342.7 158.5 531.3 207.7c198.8 51.8 403.4 40.8 597.3-14.8V0H0v283.2C59 263.6 120.6 255.7 181.8 259.4z'/><path fill='#131c34' d='M1600 0H0v136.3c62.3-20.9 127.7-27.5 192.2-19.2c93.6 12.1 180.5 47.7 263.3 89.6c2.6 1.3 5.1 2.6 7.7 3.9c158.4 81.1 319.7 170.9 500.3 223.2c210.5 61 430.8 49 636.6-16.6V0z'/><path fill='#141f39' d='M454.9 86.3C600.7 177 751.6 269.3 924.1 325c208.6 67.4 431.3 60.8 637.9-5.3c12.8-4.1 25.4-8.4 38.1-12.9V0H288.1c56 21.3 108.7 50.6 159.7 82C450.2 83.4 452.5 84.9 454.9 86.3z'/><path fill='#16213d' d='M1600 0H498c118.1 85.8 243.5 164.5 386.8 216.2c191.8 69.2 400 74.7 595 21.1c40.8-11.2 81.1-25.2 120.3-41.7V0z'/><path fill='#172442' d='M1397.5 154.8c47.2-10.6 93.6-25.3 138.6-43.8c21.7-8.9 43-18.8 63.9-29.5V0H643.4c62.9 41.7 129.7 78.2 202.1 107.4C1020.4 178.1 1214.2 196.1 1397.5 154.8z'/><path fill='#192646' d='M1315.3 72.4c75.3-12.6 148.9-37.1 216.8-72.4h-723C966.8 71 1144.7 101 1315.3 72.4z'/></g></svg>

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.0 MiB

@ -129,6 +129,57 @@ @layer utilities {
}
}
.cart-in {
animation-name: cart-in;
animation-duration: 0.1s;
animation-timing-function: ease-in;
animation-fill-mode: forwards;
}
@keyframes cart-in {
from {
border-radius: 0px;
}
to {
border-radius: 8px;
}
}
.cart-out {
animation-name: cart-out;
animation-duration: 0.1s;
animation-timing-function: ease-in;
animation-fill-mode: forwards;
}
@keyframes cart-out {
from {
border-radius: 8px;
}
to {
border-radius: 0px;
}
}
.load-rotate {
animation-name: rotate;
animation-duration: 3s;
animation-timing-function: linear;
animation-iteration-count: infinite;
}
@keyframes rotate {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
}
.icon-in {
animation: 0.2s icon-in-anim ease-out forwards;
}

@ -0,0 +1,142 @@
<template>
<div @click="openDialog" :id="'dz-' + props.name" @drop="dropFiles" @dragover="Utils.Prevent" @drag="Utils.Prevent" @dragenter="popupShow" @dragleave="popupClose"
:class="{ 'border-dashed': !props.disabled }"
class="w-full relative bg-gray-200 dark:bg-gray-900 border-2 border-gray-400 overflow-hidden p-4 flex flex-col items-center rounded-lg text-lg text-gray-900 dark:text-gray-200">
<div :id="'dz-popup-'+ props.name" class="hidden absolute z-20 bg-gray-400/90 top-0 bottom-0 left-0 right-0
pointer-events-none">
<div class="w-full h-full flex justify-center items-center">
<img src="/icons/download.png" class="invert absolute h-[80%]">
</div>
</div>
<input @change="fileSelected" :id="'dz-input-' + props.name" type="file" class="hidden" :multiple="props.multiple" :accept="props.accept">
<div v-for="file in files" class="w-full flex items-center">
<div class="relative w-full flex justify-between items-center bg-gray-100 dark:bg-gray-800
rounded-lg mb-1 p-2 mr-2 z-0 ">
<a :href="file.url" target="_blank" class="w-full flex justify-between items-center">
<div v-if="file.value.stat === 'loading'" class="absolute top-0 right-0 left-0 bottom-0">
<div :style="{ width: file.value.done + '%' }" class="bg-green-600 h-full -z-10 rounded-lg"></div>
</div>
<div class="flex items-center z-10">
<img :src="File.Icon(File.Extension(file.value.name))" class="h-10 dark:invert">
<p class="font-semibold ml-2">{{ file.value.name }}</p>
</div>
<div class="text-right z-10">
<p>{{ File.SizeToString(file.value.size) }}</p>
<p v-if="file.value.stat !== 'loading'" @click="removeFile" :data-name="file.value.name" class="underline text-red-600 text-sm cursor-pointer">Supprimer</p>
</div>
</a>
</div>
<div v-if="file.value.stat === 'loading'" class="flex items-center">
<img src="/icons/loading.svg" class="invert h-10 load-rotate">
</div>
<div v-else-if="file.value.stat === 'success'" class="flex items-center">
<img src="/icons/success.svg" class="h-10">
</div>
<div v-else-if="file.value.stat === 'error'" class="flex items-center">
<img src="/icons/error.svg" class="h-10">
</div>
</div>
<p class="font-semibold">{{ empty }}</p>
</div>
</template>
<script setup>
import { ref, computed } from 'vue';
import File from '@/file';
import Utils from '@/utils';
import StorageS3 from '@/storageS3';
const props = defineProps({
name: { type: String },
files: {
type: Array,
default: [],
},
accept: {
type: String,
default: '*',
},
multiple: {
type: Boolean,
default: true,
},
disabled: {
type: Boolean,
default: false,
},
empty: {
type: String,
default: 'Ajouter un/des fichier(s)',
}
});
const emit = defineEmits(['file-added', 'file-removed']);
const files = ref([]);
props.files.forEach(file => files.value.push(ref(file)));
defineExpose({ removeFiles: () => files.value = [] });
const empty = computed(() => {
return files.value.length ? "" : props.empty;
});
const removeFile = (e) => {
Utils.Prevent(e);
const file = files.value.filter(f => f.value.name == e.target.dataset.name)[0];
files.value = files.value.filter(f => f.value.name != file.value.name);
emit("file-removed", file.value);
}
const addFile = (file) => {
if(!files.value.filter(fileStat => fileStat.value.name == file.name).length)
{
const fileStat = ref({
name: file.name,
size: file.size,
done: 0,
stat: "loading",
key: "",
url: ""
});
files.value.push(fileStat);
StorageS3.UploadFile(file, {
onUpdate: (done) =>
{
console.log("Uploading : " + done + "% done");
fileStat.value.done = done;
},
onSuccess: async (key) => {
console.log("Uploaded : " + key);
fileStat.value.key = key;
fileStat.value.stat = "success";
const { url } = await StorageS3.GenerateSignedUrl(key);
fileStat.value.url = url;
emit("file-added", fileStat.value);
},
onError: (e) => {
console.log("Failed upload : " + e);
fileStat.value.stat = "error";
}
});
}
}
const fileSelected = (e) => { [...e.target.files].forEach(file => addFile(file)); }
const openDialog = () => { document.querySelector('#dz-input-' + props.name).click(); }
const dropFiles = (e) => {
Utils.Prevent(e);
let popup = document.querySelector(`#dz-popup-${props.name}`);
if(!popup.classList.contains("hidden")) popup.classList.add("hidden");
[...e.dataTransfer.items].forEach((item) => {
if (item.kind === "file" && (!files.value.length || props.multiple === "true")) {
const file = item.getAsFile();
if(!files.value.length || props.multiple === "true") addFile(file);
}
});
}
const popupShow = (e) => { Utils.Prevent(e); document.querySelector(`#dz-popup-${props.name}`).classList.toggle("hidden"); }
const popupClose = (e) => { Utils.Prevent(e); document.querySelector(`#dz-popup-${props.name}`).classList.toggle("hidden"); }
</script>

@ -1,11 +1,13 @@
<script setup>
import { Link } from '@inertiajs/vue3';
import NavLink from '@/Components/NavLink.vue';
import { useSlots } from 'vue';
const slots = useSlots();
</script>
<template>
<nav class="sticky w-full z-10 h-16 top-0 right-0 left-0 bg-gray-50 text-gray-900">
<div class="w-full h-full flex px-[17.5%] justify-between border-b border-gray-300">
<nav class="sticky w-full z-30 top-0 right-0 left-0">
<div class="w-full h-16 flex px-[17.5%] justify-between border-b border-gray-300 bg-gray-100 text-gray-900">
<div class="h-full flex">
<Link :href="route('home')" class="h-full mr-10">
<img src="/img/logo.png" class="h-full py-1.5">
@ -15,7 +17,7 @@ import NavLink from '@/Components/NavLink.vue';
<NavLink :href="route('home')" :active="route().current('home')">
Home
</NavLink>
<NavLink :href="route('photo.index')" :active="route().current('photo.index')">
<NavLink :href="route('photo.index')" :active="route().current('photo.*')">
Photothèque
</NavLink>
<NavLink :href="'#'" :active="false">
@ -29,6 +31,9 @@ import NavLink from '@/Components/NavLink.vue';
</NavLink>
</div>
</div>
<div v-if="slots.header" class="w-full max-h-[3.5rem] px-[17.5%] py-1.5 bg-gray-50 border-b border-gray-300 text-gray-900">
<slot name="header"/>
</div>
</nav>
<slot name="content"/>
<footer class="w-full px-[17.5%] bg-gray-50 text-gray-900 flex items-center justify-between">
@ -36,18 +41,22 @@ import NavLink from '@/Components/NavLink.vue';
<div class="flex my-8">
<div class="group mx-2">
<div class="group-hover:social-icon-in social-icon-out p-2 border border-gray-600 rounded-lg">
<img src="/img/facebook.svg" class="w-[2rem] group-hover:icon-in icon-out dark:invert">
<img src="/icons/facebook.svg" class="w-[2rem] group-hover:icon-in icon-out dark:invert">
</div>
</div>
<div class="group mx-2">
<div class="group group-hover:social-icon-in social-icon-out p-2 border border-gray-600 rounded-lg">
<img src="/img/instagram.svg" class="w-[2rem] group-hover:icon-in icon-out dark:invert">
</div>
<a target="_blank" href="https://www.instagram.com/scouts_baslac/">
<div class="group group-hover:social-icon-in social-icon-out p-2 border border-gray-600 rounded-lg">
<img src="/icons/instagram.svg" class="w-[2rem] group-hover:icon-in icon-out dark:invert">
</div>
</a>
</div>
<div class="group mx-2">
<div class="group group-hover:social-icon-in social-icon-out p-2 border border-gray-600 rounded-lg">
<img src="/img/mail.svg" class="w-[2rem] group-hover:icon-in icon-out dark:invert">
</div>
<a target="_blank" href="mailto:groupe-baslac@gmail.com">
<div class="group group-hover:social-icon-in social-icon-out p-2 border border-gray-600 rounded-lg">
<img src="/icons/mail.svg" class="w-[2rem] group-hover:icon-in icon-out dark:invert">
</div>
</a>
</div>
</div>
</footer>

@ -8,9 +8,9 @@ import GuestLayout from '@/Layouts/GuestLayout.vue';
<Head title="Home"/>
<GuestLayout>
<template #content>
<div class="relative w-full h-80 flex items-center overflow-hidden">
<img src="/img/chalet.webp">
<p class="text-center absolute text-white/90 text-[180px] font-bold left-0 right-0">Scout Baslac</p>
<div class="relative w-full h-96 flex items-center overflow-hidden">
<img src="/img/sarasin.png" class="w-full pb-96">
<p class="text-center absolute text-white/65 text-[180px] leading-[180px] font-bold left-0 right-0">Scout Baslac</p>
</div>
<div class="w-full px-[17.5%] flex flex-col">
<div class="my-5">
@ -26,14 +26,18 @@ import GuestLayout from '@/Layouts/GuestLayout.vue';
mais aussi à faire des bricolages, constructions et autres projets en fonction de leur âge.
</p>
<p class="mb-1">Plein dautres activités sont également au programme :</p>
<ul class="list-disc px-6 mb-2">
<li>Jeux de rôle</li>
<li>Marches</li>
<li>Bricolage</li>
<li>Théâtre</li>
<li>Chant</li>
<li>Etc.</li>
</ul>
<div class="w-72 grid grid-cols-2 mb-2 mx-auto">
<ul class="list-disc">
<li>Jeux de rôle</li>
<li>Marches</li>
<li>Bricolage</li>
</ul>
<ul class="list-disc">
<li>Théâtre</li>
<li>Chant</li>
<li>Etc.</li>
</ul>
</div>
<p>
Tout ce qui va permette à chacun de se développer, de se connaître.
Et tous les anciens vous le dirons, la solidarité est telle que les groupes de scout vous donnent surtout les meilleurs amis pour la vie.

@ -0,0 +1,81 @@
<script setup>
import { Head, Link } from '@inertiajs/vue3';
import GuestLayout from '@/Layouts/GuestLayout.vue';
import Dropzone from '@/Components/Dropzone.vue';
import Create from './Partials/Create.vue';
import Show from'./Partials/Show.vue';
import Modal from './Partials/Modal.vue';
import { reactive, ref } from 'vue';
const props = defineProps({
photos: {
type: Array,
default: []
},
active: false
});
const create = reactive({ active: false });
const fullScreenState = reactive({ photo: {}, active: false });
const fullScreen = (photo) => {
fullScreenState.photo = photo;
fullScreenState.active = true;
}
const gridState = reactive({ columns: 3 });
</script>
<template>
<Head title="Photos"/>
<Modal v-if="fullScreenState.active" :photoId="fullScreenState.photo" :photos="props.photos"
@close="() => { fullScreenState.photo = {}; fullScreenState.active = false; }"
/>
<GuestLayout>
<template #header>
<div class="w-full flex justify-between items-center py-1">
<div class="relative flex items-center">
<p class="font-semibold mr-4">Affichage</p>
<div class="flex items-center bg-white rounded-md shadow-sm shadow-gray-300 overflow-hidden">
<button @click="gridState.columns = 3" class="flex items-center h-full border-r border-gray-400 p-1
hover:bg-black/5">
<img src="/icons/block-content.svg" class="h-7">
</button>
<button @click="gridState.columns = 1" class="flex items-center h-full border-r border-gray-400 p-1
hover:bg-black/5">
<img src="/icons/list.svg" class="h-7">
</button>
<button @click="() => fullScreen(props.photos[0].uuid)" class="flex items-center p-1
hover:bg-black/5">
<img src="/icons/slider.svg" class="h-7">
</button>
</div>
</div>
<div class="relative flex items-center">
<button @click="create.active = !create.active" class="flex items-center">
<p class="font-semibold mr-4">Ajouter une photo</p>
<img src="/icons/add.svg" class="h-8">
</button>
<Create @close="create.active = !create.active" v-if="create.active" class="absolute -right-0 top-[110%] z-10 mt-4" />
</div>
</div>
</template>
<template #content>
<div class="w-full px-[17.5%] min-h-screen">
<div class="w-full h-full bg-black/10 py-20 px-1">
<div :class="{'grid-cols-3': gridState.columns === 3}"
class="w-full grid">
<Show v-for="(photo, index) in props.photos"
:photo="photo" :index="index" :length="props.photos.length" :columns="gridState.columns"
@full-screen="fullScreen"
/>
</div>
</div>
</div>
</template>
</GuestLayout>
</template>

@ -0,0 +1,81 @@
<script setup>
import { Head, Link, useForm } from '@inertiajs/vue3';
import File from '@/file';
import GuestLayout from '@/Layouts/GuestLayout.vue';
import Dropzone from '@/Components/Dropzone.vue';
import TextInput from '@/Components/TextInput.vue';
import InputError from '@/Components/InputError.vue';
import { onMounted, reactive, ref } from 'vue';
const dropzone = ref(null);
const imageState = reactive({
"url": "",
})
const form = useForm({
name: "",
path: "",
})
const emits = defineEmits(["close"]);
const imageAdded = (file) => {
form.path = file.key;
imageState.url = file.url;
if(form.name === "") form.name = File.Basename(file.key).split("_")[1];
}
const imageRemoved = (file) => {
form.path = "";
}
const submit = () => {
form.post("/photo", {
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": document.querySelector('input[name=_token]').value,
},
});
imageState.url = "";
form.path = "";
form.name = "";
dropzone.value.removeFiles();
emits("close");
}
</script>
<template>
<div class="text-left text-black w-[30rem] shadow-lg shadow-gray-400 rounded-lg bg-gray-50 overflow-hidden
border border-gray-300">
<div v-if="imageState.url" class="max-h-72 overflow-hidden flex items-center">
<img :src="imageState.url">
</div>
<div class="px-10 pb-5 pt-5">
<div @click="() => emits('close')" class="w-full flex justify-end ">
<img src="/icons/cancel.svg" class="h-5">
</div>
<form @submit.prevent="submit">
<p>Fichier image</p>
<Dropzone
ref="dropzone"
@file-added="imageAdded"
@file-removed="imageRemoved"
:name="photos"
:empty="'Téléversé une image'"
:multiple="false"
:accept="'image/*'"
:class="'mb-1'"
/>
<InputError :message="form.errors.path"/>
<p class="mt-3">Nom</p>
<TextInput :class="'mb-1 w-full'" v-model="form.name" required :placeholder="'Nom de la photo'"/>
<InputError :message="form.errors.name"/>
<div class="w-full flex justify-end mt-3">
<button type="submit" class="text-white font-semibold p-1 px-2 bg-primary rounded-md">Ajouter</button>
</div>
</form>
</div>
</div>
</template>

@ -0,0 +1,40 @@
<script setup>
import TextInput from '@/Components/TextInput.vue';
import { useForm } from '@inertiajs/vue3';
const props = defineProps({
photo: {
type: Object,
required: true,
}
})
const form = useForm({
name: ""
});
const emits = defineEmits(["close"]);
const submit = () => {
form.post("/photo/" + props.photo.uuid , {
headers: {
"Content-Type": "application/json",
"X-CSRF-Token": document.querySelector('input[name=_token]').value,
},
});
form.name = "";
emits("close");
}
</script>
<template>
<div class="text-left text-black shadow-md shadow-gray-500 rounded-lg
bg-gray-50 overflow-hidden border border-gray-300 p-2 w-72" >
<form @submit.prevent="submit">
<TextInput :placeholder="'Changer le nom de la photo'" :class="'w-full'" v-model="form.name"/>
<div class="w-full flex mt-3">
<button type="submit" class="text-white font-semibold p-1 px-2 bg-primary rounded-md">Changer</button>
</div>
</form>
</div>
</template>

@ -0,0 +1,81 @@
<script setup>
import { reactive } from 'vue';
const props = defineProps({
photoId: {
type: String,
required: true,
},
photos: {
type: Array,
required: true
}
});
const photo = reactive({ uuid: props.photoId, path: props.photos.filter(photo => photo.uuid == props.photoId)[0].path });
const emit = defineEmits(['close']);
const nextPhoto = () => {
let nextPhoto = { uuid: props.photos[0].uuid, path: props.photos[0].path };
let check = false;
props.photos.every((ph) => {
if(check) {
nextPhoto = ph;
return false;
}
check = ph.uuid == photo.uuid;
return true;
});
photo.path = nextPhoto.path;
photo.uuid = nextPhoto.uuid;
}
const previousPhoto = () => {
let nextPhoto = { uuid: props.photos[props.photos.length - 1].uuid, path: props.photos[props.photos.length - 1].path };
let check = false;
props.photos.reverse().every((ph) => {
if(check) {
nextPhoto = ph;
return false;
}
check = ph.uuid == photo.uuid;
return true;
});
props.photos.reverse();
photo.path = nextPhoto.path;
photo.uuid = nextPhoto.uuid;
}
const close = () => { emit('close'); };
const closeOnEscape = (e) => {
if (e.key === 'Escape' && props.show) {
close();
}
};
</script>
<template>
<div @keypress="closeOnEscape" id="modal-image" class="fixed z-40 modal-base top-0 bottom-0 left-0 right-0 bg-black/90">
<div class="w-full h-full flex items-center justify-center z-50">
<button @click="previousPhoto" class="pr-3 hover:scale-105">
<img src="/icons/next.svg" class="h-16 invert rotate-180">
</button>
<div class="relative h-4/5 max-h-5xl">
<div class="absolute right-0 p-4">
<button @click="close" class="bg-red-600 shadow-md shadow-gray-600 p-1 rounded-md">
<img src="/icons/cancel.svg" class="h-8 invert pointer-events-none">
</button>
</div>
<img :src="photo.path" class="h-full">
</div>
<button @click="nextPhoto" class="pl-3 hover:scale-105">
<img src="/icons/next.svg" class="h-16 invert">
</button>
</div>
</div>
</template>

@ -0,0 +1,75 @@
<script setup>
import { Link } from '@inertiajs/vue3';
import { useForm } from '@inertiajs/vue3';
import { reactive } from 'vue';
import Edit from './Edit.vue';
import axios from 'axios';
const props = defineProps({
photo: {
type: Object,
required: true,
},
index: {
type: Number,
required: true,
},
length: {
type: Number,
required: true,
},
columns: {
type: Number,
default: 3,
},
});
const form = useForm();
const photoState = reactive({ edit: false });
const emits = defineEmits(["full-screen"]);
const deletePhoto = async () => {
if(confirm("Voulez-vous vraiment supprimé cette photo")){
form.delete("/photo/" + props.photo.uuid, {
headers: {
"X-CSRF-Token": document.querySelector('input[name=_token]').value,
}
});
}
}
</script>
<template>
<div :class="{
'border-r': (props.index + 1) % props.columns != 0,
'border-b': props.index < props.length - props.columns,
'h-96': props.columns === 3,
'h-[25rem]': props.columns !== 3,
}"
class="group relative w-full overflow-hidden border-white hover:scale-[1.003] flex items-center bg-black/90">
<div class="hidden absolute left-0 right-0 top-0 p-2 group-hover:flex justify-between">
<div class="flex items-center">
<button @click="() => emits('full-screen', props.photo.uuid)" class="bg-black/50 p-1 rounded-md mr-2"><img src="/icons/full-screen.svg" class="h-6 invert"></button>
<div class="relative">
<button @click="photoState.edit = !photoState.edit" class="bg-black/50 p-1 rounded-md mr-2"><img src="/icons/modify.svg" class="h-6 invert"></button>
<Edit v-if="photoState.edit"
@close="() => photoState.edit = false"
:photo="props.photo"
:class="'absolute left-0 top-full mt-2'"
/>
</div>
<button @click="deletePhoto" class="bg-red-600 p-1 rounded-md"><img src="/icons/delete.png" class="h-6 invert"></button>
</div>
<div class="text-right bg-black/30 p-1 px-3 rounded-md">
<p class="text-sm text-white">{{ props.photo.name }}</p>
<p class="text-sm text-white">publier par {{ props.photo.user.name }}</p>
</div>
</div>
<div class="hidden absolute left-0 right-0 bottom-0 p-2 group-hover:flex justify-end">
<a :href="props.photo.path" target="_blank" class="bg-black/50 p-1 rounded-md"><img src="/icons/download.png" class="h-6 invert"></a>
</div>
<img :src="props.photo.path" class="w-full bg-white">
</div>
</template>

@ -0,0 +1,50 @@
export default class File {
static SizeToString(size)
{
let cpt = 0;
let units = ["octet", "Ko", "Mo", "Go", "To"];
while(size >= 1000 && size >= 1)
{
size = size / 1000;
cpt++;
}
return (Math.ceil(size * 100) / 100) + " " + units[cpt];
}
static Icon(ext)
{
let img = "/icons/fichier.png";
switch(ext.toLowerCase()) {
case 'pdf': return "/icons/pdf.png";
case 'dwg': return "/icons/dwg.png";
case 'stp':
case 'step': return "/icons/step.png";
case 'xlsx': return "/icons/excel.png";
case 'docx': return "/icons/word.png";
case 'zip':
case '7z':
case 'rar':
case 'gz': return "/icons/zip.png";
case "unitypackage": return "/icons/unity.svg";
case "png":
case "jfif":
case "jpeg":
case "jpg":
case "gif":
case "svg":
case "webp": return "/icons/photo.svg";
}
return img;
}
static Basename(filename)
{
return filename.substring(filename.lastIndexOf('/') > 0 ? filename.lastIndexOf('/') + 1 : 0, filename.lastIndexOf('.')) || filename;
}
static Extension(filename)
{
return filename.substring(filename.lastIndexOf('.')+1, filename.length) || filename;
}
}

@ -0,0 +1,106 @@
export default class StorageS3
{
static options =
{
genUrl: "/s3/generate-presigned-url",
startMultipartUrl: "/s3/start-multipart-upload",
genMultipartUrl: "/s3/generate-presigned-multipart-url",
completeMultipartUrl: "/s3/complete-multipart-upload",
proxyMultipartUrl: "/s3/proxy-multipart-upload",
partSize: 32 * 1024 * 1024,
}
static async UploadFile(file, callbacks = {
onUpdate: async (done) => {},
onSuccess: async () => {},
onError: async () => {}
})
{
try {
const uploadPromises = [];
let data = new Uint8Array(await file.arrayBuffer());
const { uploadId, key } = await StorageS3.StartMultiPartUpload(file.name);
let partIndex = 0;
for (let start = 0; start < file.size; start += StorageS3.options.partSize)
{
partIndex++;
let partNumber = partIndex;
let length = start + StorageS3.options.partSize < file.size ? start + StorageS3.options.partSize : file.size;
if(callbacks.onUpdate) await callbacks.onUpdate((length/file.size) * 100);
await new Promise(r => setTimeout(r, 200));
const partData = data.subarray(start, length);
uploadPromises.push(
StorageS3.GenerateMultipartSignedUrl(key, uploadId, partNumber, partData.length)
.then(({ url }) => StorageS3.UploadPart(url, partData, partNumber))
.then(({ ETag }) => ({ ETag, PartNumber: partNumber }))
);
}
let parts = await Promise.all(uploadPromises);
parts = parts.sort((a, b) => a.PartNumber - b.PartNumber);
await StorageS3.CompleteMultiPartUpload(key, uploadId, parts);
if(callbacks.onSuccess) await callbacks.onSuccess(key);
} catch(e) { if(callbacks.onError) await callbacks.onError(e); }
}
static async StartMultiPartUpload(key)
{
const response = await fetch(`${StorageS3.options.startMultipartUrl}?filename=${encodeURIComponent(key)}`, {
method: "GET",
headers: {
'Content-Type': 'application/json',
},
});
return response.json();
}
static async GenerateMultipartSignedUrl(key, uploadId, partNumber, partLength)
{
const response = await fetch(`${StorageS3.options.genMultipartUrl}?key=${encodeURIComponent(key)}&uploadId=${uploadId}&partNumber=${partNumber}&partLength=${partLength}`, {
method: "GET",
headers: {
'Content-Type': 'application/json',
},
});
return response.json();
}
static async GenerateSignedUrl(key)
{
const response = await fetch(`${StorageS3.options.genUrl}?key=${encodeURIComponent(key)}`, { method: "GET" });
return response.json();
}
static async UploadPart(signedUrl, partData, partNumber)
{
const response = await fetch(`${StorageS3.options.proxyMultipartUrl}`, {
method: 'PUT',
headers: {
"X-CSRF-Token": document.querySelector('input[name=_token]').value,
"X-SignedUrl": signedUrl,
"Content-Length": partData.length,
},
body: partData,
});
if (!response.ok) {
throw new Error(`Failed to upload part: ${partNumber}`);
}
return response.json(); // Returns ETag
}
static async CompleteMultiPartUpload(key, uploadId, parts)
{
const response = await fetch(StorageS3.options.completeMultipartUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
"X-CSRF-Token": document.querySelector('input[name=_token]').value,
},
body: JSON.stringify({
key,
uploadId,
parts,
}),
});
return response.json();
}
}

@ -0,0 +1,6 @@
export default class Utils {
static Prevent(e) {
e.preventDefault();
e.stopPropagation();
}
}

@ -18,6 +18,7 @@
@inertiaHead
</head>
<body class="font-roboto antialiased w-screen h-screen">
@csrf
@inertia
</body>
</html>

@ -5,14 +5,10 @@
use Illuminate\Foundation\Application;
use Illuminate\Support\Facades\Route;
use Inertia\Inertia;
use App\Http\Controllers\S3Controller;
Route::get('/', function () {
return Inertia::render('Home', [
'canLogin' => Route::has('login'),
'canRegister' => Route::has('register'),
'laravelVersion' => Application::VERSION,
'phpVersion' => PHP_VERSION,
]);
return Inertia::render('Home');
})->name('home');
Route::get('/info', function () {
@ -20,17 +16,23 @@
})->name('info');
Route::get('/photos', [PhotoController::class, 'index'])->name('photo.index');
Route::get('/photo/{id}', [ProfileController::class, 'show'])->name('photo.show');
Route::post('/photo/{id}/edit', [ProfileController::class, 'store'])->name('photo.edit');
Route::post('/photo/{id}', [ProfileController::class, 'store'])->name('photo.store');
Route::patch('/photo/{id}', [ProfileController::class, 'update'])->name('photo.update');
Route::delete('/photo/{id}', [ProfileController::class, 'destroy'])->name('photo.destroy');
Route::post('/photo', [PhotoController::class, 'store'])->name('photo.store');
Route::post('/photo/{id}', [PhotoController::class, 'update'])->name('photo.update');
Route::delete('/photo/{id}', [PhotoController::class, 'destroy'])->name('photo.destroy');
Route::get('/dashboard', function () {
return Inertia::render('Dashboard');
})->middleware(['auth', 'verified'])->name('dashboard');
Route::get("/s3/start-multipart-upload", [S3Controller::class, "StartMultipartUpload"])->name("s3.multipart.start");
Route::get("/s3/generate-presigned-multipart-url", [S3Controller::class, "GeneratePresignedMultipartUrl"])->name("s3.multipart.presigned-url");
Route::post("/s3/complete-multipart-upload", [S3Controller::class, "CompleteMultipartUpload"])->name("s3.multipart.complete");
Route::get("/s3/generate-presigned-url", [S3Controller::class, "GeneratePresignedUrl"])->name("s3.presigned-url");
Route::put("/s3/proxy-multipart-upload", [S3Controller::class, "ProxyS3"])->name("s3.proxy");
Route::get("/s3/download", [S3Controller::class, "Download"])->name("s3.download");
Route::middleware(['auth', 'verified'])->group(function () {
Route::get('/dashboard', function () {
return Inertia::render('Dashboard');
})->name('dashboard');
Route::get('/profile', [ProfileController::class, 'edit'])->name('profile.edit');
Route::patch('/profile', [ProfileController::class, 'update'])->name('profile.update');
Route::delete('/profile', [ProfileController::class, 'destroy'])->name('profile.destroy');

Loading…
Cancel
Save