diff --git a/migrations/migrations.yml b/migrations/migrations.yml
index 8afb92479..ecd6c81ae 100644
--- a/migrations/migrations.yml
+++ b/migrations/migrations.yml
@@ -99,4 +99,5 @@ migrations:
- AddOnDeleteCascadeForEventsAndPresentationMaterials
- AddSummitCalendarSyncErrorEmailMigration
- RefactorDefaultEventTypesMigration
-
+ - PopulateComponentCategoriesMigration
+ - PopulateSubCategoriesAndTagsMigration
diff --git a/openstack/code/CommunityPageBis.php b/openstack/code/CommunityPageBis.php
index 84f26e455..12e3a8272 100644
--- a/openstack/code/CommunityPageBis.php
+++ b/openstack/code/CommunityPageBis.php
@@ -71,19 +71,6 @@ function init()
Requirements::javascript('themes/openstack/javascript/community-bis.js');
}
- function getProjectGroups() {
- $groups = OpenStackComponent::$categories;
- $list = new ArrayList();
- foreach ($groups as $key => $group) {
- $list->push(new ArrayData([
- 'Name' => $group,
- 'Key' => $key
- ]));
- }
-
- return $list;
- }
-
function getComponentsByGroup($group) {
return OpenStackComponent::get()->filter('Use', $group);
}
diff --git a/software/_config.php b/software/_config.php
index 956add49f..c00bb5b7b 100644
--- a/software/_config.php
+++ b/software/_config.php
@@ -17,6 +17,9 @@
Object::add_extension('OpenStackComponent', 'OpenStackComponentAdminUI');
+Object::add_extension('OpenStackComponentCategory', 'OpenStackComponentCategoryAdminUI');
+Object::add_extension('OpenStackComponentSubCategory', 'OpenStackComponentSubCategoryAdminUI');
+Object::add_extension('OpenStackComponentTag', 'OpenStackComponentTagAdminUI');
Object::add_extension('OpenStackApiVersion', 'OpenStackApiVersionAdminUI');
Object::add_extension('OpenStackRelease', 'OpenStackReleaseAdminUI');
Object::add_extension('OpenStackReleaseSupportedApiVersion', 'OpenStackReleaseSupportedApiVersionAdminUI');
diff --git a/software/code/infrastructure/active_records/OpenStackComponent.php b/software/code/infrastructure/active_records/OpenStackComponent.php
index 6acea3abf..6d85f404f 100644
--- a/software/code/infrastructure/active_records/OpenStackComponent.php
+++ b/software/code/infrastructure/active_records/OpenStackComponent.php
@@ -20,19 +20,6 @@ class OpenStackComponent extends DataObject implements IOpenStackComponent
use SluggableEntity;
- // IMPORTANT : this fixes the order for categories on software page
- public static $categories = array(
- "Compute",
- "Storage, Backup & Recovery",
- "Networking & Content Delivery",
- "Data & Analytics",
- "Security, Identity & Compliance",
- "Management Tools",
- "Deployment Tools",
- "Application Services",
- "None"
- );
-
static $db = array
(
'Name' => 'Varchar(255)',
@@ -41,37 +28,38 @@ class OpenStackComponent extends DataObject implements IOpenStackComponent
'SupportsVersioning' => 'Boolean',
'SupportsExtensions' => 'Boolean',
'IsCoreService' => 'Boolean',
- 'Use' => 'Enum(array("Application Services","Compute","Data & Analytics","Deployment Tools","Management Tools","Monitoring & Metering","Networking & Content Delivery","Security, Identity & Compliance","Storage, Backup & Recovery","None"), "None")',
- 'HasStableBranches' => 'Boolean',
'WikiUrl' => 'Text',
- 'TCApprovedRelease' => 'Boolean',
- 'HasTeamDiversity' => 'Boolean',
- 'IncludedComputeStarterKit' => 'Boolean',
- 'VulnerabilityManaged' => 'Boolean',
'Order' => 'Int',
'YouTubeID' => 'Varchar',
'VideoDescription' => 'Text',
'VideoTitle' => 'Varchar',
- 'FollowsStandardDeprecation' => 'Boolean',
- 'SupportsUpgrade' => 'Boolean',
- 'SupportsRollingUpgrade' => 'Boolean',
'ShowOnMarketplace' => 'Boolean(1)',
'Slug' => 'Varchar(255)'
);
static $has_one = array
(
- "LatestReleasePTL" => "Member",
- "Mascot" => "Mascot"
+ "LatestReleasePTL" => "Member",
+ "Mascot" => "Mascot",
+ "SubCategory" => "OpenStackComponentSubCategory"
);
static $has_many = array
(
- 'Versions' => 'OpenStackApiVersion',
- 'RelatedContent' => 'OpenStackComponentRelatedContent',
- 'Caveats' => 'OpenStackComponentReleaseCaveat',
+ 'Versions' => 'OpenStackApiVersion',
+ 'RelatedContent' => 'OpenStackComponentRelatedContent',
+ 'Caveats' => 'OpenStackComponentReleaseCaveat'
+ );
+
+ static $many_many = array
+ (
+ 'Tags' => 'OpenStackComponentTag'
);
+ private static $many_many_extraFields = array
+ (
+ 'Tags' => array( 'SortOrder' => 'Int' )
+ );
static $belongs_many_many = array
(
@@ -299,4 +287,29 @@ public function getCaveatsForReleaseType($release_id, $type)
)
);
}
+
+ /**
+ * @param IOpenStackComponentTag $new_tag
+ * @return void
+ */
+ public function addTag(IOpenStackComponentTag $new_tag)
+ {
+ AssociationFactory::getInstance()->getMany2ManyAssociation($this, 'Tags')->add($new_tag);
+ }
+
+ /**
+ * @return IOpenStackComponentTag[]
+ */
+ public function getMaturityTags()
+ {
+ return $this->Tags()->filter('Type', 'maturity');
+ }
+
+ /**
+ * @return IOpenStackComponentTag[]
+ */
+ public function getInfoTags()
+ {
+ return $this->Tags()->filter('Type', 'info');
+ }
}
\ No newline at end of file
diff --git a/software/code/infrastructure/active_records/OpenStackComponentCategory.php b/software/code/infrastructure/active_records/OpenStackComponentCategory.php
new file mode 100644
index 000000000..9c8c560d9
--- /dev/null
+++ b/software/code/infrastructure/active_records/OpenStackComponentCategory.php
@@ -0,0 +1,110 @@
+ 'Varchar(255)',
+ 'Description' => 'Text',
+ 'Order' => 'Int'
+ );
+
+ static $many_many = array
+ (
+ 'SubCategories' => 'OpenStackComponentSubCategory'
+ );
+
+ static $many_many_extraFields = array(
+ 'SubCategories' => array(
+ 'SubCatOrder' => 'Int'
+ )
+ );
+
+ /**
+ * @return int
+ */
+ public function getIdentifier()
+ {
+ return (int)$this->getField('ID');
+ }
+
+ public function getName()
+ {
+ return $this->getField('Name');
+ }
+
+ public function setName($name)
+ {
+ $this->setField('Name', $name);
+ }
+
+ public function getDescription()
+ {
+ return $this->getField('Description');
+ }
+
+ public function setDescription($description)
+ {
+ $this->setField('Description', $description);
+ }
+
+ public function getOrder()
+ {
+ return $this->getField('Order');
+ }
+
+ public function setOrder($order)
+ {
+ $this->setField('Order', $order);
+ }
+
+ /**
+ * @return array
+ * @throws Exception
+ */
+ public function getSubCategories()
+ {
+ return AssociationFactory::getInstance()->getMany2ManyAssociation($this, 'SubCategories')->toArray();
+ }
+
+ /**
+ * @param IOpenStackComponentSubCategory $new_sub_category
+ * @throws Exception
+ */
+ public function addSubCategory(IOpenStackComponentSubCategory $new_sub_category)
+ {
+ AssociationFactory::getInstance()->getMany2ManyAssociation($this, 'SubCategories')->add($new_sub_category);
+ }
+
+ /**
+ * @param int $component_id
+ * @return bool
+ */
+ public function hasOpenStackComponent($component_id)
+ {
+ foreach ($this->getSubCategories() as $subCategory) {
+ if ($subCategory->hasOpenStackComponent($component_id)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+}
\ No newline at end of file
diff --git a/software/code/infrastructure/active_records/OpenStackComponentSubCategory.php b/software/code/infrastructure/active_records/OpenStackComponentSubCategory.php
new file mode 100644
index 000000000..7af1b257a
--- /dev/null
+++ b/software/code/infrastructure/active_records/OpenStackComponentSubCategory.php
@@ -0,0 +1,108 @@
+ 'Varchar(255)',
+ 'Description' => 'Text'
+ );
+
+ static $has_many = array
+ (
+ 'OpenStackComponents' => 'OpenStackComponent'
+ );
+
+ static $belongs_many_many = array
+ (
+ 'Categories' => 'OpenStackComponentCategory'
+ );
+
+ /**
+ * @return int
+ */
+ public function getIdentifier()
+ {
+ return (int)$this->getField('ID');
+ }
+
+ public function getName()
+ {
+ return $this->getField('Name');
+ }
+
+ public function setName($name)
+ {
+ $this->setField('Name', $name);
+ }
+
+ public function getDescription()
+ {
+ return $this->getField('Description');
+ }
+
+ public function setDescription($description)
+ {
+ $this->setField('Description', $description);
+ }
+
+ public function getOrder()
+ {
+ return $this->getField('Order');
+ }
+
+ public function setOrder($order)
+ {
+ $this->setField('Order', $order);
+ }
+
+ /**
+ * @return array
+ * @throws Exception
+ */
+ public function getOpenStackComponents()
+ {
+ return AssociationFactory::getInstance()->getOne2ManyAssociation($this, 'OpenStackComponents')->toArray();
+ }
+
+ /**
+ * @param IOpenStackComponent $new_component
+ * @throws Exception
+ */
+ public function addOpenStackComponent(IOpenStackComponent $new_component)
+ {
+ AssociationFactory::getInstance()->getOne2ManyAssociation($this, 'OpenStackComponents')->add($new_component);
+ }
+
+ /**
+ * @param int $component_id
+ * @return bool
+ */
+ public function hasOpenStackComponent($component_id)
+ {
+ foreach ($this->getOpenStackComponents() as $component) {
+ if ($component->getIdentifier() == $component_id) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+}
\ No newline at end of file
diff --git a/software/code/infrastructure/active_records/OpenStackComponentTag.php b/software/code/infrastructure/active_records/OpenStackComponentTag.php
new file mode 100644
index 000000000..080436aa9
--- /dev/null
+++ b/software/code/infrastructure/active_records/OpenStackComponentTag.php
@@ -0,0 +1,73 @@
+ 'Varchar(255)',
+ 'Type' => "Enum('maturity, info', 'maturity')",
+ 'Label' => 'Varchar(255)',
+ 'Description' => 'Text',
+ 'Link' => 'Varchar(255)',
+ 'LabelTranslationKey' => 'Varchar(255)',
+ 'DescriptionTranslationKey' => 'Varchar(255)',
+ 'Enabled' => 'Boolean(1)'
+ );
+
+ /**
+ * @return int
+ */
+ public function getIdentifier()
+ {
+ return (int)$this->getField('ID');
+ }
+
+ public function getName()
+ {
+ return $this->getField('Name');
+ }
+
+ public function setName($name)
+ {
+ $this->setField('Name', $name);
+ }
+
+ public function getType()
+ {
+ return $this->getField('Type');
+ }
+
+ public function setType($type)
+ {
+ $this->setField('Type', $type);
+ }
+
+ public function getTranslatedLabel()
+ {
+ return _t('Software.'.strtoupper($this->LabelTranslationKey), $this->Label);
+ }
+
+ public function getTranslatedDescription()
+ {
+ return _t('Software.'.strtoupper($this->DescriptionTranslationKey), $this->Description);
+ }
+
+
+
+}
\ No newline at end of file
diff --git a/software/code/infrastructure/active_records/OpenStackRelease.php b/software/code/infrastructure/active_records/OpenStackRelease.php
index 6aecdd3b3..7891ad969 100644
--- a/software/code/infrastructure/active_records/OpenStackRelease.php
+++ b/software/code/infrastructure/active_records/OpenStackRelease.php
@@ -71,7 +71,7 @@ class OpenStackRelease
(
'SupportedApiVersions' => 'OpenStackReleaseSupportedApiVersion',
'SampleConfigurationTypes' => 'OpenStackSampleConfigurationType',
- 'Caveats' => 'OpenStackComponentReleaseCaveat',
+ 'Caveats' => 'OpenStackComponentReleaseCaveat'
);
@@ -458,7 +458,7 @@ public function getOpenStackComponentsFiltered($term = '', $adoption = 0, $matur
}
$final = array();
- $res = $query->sort(array('Use'=>'ASC','IsCoreService'=>'DESC', 'Order'=>'ASC'))->toArray();
+ $res = $query->sort(array('Category.Name'=>'ASC','IsCoreService'=>'DESC', 'Order'=>'ASC'))->toArray();
foreach($res as $c)
{
if($c->getAge() >= $age)
diff --git a/software/code/infrastructure/active_records/OpenStackReleaseSupportedApiVersion.php b/software/code/infrastructure/active_records/OpenStackReleaseSupportedApiVersion.php
index b1f5e4cae..81090aa83 100644
--- a/software/code/infrastructure/active_records/OpenStackReleaseSupportedApiVersion.php
+++ b/software/code/infrastructure/active_records/OpenStackReleaseSupportedApiVersion.php
@@ -27,7 +27,6 @@ class OpenStackReleaseSupportedApiVersion
];
static $has_one = [
-
'OpenStackComponent' => 'OpenStackComponent',
'ApiVersion' => 'OpenStackApiVersion',
'Release' => 'OpenStackRelease',
diff --git a/software/code/migrations/PopulateComponentCategoriesMigration.php b/software/code/migrations/PopulateComponentCategoriesMigration.php
new file mode 100644
index 000000000..07552df3f
--- /dev/null
+++ b/software/code/migrations/PopulateComponentCategoriesMigration.php
@@ -0,0 +1,63 @@
+ $category) {
+ if (!$new_category = OpenStackComponentCategory::get()->filter('Name', $category)->first()) {
+ $new_category = new OpenStackComponentCategory();
+ $new_category->Name = $category;
+ $new_category->Order = $order;
+ }
+
+ $component_ids = OpenStackComponent::get()->filter('Use', $category)->column('ID');
+ if ($component_ids) {
+ $new_category->OpenStackComponents()->setByIDList($component_ids);
+ }
+
+ $new_category->write();
+ }
+
+ /*$SQL = <<OpenStack Component
"));
$fields->push(new TextField("Name", "Name"));
$fields->push(new TextField("CodeName", "Code Name"));
- $fields->push(new DropdownField('Mascot', 'Mascot', Mascot::get()->map()));
+ $fields->push(new DropdownField('MascotID', 'Mascot', Mascot::get()->map('ID', 'Name')));
$fields->push(new TextField("Description", "Description"));
$fields->push(new TextField("YouTubeID", "Video (YouTubeID)"));
$fields->push(new TextField("VideoTitle", "Video Title"));
@@ -46,14 +46,12 @@ public function updateCMSFields(FieldList $fields)
$fields->push(new CheckboxField('SupportsExtensions', 'Supports Extensions?'));
$fields->push(new CheckboxField('IsCoreService', 'Is Core Service?'));
$fields->push(new CheckboxField('ShowOnMarketplace', 'Show On Marketplace?'));
- $fields->push(new DropdownField('Use', 'Project Category', $this->owner->dbObject('Use')->enumValues()));
+ $categories = OpenStackComponentSubCategory::get()->map('ID', 'Name');
+ $fields->push(new DropdownField('SubCategoryID', 'Project Sub Category', $categories));
if ($this->owner->getSupportsVersioning()) {
-
$versions_config = new GridFieldConfig_RecordEditor();
-
$versions = new GridField("Versions", "Versions", $this->owner->Versions(), $versions_config);
-
$fields->push($versions);
}
@@ -62,6 +60,11 @@ public function updateCMSFields(FieldList $fields)
$related_content = new GridField("RelatedContent", "RelatedContent", $this->owner->RelatedContent(), $config);
$fields->push($related_content);
+ $config = new GridFieldConfig_RecordEditor();
+ $config->addComponent(new GridFieldSortableRows('SortOrder'));
+ $component_tags = new GridField("Tags", "Component Tags", $this->owner->Tags(), $config);
+ $fields->push($component_tags);
+
return $fields;
}
diff --git a/software/code/ui/admin/OpenStackComponentCategoryAdminUI.php b/software/code/ui/admin/OpenStackComponentCategoryAdminUI.php
new file mode 100644
index 000000000..74083e7c4
--- /dev/null
+++ b/software/code/ui/admin/OpenStackComponentCategoryAdminUI.php
@@ -0,0 +1,62 @@
+ 'Name',
+ 'Description' => 'Description'
+ ];
+
+ /**
+ * @param FieldList $fields
+ * @return FieldList|void
+ */
+ public function updateCMSFields(FieldList $fields)
+ {
+ $oldFields = $fields->toArray();
+ foreach ($oldFields as $field) {
+ $fields->remove($field);
+ }
+ $fields->push(new LiteralField("Title", "OpenStack Component Category
"));
+ $fields->push(new TextField("Name", "Name"));
+ $fields->push(new TextField("Description", "Description"));
+
+ $config = new GridFieldConfig_RelationEditor();
+ $config->addComponent(new GridFieldSortableRows('SubCatOrder'));
+ $sub_categories = new GridField("SubCategories", "Sub-Categories", $this->owner->SubCategories(), $config);
+ $fields->push($sub_categories);
+
+ }
+
+ public function onBeforeWrite()
+ {
+ //create group here?
+ parent::onBeforeWrite();
+ }
+
+ function getCMSValidator()
+ {
+ return $this->getValidator();
+ }
+
+ function getValidator()
+ {
+ $validator = new RequiredFields(array('Name'));
+
+ return $validator;
+ }
+
+}
\ No newline at end of file
diff --git a/software/code/ui/admin/OpenStackComponentSubCategoryAdminUI.php b/software/code/ui/admin/OpenStackComponentSubCategoryAdminUI.php
new file mode 100644
index 000000000..87f7dc904
--- /dev/null
+++ b/software/code/ui/admin/OpenStackComponentSubCategoryAdminUI.php
@@ -0,0 +1,64 @@
+ 'Name',
+ 'Description' => 'Description'
+ ];
+
+ /**
+ * @param FieldList $fields
+ * @return FieldList|void
+ */
+ public function updateCMSFields(FieldList $fields)
+ {
+ $oldFields = $fields->toArray();
+ foreach ($oldFields as $field) {
+ $fields->remove($field);
+ }
+ $fields->push(new LiteralField("Title", "OpenStack Component Sub Category
"));
+ $fields->push(new TextField("Name", "Name"));
+ $fields->push(new TextField("Description", "Description"));
+
+ if($this->owner->ID) {
+ $config = new GridFieldConfig_RelationEditor();
+ $config->addComponent(new GridFieldSortableRows('Order'));
+ $components = new GridField("OpenStackComponents", "Components", $this->owner->OpenStackComponents(), $config);
+ $fields->push($components);
+ }
+
+ }
+
+ public function onBeforeWrite()
+ {
+ //create group here?
+ parent::onBeforeWrite();
+ }
+
+ function getCMSValidator()
+ {
+ return $this->getValidator();
+ }
+
+ function getValidator()
+ {
+ $validator = new RequiredFields(array('Name'));
+
+ return $validator;
+ }
+
+}
\ No newline at end of file
diff --git a/software/code/ui/admin/OpenStackComponentTagAdminUI.php b/software/code/ui/admin/OpenStackComponentTagAdminUI.php
new file mode 100644
index 000000000..78eecbda4
--- /dev/null
+++ b/software/code/ui/admin/OpenStackComponentTagAdminUI.php
@@ -0,0 +1,66 @@
+ 'Name',
+ 'Type' => 'Type',
+ 'Label' => 'Label',
+ 'Enabled' => 'Enabled'
+ ];
+
+ /**
+ * @param FieldList $fields
+ * @return FieldList|void
+ */
+ public function updateCMSFields(FieldList $fields)
+ {
+ $oldFields = $fields->toArray();
+ foreach ($oldFields as $field) {
+ $fields->remove($field);
+ }
+
+ $fields->push(new LiteralField("Title", "OpenStack Component Tag
"));
+ $fields->push(new TextField("Name", "Name"));
+ $fields->push(new DropdownField("Type", "Type", $this->owner->dbObject('Type')->enumValues()));
+ $fields->push(new TextField("Label", "Label"));
+ $fields->push(new TextField("Description", "Description"));
+ $fields->push(new TextField("Link", "Link"));
+ $fields->push(new TextField("LabelTranslationKey", "Label Translation Key"));
+ $fields->push(new TextField("DescriptionTranslationKey", "Description Translation Key"));
+ $fields->push(new CheckboxField("Enabled", "Enabled?"));
+
+ }
+
+ public function onBeforeWrite()
+ {
+ //create group here?
+ parent::onBeforeWrite();
+ }
+
+ function getCMSValidator()
+ {
+ return $this->getValidator();
+ }
+
+ function getValidator()
+ {
+ $validator = new RequiredFields(array('Name'));
+
+ return $validator;
+ }
+
+}
\ No newline at end of file
diff --git a/software/code/ui/admin/SoftwareModelAdmin.php b/software/code/ui/admin/SoftwareModelAdmin.php
index 5447a23d1..7f187ab7c 100644
--- a/software/code/ui/admin/SoftwareModelAdmin.php
+++ b/software/code/ui/admin/SoftwareModelAdmin.php
@@ -19,6 +19,9 @@ class SoftwareModelAdmin extends ModelAdmin
'OpenStackComponent',
'OpenStackRelease',
'OpenStackSampleConfig',
+ 'OpenstackComponentCategory',
+ 'OpenstackComponentSubCategory',
+ 'OpenstackComponentTag',
'Mascot'
);
@@ -36,11 +39,14 @@ public function getEditForm($id = null, $fields = null) {
$form = parent:: getEditForm($id, $fields);
- if($this->modelClass === 'OpenStackComponent' || $this->modelClass === 'OpenStackSampleConfig') {
- $gridField = $form->Fields()->fieldByName($this->sanitiseClassName($this->modelClass));
- $config = $gridField->getConfig();
- $config->addComponent(new GridFieldSortableRows('Order'));
+ if($this->modelClass === 'OpenStackComponent' ||
+ $this->modelClass === 'OpenStackSampleConfig' ||
+ $this->modelClass === 'OpenstackComponentCategory') {
+ $gridField = $form->Fields()->fieldByName($this->sanitiseClassName($this->modelClass));
+ $config = $gridField->getConfig();
+ $config->addComponent(new GridFieldSortableRows('Order'));
}
+
if($this->modelClass === 'OpenStackRelease') {
$gridField = $form->Fields()->fieldByName($this->sanitiseClassName($this->modelClass));
$config = $gridField->getConfig();
diff --git a/software/templates/Layout/SoftwareHomePage_getComponent.ss b/software/templates/Layout/SoftwareHomePage_getComponent.ss
index 487fb4ff9..4c653d687 100644
--- a/software/templates/Layout/SoftwareHomePage_getComponent.ss
+++ b/software/templates/Layout/SoftwareHomePage_getComponent.ss
@@ -32,53 +32,6 @@