Page MenuHomeIn-Portal Phabricator

D120.id361.diff
No OneTemporary

File Metadata

Created
Mon, Jan 6, 6:09 AM

D120.id361.diff

Index: core/admin_templates/categories/categories_edit.tpl
===================================================================
--- core/admin_templates/categories/categories_edit.tpl
+++ core/admin_templates/categories/categories_edit.tpl
@@ -78,7 +78,7 @@
<inp2:m_RenderElement name="inp_edit_category" prefix="c" field="SymLinkCategoryId" title="la_fld_SymLinkCategoryId"/>
- <inp2:m_RenderElement name="subsection" prefix="c" fields="Title,MenuTitle,FriendlyURL,ParentId,Template,FormId,FormSubmittedTemplate,IsMenu,Type,Protected" title="la_section_Page"/>
+ <inp2:m_RenderElement name="subsection" prefix="c" fields="Title,MenuTitle,FriendlyURL,ParentId,Template,FormId,FormSubmittedTemplate,IsMenu,Type,Protected,IncludeInSitemap" title="la_section_Page"/>
<inp2:m_RenderElement name="inp_edit_box_ml" prefix="c" field="Title" title="la_fld_PageContentTitle" size="40"/>
<inp2:m_RenderElement name="inp_edit_box_ml" prefix="c" field="MenuTitle" title="la_fld_PageMentTitle" size="40"/>
@@ -147,6 +147,8 @@
<inp2:m_RenderElement name="inp_label" prefix="c" field="Protected" title="la_fld_Protected"/>
</inp2:m_if>
+ <inp2:m_RenderElement name="inp_edit_checkbox" prefix="c" field="IncludeInSitemap" title="la_fld_IncludeInSitemap"/>
+
<inp2:m_RenderElement name="subsection" prefix="c" fields="Status,DirectLinkEnabled,RequireSSL,RequireLogin,NewItem,EditorsPick,Priority,UseMenuIconUrl,MenuIconUrl,UseExternalUrl,ExternalUrl,CreatedOn,MetaKeywords,MetaDescription,IndexTools" title="la_section_Properties"/>
<inp2:m_if check="c_PageEditable">
<inp2:m_RenderElement name="inp_edit_radio" prefix="c" field="Status" title="la_fld_Status"/>
@@ -315,4 +317,4 @@
disable_categories('<inp2:c_InputName name="ParentId"/>', <inp2:c_AllowedCategoriesJSON/>);
</script>
-<inp2:m_include t="incs/footer"/>
\ No newline at end of file
+<inp2:m_include t="incs/footer"/>
Index: core/install/english.lang
===================================================================
--- core/install/english.lang
+++ core/install/english.lang
@@ -208,6 +208,7 @@
<PHRASE Label="la_config_SessionBrowserSignatureCheck" Module="Core" Type="1">U2Vzc2lvbiBTZWN1cml0eSBDaGVjayBiYXNlZCBvbiBCcm93c2VyIFNpZ25hdHVyZQ==</PHRASE>
<PHRASE Label="la_config_SessionCookieDomains" Module="Core" Type="1">U2Vzc2lvbiBDb29raWUgRG9tYWlucyAoc2luZ2xlIGRvbWFpbiBwZXIgbGluZSk=</PHRASE>
<PHRASE Label="la_config_SessionIPAddressCheck" Module="Core" Type="1">U2Vzc2lvbiBTZWN1cml0eSBDaGVjayBiYXNlZCBvbiBJUA==</PHRASE>
+ <PHRASE Label="la_config_SitemapInvisibleCategoriesCatalogVisibility" Module="Core" Type="1">U2VjdGlvbnMgaGlkZGVuIGZyb20gU2l0ZW1hcA==</PHRASE>
<PHRASE Label="la_config_SiteNameSubTitle" Module="Core" Type="1">V2Vic2l0ZSBTdWJ0aXRsZQ==</PHRASE>
<PHRASE Label="la_config_site_zone" Module="Core" Type="1">VGltZSB6b25lIG9mIHRoZSBzaXRl</PHRASE>
<PHRASE Label="la_config_SoftMaintenanceTemplate" Module="Core" Type="1" Hint="VGhpcyB0ZW1wbGF0ZSB3aWxsIGJlIHNob3duIHRvIHRoZSBGcm9udCBFbmQgdXNlcnMgd2hlbiBTb2Z0IE1haW50ZW5hbmNlIG1vZGUgaXMgYWN0aXZlLg==">VGVtcGxhdGUgZm9yIFNvZnQgTWFpbnRlbmFuY2U=</PHRASE>
@@ -489,6 +490,7 @@
<PHRASE Label="la_fld_ImportOverwrite" Module="Core" Type="1" Hint="RW5hYmxpbmcgdGhpcyBvcHRpb24gd2lsbCB1bmRvIGFueSBjaGFuZ2VzIHlvdSBoYXZlIG1hZGUgdG8gZXhpc3RpbmcgcGhyYXNlcw==">T3ZlcndyaXRlIEV4aXN0aW5nIFBocmFzZXM=</PHRASE>
<PHRASE Label="la_fld_ImportSynced" Module="Core" Type="1" Hint="RW5hYmxpbmcgdGhpcyBvcHRpb24gd2lsbCBtYXJrIGFsbCBuZXcgbGFiZWxzIGZyb20gdGhpcyBsYW5ndWFnZSBwYWNrIHN5bmNlZCB3aXRoIGFsbCBvdGhlciBsYW5ndWFnZXMu">SW1wb3J0IE5ldyBQaHJhc2VzIGFzIFN5bmNlZA==</PHRASE>
<PHRASE Label="la_fld_IncludeFieldTitles" Module="Core" Type="1">SW5jbHVkZSBmaWVsZCB0aXRsZXM=</PHRASE>
+ <PHRASE Label="la_fld_IncludeInSitemap" Module="Core" Type="1">SW5jbHVkZSBpbiBTaXRlbWFw</PHRASE>
<PHRASE Label="la_fld_IncludeSublevels" Module="Core" Type="1" Column="SW5jbHVkZSBTdWJsZXZlbHM=">SW5jbHVkZSBTdWJsZXZlbHM=</PHRASE>
<PHRASE Label="la_fld_InputDateFormat" Module="Core" Type="1">SW5wdXQgRGF0ZSBGb3JtYXQ=</PHRASE>
<PHRASE Label="la_fld_InputTimeFormat" Module="Core" Type="1">SW5wdXQgVGltZSBGb3JtYXQ=</PHRASE>
@@ -840,6 +842,7 @@
<PHRASE Label="la_opt_Address" Module="Core" Type="1">QWRkcmVzcw==</PHRASE>
<PHRASE Label="la_opt_After" Module="Core" Type="1">QWZ0ZXI=</PHRASE>
<PHRASE Label="la_opt_Allow" Module="Core" Type="1">QWxsb3c=</PHRASE>
+ <PHRASE Label="la_opt_AlwaysShownInCatalog" Module="Core" Type="1">QWx3YXlzIFNob3duIGluIENhdGFsb2c=</PHRASE>
<PHRASE Label="la_opt_AnimationCustom" Module="Core" Type="1">Q3VzdG9t</PHRASE>
<PHRASE Label="la_opt_AnimationFade" Module="Core" Type="1">RmFkZQ==</PHRASE>
<PHRASE Label="la_opt_AnimationSlide" Module="Core" Type="1">U2xpZGU=</PHRASE>
@@ -980,6 +983,7 @@
<PHRASE Label="la_opt_Semicolon" Module="Core" Type="1">U2VtaS1jb2xvbg==</PHRASE>
<PHRASE Label="la_opt_Sent" Module="Core" Type="1">U2VudA==</PHRASE>
<PHRASE Label="la_opt_September" Module="Core" Type="1">U2VwdGVtYmVy</PHRASE>
+ <PHRASE Label="la_opt_ShownInCatalogOnlyInDebugMode" Module="Core" Type="1">U2hvd24gaW4gQ2F0YWxvZyBPbmx5IGluIERlYnVnIE1vZGU=</PHRASE>
<PHRASE Label="la_opt_Silent" Module="Core" Type="1">U2lsZW50</PHRASE>
<PHRASE Label="la_opt_Skipped" Module="Core" Type="1">U2tpcHBlZA==</PHRASE>
<PHRASE Label="la_opt_Space" Module="Core" Type="1">U3BhY2U=</PHRASE>
Index: core/install/install_data.sql
===================================================================
--- core/install/install_data.sql
+++ core/install/install_data.sql
@@ -13,10 +13,11 @@
INSERT INTO SystemSettings VALUES(DEFAULT, 'RecycleBinFolder', '', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_RecycleBinFolder', 'text', NULL, NULL, 10.10, 0, 0, NULL);
INSERT INTO SystemSettings VALUES(DEFAULT, 'CheckViewPermissionsInCatalog', '0', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_CheckViewPermissionsInCatalog', 'radio', NULL, '1=la_Yes||0=la_No', 10.11, 0, 1, 'hint:la_config_CheckViewPermissionsInCatalog');
INSERT INTO SystemSettings VALUES(DEFAULT, 'CategoryPermissionRebuildMode', '3', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_CategoryPermissionRebuildMode', 'select', NULL, '1=la_opt_Manual||2=la_opt_Silent||3=la_opt_Automatic', 10.12, 0, 0, 'hint:la_config_CategoryPermissionRebuildMode');
-INSERT INTO SystemSettings VALUES(DEFAULT, 'FilenameSpecialCharReplacement', '-', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_FilenameSpecialCharReplacement', 'select', NULL, '_=+_||-=+-', 10.13, 0, 0, NULL);
-INSERT INTO SystemSettings VALUES(DEFAULT, 'Search_MinKeyword_Length', '3', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_Search_MinKeyword_Length', 'text', NULL, NULL, 10.14, 0, 0, NULL);
-INSERT INTO SystemSettings VALUES(DEFAULT, 'ExcludeTemplateSectionsFromSearch', '0', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_ExcludeTemplateSectionsFromSearch', 'checkbox', '', '', 10.15, 0, 0, NULL);
-INSERT INTO SystemSettings VALUES(DEFAULT, 'UpdateCountersOnFilterChange', '1', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_UpdateCountersOnFilterChange', 'checkbox', '', '', 10.16, 0, 0, NULL);
+INSERT INTO SystemSettings VALUES(DEFAULT, 'SitemapInvisibleCategoriesCatalogVisibility', '1', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_SitemapInvisibleCategoriesCatalogVisibility', 'radio', NULL, '1=la_opt_AlwaysShownInCatalog||2=la_opt_ShownInCatalogOnlyInDebugMode', 10.13, 0, 0, '');
+INSERT INTO SystemSettings VALUES(DEFAULT, 'FilenameSpecialCharReplacement', '-', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_FilenameSpecialCharReplacement', 'select', NULL, '_=+_||-=+-', 10.14, 0, 0, NULL);
+INSERT INTO SystemSettings VALUES(DEFAULT, 'Search_MinKeyword_Length', '3', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_Search_MinKeyword_Length', 'text', NULL, NULL, 10.15, 0, 0, NULL);
+INSERT INTO SystemSettings VALUES(DEFAULT, 'ExcludeTemplateSectionsFromSearch', '0', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_ExcludeTemplateSectionsFromSearch', 'checkbox', '', '', 10.16, 0, 0, NULL);
+INSERT INTO SystemSettings VALUES(DEFAULT, 'UpdateCountersOnFilterChange', '1', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_UpdateCountersOnFilterChange', 'checkbox', '', '', 10.17, 0, 0, NULL);
INSERT INTO SystemSettings VALUES(DEFAULT, 'Category_MetaKey', '', 'In-Portal', 'in-portal:configure_categories', 'la_Text_MetaInfo', 'la_category_metakey', 'textarea', '', '', 20.01, 0, 1, NULL);
INSERT INTO SystemSettings VALUES(DEFAULT, 'Category_MetaDesc', '', 'In-Portal', 'in-portal:configure_categories', 'la_Text_MetaInfo', 'la_category_metadesc', 'textarea', '', '', 20.02, 0, 1, NULL);
Index: core/install/install_schema.sql
===================================================================
--- core/install/install_schema.sql
+++ core/install/install_schema.sql
@@ -597,6 +597,7 @@
PromoBlockGroupId int(10) unsigned NOT NULL DEFAULT '0',
RequireSSL tinyint(4) NOT NULL DEFAULT '0',
RequireLogin tinyint(4) NOT NULL DEFAULT '0',
+ IncludeInSitemap tinyint(4) NOT NULL DEFAULT '1',
PRIMARY KEY (CategoryId),
UNIQUE KEY ResourceId (ResourceId),
KEY ParentId (ParentId),
Index: core/install/upgrades.sql
===================================================================
--- core/install/upgrades.sql
+++ core/install/upgrades.sql
@@ -3026,3 +3026,9 @@
UPDATE Modules
SET ClassNamespace = 'InPortal\\Core'
WHERE `Name` IN ('Core', 'In-Portal');
+
+ALTER TABLE Categories ADD IncludeInSitemap TINYINT(4) NOT NULL DEFAULT 1;
+UPDATE SystemSettings
+SET DisplayOrder = ROUND(DisplayOrder + 0.01, 2)
+WHERE (DisplayOrder BETWEEN 10.13 AND 10.18) AND (ModuleOwner = 'In-Portal') AND (Section = 'in-portal:configure_categories');
+INSERT INTO SystemSettings VALUES(DEFAULT, 'SitemapInvisibleCategoriesCatalogVisibility', '1', 'In-Portal', 'in-portal:configure_categories', 'la_title_General', 'la_config_SitemapInvisibleCategoriesCatalogVisibility', 'radio', NULL, '1=la_opt_AlwaysShownInCatalog||2=la_opt_ShownInCatalogOnlyInDebugMode', 10.13, 0, 0, '');
Index: core/kernel/constants.php
===================================================================
--- core/kernel/constants.php
+++ core/kernel/constants.php
@@ -233,3 +233,9 @@
const STATUS_SKIPPED = 3;
}
+
+ class Visibility
+ {
+ const ALWAYS_SHOWN = 1;
+ const SHOWN_ONLY_IN_DEBUG_MODE = 2;
+ }
Index: core/units/categories/categories_config.php
===================================================================
--- core/units/categories/categories_config.php
+++ core/units/categories/categories_config.php
@@ -426,6 +426,11 @@
'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1,
'not_null' => 1, 'default' => 0
),
+ 'IncludeInSitemap' => array(
+ 'type' => 'int',
+ 'formatter' => 'kOptionsFormatter', 'options' => array(1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1,
+ 'not_null' => 1, 'default' => 1,
+ ),
),
'VirtualFields' => Array (
@@ -540,4 +545,4 @@
'DefaultSorting1Dir' => 'Category_Sortorder',
'DefaultSorting2Dir' => 'Category_Sortorder2',
),
-);
\ No newline at end of file
+);
Index: core/units/categories/categories_event_handler.php
===================================================================
--- core/units/categories/categories_event_handler.php
+++ core/units/categories/categories_event_handler.php
@@ -549,6 +549,28 @@
/* @var $search_helper kSearchHelper */
$search_helper->SetComplexFilter($event, $type_clauses, implode(',', $types), implode(',', $except_types));
+ $this->setSitemapFilter($object);
+ }
+
+ /**
+ * Sets sitemap filter
+ *
+ * @param kDBList $object Object.
+ *
+ * @return void
+ */
+ protected function setSitemapFilter(kDBList $object)
+ {
+ if ( !$this->Application->isAdmin ) {
+ return;
+ }
+
+ /** @var CategoryHelper $category_helper */
+ $category_helper = $this->Application->recallObject('CategoryHelper');
+
+ if ( $category_helper->showSitemapOnlyCategories() ) {
+ $object->addFilter('sitemap_filter', '%1$s.IncludeInSitemap = 1');
+ }
}
/**
@@ -2017,6 +2039,10 @@
// this will override any global "m_cat_id"
$page_category = $this->_getParentCategoryFromPath(explode('||', $template_info['section']), $root_category, $theme_id);
}
+
+ if ( array_key_exists('in_sitemap', $template_info) ) {
+ $in_sitemap = $template_info['in_sitemap'] ? 1 : 0;
+ }
}
}
else {
@@ -2045,6 +2071,10 @@
$object->SetDBField('l' . $primary_language . '_Description', $page_description);
$object->SetDBField('l' . $current_language . '_Description', $page_description);
+ if ( isset($in_sitemap) ) {
+ $object->SetDBField('IncludeInSitemap', $in_sitemap);
+ }
+
return $object->Create();
}
Index: core/units/helpers/category_helper.php
===================================================================
--- core/units/helpers/category_helper.php
+++ core/units/helpers/category_helper.php
@@ -31,6 +31,24 @@
var $_primaryLanguageId = false;
/**
+ * Show sitemap only categories
+ *
+ * @var boolean
+ */
+ protected $showSitemapOnlyCategories = false;
+
+ /**
+ * Set showSitemapOnlyCategories property
+ *
+ * @return CategoryHelper
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ $this->showSitemapOnlyCategories = $this->showSitemapOnlyCategories();
+ }
+
+ /**
* Returns module information based on given module name or current category (relative to module root categories)
*
* @param Array $params
@@ -98,6 +116,10 @@
return Array ();
}
+ if ( !$data['IncludeInSitemap'] && $this->showSitemapOnlyCategories ) {
+ return array();
+ }
+
$category_language = $data['l' . $language_id . '_Name'] ? $language_id : $this->_primaryLanguageId;
$ret = Array ($parent_category_id => str_repeat('&mdash;', $level) . ' ' . $data['l' . $category_language . '_Name']);
@@ -113,6 +135,21 @@
}
/**
+ * Checks if need show sitemap only categories
+ *
+ * @return boolean
+ */
+ public function showSitemapOnlyCategories()
+ {
+ $visibility = $this->Application->ConfigValue('SitemapInvisibleCategoriesCatalogVisibility');
+
+ return (
+ !$this->Application->isDebugMode()
+ && $visibility == Visibility::SHOWN_ONLY_IN_DEBUG_MODE
+ );
+ }
+
+ /**
* Returns information about children under parent path (recursive)
*
* @param int $parent_category_id
@@ -131,7 +168,8 @@
$fields[] = 'l' . $language_id . '_Name';
}
- $sql = 'SELECT CategoryId AS id, ' . implode(', ', $fields) . ', ParentId, Template, ThemeId
+ $sql = 'SELECT CategoryId AS id, ' . implode(', ', $fields) . ',
+ ParentId, Template, ThemeId, IncludeInSitemap
FROM ' . TABLE_PREFIX . 'Categories
ORDER BY Priority DESC';
$items = $this->Conn->Query($sql, 'id');
@@ -378,4 +416,4 @@
return $text;
}
- }
\ No newline at end of file
+ }
Index: core/units/helpers/themes_helper.php
===================================================================
--- core/units/helpers/themes_helper.php
+++ core/units/helpers/themes_helper.php
@@ -475,47 +475,89 @@
return $this->parseTemplateMetaInfo($template_file);
}
- function parseTemplateMetaInfo($template_file)
+ /**
+ * Parses template meta info
+ *
+ * @param string $template_file Template file.
+ *
+ * @return array
+ * @throws Exception When invalid template meta tag is found.
+ */
+ public function parseTemplateMetaInfo($template_file)
{
- if (!file_exists($template_file)) {
+ if ( !file_exists($template_file) ) {
// when template without info it's placed in top category
- return Array ();
+ return array();
}
$template_data = file_get_contents($template_file);
- if (substr($template_data, 0, 6) == '<!--##') {
- // template starts with comment in such format
- /*<!--##
- <NAME></NAME>
- <DESC></DESC>
- <SECTION>||</SECTION>
- ##-->*/
-
- $comment_end = strpos($template_data, '##-->');
- if ($comment_end === false) {
- // badly formatted comment
- return Array ();
- }
-
- $comment = trim( substr($template_data, 6, $comment_end - 6) );
- if (preg_match_all('/<(NAME|DESC|SECTION)>(.*?)<\/(NAME|DESC|SECTION)>/is', $comment, $regs)) {
- $ret = Array ();
- foreach ($regs[1] as $param_order => $param_name) {
- $ret[ strtolower($param_name) ] = trim($regs[2][$param_order]);
- }
+ // template starts with comment in such format
+ /*<!--##
+ <NAME></NAME>
+ <DESC></DESC>
+ <SECTION>||</SECTION>
+ ##-->*/
- if (array_key_exists('section', $ret) && $ret['section']) {
- $category_path = explode('||', $ret['section']);
- $category_path = array_map('trim', $category_path);
- $ret['section'] = implode('||', $category_path);
- }
+ if ( substr($template_data, 0, 6) != '<!--##' ) {
+ return array();
+ }
+
+ $comment_end = strpos($template_data, '##-->');
+
+ if ( $comment_end === false ) {
+ // Badly formatted comment.
+ return array();
+ }
+
+ $ret = array();
+ $comment = trim(substr($template_data, 6, $comment_end - 6));
+ $allowed_settings = array('name', 'desc', 'section', 'in_sitemap');
- return $ret;
+ /** @var SimpleXMLElement[] $meta_info */
+ $meta_info = simplexml_load_string('<meta_info>' . $comment . '</meta_info>');
+
+ if ( $meta_info === false ) {
+ // Malformed XML. SimpleXML will print an error itself.
+ return array();
+ }
+
+ foreach ( $meta_info as $setting ) {
+ $setting_name = strtolower($setting->getName());
+
+ if ( !in_array($setting_name, $allowed_settings) ) {
+ trigger_error(
+ 'Setting "' . $setting_name . '" not supported in "' . $template_file . '" template',
+ E_USER_WARNING
+ );
+ continue;
+ }
+
+ $ret[$setting_name] = trim($setting);
+ }
+
+ if ( array_key_exists('section', $ret) && $ret['section'] ) {
+ $category_path = explode('||', $ret['section']);
+ $category_path = array_map('trim', $category_path);
+ $ret['section'] = implode('||', $category_path);
+ }
+
+ if ( array_key_exists('in_sitemap', $ret) ) {
+ $value = strtolower($ret['in_sitemap']);
+
+ if ( strlen($value) == 0 || in_array($value, array('yes', 'true', '1')) ) {
+ $ret['in_sitemap'] = true;
+ }
+ elseif ( in_array($value, array('no', 'false', '0')) ) {
+ $ret['in_sitemap'] = false;
+ }
+ else {
+ $error_msg = 'The "IN_SITEMAP" setting in "' . $template_file;
+ throw new Exception($error_msg . '" template has unsupported value. Please use "yes" or "no".');
}
}
- return Array ();
+ return $ret;
}
/**
Index: core/units/structure/structure_config.php
===================================================================
--- core/units/structure/structure_config.php
+++ core/units/structure/structure_config.php
@@ -215,7 +215,12 @@
'formatter' => 'kOptionsFormatter', 'options' => Array (1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1,
'not_null' => 1, 'default' => 1
),
- 'DirectLinkAuthKey' => Array ('type' => 'string', 'max_len' => 20, 'not_null' => 1, 'default' => '')
+ 'DirectLinkAuthKey' => array('type' => 'string', 'max_len' => 20, 'not_null' => 1, 'default' => ''),
+ 'IncludeInSitemap' => array(
+ 'type' => 'int',
+ 'formatter' => 'kOptionsFormatter', 'options' => array(1 => 'la_Yes', 0 => 'la_No'), 'use_phrases' => 1,
+ 'not_null' => 1, 'default' => 1,
+ ),
),
'VirtualFields' => Array (
@@ -274,4 +279,4 @@
'DefaultSorting1Dir' => 'Category_Sortorder',
'DefaultSorting2Dir' => 'Category_Sortorder2',
),
-);
\ No newline at end of file
+);

Event Timeline