Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

GH-88: System Specs #313

Closed
wants to merge 12 commits into from
Closed
32 changes: 32 additions & 0 deletions taccsite_cms/contrib/taccsite_system_specs/TODO.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# To Do

## Preparation for Urgent

- [x] Re-word "Read More / See All" ticket as "- Styles" ticket.

## Urgent

- [x] Undo initial commit and create indpendent branches for:
- [x] `c-see-all-link` → `task/GH-298-add-see-all-component`
- [x] `c-data-list` → `task/GH-75-styles`
- [x] plan for not loading new components in `site.css` → (merged to `main`)
- [x] changes to `taccsite_sysmon` → `task/GH-89`
- [x] changes to `x-truncate` → (merged to `main`)

## Problems to Fix

- [x] Prevent duplicate entires in "Internal Link".
- [ ] Add missing link feature to "Data List Item" plugin. → GH-75
- [ ] Find makeshift way to list dependency plugins i.e. taccsite_data_list.

## Continued Development

- [x] Add "Data List" plugin. → GH-75
- [x] Add "Data List Item" plugin. → GH-75
- [x] Integrate "Data List(…)" plugins into "System Specs" plugin.
- [x] Create new "See All - Component" ticket. → GH-298
- [ ] Style the new markup.

## Related Development Planning

- [x] Create new "See All - Plugin" ticket. → GH-299
Empty file.
124 changes: 124 additions & 0 deletions taccsite_cms/contrib/taccsite_system_specs/cms_plugins.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
from cms.plugin_pool import plugin_pool
from django.utils.translation import gettext_lazy as _

from djangocms_link.cms_plugins import LinkPlugin

from taccsite_cms.contrib.constants import TEXT_FOR_NESTED_PLUGIN_CONTENT_ADD
from taccsite_cms.contrib.helpers import concat_classnames

from .constants import DEFAULT_OTHER_TITLE

from .models import TaccsiteSystemSpecs

@plugin_pool.register_plugin
class TaccsiteSystemSpecsPlugin(LinkPlugin):
"""
Components > "System Specs" Plugin
"""
module = 'TACC Site'
model = TaccsiteSystemSpecs
name = _('System Specs')
render_template = 'system_specs.html'
def get_render_template(self, context, instance, placeholder):
return self.render_template

cache = True
text_enabled = False
allow_children = True
child_classes = [
'TaccsiteSystemMonitorPlugin',
'PicturePlugin',
'Bootstrap4PicturePlugin',
'TaccsiteDataListPlugin',
]

fieldsets = [
(_('Specifications'), {
'fields': (
'system_desc',
'system_processor_count',
'system_processor_type',
'system_node_ram',
'system_network',
'system_performance',
'system_memory',
)
}),
(_('Footer link'), {
'classes': ('collapse',),
'description': 'The "See More Detailed Specs" link at the bottom of the list. "Display name" is for alternate link text.',
'fields': (
('external_link', 'internal_link'),
('anchor', 'target'),
'name',
)
}),
(_('Subsystems and/or resources - Introduction'), {
'fields': (
'other_title',
'other_desc',
)
}),
(_('Subsystems and/or resources - Data'), {
'classes': ('collapse',),
'description': TEXT_FOR_NESTED_PLUGIN_CONTENT_ADD.format(
element='data',
plugin_name='Data List'
),
'fields': ()
}),
(_('Image'), {
'classes': ('collapse',),
'description': TEXT_FOR_NESTED_PLUGIN_CONTENT_ADD.format(
element='an image',
plugin_name='(…) Image'
),
'fields': ()
}),
(_('System monitor'), {
'classes': ('collapse',),
'description': TEXT_FOR_NESTED_PLUGIN_CONTENT_ADD.format(
element='a system monitor',
plugin_name='(…) System Monitor'
),
'fields': ()
}),
(_('Advanced settings'), {
'classes': ('collapse',),
'fields': (
'attributes',
)
}),
]

# Render

