GetForLink(); $oContentLayout->AddMainBlock(TitleUIBlockFactory::MakeForPage(Dict::S('UI:Preferences:Title'))); ////////////////////////////////////////////////////////////////////////// // // User interface // ////////////////////////////////////////////////////////////////////////// // Create panel $oUIPanel = PanelUIBlockFactory::MakeNeutral(Dict::S('UI:Preferences:UserInterface:Title')); $oContentLayout->AddMainBlock($oUIPanel); // Create form $oUIForm = new Form('ibo-form-for-user-interface-preferences'); $oUIPanel->AddSubBlock($oUIForm); // Prepare form $oUIForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('operation', 'apply_user_interface')) ->AddSubBlock($oAppContext->GetForFormBlock()) ->SetOnSubmitJsCode('return ValidateOtherSettings();'); $oMultiColContainer = new MultiColumn(); $oUIForm->AddSubBlock($oMultiColContainer); $oFirstColumn = new Column(); $oMultiColContainer->AddColumn($oFirstColumn); $oSecondColumn = new Column(); $oMultiColContainer->AddColumn($oSecondColumn); // Prepare buttons $oUIToolbar = ToolbarUIBlockFactory::MakeForButton(null, ['ibo-is-fullwidth']); $oUIForm->AddSubBlock($oUIToolbar); // - Cancel button $oUICancelButton = ButtonUIBlockFactory::MakeForCancel(); $oUIToolbar->AddSubBlock($oUICancelButton); $oUICancelButton->SetOnClickJsCode("window.location.href = '$sURL'"); // - Submit button $oUISubmitButton = ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('UI:Button:Apply'), 'operation', 'apply_user_interface', true); $oUIToolbar->AddSubBlock($oUISubmitButton); // General $oGeneralFieldset = FieldSetUIBlockFactory::MakeStandard(Dict::S('UI:Preferences:General:Title'), 'ibo-fieldset-for-language-preferences'); $oGeneralFieldset->AddSubBlock(GetLanguageFieldBlock()); if (true === MetaModel::GetConfig()->Get('user_preferences.allow_backoffice_theme_override')) { $oGeneralFieldset->AddSubBlock(GetThemeFieldBlock()); } $oFirstColumn->AddSubBlock($oGeneralFieldset); // Lists $oListsFieldset = FieldSetUIBlockFactory::MakeStandard(Dict::S('UI:Preferences:Lists:Title'), 'ibo-fieldset-for-lists-preferences'); $oFirstColumn->AddSubBlock($oListsFieldset); $oListsFieldset->AddSubBlock(GetListPageSizeFieldBlock()); // Tabs $oTabsFieldset = FieldSetUIBlockFactory::MakeStandard(Dict::S('UI:Preferences:Tabs:Title'), 'ibo-fieldset-for-tabs-preferences'); $oFirstColumn->AddSubBlock($oTabsFieldset); $oTabsFieldset->AddSubBlock(GetTabsLayoutFieldBlock()); $oTabsFieldset->AddSubBlock(GetTabsNavigationFieldBlock()); // Activity panel $oActivityPanelfieldset = FieldSetUIBlockFactory::MakeStandard(Dict::S('UI:Preferences:ActivityPanel:Title'), 'ibo-fieldset-for-activity-panel'); $oSecondColumn->AddSubBlock($oActivityPanelfieldset); $oActivityPanelfieldset->AddSubBlock(GetActivityPanelEntryFormOpenedFieldBlock()); // Misc. options $oMiscOptionsFieldset = FieldSetUIBlockFactory::MakeStandard(Dict::S('UI:FavoriteOtherSettings'), 'ibo-fieldset-for-misc-options'); $oSecondColumn->AddSubBlock($oMiscOptionsFieldset); $oMiscOptionsFieldset->AddSubBlock(GetObsoleteDataFieldBlock()); $oMiscOptionsFieldset->AddSubBlock(GetSummaryCardsFieldBlock()); $oMiscOptionsFieldset->AddSubBlock(GetToastsPositionFieldBlock()); $oP->add_script( << 0)) { $('#v_default_page_size').html(''); $('#ibo-misc-settings-submit').prop('disabled', false); return true; } else { $('#v_default_page_size').html(''); $('#ibo-misc-settings-submit').prop('disabled', true); return false; } } JS ); ////////////////////////////////////////////////////////////////////////// // // Notifications // ////////////////////////////////////////////////////////////////////////// $oNotificationsBlock = new Panel(Dict::S('UI:Preferences:Notifications'), array(), Panel::ENUM_COLOR_SCHEME_GREY, 'ibo-notifications'); $sNotificationsCenterUrl = Router::GetInstance()->GenerateUrl(NotificationsCenterController::ROUTE_NAMESPACE.'.display_page', [], true); $oNotificationsBlock->AddSubBlock(new Html('

