grafikart / filemanager-element Goto Github PK
View Code? Open in Web Editor NEWA simple file browser distributed as a custom element
License: MIT License
A simple file browser distributed as a custom element
License: MIT License
Salut grand manitou du code !
Comme évoqué ensemble sur ton stream, petite issue pour demander l'ajout d'un bouton d'upload pour les mobiles/tablettes où le drag and drop n'est pas possible.
Merci beaucoup pour ton travail !
120_
Ajouter sur le composant un parametre : readonly.
De cette façon si readonly est true:
l'utilisateur ne pourra pas ajouter ou supprimer des dossier ou des fichiers.
Hello, tout est dans le titre :) Pour des petits fichiers, c'est instantané et du coup c cool mais pour des vidéos, et bien là, on n'a pas de progressbar pour indiquer où ça en est. Ce serait cool :).
Salut,
J'ai eu une erreur de compilation en utilisant Webpack.
ERROR in ./node_modules/filemanager-element/FileManager.css
Module build failed (from ./node_modules/mini-css-extract-plugin/dist/loader.js):
ModuleBuildError: Module build failed (from ./node_modules/postcss-loader/dist/cjs.js):
ParserError: Syntax Error at line: 1, column 57
at /home/vagrant/domain.com/node_modules/filemanager-element/FileManager.css:1:6481
at Parser.error (/home/vagrant/domain.com/node_modules/postcss-values-parser/lib/parser.js:127:11)
at Parser.operator (/home/vagrant/domain.com/node_modules/postcss-values-parser/lib/parser.js:162:20)
at Parser.parseTokens (/home/vagrant/domain.com/node_modules/postcss-values-parser/lib/parser.js:245:14)
at Parser.loop (/home/vagrant/domain.com/node_modules/postcss-values-parser/lib/parser.js:132:12)
at Parser.parse (/home/vagrant/domain.com/node_modules/postcss-values-parser/lib/parser.js:51:17)
at parse (/home/vagrant/domain.com/node_modules/postcss-custom-properties/index.cjs.js:47:30)
at /home/vagrant/domain.com/node_modules/postcss-custom-properties/index.cjs.js:333:24
at /home/vagrant/domain.com/node_modules/postcss/lib/container.js:72:18
at /home/vagrant/domain.com/node_modules/postcss/lib/container.js:55:18
at Rule.each (/home/vagrant/domain.com/node_modules/postcss/lib/container.js:41:16)
at processResult (/home/vagrant/domain.com/node_modules/webpack/lib/NormalModule.js:753:19)
at /home/vagrant/domain.com/node_modules/webpack/lib/NormalModule.js:855:5
at /home/vagrant/domain.com/node_modules/loader-runner/lib/LoaderRunner.js:399:11
at /home/vagrant/domain.com/node_modules/loader-runner/lib/LoaderRunner.js:251:18
at context.callback (/home/vagrant/domain.com/node_modules/loader-runner/lib/LoaderRunner.js:124:13)
at Object.loader (/home/vagrant/domain.com/node_modules/postcss-loader/dist/index.js:96:7)
@ ./src/dashboard/js/styles/file-manager.js 1:0-45
1 ERROR in child compilations (Use 'stats.children: true' resp. '--stats-children' for more details)
webpack 5.69.1 compiled with 2 errors in 49283 ms
Pas d'erreur en mode watch
.
Fichier de configuration:
const path = require("path")
const { CleanWebpackPlugin } = require("clean-webpack-plugin")
const { WebpackManifestPlugin } = require("webpack-manifest-plugin")
const MiniCssExtractPlugin = require("mini-css-extract-plugin")
const CssMinimizerPlugin = require("css-minimizer-webpack-plugin")
const TerserWebpackPlugin = require("terser-webpack-plugin")
const MomentLocalesPlugin = require("moment-locales-webpack-plugin")
const build = process.env.NODE_ENV === "local"
const watch = process.env.NODE_ENV === "watch"
const output = {
path: path.resolve(__dirname, "public_html/dist/dashboard"),
publicPath: "https://statics.domain.com/dashboard/",
filename: "js/[name].[chunkhash:8].js",
assetModuleFilename: "img/[hash][ext][query]"
}
const rules = [
{
test: /\.(png|jpe?g|gif|svg)$/i,
type: "asset",
parser: {
dataUrlCondition: {
maxSize: 1024 // 1 Ko
}
}
},
{
test: /\.(woff2?|eot|ttf|otf|svg)$/i,
exclude: [/images/],
type: "asset/resource",
generator: {
filename: "fonts/[name][ext][query]"
}
},
{
test: /\.(s[ac]|c)ss$/i, // scss, sass or css
use: [
{
loader: MiniCssExtractPlugin.loader,
options: {
publicPath: "../"
}
},
"css-loader",
"postcss-loader",
"sass-loader"
]
},
{
test: /\.jsx?$/,
exclude: /node_modules/,
use: {
loader: "babel-loader"
}
},
]
const mode = build === false ? "development" : "production"
const target = build === false ? "web" : "browserslist"
const stats = build === false ? "errors-warnings" : "normal"
const devtool = mode !== "production" ? "source-map" : false
const manifestFilename = path.resolve(__dirname, "app/manifest-dashboard.json")
const plugins = [
new CleanWebpackPlugin({
cleanOnceBeforeBuildPatterns: ["**/*", "!../js", "../js/auth/**"],
cleanAfterEveryBuildPatterns: ["css/*.js"],
dangerouslyAllowCleanPatternsOutsideProject: true,
protectWebpackAssets: false,
verbose: true,
dry: false
}),
new MiniCssExtractPlugin({ filename: "css/[name].[chunkhash:8].css" }),
new MomentLocalesPlugin({
localesToKeep: ["fr"],
}),
new WebpackManifestPlugin({
fileName: manifestFilename
}),
]
const styleEntries = {
"style": {
import: "./src/dashboard/js/styles/style.js",
filename: "css/[name].[chunkhash:8].js"
},
"style-dark": {
import: "./src/dashboard/js/styles/style-dark.js",
filename: "css/[name].[chunkhash:8].js"
},
"intl-tel-input": {
import: "./src/dashboard/js/styles/intl-tel-input.js",
filename: "css/[name].[chunkhash:8].js"
},
"file-manager": {
import: "./src/dashboard/js/styles/file-manager.js",
filename: "css/[name].[chunkhash:8].js"
},
}
const authEntries = {
"signup": {
import: "./src/dashboard/js/auth/signup.js",
filename: "../js/auth/[name].[chunkhash:8].js",
dependOn: "app"
},
"login": {
import: "./src/dashboard/js/auth/login.js",
filename: "../js/auth/[name].[chunkhash:8].js",
dependOn: "app"
},
"forgot-password": {
import: "./src/dashboard/js/auth/forgot-password.js",
filename: "../js/auth/[name].[chunkhash:8].js",
dependOn: "app"
},
"forgot-password-confirm": {
import: "./src/dashboard/js/auth/forgot-password-confirm.js",
filename: "../js/auth/[name].[chunkhash:8].js",
dependOn: "app"
},
"reset-password": {
import: "./src/dashboard/js/auth/reset-password.js",
filename: "../js/auth/[name].[chunkhash:8].js",
dependOn: "app"
},
}
const dashboardEntries = {
"moderators": {
import: "./src/dashboard/js/moderators/index.js",
filename: "js/moderators/[name].[chunkhash:8].js",
dependOn: "app"
},
"moderators-crud": {
import: "./src/dashboard/js/moderators/crud.js",
filename: "js/moderators/[name].[chunkhash:8].js",
dependOn: "app"
},
"newest-brands": {
import: "./src/dashboard/js/newest/brands/index.js",
filename: "js/newest/brands/[name].[chunkhash:8].js",
dependOn: "app"
},
"newest-brands-crud": {
import: "./src/dashboard/js/newest/brands/crud.js",
filename: "js/newest/brands/[name].[chunkhash:8].js",
dependOn: "app"
},
"brand-sale-points": {
import: "./src/dashboard/js/newest/brands/sale-points.js",
filename: "js/newest/brands/[name].[chunkhash:8].js",
dependOn: "app"
},
"brand-sale-point-crud": {
import: "./src/dashboard/js/newest/brands/sale-point-crud.js",
filename: "js/newest/brands/[name].[chunkhash:8].js",
dependOn: "app"
},
"newest-cars": {
import: "./src/dashboard/js/newest/cars/index.js",
filename: "js/newest/cars/[name].[chunkhash:8].js",
dependOn: "app"
},
"newest-cars-crud": {
import: "./src/dashboard/js/newest/cars/crud.js",
filename: "js/newest/cars/[name].[chunkhash:8].js",
dependOn: "app"
},
"newest-cars-show": {
import: "./src/dashboard/js/newest/cars/show.js",
filename: "js/newest/cars/[name].[chunkhash:8].js",
dependOn: "app"
},
"posts": {
import: "./src/dashboard/js/posts/index.js",
filename: "js/posts/[name].[chunkhash:8].js",
dependOn: "app"
},
"posts-crud": {
import: "./src/dashboard/js/posts/crud.js",
filename: "js/posts/[name].[chunkhash:8].js",
dependOn: "app"
},
"media-pictures": {
import: "./src/dashboard/js/media/pictures/index.js",
filename: "js/media/pictures/[name].[chunkhash:8].js",
dependOn: "app"
},
"adserver-advertisers-crud": {
import: "./src/dashboard/js/adserver/advertisers/crud.js",
filename: "js/adserver/advertisers/[name].[chunkhash:8].js",
dependOn: "app"
},
"adserver-campaigns-index": {
import: "./src/dashboard/js/adserver/campaigns/index.js",
filename: "js/adserver/campaigns/[name].[chunkhash:8].js",
dependOn: "app"
},
}
let Config = {
mode: mode,
target: target,
stats: stats,
entry: {
app: ["./src/dashboard/js/app.js"],
...styleEntries,
...authEntries,
...dashboardEntries,
},
output: output,
module: {
rules: rules
},
plugins: plugins,
devtool: devtool
}
if (mode === "production") {
Config.optimization = {
minimize: true,
minimizer: [
new TerserWebpackPlugin({
terserOptions: {
format: {
comments: false
}
},
extractComments: false
}),
new CssMinimizerPlugin()
]
}
}
if (watch === true) {
Config.watchOptions = {
ignored: /node_modules/,
poll: 1000,
}
}
module.exports = Config
Petite suggestion pour ajouter un attribut pour avoir un fichier déjà sélectionné à l'ouverture du filemanager. On lui passerait le path du fichier (ou du dossier seulement) et il est automatiquement chargé ;)
Comment associer un header personnalité ou un token type csrf à la requête qui est envoyé au serveur pour des besoins de protection ou d'authentification!
Salut,
J'ai un petit souci avec l'explorateur de fichier (standalone). J'ai un dossier qui contient des images et un dossier, qui lui même contient des images et un dossier et qui lui même a des images.
Quand je clique sur / j'ai bien mes images mais dès que je clique sur le premier dossier j'ai cette erreur dans la console. J'ai débuggé un peu et c'est bizarre car $filesQuery.data
contient bien un objet avec des infos correspondantes à la spécification OpenAPI mais impossible d'appeler la fonction filter
dessus.
[
{
"id": "dossier-123/P1100940_5d1ceace5ddee.jpg",
"name": "P1100940_5d1ceace5ddee.jpg",
"url": "https://__MY_URL__/buckets/images/dossier-123/P1100940_5d1ceace5ddee.jpg",
"size": 392282,
"folder": "dossier-123",
"thumbnail": "https://__MY_URL__/buckets/images/dossier-123/P1100940_5d1ceace5ddee.jpg?func=cropfit&w=75&h=75&bg_color=auto"
},
{
"id": "dossier-123/P1130411_5f4f44984eb36.jpg",
"name": "P1130411_5f4f44984eb36.jpg",
"url": "https://__MY_URL__/buckets/images/dossier-123/P1130411_5f4f44984eb36.jpg",
"size": 450185,
"folder": "dossier-123",
"thumbnail": "https://__MY_URL__/buckets/images/dossier-123/P1130411_5f4f44984eb36.jpg?func=cropfit&w=75&h=75&bg_color=auto"
},
{
"id": "dossier-123/P1130413_5f4f44c1ef6a9.jpg",
"name": "P1130413_5f4f44c1ef6a9.jpg",
"url": "https://__MY_URL__/buckets/images/dossier-123/P1130413_5f4f44c1ef6a9.jpg",
"size": 379824,
"folder": "dossier-123",
"thumbnail": "https://__MY_URL__/buckets/images/dossier-123/P1130413_5f4f44c1ef6a9.jpg?func=cropfit&w=75&h=75&bg_color=auto"
},
{
"id": "dossier-123/garage-65e20efc102c3.png",
"name": "garage-65e20efc102c3.png",
"url": "https://__MY_URL__/buckets/images/dossier-123/garage-65e20efc102c3.png",
"size": 114646,
"folder": "dossier-123",
"thumbnail": "https://__MY_URL__/buckets/images/dossier-123/garage-65e20efc102c3.png?func=cropfit&w=75&h=75&bg_color=auto"
},
{
"id": "dossier-123/garage-65e20f2ae7c8d.png",
"name": "garage-65e20f2ae7c8d.png",
"url": "https://__MY_URL__/buckets/images/dossier-123/garage-65e20f2ae7c8d.png",
"size": 114646,
"folder": "dossier-123",
"thumbnail": "https://__MY_URL__/buckets/images/dossier-123/garage-65e20f2ae7c8d.png?func=cropfit&w=75&h=75&bg_color=auto"
},
{
"id": "dossier-123/harley-65e210f596ffd.jpg",
"name": "harley-65e210f596ffd.jpg",
"url": "https://__MY_URL__/buckets/images/dossier-123/harley-65e210f596ffd.jpg",
"size": 455820,
"folder": "dossier-123",
"thumbnail": "https://__MY_URL__/buckets/images/dossier-123/harley-65e210f596ffd.jpg?func=cropfit&w=75&h=75&bg_color=auto"
}
]
Je suis un peu bloqué et je n'ai pas moyen d'utiliser le filemanager.
Une idée pour solutionner le problème ?
Merci
Hello !
Déjà très bonne librairie, c'est très cool.
Je ne sais pas si c'est possible, mais le problème, c'est que la librairie est finalement assez couplée avec le backend et avec la nécessité d'avoir une API qui suit une structure spécifique, ce qui n'est pas forcément pertinent.
Je propose de pouvoir réimplémenter les méthodes comme getFiles
, getFolder
, etc... La librairie n'a pas besoin de savoir si c'est une API derrière, ou juste un passage en props via un autre script JS
L'idée serait de pouvoir passer un adapter qui implémenterait une interface lors de l'enregistrement du custom component.
Si c'est le cas, la librairie utiliserait les méthodes de l'adapter, pour récupérer et interagir avec les données.
L'énorme avantage c'est que du coup, nous ne devons plus forcément suivre un schéma spécifique au niveau de l'API, le temps qu'on retourne ce qu'il faut au niveau de l'adapter, c'est bon. On peut également intégrer le client http que l'on souhaite, par exemple un client GraphQL au lieu de se limiter à une API REST.
import { FileManager, FileManagerActionsInterface } from 'filemanager-element'
import 'filemanager-element/FileManager.css'
class CustomFileManagerAdapter implements FileManagerActionsInterface {
public async getFiles() {
// Custom code here to fetch files from anything I want
// I can even use a GraphQL client here !
return myHttpClient.fetch("/api/something");
}
public async getFolders() {}
// Other methods....
}
// Here, we register the FileManager component with our custom adapter
FileManager.register({
adapter: new CustomFileManagerAdapter()
});
CustomFileManagerInterface.ts : (Should be provided by the library)
interface File {
id: string;
name: string;
url: string;
size: number;
folder: string;
thumbnail: string;
}
interface Folder {
id: string;
name: string;
parent: string | null;
}
interface FileManagerActionsInterface {
getFiles(): Promise<Array<number, File>>;
getFolders(): Promise<Array<number, Folder>>;
// Other methods ....
}
Vous en pensez quoi ?
Bonjour @Grafikart ,
Je viens d'utiliser votre librairie dans le cadre de mon projet Symfony.
J'ai adapté tout le code et tout fonctionne bien sauf pour la suppression des images.
Dans mon api, je supprime bien l'image puis je retourne un no-content.
Mais je ne comprends pas pourquoi le filemanager ne s'actualise pas et ne supprime pas l'image dans le visuel alors qu'elle est bien supprimé du serveur.
Affichage en ligne ou grid ne change rien malheureusement.
Merci de ta réponse !
Salut,
Afin d'être maintenu à jour des nouveautés de la lib, est-il possible de publier des releases en même temps que les tags ? Cela permet de watch de le repo et d'avoir une notif quand une nouvelle version est dispo.
Par défaut, Github ne permet pas de watch sur un tag.
Merci
Salut,
Avec des milliers de fichiers, il est préférable de les lister avec un système de pagination.
Ajout de l'attribut pagination
(optionnel) dans le custom element.
Paramètres additionnels dans la requête si l'attribut pagination
est intégré:
{page: 1, limit: 20}
Merci.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.