production-taskbar / backend / taskbar / models.py
models.py
Raw
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}'