def render(self, context, instance, placeholder):
context = super().render(context, instance, placeholder)
request = context['request']

classes = concat_classnames([
's-system-specs',
instance.attributes.get('class'),
])
instance.attributes['class'] = classes

# To identify child plugins
for plugin_instance in instance.child_plugin_instances:
print(type(plugin_instance).__name__)
if (type(plugin_instance).__name__ == 'TaccsiteSysmon'):
context.update({ 'sysmon_plugin': plugin_instance })
if (type(plugin_instance).__name__ == 'Picture' or
type(plugin_instance).__name__ == 'Bootstrap4Picture'):
context.update({ 'image_plugin': plugin_instance })
if (type(plugin_instance).__name__ == 'TaccsiteDataList'):
context.update({ 'data_plugin': plugin_instance })

context.update({
'default_other_title': DEFAULT_OTHER_TITLE,
'has_other': instance.other_title or instance.other_desc,
'link_url': instance.get_link(),
'link_text': instance.name,
'link_target': instance.target
})
return context
1 change: 1 addition & 0 deletions taccsite_cms/contrib/taccsite_system_specs/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DEFAULT_OTHER_TITLE = 'Subsystems and Associated Resources'
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
# Generated by Django 2.2.16 on 2021-08-06 04:17

from django.db import migrations, models
import django.db.models.deletion
import djangocms_attributes_field.fields
import djangocms_link.validators
import filer.fields.file


class Migration(migrations.Migration):

initial = True

dependencies = [
('filer', '0012_file_mime_type'),
('cms', '0022_auto_20180620_1551'),
]

operations = [
migrations.CreateModel(
name='TaccsiteSystemSpecs',
fields=[
('template', models.CharField(choices=[('default', 'Default')], default='default', max_length=255, verbose_name='Template')),
('name', models.CharField(blank=True, max_length=255, verbose_name='Display name')),
('external_link', models.CharField(blank=True, help_text='Provide a link to an external source.', max_length=2040, validators=[djangocms_link.validators.IntranetURLValidator(intranet_host_re=None)], verbose_name='External link')),
('anchor', models.CharField(blank=True, help_text='Appends the value only after the internal or external link. Do <em>not</em> include a preceding "#" symbol.', max_length=255, verbose_name='Anchor')),
('mailto', models.EmailField(blank=True, max_length=255, verbose_name='Email address')),
('phone', models.CharField(blank=True, max_length=255, verbose_name='Phone')),
('target', models.CharField(blank=True, choices=[('_blank', 'Open in new window'), ('_self', 'Open in same window'), ('_parent', 'Delegate to parent'), ('_top', 'Delegate to top')], max_length=255, verbose_name='Target')),
('attributes', djangocms_attributes_field.fields.AttributesField(blank=True, default=dict, verbose_name='Attributes')),
('cmsplugin_ptr', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, related_name='taccsite_system_specs_taccsitesystemspecs', serialize=False, to='cms.CMSPlugin')),
('system_desc', models.TextField(default='', help_text='Description of the system machine and mission.', verbose_name='System Description')),
('system_processor_count', models.IntegerField(blank=True, help_text='The number of processors in the system', null=True, verbose_name='Processors')),
('system_processor_type', models.CharField(blank=True, help_text='The number of processors in the system', max_length=50, verbose_name='Processor Type')),
('system_node_ram', models.CharField(blank=True, help_text='The amount of RAM in each node of the system, including the unit. (Reminder: Type "GB" for Gigabyte, not "Gb".)', max_length=50, verbose_name='RAM per Node')),
('system_network', models.CharField(blank=True, help_text='The network hardware in the system. (Reminder: Type "Gb" for Gigabit, not GB.)', max_length=50, verbose_name='Network')),
('system_performance', models.CharField(blank=True, help_text='The peak performance of the system, including the unit. (Reminder: Type number, then space, then unit; example: "38.8 PetaFLOPS".)', max_length=50, verbose_name='Peak Performance')),
('system_memory', models.CharField(blank=True, help_text='The amount of memory for the system, including the unit. (Reminder: Type "PB" for Petabyte, not "Pb".)', max_length=50, verbose_name='Memory')),
('other_title', models.CharField(blank=True, help_text='An alternate title to replace "Subsystems and Associated Resources".', max_length=40, verbose_name='Alternate Resources Title')),
('other_desc', models.TextField(blank=True, default='', help_text='Description of "Subsystems and Associated Resources".', verbose_name='Resources Description')),
('file_link', filer.fields.file.FilerFileField(blank=True, help_text='If provided links a file from the filer app.', null=True, on_delete=django.db.models.deletion.SET_NULL, to='filer.File', verbose_name='File link')),
('internal_link', models.ForeignKey(blank=True, help_text='If provided, overrides the external link.', null=True, on_delete=django.db.models.deletion.SET_NULL, to='cms.Page', verbose_name='Internal link')),
],
options={
'abstract': False,
},
bases=('cms.cmsplugin',),
),
]
Empty file.
95 changes: 95 additions & 0 deletions taccsite_cms/contrib/taccsite_system_specs/models.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
from django.core.exceptions import ValidationError
from django.utils.translation import gettext_lazy as _

