from __future__ import annotations from django.core.validators import (MaxValueValidator, MinValueValidator, RegexValidator) from django.db import models from django.utils.translation import gettext_lazy as _ from filebrowser.fields import FileBrowseField from simple_history.models import HistoricalRecords is_active_translation = _('is active') # Deprecated functions, leaved for initial migration compatibility def del_icon_file(): # type: ignore pass def set_icon_filename(): # type: ignore pass class CommonProgram(models.Model): name = models.CharField( unique=True, max_length=20, verbose_name=_('name'), ) label = models.CharField( max_length=20, blank=True, null=False, verbose_name=_('label'), ) label.help_text = _('If not empty used as name in frontend') description = models.CharField( max_length=80, default='', blank=True, verbose_name=_('description'), ) icon = FileBrowseField( blank=True, null=True, directory='icons/', max_length=200, verbose_name=_('icon'), ) is_active = models.BooleanField( default=True, verbose_name=is_active_translation, ) order = models.IntegerField( default=10, validators=[MinValueValidator(0), MaxValueValidator(20)], verbose_name=_('order'), ) order.help_text = _( 'Order reflected to frontend, less - first, same - autosorting') history = HistoricalRecords(cascade_delete_history=True, inherit=True) class Meta: abstract = True ordering = ['-id'] class CommonExecutable(CommonProgram): executable_path = models.CharField( max_length=200, default='', verbose_name=_('executable path'), ) fallback_path = models.CharField( max_length=200, blank=True, null=True, verbose_name=_('fallback path'), help_text=_( 'If start fails from executable path, try run from fallback')) parameters = models.CharField( max_length=255, blank=True, default='', verbose_name=_('parameters'), ) parameters.help_text = _('Run with arguments passed to executable') # ... class Meta: abstract = True ordering = ['-id'] class UtilitySoftware(CommonExecutable): class Meta: verbose_name = _('utility software') verbose_name_plural = _('utilities software') def __str__(self) -> str: return f'{self.name}({self.order}) {self.description}' class Site(CommonProgram): url = models.URLField( max_length=200, verbose_name=_('url'), ) is_program = models.BooleanField( default=False, verbose_name=_('is program'), ) is_program.help_text = _( 'Define if site is production web-application and must be placed in program section' ) open_with_default_browser = models.BooleanField( default=False, verbose_name=_('open with default browser'), ) open_with_default_browser.help_text = _( 'Open with default system browser instead of electron browser window') is_frameless = models.BooleanField( default=False, verbose_name=_('is frameless'), ) is_frameless.help_text = _( 'Open frameless window like in kiosk mode (doesn`t work with default browser)' ) class Meta: verbose_name = _('site') verbose_name_plural = _('sites') def __str__(self) -> str: return f'{self.name}({self.order}) {self.description}' class Program(CommonExecutable): window_process = models.CharField( max_length=200, blank=True, default='', verbose_name=_('window process'), ) window_process.help_text = _( 'Specify the main window process name in case of launching via bat\cmd.' ) class Meta: verbose_name = _('program') verbose_name_plural = _('programs') def __str__(self) -> str: return f'{self.name}({self.order}) {self.description}' class Location(models.Model): name = models.CharField( unique=True, max_length=12, verbose_name=_('name'), ) description = models.CharField( max_length=30, default='', blank=True, verbose_name=_('description'), ) ip_adresses = models.CharField( max_length=128, blank=True, null=False, default='', verbose_name=_('ip addresses'), ) ip_adresses.help_text = _( 'Regex pattern for IP adresses for this location, used by client to detect his location' ) password = models.CharField( max_length=8, validators=[RegexValidator('^\d+$', 'Only numbers, 8 max')], blank=True, null=False, verbose_name=_('password'), ) password.help_text = _( 'Admin password to access admin features on frontend') default_sites = models.ManyToManyField( Site, blank=True, verbose_name=_('default sites'), ) default_utility_software = models.ManyToManyField( UtilitySoftware, blank=True, verbose_name=_('default utility software'), ) history = HistoricalRecords(cascade_delete_history=True) class Meta: verbose_name = _('location') verbose_name_plural = _('locations') ordering = ['-id'] def __str__(self) -> str: return f'{self.name}' class ExclusiveProgram(CommonExecutable): location = models.ForeignKey( Location, on_delete=models.SET_NULL, null=True, blank=False, verbose_name=_('location'), ) class Meta: verbose_name = _('exclusive program') verbose_name_plural = _('exclusive programs') unique_together = ( 'name', 'location', ) def __str__(self) -> str: return f'{f"{self.location_id}: " if self.location_id else ""}{self.name}({self.order}) {self.description}' #type: ignore class WorkplaceType(models.Model): name = models.CharField( max_length=12, verbose_name=_('name'), ) description = models.CharField( max_length=30, default='', blank=True, verbose_name=_('description'), ) programs = models.ManyToManyField( Program, verbose_name=_('program'), ) utility_software = models.ManyToManyField( UtilitySoftware, blank=True, verbose_name=_('utility software'), ) sites = models.ManyToManyField( Site, blank=True, verbose_name=_('site'), ) location = models.ForeignKey( Location, on_delete=models.CASCADE, null=False, verbose_name=_('location'), ) is_active = models.BooleanField( default=True, verbose_name=is_active_translation, ) history = HistoricalRecords(cascade_delete_history=True) class Meta: verbose_name = _('workplace type') verbose_name_plural = _('workplace types') ordering = ['-id'] unique_together = ( 'name', 'location', ) def __str__(self) -> str: return f'{self.location_id}: {self.name} {self.description}' #type: ignore class Workplace(models.Model): hostname = models.CharField( unique=True, max_length=18, verbose_name=_('hostname'), ) description = models.CharField( max_length=30, blank=True, null=False, default='', verbose_name=_('description'), ) workplace_type = models.ForeignKey( WorkplaceType, on_delete=models.CASCADE, verbose_name=_('workplace type'), ) workplace_name = models.CharField( max_length=32, blank=True, null=True, verbose_name=_('workplace name'), help_text=_('name in production system'), ) workplace_system = models.CharField( max_length=16, blank=True, null=True, verbose_name=_('workplace system'), help_text=_('production system to which the workplace belongs'), ) exclusive_program = models.OneToOneField( ExclusiveProgram, on_delete=models.SET_NULL, null=True, blank=True, verbose_name=_('exclusive programs'), ) sources = models.ManyToManyField( 'links.Source', blank=True, verbose_name=_('sources'), ) process = models.ManyToManyField( 'links.Process', blank=True, verbose_name=_('process'), ) sub_process = models.ManyToManyField( 'links.SubProcess', blank=True, verbose_name=_('sub-process'), ) sites = models.ManyToManyField( Site, blank=True, verbose_name=_('sites'), ) is_active = models.BooleanField( default=True, verbose_name=is_active_translation, ) last_seen = models.DateTimeField( null=True, blank=True, verbose_name=_('last seen'), ) history = HistoricalRecords(cascade_delete_history=True, excluded_fields=[ 'last_seen', 'workplace_name', 'workplace_system', ]) class Meta: verbose_name = _('workplace') verbose_name_plural = _('workplaces') ordering = ['-id'] def __str__(self) -> str: return f'{self.hostname}: {self.description}'