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 = << 'assert:follows-standard-deprecation', + 'Label' => 'follows standard deprecation', + 'Type' => 'maturity', + 'Description' => 'The “assert:follows-standard-deprecation” tag asserts that the project will follow standard feature deprecation rules', + 'Link' => 'http://governance.openstack.org/reference/tags/assert_follows-standard-deprecation.html', + 'LabelTranslationKey' => 'FOLLOW_DEPRECATION', + 'DescriptionTranslationKey' => 'DEPRECATION_TAG_DESCRIPTION', + ], + [ + 'Name' => 'supports-api-interoperability', + 'Label' => 'supports api interoperability', + 'Type' => 'maturity', + 'Description' => '', + 'Link' => '', + 'LabelTranslationKey' => '', + 'DescriptionTranslationKey' => '', + ], + [ + 'Name' => 'assert:supports-upgrade', + 'Label' => 'supports minimal cold (offline) upgrade capabilities', + 'Type' => 'maturity', + 'Description' => 'asserts that the project will support minimal cold (offline) upgrade capabilities', + 'Link' => 'http://governance.openstack.org/reference/tags/assert_supports-upgrade.html', + 'LabelTranslationKey' => 'MINIMAL_UPGRADE', + 'DescriptionTranslationKey' => 'MINIMAL_UPGRADE_DESCRIPTION', + ], + [ + 'Name' => 'assert:supports-rolling-upgrade', + 'Label' => 'supports minimal rolling upgrade capabilities', + 'Type' => 'maturity', + 'Description' => 'tag asserts that the project will support minimal rolling upgrade capabilities.', + 'Link' => 'http://governance.openstack.org/reference/tags/assert_supports-rolling-upgrade.html', + 'LabelTranslationKey' => 'MINIMAL_ROLLING', + 'DescriptionTranslationKey' => 'MINIMAL_ROLLING_DESCRIPTION', + ], + [ + 'Name' => 'supports-zero-downtime-upgrade', + 'Label' => 'supports zero downtime upgrade', + 'Type' => 'maturity', + 'Description' => '', + 'Link' => '', + 'LabelTranslationKey' => '', + 'DescriptionTranslationKey' => '', + ], + [ + 'Name' => 'vulnerability:managed', + 'Label' => 'Are vulnerability issues managed by the OpenStack security team?', + 'Type' => 'info', + 'Description' => '', + 'Link' => 'http://governance.openstack.org/reference/tags/vulnerability_managed.html', + 'LabelTranslationKey' => 'VULNERABILITY_ISSUES', + 'DescriptionTranslationKey' => '', + ], + [ + 'Name' => 'team:diverse-affiliation', + 'Label' => 'team has achieved corporate diversity', + 'Type' => 'info', + 'Description' => 'A project with this tag has achieved a level of diversity in the affiliation of contributors that is indicative of a healthy collaborative project. This tag exists in the ‘team’ category, which as the name implies, covers information about the team itself. Another example of a tag that could exist in this category is one that conveys the size of the team that is actively contributing.', + 'Link' => 'http://governance.openstack.org/reference/tags/team_diverse-affiliation.html', + 'LabelTranslationKey' => 'USED_IN_CORPORATE', + 'DescriptionTranslationKey' => 'PROJECT_DIVERSITY', + ], + [ + 'Name' => 'stable:follows-policy', + 'Label' => 'is maintained following the common Stable branch policy', + 'Type' => 'info', + 'Description' => '', + 'Link' => 'http://docs.openstack.org/project-team-guide/stable-branches.html', + 'LabelTranslationKey' => 'STABLE_BRANCHES', + 'DescriptionTranslationKey' => '', + ], + [ + 'Name' => 'status:maintenance-mode', + 'Label' => 'status maintenance mode', + 'Type' => 'info', + 'Description' => '', + 'Link' => '', + 'LabelTranslationKey' => '', + 'DescriptionTranslationKey' => '', + ] + ); + + $categories = array( + [ + 'Name' => 'OpenStack', + 'Description' => 'user-facing components that deployers may opt to deploy to add functionality to their OpenStack deployment.', + 'Order' => 1, + 'SubCategories' => [ + ['Name' => 'Web frontend', 'Order' => 1, 'Components' => ['Horizon']], + ['Name' => 'API proxies', 'Order' => 2, 'Components' => ['EC2API']], + ['Name' => 'Workload provisioning', 'Order' => 3, 'Components' => ['Magnum','Trove','Sahara']], + ['Name' => 'Application lifecycle', 'Order' => 4, 'Components' => ['Murano','Freezer','Solum','Masakari']], + ['Name' => 'Orchestration', 'Order' => 5, 'Components' => ['Heat','Mistral','Aodh','Senlin','Zaqar','Blazar']], + ['Name' => 'Compute', 'Order' => 6, 'Components' => ['Nova','Ironic','Zun']], + ['Name' => 'Networking', 'Order' => 7, 'Components' => ['Neutron','Octavia','Designate']], + ['Name' => 'Storage', 'Order' => 8, 'Components' => ['Swift','Cinder','Manila']], + ['Name' => 'Shared services', 'Order' => 9, 'Components' => ['Keystone','Glance','Barbican','Searchlight','Karbor']] + ] + ], + [ + 'Name' => 'OpenStack Operations', + 'Description' => 'mainly operator-facing components that deployers may opt to deploy to facilitate managing their OpenStack deployment.', + 'Order' => 2, + 'SubCategories' => [ + ['Name' => 'Monitoring tools', 'Order' => 1, 'Components' => ['Ceilometer','Panko','Monasca']], + ['Name' => 'Optimization / Policy tools', 'Order' => 2, 'Components' => ['Watcher','Vitrage','Congress','Rally','Cyborg']], + ['Name' => 'Billing / Business logic', 'Order' => 3, 'Components' => ['CloudKitty']], + ['Name' => 'Multi-region tools', 'Order' => 4, 'Components' => ['Tricircle']] + ] + ], + [ + 'Name' => 'OpenStack LifeCycle Management', + 'Description' => 'tools and recipes that deployers may choose to help them deploy and maintain the lifecycle of their OpenStack deployment.', + 'Order' => 3, + 'SubCategories' => [ + ['Name' => 'Deployment/Lifecycle tools', 'Order' => 1, 'Components' => ['Kolla-Ansible','Kolla-K8s','TripleO','Bifrost']], + ['Name' => 'Packaging recipes', 'Order' => 2, 'Components' => ['RPM','Ansible','Puppet','Chef','Charms','Helm','OCI containers']] + ] + ], + [ + 'Name' => 'OpenStack User', + 'Description' => 'tools that end users may want to install to interact with an OpenStack cloud', + 'Order' => 4, + 'SubCategories' => [ + ['Name' => 'SDK', 'Order' => 1, 'Components' => ['OpenStackClient','Shade','Python SDK']], + ] + ], + [ + 'Name' => 'OpenStack Adjacent Enablers', + 'Description' => 'bridges that let you reuse OpenStack components in other infra stacks', + 'Order' => 5, + 'SubCategories' => [ + ['Name' => 'Container infrastructure', 'Order' => 1, 'Components' => ['Kuryr','Fuxi']], + ['Name' => 'NFV', 'Order' => 2, 'Components' => ['Tacker']], + ] + ] + ); + + foreach ($tags as $tag) { + if (!$tag_obj = OpenStackComponentTag::get()->filter('Name', $tag['Name'])->first()) { + $tag_obj = new OpenStackComponentTag(); + $tag_obj->Name = $tag['Name']; + } + + $tag_obj->Label = $tag['Label']; + $tag_obj->Type = $tag['Type']; + $tag_obj->Description = $tag['Description']; + $tag_obj->Link = $tag['Link']; + $tag_obj->LabelTranslationKey = $tag['LabelTranslationKey']; + $tag_obj->DescriptionTranslationKey = $tag['DescriptionTranslationKey']; + $tag_obj->write(); + } + + // remove all current categories + + $old_categories = OpenStackComponentCategory::get(); + foreach( $old_categories as $old_cat) { + $old_cat->delete(); + } + + // add new categories heriarchy + + foreach ($categories as $cat) { + if (!$cat_obj = OpenStackComponentCategory::get()->filter('Name', $cat['Name'])->first()) { + $cat_obj = new OpenStackComponentCategory(); + $cat_obj->Name = $cat['Name']; + $cat_obj->write(); + } + + $cat_obj->Description = $cat['Description']; + $cat_obj->Order = $cat['Order']; + + foreach ($cat['SubCategories'] as $sub_cat) { + if (!$sub_cat_obj = OpenStackComponentSubCategory::get()->filter('Name', $sub_cat['Name'])->first()) { + $sub_cat_obj = new OpenStackComponentSubCategory(); + $sub_cat_obj->Name = $sub_cat['Name']; + $sub_cat_obj->write(); + } + + foreach ($sub_cat['Components'] as $comp) { + $comp_obj = OpenStackComponent::get()->where("Name = '".$comp."' OR CodeName = '".$comp."'")->first(); + if ($comp_obj) { + $sub_cat_obj->OpenStackComponents()->add($comp_obj); + } + } + + $sub_cat_obj->write(); + $cat_obj->SubCategories()->add($sub_cat_obj, ['SubCatOrder' => $sub_cat['Order'] ]); + } + + $cat_obj->write(); + } + + } +} \ No newline at end of file diff --git a/software/code/model/IOpenStackComponent.php b/software/code/model/IOpenStackComponent.php index 5f0795d45..805f68288 100644 --- a/software/code/model/IOpenStackComponent.php +++ b/software/code/model/IOpenStackComponent.php @@ -82,4 +82,20 @@ public function getSupportedReleases(); */ public function getAge($unit = 'Yrs'); + /** + * @param IOpenStackComponentTag $new_tag + * @return void + */ + public function addTag(IOpenStackComponentTag $new_tag); + + /** + * @return IOpenStackComponentTag[] + */ + public function getMaturityTags(); + + /** + * @return IOpenStackComponentTag[] + */ + public function getInfoTags(); + } \ No newline at end of file diff --git a/software/code/model/IOpenStackComponentCategory.php b/software/code/model/IOpenStackComponentCategory.php new file mode 100644 index 000000000..6bb6f3592 --- /dev/null +++ b/software/code/model/IOpenStackComponentCategory.php @@ -0,0 +1,51 @@ +getOpenStackComponentsFiltered($term, $adoption, $maturity, $age); - $cat_enum = OpenStackComponent::$categories; - $categories = array_fill_keys($cat_enum, array()); + $categories = OpenStackComponentCategory::get()->sort('Order'); + $subcategories = new DataList('OpenStackComponentSubCategory'); + + foreach ($categories as $category) { + $subcategories->addMany($category->SubCategories()); + } + + $component_categories = array_fill_keys($subcategories->column('Name'), array()); foreach($components as $c) { - $categories[$c->Use][] = $this->serializer->serialize($c); + if ($c->SubCategory()->Exists()) { + $component_categories[$c->SubCategory()->Name][] = $this->serializer->serialize($c); + } } - return array_filter($categories); + return array_filter($component_categories); } /** diff --git a/software/code/tasks/IngestOpenStackComponentsDataCronTask.php b/software/code/tasks/IngestOpenStackComponentsDataCronTask.php index 2610a721b..f8a95c34a 100644 --- a/software/code/tasks/IngestOpenStackComponentsDataCronTask.php +++ b/software/code/tasks/IngestOpenStackComponentsDataCronTask.php @@ -62,7 +62,6 @@ public function run() $this->getInstallationGuideStatus($release); $this->getSDKSupport($release); $this->getQualityOfPackages($release); - $this->calculateMaturityPoints($release); $this->getStackAnalytics($release); } }); @@ -185,6 +184,8 @@ private function processProjects() $tags = isset($info['tags']) ? $info['tags'] : []; $ptl_member = null; + $component->WikiUrl = $wiki; + if(!empty($ptl)) { if(is_array($ptl) && isset($ptl['name'])) @@ -223,20 +224,15 @@ private function processProjects() } } - $team_diverse_affiliation = false; - $is_service = false; - $has_stable_branches = false; - $tc_approved_release = false; - $starter_kit = false; - $vulnerability_managed = false; - $follows_standard_deprecation = false; - $supports_upgrade = false; - $supports_rolling_upgrade = false; - foreach($tags as $tag) { - if($tag === "team:diverse-affiliation" ) - $team_diverse_affiliation = true; + if( !$tag_obj = OpenStackComponentTag::get()->filter('Name', $tag)->first() ) { + $tag_obj = new OpenStackComponentTag(); + $tag_obj->Name = $tag; + $tag_obj->write(); + } + + $component->addTag($tag_obj); } $deliverables = isset($info['deliverables']) ? $info['deliverables'] : array(); @@ -245,33 +241,14 @@ private function processProjects() foreach($service_tags as $tag) { - if($tag === "type:service" ) - $is_service = true; - if($tag === "stable:follows-policy" ) - $has_stable_branches = true; - if($tag === "tc-approved-release" ) - $tc_approved_release = true; - if($tag === "starter-kit:compute" ) - $starter_kit = true; - if($tag === "vulnerability:managed" ) - $vulnerability_managed = true; - if($tag === "assert:follows-standard-deprecation" ) - $follows_standard_deprecation = true; - if($tag === "assert:supports-upgrade" ) - $supports_upgrade = true; - if($tag === "assert:supports-rolling-upgrade" ) - $supports_rolling_upgrade = true; - } + if( !$tag_obj = OpenStackComponentTag::get()->filter('Name', $tag)->first() ) { + $tag_obj = new OpenStackComponentTag(); + $tag_obj->Name = $tag; + $tag_obj->write(); + } - $component->HasStableBranches = $has_stable_branches; - $component->WikiUrl = $wiki; - $component->TCApprovedRelease = $tc_approved_release; - $component->HasTeamDiversity = $team_diverse_affiliation; - $component->IncludedComputeStarterKit = $starter_kit; - $component->VulnerabilityManaged = $vulnerability_managed; - $component->FollowsStandardDeprecation = $follows_standard_deprecation; - $component->SupportsUpgrade = $supports_upgrade; - $component->SupportsRollingUpgrade = $supports_rolling_upgrade; + $component->addTag($tag_obj); + } if(!is_null($ptl_member)) { echo sprintf('setting PTL %s %s (%s) to Component %s', $ptl_member->FirstName, $ptl_member->Surname, $ptl_member->Email, $component->Name).PHP_EOL; @@ -477,45 +454,6 @@ private function getProductionUseStatus(OpenStackRelease $release) $release->write(); } - private function calculateMaturityPoints(OpenStackRelease $release) - { - $components = $release->OpenStackComponents(); - - foreach($components as $c) - { - $points = 0; - if($c->Adoption > 75) - { - $points += 1; - } - if($c->HasInstallationGuide) - { - $points += 1; - } - if($c->HasTeamDiversity) - { - $points += 1; - } - if($c->HasStableBranches) - { - $points += 1; - } - if($c->FollowsStandardDeprecation) - { - $points += 1; - } - if($c->SupportsUpgrade) - { - $points += 1; - } - if($c->SupportsRollingUpgrade) - { - $points += 1; - } - $components->add($c, array('MaturityPoints' => $points)); - } - } - private function getSDKSupport(OpenStackRelease $release) { $components = $release->OpenStackComponents(); diff --git a/software/code/ui/SoftwareHomePage.php b/software/code/ui/SoftwareHomePage.php index 055696dd7..c1451ec5c 100644 --- a/software/code/ui/SoftwareHomePage.php +++ b/software/code/ui/SoftwareHomePage.php @@ -124,7 +124,7 @@ public function index(SS_HTTPRequest $request) array ( 'IsCoreService' => true, - 'Use' => 'Object Storage' + 'Category.Name' => 'Object Storage' ) )->sort('Order','ASC'), 'ComputeCoreServices' => $release->OpenStackComponents()->filter @@ -132,7 +132,7 @@ public function index(SS_HTTPRequest $request) array ( 'IsCoreService' => true, - 'Use' => 'Compute' + 'Category.Name' => 'Compute' ) )->sort('Order','ASC'), 'NoneCoreServices' => $release->OpenStackComponents()->filter @@ -140,7 +140,7 @@ public function index(SS_HTTPRequest $request) array ( 'IsCoreService' => true, - 'Use' => 'None' + 'Category.Name' => 'None' ) )->sort('Order','ASC'), 'OptionalServices' => $release->OpenStackComponents()->filter @@ -228,19 +228,15 @@ public function getComponent(SS_HTTPRequest $request) $has_maturity_indicators = ($component->Adoption > 75) || ($component->SDKSupport > 7) - || ($component->HasInstallationGuide) - || ($component->HasTeamDiversity) - || ($component->HasStableBranches) - || ($component->FollowsStandardDeprecation) - || ($component->SupportsUpgrade) - || ($component->SupportsRollingUpgrade); + || ($component->HasInstallationGuide); $has_release_desc = $component->ReleaseMileStones || $component->ReleaseCycleWithIntermediary || $component->ReleaseTrailing || $component->ReleaseIndependent; - $has_additional_info = $component->VulnerabilityManaged || $has_release_desc; + + $has_additional_info = (count($component->getInfoTags()) > 0) || $has_release_desc; return $this->render ( diff --git a/software/code/ui/admin/OpenStackComponentAdminUI.php b/software/code/ui/admin/OpenStackComponentAdminUI.php index e7084f1e8..332756aeb 100644 --- a/software/code/ui/admin/OpenStackComponentAdminUI.php +++ b/software/code/ui/admin/OpenStackComponentAdminUI.php @@ -37,7 +37,7 @@ public function updateCMSFields(FieldList $fields) $fields->push(new LiteralField("Title", "

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 @@