'.Dict::Format('UI:Preferences:Notifications+', $sNotificationsCenterUrl).'

')); $oContentLayout->AddMainBlock($oNotificationsBlock); ////////////////////////////////////////////////////////////////////////// // // Favorite Organizations // ////////////////////////////////////////////////////////////////////////// $oFavoriteOrganizationsBlock = new Panel(Dict::S('UI:FavoriteOrganizations'), array(), 'grey', 'ibo-favorite-organizations'); $oFavoriteOrganizationsBlock->SetSubTitle(Dict::S('UI:FavoriteOrganizations+')); $oFavoriteOrganizationsBlock->AddCSSClass('ibo-datatable-panel'); $oFavoriteOrganizationsForm = new Form(); $oFavoriteOrganizationsBlock->AddSubBlock($oFavoriteOrganizationsForm); // Favorite organizations: the organizations listed in the drop-down menu $sOQL = ApplicationMenu::GetFavoriteSiloQuery(); $oFilter = DBObjectSearch::FromOQL($sOQL); $oBlock = new DisplayBlock($oFilter, 'list', false); $aFavoriteOrgs = appUserPreferences::GetPref('favorite_orgs', null); $sIdFavoriteOrganizations = 1; $oFavoriteOrganizationsForm->AddSubBlock($oBlock->GetDisplay($oP, $sIdFavoriteOrganizations, [ 'menu' => false, 'selection_mode' => true, 'selection_type' => 'multiple', 'table_id' => 'user_prefs', 'surround_with_panel' => false, 'selected_rows' => $aFavoriteOrgs, ])); $oFavoriteOrganizationsForm->AddSubBlock($oAppContext->GetForFormBlock()); // Button toolbar $oFavoriteOrganizationsToolBar = ToolbarUIBlockFactory::MakeForButton(null, ['ibo-is-fullwidth']); $oFavoriteOrganizationsForm->AddSubBlock($oFavoriteOrganizationsToolBar); // - Cancel button $oFavoriteOrganizationsCancelButton = ButtonUIBlockFactory::MakeForCancel(Dict::S('UI:Button:Cancel')); $oFavoriteOrganizationsToolBar->AddSubBlock($oFavoriteOrganizationsCancelButton); $oFavoriteOrganizationsCancelButton->SetOnClickJsCode("window.location.href = '$sURL'"); // - Submit button $oFavoriteOrganizationsSubmitButton = ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('UI:Button:Apply'), 'operation', 'apply', true); $oFavoriteOrganizationsToolBar->AddSubBlock($oFavoriteOrganizationsSubmitButton); // TODO 3.0 have this code work again, currently it prevents the display of favorite organizations and shortcuts. // if ($aFavoriteOrgs == null) { // // All checked // $oP->add_ready_script( // <<AddMainBlock($oFavoriteOrganizationsBlock); ////////////////////////////////////////////////////////////////////////// // // Shortcuts // ////////////////////////////////////////////////////////////////////////// $oShortcutsBlock = new BlockShortcuts(Dict::S('Menu:MyShortcuts'), array(), 'grey', 'ibo-shortcuts'); $oShortcutsBlock->AddCSSClass('ibo-datatable-panel'); $oShortcutsBlock->sIdShortcuts = 'shortcut_list'; $oShortcutsFilter = new DBObjectSearch('Shortcut'); $oShortcutsFilter->AddCondition('user_id', UserRights::GetUserId(), '='); $oBlock = new DisplayBlock($oShortcutsFilter, 'list', false); $oShortcutsBlock->AddSubBlock($oBlock->GetDisplay($oP, $oShortcutsBlock->sIdShortcuts, [ 'view_link' => false, 'menu' => false, 'toolkit_menu' => false, 'selection_mode' => true, 'selection_type' => 'multiple', 'table_id' => 'user_prefs_shortcuts', 'surround_with_panel' => false, 'id_for_select' => 'Shortcut/_key_', ])); $oSet = new DBObjectSet($oShortcutsFilter); if ($oSet->Count() > 0) { $oShortcutsToolBar = ToolbarUIBlockFactory::MakeForButton(); $oShortcutsBlock->AddSubBlock($oShortcutsToolBar); // - Rename button $oShortcutsRenameButton = ButtonUIBlockFactory::MakeForSecondaryAction(Dict::S('UI:Button:Rename'), null, null, false, "shortcut_btn_rename"); $oShortcutsToolBar->AddSubBlock($oShortcutsRenameButton); // - Delete button $oShortcutsDeleteButton = ButtonUIBlockFactory::MakeForSecondaryAction(Dict::S('UI:Button:Delete'), null, null, false, "shortcut_btn_delete"); $oShortcutsToolBar->AddSubBlock($oShortcutsDeleteButton); } $oContentLayout->AddMainBlock($oShortcutsBlock); ////////////////////////////////////////////////////////////////////////// // // Newsroom // ////////////////////////////////////////////////////////////////////////// $iCountProviders = 0; $oUser = UserRights::GetUserObject(); /** @var iNewsroomProvider[] $aProviders */ $aProviders = InterfaceDiscovery::GetInstance()->FindItopClasses(iNewsroomProvider::class); foreach($aProviders as $cProvider) { $oProvider = new $cProvider(); if ($oProvider->IsApplicable($oUser)) { $iCountProviders++; } } $bNewsroomEnabled = (MetaModel::GetConfig()->Get('newsroom_enabled') !== false); if ($bNewsroomEnabled && ($iCountProviders > 0)) { $oNewsroomBlock = new Panel(Dict::S('UI:Newsroom:Preferences'), array(), 'grey', 'ibo-newsroom'); $sNewsroomHtml = ''; $sNewsroomHtml .= '
'; $iNewsroomDisplaySize = (int)appUserPreferences::GetPref('newsroom_display_size', 7); if ($iNewsroomDisplaySize < 1) $iNewsroomDisplaySize = 1; if ($iNewsroomDisplaySize > 20) $iNewsroomDisplaySize = 20; $sInput = ''; $sIcon = ''; $sNewsroomHtml .= Dict::Format('UI:Newsroom:DisplayAtMost_X_Messages', $sInput, $sIcon); /** * @var iNewsroomProvider[] $aProviders */ $sAppRootUrl = utils::GetAbsoluteUrlAppRoot(); foreach($aProviders as $cProvider) { $oProvider = new $cProvider(); if ($oProvider->IsApplicable($oUser)) { $sUrl = $oProvider->GetPreferencesUrl(); $sProviderClass = get_class($oProvider); $sPreferencesLink = ''; if ($sUrl !== null) { if(substr($sUrl, 0, strlen($sAppRootUrl)) === $sAppRootUrl) { $sTarget = ''; // Internal link, open in the same window } else { $sTarget = ' target="_blank"'; // External link, open in new window } $sPreferencesLink = ' - '.Dict::S('UI:Newsroom:ConfigurationLink').''; } $sCheckedForHtml = appUserPreferences::GetPref('newsroom_provider_'.$sProviderClass, true) ? 'checked' : ''; // Forbid disabling internal newsroom provider $sDisabledForHtml = $sProviderClass === iTopNewsroomProvider::class ? 'disabled' : ''; $sNewsroomHtml .= '
'.$sPreferencesLink.'
'; } } $sNewsroomHtml .= $oAppContext->GetForForm(); $oNewsroomToolbar = ToolbarUIBlockFactory::MakeForButton(); // - Reset button $oNewsroomResetCacheButton = ButtonUIBlockFactory::MakeForAlternativeDestructiveAction(Dict::S('UI:Newsroom:ResetCache')); $oNewsroomResetCacheButton->SetOnClickJsCode(<<AddSubBlock($oNewsroomResetCacheButton); // - Cancel button $oNewsroomCancelButton = ButtonUIBlockFactory::MakeForCancel(Dict::S('UI:Button:Cancel')); $oNewsroomCancelButton->SetOnClickJsCode("window.location.href = '$sURL'"); $oNewsroomToolbar->AddSubBlock($oNewsroomCancelButton); // - Submit button $oNewsroomSubmitButton = ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('UI:Button:Apply'), 'operation', 'apply_newsroom_preferences', true); $oNewsroomToolbar->AddSubBlock($oNewsroomSubmitButton); $sNewsroomEndHtml = ''; $oNewsroomEndHtmlBlock = new Html($sNewsroomEndHtml); $oNewsroomHtmlBlock = new Html($sNewsroomHtml); $oNewsroomBlock->AddSubBlock($oNewsroomHtmlBlock); $oNewsroomBlock->AddSubBlock($oNewsroomToolbar); $oNewsroomBlock->AddSubBlock($oNewsroomEndHtmlBlock); $oContentLayout->AddMainBlock($oNewsroomBlock); } ////////////////////////////////////////////////////////////////////////// // // User defined keyboard shortcut // ////////////////////////////////////////////////////////////////////////// // Panel $oKeyboardShortcutBlock = new Panel(Dict::S('UI:Preferences:PersonalizeKeyboardShortcuts:Title'), array(), 'grey', 'ibo_keyboard_shortcuts'); // Form $oKeyboardShortcutForm = new Form('ibo-form-for-user-interface-preferences'); $oKeyboardShortcutForm->AddSubBlock(InputUIBlockFactory::MakeForHidden('operation', 'apply_keyboard_shortcuts')) ->AddSubBlock($oAppContext->GetForFormBlock()); $oKeyboardShortcutBlock->AddSubBlock($oKeyboardShortcutForm); $sKeyboardShortcutBlockId = $oKeyboardShortcutBlock->GetId(); // JS keyboard listener $oP->add_script( << $aKeyboardShortcut) { // Recording button $oButton = ButtonUIBlockFactory::MakeForAlternativeSecondaryAction(''); $oButton->SetIconClass('fas fa-pen')->SetTooltip($sKeyboardShortcutsButtonTooltip)->SetOnClickJsCode( <<GetInput()->AddCSSClasses(['ibo-keyboard-shortcut--input']); $oKeyboardShortcutForm->AddSubBlock(new Html('
')); $oKeyboardShortcutForm->AddSubBlock($oInput); $oKeyboardShortcutForm->AddSubBlock($oButton); $oKeyboardShortcutForm->AddSubBlock(new Html('
')); } // Prepare buttons $oKeyboardShortcutToolbar = ToolbarUIBlockFactory::MakeForButton(null, ['ibo-is-fullwidth']); $oKeyboardShortcutForm->AddSubBlock($oKeyboardShortcutToolbar); // - Cancel button $oKeyboardShortcutCancelButton = ButtonUIBlockFactory::MakeForCancel(); $oKeyboardShortcutToolbar->AddSubBlock($oKeyboardShortcutCancelButton); $oKeyboardShortcutCancelButton->SetOnClickJsCode("window.location.href = '$sURL'"); // - Reset button $oKeyboardShortcutResetButton = ButtonUIBlockFactory::MakeForSecondaryAction(Dict::S('UI:Preferences:PersonalizeKeyboardShortcuts:Button:Reset'), 'operation', 'reset_keyboard_shortcuts', true); $oKeyboardShortcutResetButton->SetTooltip(Dict::S('UI:Preferences:PersonalizeKeyboardShortcuts:Button:Reset:Tooltip')); $oKeyboardShortcutToolbar->AddSubBlock($oKeyboardShortcutResetButton); // - Submit button $oKeyboardShortcutSubmitButton = ButtonUIBlockFactory::MakeForPrimaryAction(Dict::S('UI:Button:Apply'), 'operation', 'apply_keyboard_shortcuts', true); $oKeyboardShortcutToolbar->AddSubBlock($oKeyboardShortcutSubmitButton); $oContentLayout->AddMainBlock($oKeyboardShortcutBlock); ////////////////////////////////////////////////////////////////////////// // // User picture placeholder // ////////////////////////////////////////////////////////////////////////// $oUserPicturePlaceHolderBlock = new Panel(Dict::S('UI:Preferences:ChooseAPlaceholder'), array(), 'grey', 'ibo-user-picture-placeholder'); $sUserPicturesFolderRelPath = 'images/user-pictures/'; $sUserPicturesFolderAbsPath = APPROOT . $sUserPicturesFolderRelPath; $sUserPicturesFolderAbsUrl = utils::GetAbsoluteUrlAppRoot() . $sUserPicturesFolderRelPath; $sUserDefaultPicture = appUserPreferences::GetPref('user_picture_placeholder', 'default-placeholder.png'); $sUserPicturePlaceHolderHtml = ''; $sUserPicturePlaceHolderHtml .= '

