mirror of
				https://github.com/inventree/InvenTree.git
				synced 2025-10-31 13:15:43 +00:00 
			
		
		
		
	[plugins] allow static files for plugins (#7425)
* Add 'clear' option to 'invoke static' * Add functions for copying static files from installed plugins * Collect plugin static files as part of 'invoke static' * Add 'activate' method for PluginConfig * Run as part of `invoke plugins`
This commit is contained in:
		| @@ -0,0 +1,13 @@ | ||||
| """Management command to collect plugin static files.""" | ||||
|  | ||||
| from django.core.management import BaseCommand | ||||
|  | ||||
|  | ||||
| class Command(BaseCommand): | ||||
|     """Collect static files for all installed plugins.""" | ||||
|  | ||||
|     def handle(self, *args, **kwargs): | ||||
|         """Run the management command.""" | ||||
|         from plugin.staticfiles import collect_plugins_static_files | ||||
|  | ||||
|         collect_plugins_static_files() | ||||
| @@ -125,7 +125,7 @@ def canAppAccessDatabase( | ||||
|         excluded_commands.append('test') | ||||
|  | ||||
|     if not allow_plugins: | ||||
|         excluded_commands.extend(['collectstatic']) | ||||
|         excluded_commands.extend(['collectstatic', 'collectplugins']) | ||||
|  | ||||
|     for cmd in excluded_commands: | ||||
|         if cmd in sys.argv: | ||||
|   | ||||
| @@ -12,6 +12,7 @@ from django.utils.translation import gettext_lazy as _ | ||||
|  | ||||
| import common.models | ||||
| import InvenTree.models | ||||
| import plugin.staticfiles | ||||
| from plugin import InvenTreePlugin, registry | ||||
|  | ||||
|  | ||||
| @@ -186,6 +187,20 @@ class PluginConfig(InvenTree.models.MetadataMixin, models.Model): | ||||
|  | ||||
|         return getattr(self.plugin, 'is_package', False) | ||||
|  | ||||
|     def activate(self, active: bool) -> None: | ||||
|         """Set the 'active' status of this plugin instance.""" | ||||
|         from InvenTree.tasks import check_for_migrations, offload_task | ||||
|  | ||||
|         if self.active == active: | ||||
|             return | ||||
|  | ||||
|         self.active = active | ||||
|         self.save() | ||||
|  | ||||
|         if active: | ||||
|             offload_task(check_for_migrations) | ||||
|             offload_task(plugin.staticfiles.copy_plugin_static_files, self.key) | ||||
|  | ||||
|  | ||||
| class PluginSetting(common.models.BaseInvenTreeSetting): | ||||
|     """This model represents settings for individual plugins.""" | ||||
|   | ||||
| @@ -208,15 +208,7 @@ class PluginActivateSerializer(serializers.Serializer): | ||||
|  | ||||
|     def update(self, instance, validated_data): | ||||
|         """Apply the new 'active' value to the plugin instance.""" | ||||
|         from InvenTree.tasks import check_for_migrations, offload_task | ||||
|  | ||||
|         instance.active = validated_data.get('active', True) | ||||
|         instance.save() | ||||
|  | ||||
|         if instance.active: | ||||
|             # A plugin has just been activated - check for database migrations | ||||
|             offload_task(check_for_migrations) | ||||
|  | ||||
|         instance.activate(validated_data.get('active', True)) | ||||
|         return instance | ||||
|  | ||||
|  | ||||
|   | ||||
							
								
								
									
										92
									
								
								src/backend/InvenTree/plugin/staticfiles.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								src/backend/InvenTree/plugin/staticfiles.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| """Static files management for InvenTree plugins.""" | ||||
|  | ||||
| import logging | ||||
| from pathlib import Path | ||||
|  | ||||
| from django.contrib.staticfiles.storage import staticfiles_storage | ||||
|  | ||||
| from plugin.registry import registry | ||||
|  | ||||
| logger = logging.getLogger('inventree') | ||||
|  | ||||
|  | ||||
| def clear_static_dir(path, recursive=True): | ||||
|     """Clear the specified directory from the 'static' output directory. | ||||
|  | ||||
|     Arguments: | ||||
|         path: The path to the directory to clear | ||||
|         recursive: If True, clear the directory recursively | ||||
|     """ | ||||
|     if not staticfiles_storage.exists(path): | ||||
|         return | ||||
|  | ||||
|     dirs, files = staticfiles_storage.listdir(path) | ||||
|  | ||||
|     for f in files: | ||||
|         staticfiles_storage.delete(f'{path}/{f}') | ||||
|  | ||||
|     if recursive: | ||||
|         for d in dirs: | ||||
|             clear_static_dir(f'{path}/{d}', recursive=True) | ||||
|             staticfiles_storage.delete(d) | ||||
|  | ||||
|  | ||||
| def collect_plugins_static_files(): | ||||
|     """Copy static files from all installed plugins into the static directory.""" | ||||
|     registry.check_reload() | ||||
|  | ||||
|     logger.info('Collecting static files for all installed plugins.') | ||||
|  | ||||
|     for slug in registry.plugins.keys(): | ||||
|         copy_plugin_static_files(slug) | ||||
|  | ||||
|  | ||||
| def copy_plugin_static_files(slug): | ||||
|     """Copy static files for the specified plugin.""" | ||||
|     registry.check_reload() | ||||
|  | ||||
|     plugin = registry.get_plugin(slug) | ||||
|  | ||||
|     if not plugin: | ||||
|         return | ||||
|  | ||||
|     logger.info("Copying static files for plugin '%s'") | ||||
|  | ||||
|     # Get the source path for the plugin | ||||
|     source_path = plugin.path().joinpath('static') | ||||
|  | ||||
|     if not source_path.is_dir(): | ||||
|         return | ||||
|  | ||||
|     # Create prefix for the destination path | ||||
|     destination_prefix = f'plugins/{slug}/' | ||||
|  | ||||
|     # Clear the destination path | ||||
|     clear_static_dir(destination_prefix) | ||||
|  | ||||
|     items = list(source_path.glob('*')) | ||||
|  | ||||
|     idx = 0 | ||||
|     copied = 0 | ||||
|  | ||||
|     while idx < len(items): | ||||
|         item = items[idx] | ||||
|  | ||||
|         idx += 1 | ||||
|  | ||||
|         if item.is_dir(): | ||||
|             items.extend(item.glob('*')) | ||||
|             continue | ||||
|  | ||||
|         if item.is_file(): | ||||
|             relative_path = item.relative_to(source_path) | ||||
|  | ||||
|             destination_path = f'{destination_prefix}{relative_path}' | ||||
|  | ||||
|             with item.open('rb') as src: | ||||
|                 staticfiles_storage.save(destination_path, src) | ||||
|  | ||||
|             logger.debug(f'- copied {item} to {destination_path}') | ||||
|             copied += 1 | ||||
|  | ||||
|     logger.info(f"Copied %s static files for plugin '%s'.", copied, slug) | ||||
		Reference in New Issue
	
	Block a user