-
-
-
-
-
- <% if $Component.Adoption > 0 %> -
- {$Component.Adoption}% -
- <% else %> -
- <% end_if %> -
- <%t Software.ADOPTION 'Adoption' %> -
-
-
- <% if $Component.MaturityPoints > 0 %> -
- $Component.MaturityPoints - <%t Openstack.RANGE_OF 'of' %> - $Top.getMaxAllowedMaturityPoints -
- <% else %> -
- <% end_if %> -
- <%t Software.MATURITY 'Maturity' %> -
-
-
-
- $Component.Age yrs -
-
- <%t Software.AGE 'Age' %> -
-
-
-
- -
-
@@ -136,59 +89,20 @@ <% end_if %> - <% if $Component.HasTeamDiversity %> - - - - $Component.CodeName <%t Software.USED_IN_CORPORATE ' team has achieved corporate diversity' %> - " title="" data-placement="right" data-toggle="popover" data-original-title="<%t Software.WHAT_DOES_MEAN 'What does this mean?' %>"> - - <%t Openstack.VIEW_DETAILS 'View details' %> - - <% end_if %> - - <% if $Component.HasStableBranches %> - - - - $Component.CodeName <%t Software.STABLE_BRANCHES 'is maintained following the common Stable branch policy' %> - - <%t Openstack.VIEW_DETAILS 'View details' %> - - <% end_if %> - - <% if $Component.FollowsStandardDeprecation %> + <% loop $Component.getMaturityTags() %> - $Component.CodeName <%t Software.FOLLOW_DEPRECATION 'follows standard deprecation' %> - - - <%t Openstack.VIEW_DETAILS 'View details' %> - - <% end_if %> - - <% if $Component.SupportsUpgrade %> - - - - $Component.CodeName <%t Software.MINIMAL_UPGRADE 'supports minimal cold (offline) upgrade capabilities' %> - - - <%t Openstack.VIEW_DETAILS 'View details' %> - - <% end_if %> - - <% if $Component.SupportsRollingUpgrade %> - - - - $Component.CodeName <%t Software.MINIMAL_ROLLING 'supports minimal rolling upgrade capabilities' %> - + {$Top.Component.CodeName} {$getTranslatedLabel()} + + + - <%t Openstack.VIEW_DETAILS 'View details' %> + + <%t Openstack.VIEW_DETAILS 'View details' %> + - <% end_if %> + <% end_loop %> @@ -209,58 +123,54 @@ - <% if $HasReleaseDesc %> - - - <%t Software.HOW_RELEASED 'How is this project released?' %> - - - - - - <%t Openstack.VIEW_DETAILS 'View details' %> - - <% end_if %> - <% if $Component.VulnerabilityManaged %> - - - <%t Software.VULNERABILITY_ISSUES 'Are vulnerability issues managed by the OpenStack security team?' %> - - -
    -
  • class="on" <% end_if %>> - <% if $Component.VulnerabilityManaged %> - <%t Openstack.YES 'Yes' %> - <% else %> - <%t Openstack.NO 'No' %> - <% end_if %> -
  • -
- - <%t Openstack.VIEW_DETAILS 'View details' %> - - <% end_if %> + <% if $HasReleaseDesc %> + + + <%t Software.HOW_RELEASED 'How is this project released?' %> + + + + + + <%t Openstack.VIEW_DETAILS 'View details' %> + + <% end_if %> + <% loop $Component.getInfoTags() %> + + {$getTranslatedLabel()} + +
    +
  • + <%t Openstack.YES 'Yes' %> +
  • +
+ + + <%t Openstack.VIEW_DETAILS 'View details' %> + + + <% end_loop %>