'.Dict::S('UI:Preferences:ChooseAPlaceholder+').'

'; foreach (scandir($sUserPicturesFolderAbsPath) as $sUserPicture) { if ($sUserPicture === '.' || $sUserPicture === '..') { continue; } $sAdditionalClass = ''; if ($sUserDefaultPicture === $sUserPicture) { $sAdditionalClass = ' ibo-is-active'; } $sUserPicturePlaceHolderHtml .= ' '; } $sUserPictureChangedSuccessMessage = Dict::S('UI:Preferences:ChooseAPlaceholder:Success:Message'); $oP->add_ready_script( << HTML ; $oUserPicturePlaceHolderHtmlBlock = new Html($sUserPicturePlaceHolderHtml); $oUserPicturePlaceHolderBlock->AddSubBlock($oUserPicturePlaceHolderHtmlBlock); $oContentLayout->AddMainBlock($oUserPicturePlaceHolderBlock); /** @var iPreferencesExtension $oLoginExtensionInstance */ foreach (MetaModel::EnumPlugins('iPreferencesExtension') as $oPreferencesExtensionInstance) { $oPreferencesExtensionInstance->DisplayPreferences($oP); } ////////////////////////////////////////////////////////////////////////// // // Footer // $oP->SetContentLayout($oContentLayout); } /** * @return \Combodo\iTop\Application\UI\Base\iUIBlock * @since 3.0.0 */ function GetLanguageFieldBlock(): iUIBlock { $aAvailableLanguages = Dict::GetLanguages(); $aSortedLanguages = array(); foreach ($aAvailableLanguages as $sCode => $aLang) { if (MetaModel::GetConfig()->Get('demo_mode') && ($sCode !== Dict::GetUserLanguage())) { // Demo mode: only the current user language is listed in the available choices continue; } $aSortedLanguages[$aLang['description']] = $sCode; } ksort($aSortedLanguages); $oSelect = SelectUIBlockFactory::MakeForSelectWithLabel('language', Dict::S('UI:FavoriteLanguage')); /** @var \Combodo\iTop\Application\UI\Base\Component\Input\Select\Select $oSelectInput */ foreach ($aSortedLanguages as $sCode) { $bSelected = ($sCode === Dict::GetUserLanguage()); $oSelect->AddSubBlock(SelectOptionUIBlockFactory::MakeForSelectOption($sCode, $aAvailableLanguages[$sCode]['description'].' ('.$aAvailableLanguages[$sCode]['localized_description'].')', $bSelected)); } return $oSelect; } /** * @return \Combodo\iTop\Application\UI\Base\iUIBlock * @since 3.0.0 */ function GetThemeFieldBlock(): iUIBlock { $aAvailableThemes = ThemeHandler::GetAvailableThemes(); $oSelect = SelectUIBlockFactory::MakeForSelectWithLabel('theme', Dict::S('UI:Preferences:General:Theme')); foreach ($aAvailableThemes as $sCode => $sLabel) { if (MetaModel::GetConfig()->Get('demo_mode') && ($sCode !== ThemeHandler::GetApplicationThemeId())) { // Demo mode: only the current app. theme is listed in the available choices continue; } $bSelected = ($sCode === ThemeHandler::GetCurrentUserThemeId()); if ($sCode === MetaModel::GetConfig()->Get('backoffice_default_theme')) { $sLabel = Dict::Format('UI:Preferences:General:Theme:DefaultThemeLabel', $sLabel); } $oSelect->AddSubBlock(SelectOptionUIBlockFactory::MakeForSelectOption($sCode, $sLabel, $bSelected)); } return $oSelect; } /** * @return \Combodo\iTop\Application\UI\Base\iUIBlock * @throws \CoreException * @throws \CoreUnexpectedValue * @throws \MySQLException * @since 3.0.0 */ function GetListPageSizeFieldBlock(): iUIBlock { $iDefaultPageSize = (int)appUserPreferences::GetPref('default_page_size', MetaModel::GetConfig()->GetMinDisplayLimit()); $sInputHtml = ''; $sHtml = '