from django.db import models

from djangocms_link.models import AbstractLink

from taccsite_cms.contrib.helpers import clean_for_abstract_link

from .constants import DEFAULT_OTHER_TITLE

class TaccsiteSystemSpecs(AbstractLink):
"""
Components > "System Specs" Model
"""
system_desc = models.TextField(
verbose_name=_('System Description'),
help_text=_('Description of the system machine and mission.'),
blank=False,
default=''
)
system_processor_count = models.IntegerField(
verbose_name=_('Processors'),
help_text=_('The number of processors in the system'),
blank=True,
null=True,
# HELP: Is it worth it to create a min. value zero to avoid neg. values?
# SEE: https://stackoverflow.com/a/849426/11817077
# min_value=0,
)
system_processor_type = models.CharField(
verbose_name=_('Processor Type'),
help_text=_('The number of processors in the system'),
blank=True,
max_length=50,
)
system_node_ram = models.CharField(
verbose_name=_('RAM per Node'),
help_text=_('The amount of RAM in each node of the system, including the unit. (Reminder: Type "GB" for Gigabyte, not "Gb".)'),
blank=True,
max_length=50,
)
system_network = models.CharField(
verbose_name=_('Network'),
help_text=_('The network hardware in the system. (Reminder: Type "Gb" for Gigabit, not GB.)'),
blank=True,
max_length=50,
)
system_performance = models.CharField(
verbose_name=_('Peak Performance'),
help_text=_('The peak performance of the system, including the unit. (Reminder: Type number, then space, then unit; example: "38.8 PetaFLOPS".)'),
blank=True,
max_length=50,
)
system_memory = models.CharField(
verbose_name=_('Memory'),
help_text=_('The amount of memory for the system, including the unit. (Reminder: Type "PB" for Petabyte, not "Pb".)'),
blank=True,
max_length=50,
)

other_title = models.CharField(
verbose_name=_('Alternate Resources Title'),
help_text=_('An alternate title to replace "%(default_value)s".') % { 'default_value': DEFAULT_OTHER_TITLE },
blank=True,
max_length=40, # Based on approx. space available in design
)
other_desc = models.TextField(
verbose_name=_('Resources Description'),
help_text=_('Description of "%(default_value)s".') % { 'default_value': DEFAULT_OTHER_TITLE },
blank=True,
default=''
)

def get_short_description(self):
return self.system_desc



# Parent

link_is_optional = True

class Meta:
abstract = False

# Validate
def clean(self):
clean_for_abstract_link(__class__, self)

# If user provided link text, then require link
if self.name and not self.get_link():
raise ValidationError(
_('Please provide a footer link or delete its display name.'), code='invalid'
)
Loading