'.Dict::Format('UI:Favorites:Default_X_ItemsPerPage', $sInputHtml).'

'; return new Html($sHtml); } /** * @return \Combodo\iTop\Application\UI\Base\iUIBlock * @return 3.0.0 * @throws \CoreUnexpectedValue * @throws \MySQLException * @throws \CoreException */ function GetTabsLayoutFieldBlock(): iUIBlock { $sCurrentValue = appUserPreferences::GetPref('tab_layout', false); $aOptionsValues = [ 'horizontal', 'vertical', ]; $oSelect = SelectUIBlockFactory::MakeForSelectWithLabel('tab_layout', Dict::S('UI:Preferences:Tabs:Layout:Label')); foreach ($aOptionsValues as $sValue) { $oSelect->AddSubBlock(SelectOptionUIBlockFactory::MakeForSelectOption( $sValue, Dict::S('UI:Preferences:Tabs:Layout:'.ucfirst($sValue)), $sValue === $sCurrentValue) ); } return $oSelect; } /** * @return \Combodo\iTop\Application\UI\Base\iUIBlock * @throws \CoreException * @throws \CoreUnexpectedValue * @throws \MySQLException * @since 3.0.0 */ function GetTabsNavigationFieldBlock(): iUIBlock { $bCurrentValue = appUserPreferences::GetPref('tab_scrollable', false); $sCurrentValueAsString = $bCurrentValue ? 'true' : 'false'; $aOptionsValues = [ 'true' => 'Scrollable', 'false' => 'Classic', ]; $oSelect = SelectUIBlockFactory::MakeForSelectWithLabel('tab_scrollable', Dict::S('UI:Preferences:Tabs:Scrollable:Label')); foreach ($aOptionsValues as $sValue => $sDictEntrySuffix) { $oSelect->AddSubBlock(SelectOptionUIBlockFactory::MakeForSelectOption( $sValue, Dict::S('UI:Preferences:Tabs:Scrollable:'.$sDictEntrySuffix), $sValue === $sCurrentValueAsString) ); } return $oSelect; } /** * @return \Combodo\iTop\Application\UI\Base\iUIBlock * @throws \CoreException * @throws \CoreUnexpectedValue * @throws \MySQLException * @since 3.0.0 */ function GetActivityPanelEntryFormOpenedFieldBlock(): iUIBlock { // First check if user has a pref. $bOpened = appUserPreferences::GetPref('activity_panel.is_entry_form_opened', null); if (null === $bOpened) { // Otherwise get the default config. param. $bOpened = MetaModel::GetConfig()->Get('activity_panel.entry_form_opened_by_default'); } $sCheckedForHtmlAttribute = $bOpened ? 'checked="checked"' : ''; $sLabel = Dict::S('UI:Preferences:ActivityPanel:EntryFormOpened'); $sLabelDescription = Dict::S('UI:Preferences:ActivityPanel:EntryFormOpened+'); $sHtml = <<

HTML; return new Html($sHtml); } /** * @return \Combodo\iTop\Application\UI\Base\iUIBlock * @throws \CoreException * @throws \CoreUnexpectedValue * @throws \MySQLException * @since 3.0.0 */ function GetObsoleteDataFieldBlock(): iUIBlock { $bShow = utils::IsArchiveMode() || appUserPreferences::GetPref('show_obsolete_data', MetaModel::GetConfig()->Get('obsolescence.show_obsolete_data')); $sSelectedForHtmlAttribute = $bShow ? ' checked="checked"' : ''; $sDisabledForHtmlAttribute = utils::IsArchiveMode() ? 'disabled="disabled"' : ''; $sLabel = Dict::S('UI:Favorites:ShowObsoleteData'); $sLabelDescription = Dict::S('UI:Favorites:ShowObsoleteData+'); $sHtml = <<

HTML; return new Html($sHtml); } /** * @return \Combodo\iTop\Application\UI\Base\iUIBlock * @throws \CoreException * @throws \CoreUnexpectedValue * @throws \MySQLException * @since 3.1.0 */ function GetSummaryCardsFieldBlock(): iUIBlock { $bShow = appUserPreferences::GetPref('show_summary_cards', true); $sSelectedForHtmlAttribute = $bShow ? 'checked="checked"' : ''; $sLabel = Dict::S('UI:Favorites:General:ShowSummaryCards'); $sLabelDescription = Dict::S('UI:Favorites:General:ShowSummaryCards+'); $sHtml = <<

HTML; return new Html($sHtml); } /** * @return \Combodo\iTop\Application\UI\Base\iUIBlock * @throws \CoreException * @throws \CoreUnexpectedValue * @throws \MySQLException * @since 3.2.0 */ function GetToastsPositionFieldBlock(): iUIBlock { $sPosition = appUserPreferences::GetPref('toasts_vertical_position', "bottom"); $oSelect = SelectUIBlockFactory::MakeForSelectWithLabel('toasts_vertical_position', Dict::S('UI:Preferences:General:Toasts')); $oSelect->AddSubBlock(SelectOptionUIBlockFactory::MakeForSelectOption("bottom", Dict::S('UI:Preferences:General:Toasts:Bottom'), $sPosition === "bottom")); $oSelect->AddSubBlock(SelectOptionUIBlockFactory::MakeForSelectOption("top", Dict::S('UI:Preferences:General:Toasts:Top'), $sPosition === "top")); return $oSelect; } ///////////////////////////////////////////////////////////////////////////// // // Main program // ///////////////////////////////////////////////////////////////////////////// require_once(APPROOT.'/application/loginwebpage.class.inc.php'); LoginWebPage::DoLogin(); // Check user rights and prompt if needed $iStep = utils::ReadParam('step', 1); $oPage = new iTopWebPage(Dict::S('UI:Preferences')); $oPage->DisableBreadCrumb(); $sOperation = utils::ReadParam('operation', ''); try { $bOperationUsed = false; /** @var iPreferencesExtension $oLoginExtensionInstance */ foreach (MetaModel::EnumPlugins('iPreferencesExtension') as $oPreferencesExtensionInstance) { if ($oPreferencesExtensionInstance->ApplyPreferences($oPage, $sOperation)) { $bOperationUsed = true; break; } } if (!$bOperationUsed) { switch ($sOperation) { case 'apply': $oFilter = DBObjectSearch::FromOQL('SELECT Organization'); $sSelectionMode = utils::ReadParam('selectionMode', ''); $aExceptions = utils::ReadParam('storedSelection', array()); if (($sSelectionMode == 'negative') && (count($aExceptions) == 0)) { // All Orgs selected appUserPreferences::SetPref('favorite_orgs', null); } else { // Some organizations selected... store them $aSelectOrgs = utils::ReadMultipleSelection($oFilter); appUserPreferences::SetPref('favorite_orgs', $aSelectOrgs); } $oPage->ResetNavigationMenuLayout(); DisplayPreferences($oPage); break; case 'apply_user_interface': // Language $sLangCode = utils::ReadParam('language', 'EN US'); $oUser = UserRights::GetUserObject(); $oUser->Set('language', $sLangCode); utils::PushArchiveMode(false); $oUser->AllowWrite(true); $oUser->DBUpdate(); utils::PopArchiveMode(); // Theme $sThemeId = utils::ReadParam('theme', ''); if (!empty($sThemeId) && ThemeHandler::IsValidTheme($sThemeId)) { appUserPreferences::SetPref('backoffice_theme', $sThemeId); } // List $iDefaultPageSize = (int)utils::ReadParam('default_page_size', -1); if ($iDefaultPageSize > 0) { appUserPreferences::SetPref('default_page_size', $iDefaultPageSize); } // Tabs // - Layout $sLayout = utils::ReadParam('tab_layout', 'horizontal'); $sLayoutAllowedValues = ['horizontal', 'vertical']; if (in_array($sLayout, $sLayoutAllowedValues, true)) { appUserPreferences::SetPref('tab_layout', $sLayout); } // - Navigation $bScrollable = utils::ReadParam('tab_scrollable', 'false') === 'true'; appUserPreferences::SetPref('tab_scrollable', $bScrollable); // Rich text editor $bToolbarExpanded = utils::ReadParam('toolbarexpanded', 'false') === 'true'; $aRichTextConfig = json_decode(appUserPreferences::GetPref('richtext_config', '{}'), true); $aRichTextConfig['toolbarStartupExpanded'] = $bToolbarExpanded; appUserPreferences::SetPref('richtext_config', json_encode($aRichTextConfig)); // Activity panel $bActivityPanelEntryFormOpened = (bool)utils::ReadParam('activity_panel_entry_form_opened', 0); appUserPreferences::SetPref('activity_panel.is_entry_form_opened', $bActivityPanelEntryFormOpened); // Misc. // - Obsolete data $bShowObsoleteData = (bool)utils::ReadParam('show_obsolete_data', 0); appUserPreferences::SetPref('show_obsolete_data', $bShowObsoleteData); // - Summary cards $bShowSummaryCards = (bool)utils::ReadParam('show_summary_cards', 0); appUserPreferences::SetPref('show_summary_cards', $bShowSummaryCards); // - Toast notifications $sToastsVerticalPosition = utils::ReadParam('toasts_vertical_position', "bottom"); if(utils::IsNotNullOrEmptyString($sToastsVerticalPosition) && in_array($sToastsVerticalPosition, ["bottom", "top"], true)) { appUserPreferences::SetPref('toasts_vertical_position', $sToastsVerticalPosition); } // Redirect to force a reload/display of the page in case language has been changed $oAppContext = new ApplicationContext(); $sURL = utils::GetAbsoluteUrlAppRoot().'pages/preferences.php?'.$oAppContext->GetForLink(); $oPage->add_header('Location: '.$sURL); break; case 'apply_keyboard_shortcuts': /** @var iKeyboardShortcut[] $aShortcutClasses */ $aShortcutClasses = InterfaceDiscovery::GetInstance()->FindItopClasses(iKeyboardShortcut::class); $aShortcutPrefs = []; foreach ($aShortcutClasses as $cShortcutPlugin) { foreach ($cShortcutPlugin::GetShortcutKeys() as $aShortcutKey) { $sKey = utils::ReadParam($aShortcutKey['id'], $aShortcutKey['key'], true, 'raw_data'); $aShortcutPrefs[$aShortcutKey['id']] = strtolower(utils::HtmlEntities($sKey)); } } appUserPreferences::SetPref('keyboard_shortcuts', $aShortcutPrefs); DisplayPreferences($oPage); break; case 'reset_keyboard_shortcuts': appUserPreferences::UnsetPref('keyboard_shortcuts'); DisplayPreferences($oPage); break; case 'apply_newsroom_preferences': $iCountProviders = 0; $oUser = UserRights::GetUserObject(); /** @var iNewsroomProvider[] $aProviders */ $aProviders = InterfaceDiscovery::GetInstance()->FindItopClasses(iNewsroomProvider::class); foreach ($aProviders as $cProvider) { $oProvider = new $cProvider(); if ($oProvider->IsApplicable($oUser)) { $iCountProviders++; } } $bNewsroomEnabled = (MetaModel::GetConfig()->Get('newsroom_enabled') !== false); if ($bNewsroomEnabled && ($iCountProviders > 0)) { $iNewsroomDisplaySize = (int)utils::ReadParam('newsroom_display_size', 7); if ($iNewsroomDisplaySize < 1) { $iNewsroomDisplaySize = 1; } if ($iNewsroomDisplaySize > 20) { $iNewsroomDisplaySize = 20; } $iCurrentDisplaySize = (int)appUserPreferences::GetPref('newsroom_display_size', $iNewsroomDisplaySize); if ($iCurrentDisplaySize != $iNewsroomDisplaySize) { // Save the preference only if it differs from the current (or default) value appUserPreferences::SetPref('newsroom_display_size', $iNewsroomDisplaySize); } } $bProvidersModified = false; foreach ($aProviders as $cProvider) { // Forbid disabling internal newsroom provider if ($cProvider === iTopNewsroomProvider::class) { continue; } $oProvider = new $cProvider(); if ($oProvider->IsApplicable($oUser)) { $sProviderClass = get_class($oProvider); $bProviderEnabled = (utils::ReadParam('newsroom_provider_'.$sProviderClass, 'off') == 'on'); $bCurrentValue = appUserPreferences::GetPref('newsroom_provider_'.$sProviderClass, true); if ($bCurrentValue != $bProviderEnabled) { // Save the preference only if it differs from the current value $bProvidersModified = true; appUserPreferences::SetPref('newsroom_provider_'.$sProviderClass, $bProviderEnabled); } } } if ($bProvidersModified) { $oPage->add_ready_script( <<SetBreadCrumbEntry('ui-tool-preferences', Dict::S('UI:Preferences'), Dict::S('UI:Preferences'), '', 'fas fa-user-cog', iTopWebPage::ENUM_BREADCRUMB_ENTRY_ICON_TYPE_CSS_CLASSES); DisplayPreferences($oPage); } } $oPage->output(); } catch(CoreException $e) { require_once(APPROOT.'/setup/setuppage.class.inc.php'); $oP = new ErrorPage(Dict::S('UI:PageTitle:FatalError')); $oP->add("

".Dict::S('UI:FatalErrorMessage')."

\n"); $oP->error(Dict::Format('UI:Error_Details', $e->getHtmlDesc())); $oP->output(); if (MetaModel::IsLogEnabledIssue()) { if (MetaModel::IsValidClass('EventIssue')) { $oLog = new EventIssue(); $oLog->Set('message', $e->getMessage()); $oLog->Set('userinfo', ''); $oLog->Set('issue', $e->GetIssue()); $oLog->Set('impact', 'Page could not be displayed'); $oLog->Set('callstack', $e->getTrace()); $oLog->Set('data', $e->getContextData()); $oLog->DBInsertNoReload(); } IssueLog::Error($e->getMessage()); } // For debugging only //throw $e; } catch(Exception $e) { require_once(APPROOT.'/setup/setuppage.class.inc.php'); $oP = new ErrorPage(Dict::S('UI:PageTitle:FatalError')); $oP->add("

".Dict::S('UI:FatalErrorMessage')."

\n"); $oP->error(Dict::Format('UI:Error_Details', $e->getMessage())); $oP->output(); if (MetaModel::IsLogEnabledIssue()) { if (MetaModel::IsValidClass('EventIssue')) { $oLog = new EventIssue(); $oLog->Set('message', $e->getMessage()); $oLog->Set('userinfo', ''); $oLog->Set('issue', 'PHP Exception'); $oLog->Set('impact', 'Page could not be displayed'); $oLog->Set('callstack', $e->getTrace()); $oLog->Set('data', array()); $oLog->DBInsertNoReload(); } IssueLog::Error($e->getMessage()); } }