From e82c1e68817ffad24164018d37b7b3822422b281 Mon Sep 17 00:00:00 2001 From: daniel Date: Fri, 16 Jun 2023 13:47:25 +0200 Subject: [PATCH 001/116] wip integration integriaIMS pandora_enterprise#11471 --- .../godmode/users/user_management.php | 56 +++ pandora_console/include/functions_html.php | 8 +- pandora_console/include/functions_menu.php | 8 +- pandora_console/include/lib/ITSM/ITSM.php | 174 +++++++ pandora_console/include/lib/ITSM/Manager.php | 470 ++++++++++++++++++ pandora_console/operation/ITSM/itsm.php | 73 +++ pandora_console/operation/menu.php | 31 ++ .../views/ITSM/ITSMDashboardView.php | 65 +++ .../views/ITSM/ITSMTicketEditView.php | 294 +++++++++++ .../views/ITSM/ITSMTicketListView.php | 131 +++++ 10 files changed, 1304 insertions(+), 6 deletions(-) create mode 100644 pandora_console/include/lib/ITSM/ITSM.php create mode 100644 pandora_console/include/lib/ITSM/Manager.php create mode 100644 pandora_console/operation/ITSM/itsm.php create mode 100644 pandora_console/views/ITSM/ITSMDashboardView.php create mode 100644 pandora_console/views/ITSM/ITSMTicketEditView.php create mode 100644 pandora_console/views/ITSM/ITSMTicketListView.php diff --git a/pandora_console/godmode/users/user_management.php b/pandora_console/godmode/users/user_management.php index b03c79f374..21a05b6d02 100644 --- a/pandora_console/godmode/users/user_management.php +++ b/pandora_console/godmode/users/user_management.php @@ -762,6 +762,62 @@ $userManagementTable->data['fields_addSettings'][1] .= html_print_div( true ); + +if ($config['integria_enabled'] && $config['integria_user_level_conf']) { + // Integria IMS user remote login. + $table_remote = new StdClass(); + $table_remote->data = []; + $table_remote->width = '100%'; + $table_remote->id = 'integria-remote-setup'; + $table_remote->class = 'white_box'; + $table_remote->size['name'] = '30%'; + $table_remote->style['name'] = 'font-weight: bold'; + + // Integria IMS user level authentication. + // Title. + $row = []; + $row['control'] = '

'.__('Integria user configuration').':

'; + $table_remote->data['integria_user_level_conf'] = $row; + + // Integria IMS user. + $row = []; + $row['name'] = __('User'); + $row['control'] = html_print_input_text('integria_user_level_user', $user_info['integria_user_level_user'], '', 30, 100, true); + $table_remote->data['integria_user_level_user'] = $row; + + // Integria IMS pass. + $row = []; + $row['name'] = __('Password'); + $row['control'] = html_print_input_password('integria_user_level_pass', io_output_password($user_info['integria_user_level_pass']), '', 30, 100, true); + $table_remote->data['integria_user_level_pass'] = $row; + + // Test. + $integria_host = db_get_value('value', 'tconfig', 'token', 'integria_hostname'); + $integria_api_pass = db_get_value('value', 'tconfig', 'token', 'integria_api_pass'); + + $row = []; + $row['name'] = __('Test'); + $row['control'] = html_print_button( + __('Start'), + 'test-integria', + false, + 'integria_connection_test("'.$integria_host.'",'.$integria_api_pass.')', + [ 'icon' => 'next' ], + true + ); + $row['control'] .= ' '; + $row['control'] .= ' '; + $row['control'] .= ' '; + $row['control'] .= ''; + $table_remote->data['integria_test'] = $row; + + hd('Entra'); + // echo '
'; + $userManagementTable->colspan['pandoraitsm'] = 2; + $userManagementTable->data['pandoraitsm'] = html_print_table($table_remote, true); + // echo '
'; +} + if (isset($CodeQRTable) === true || isset($apiTokenContent) === true) { // QR Code and API Token advice. html_print_div( diff --git a/pandora_console/include/functions_html.php b/pandora_console/include/functions_html.php index f3a23ce1e8..547a77d64d 100644 --- a/pandora_console/include/functions_html.php +++ b/pandora_console/include/functions_html.php @@ -6125,8 +6125,6 @@ function html_print_autocomplete_users_from_integria( $attrs['class'] = $class; } - ui_print_help_tip(__('Type at least two characters to search the user.'), false); - html_print_input_text_extended( $name, $default, @@ -6138,7 +6136,7 @@ function html_print_autocomplete_users_from_integria( '', $attrs ); - html_print_input_hidden($name.'_hidden', $id_agent_module); + html_print_input_hidden($name.'_hidden', $default); $javascript_ajax_page = ui_get_full_url('ajax.php', false, false, false, false); ?> @@ -6158,9 +6156,9 @@ function html_print_autocomplete_users_from_integria( var term = request.term; //Word to search data_params = { - page: "include/ajax/integria_incidents.ajax", + page: "operation/ITSM/itsm", search_term: term, - get_users: 1, + method: "getUserSelect", }; jQuery.ajax ({ diff --git a/pandora_console/include/functions_menu.php b/pandora_console/include/functions_menu.php index 35ee78db39..7d3d229f7b 100644 --- a/pandora_console/include/functions_menu.php +++ b/pandora_console/include/functions_menu.php @@ -145,6 +145,12 @@ function menu_print_menu(&$menu) if (empty($new_msg) === false) { $sec2 = 'operation/messages/message_edit&new_msg='.$new_msg; } + } else if ($sec2 === 'operation/ITSM/itsm') { + $sec2 = (string) get_parameter('sec2'); + $operation = (string) get_parameter('operation', ''); + if (empty($operation) === false) { + $sec2 = $sec2.'&operation='.$operation; + } } else { $sec2 = (string) get_parameter('sec2'); } @@ -285,7 +291,7 @@ function menu_print_menu(&$menu) } } - // Set class. + // Set class.; if (($sec2 == $subsec2 || $allsec2 == $subsec2 || $selected_submenu2) && isset($sub[$subsec2]['options']) && (get_parameter_get($sub[$subsec2]['options']['name']) == $sub[$subsec2]['options']['value']) diff --git a/pandora_console/include/lib/ITSM/ITSM.php b/pandora_console/include/lib/ITSM/ITSM.php new file mode 100644 index 0000000000..fddd63650c --- /dev/null +++ b/pandora_console/include/lib/ITSM/ITSM.php @@ -0,0 +1,174 @@ +userLevelConf = (bool) $config['integria_user_level_conf']; + $this->url = $config['integria_hostname']; + + $this->userBearer = $config['integria_pass']; + if ($this->userLevelConf === true) { + $this->userBearer = $user_info['integria_user_level_pass']; + } + + } + + + /** + * Call api ITSM. + * + * @param string $action Endpoint. + * @param array $queryParams Params send get. + * @param array $postFields Params send post. + * @param mixed $id Specific id for path. + * @param string|null $method Request method. + * + * @return array Array result. + * @throws \Exception On error. + */ + public function callApi( + string $action, + ?array $queryParams=null, + ?array $postFields=null, + mixed $id=null, + ?string $method='POST' + ) { + $headers = [ + 'accept: application/json', + 'Content-Type: application/json', + 'Authorization: Bearer '.$this->userBearer, + ]; + + $path = $this->pathAction($action, $queryParams, $id); + $url = $this->url.$path; + + $ch = curl_init(); + curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); + curl_setopt($ch, CURLOPT_URL, $url); + curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); + curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method); + curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($postFields)); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + curl_setopt($ch, CURLOPT_VERBOSE, true); + $result = curl_exec($ch); + + $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE); + + $result = json_decode($result, true); + if (json_last_error() !== JSON_ERROR_NONE) { + throw new \Exception(__('Invalid response')); + } + + if ($http_status !== 200) { + throw new \Exception($result['error']); + } + + return $result; + } + + + /** + * Convert path to endpoint ITSM. + * + * @param string $action EndPoint. + * @param array|null $queryParams Params to url. + * @param mixed $id Specific id for path. + * + * @return string Return path to Endpoint. + */ + private function pathAction(string $action, ?array $queryParams=null, mixed $id=null): string + { + $path = ''; + switch ($action) { + case 'listTickets': + $path = '/incidence/list'; + break; + + case 'listObjectTypes': + $path = '/incidencetype/list'; + break; + + case 'listGroups': + $path = '/group/list'; + break; + + case 'listResolutions': + $path = '/incidence/resolution/list'; + break; + + case 'listStatus': + $path = '/incidence/status/list'; + break; + + case 'listUsers': + $path = '/user/list'; + break; + + case 'createIncidence': + $path = '/incidence'; + break; + + case 'updateIncidence': + $path = '/incidence/'.$id; + break; + + default: + // Not posible. + break; + } + + if (empty($queryParams) === false) { + if (isset($queryParams['direction']) === true) { + $queryParams['sortDirection'] = $queryParams['direction']; + unset($queryParams['direction']); + } + + if (isset($queryParams['field']) === true) { + $queryParams['sortField'] = $queryParams['field']; + unset($queryParams['field']); + } + + $path .= '?'; + $path .= http_build_query($queryParams); + } + + return $path; + } + + +} diff --git a/pandora_console/include/lib/ITSM/Manager.php b/pandora_console/include/lib/ITSM/Manager.php new file mode 100644 index 0000000000..0fbe7bcd49 --- /dev/null +++ b/pandora_console/include/lib/ITSM/Manager.php @@ -0,0 +1,470 @@ +operation = \get_parameter('operation', 0); + + // Urls. + $this->url = \ui_get_full_url( + 'index.php?sec=reporting&sec2=operation/dashboard/dashboard' + ); + + $this->ajaxController = $page; + } + + + /** + * Checks if target method is available to be called using AJAX. + * + * @param string $method Target method. + * + * @return boolean True allowed, false not. + */ + public function ajaxMethod(string $method): bool + { + return in_array($method, $this->AJAXMethods); + } + + + /** + * Prints error. + * + * @param string $msg Message. + * + * @return void + */ + public function error(string $msg) + { + if ((bool) \is_ajax() === true) { + echo json_encode(['error' => $msg]); + } else { + \ui_print_error_message($msg); + } + } + + + /** + * Init manager ITSM. + * + * @return void + */ + public function run() + { + switch ($this->operation) { + case 'list': + $this->showList(); + break; + + case 'edit': + $this->showEdit(); + break; + + case 'dashboard': + default: + $this->showDashboard(); + break; + } + } + + + /** + * Draw list tickets. + * + * @return void + */ + private function showList() + { + View::render( + 'ITSM/ITSMTicketListView', + [ + 'ajaxController' => $this->ajaxController, + 'urlAjax' => \ui_get_full_url('ajax.php'), + ] + ); + } + + + /** + * Draw list tickets. + * + * @return void + */ + private function showEdit() + { + $create_incidence = (bool) \get_parameter('create_incidence', 0); + $update_incidence = (bool) \get_parameter('update_incidence', 0); + $idIncidence = \get_parameter('idIncidence', 0); + $incidence = [ + 'title' => \get_parameter('title', ''), + 'idIncidenceType' => \get_parameter('idIncidenceType', 0), + 'idGroup' => \get_parameter('idGroup', 0), + 'priority' => 'LOW', + // \get_parameter('priority', 'LOW'), + 'status' => \get_parameter('status', 'NEW'), + 'idCreator' => \get_parameter('idCreator', ''), + 'owner' => \get_parameter('owner_hidden', ''), + 'resolution' => \get_parameter('resolution', null), + 'description' => \get_parameter('description', ''), + ]; + + $error = ''; + $ITSM = new ITSM(); + try { + $objectTypes = $this->getObjectypes($ITSM); + $groups = $this->getGroups($ITSM); + // $priorities = $ITSM->callApi('listPriorities'); + $resolutions = $this->getResolutions($ITSM); + $status = $this->getStatus($ITSM); + } catch (\Throwable $th) { + $error = $th->getMessage(); + } + + $successfullyMsg = ''; + try { + if ($create_incidence === true) { + $incidence = $this->createIncidence($ITSM, $incidence); + $idIncidence = $incidence['idIncidence']; + $successfullyMsg = __('Successfully create ticket'); + } + + if ($update_incidence === true) { + $incidence = $this->updateIncidence($ITSM, $incidence, $idIncidence); + $successfullyMsg = __('Successfully update ticket'); + } + } catch (\Throwable $th) { + $error = $th->getMessage(); + } + + View::render( + 'ITSM/ITSMTicketEditView', + [ + 'ajaxController' => $this->ajaxController, + 'urlAjax' => \ui_get_full_url('ajax.php'), + 'objectTypes' => $objectTypes, + 'groups' => $groups, + 'priorities' => [], + 'resolutions' => $resolutions, + 'status' => $status, + 'error' => $error, + 'incidence' => $incidence, + 'idIncidence' => $idIncidence, + 'successfullyMsg' => $successfullyMsg, + ] + ); + } + + + /** + * Get Incidences types. + * + * @param ITSM $ITSM Object for callApi. + * + * @return array Return mode select. + */ + private function getObjectypes(ITSM $ITSM): array + { + $listObjectTypes = $ITSM->callApi('listObjectTypes'); + $result = []; + foreach ($listObjectTypes['data'] as $objectType) { + $result[$objectType['idIncidenceType']] = $objectType['name']; + } + + return $result; + } + + + /** + * Get Groups. + * + * @param ITSM $ITSM Object for callApi. + * + * @return array Return mode select. + */ + private function getGroups(ITSM $ITSM): array + { + $listGroups = $ITSM->callApi('listGroups'); + $result = []; + foreach ($listGroups['data'] as $group) { + if ($group['idGroup'] > 1) { + $result[$group['idGroup']] = $group['name']; + } + } + + return $result; + } + + + /** + * Get Resolutions. + * + * @param ITSM $ITSM Object for callApi. + * + * @return array Return mode select. + */ + private function getResolutions(ITSM $ITSM): array + { + $listResolutions = $ITSM->callApi('listResolutions'); + $result = []; + foreach ($listResolutions['data'] as $resolution) { + $result[$resolution['idIncidenceResolution']] = $resolution['name']; + } + + return $result; + } + + + /** + * Create incidence + * + * @param ITSM $ITSM Object for callApi. + * @param array $incidence Params insert. + * + * @return array + */ + private function createIncidence(ITSM $ITSM, array $incidence): array + { + $incidence = $ITSM->callApi('createIncidence', null, $incidence); + return $incidence; + } + + + /** + * Update incidence + * + * @param ITSM $ITSM Object for callApi. + * @param array $incidence Params insert. + * @param integer $idIncidence Id incidence. + * + * @return array + */ + private function updateIncidence(ITSM $ITSM, array $incidence, int $idIncidence): array + { + $incidence = $ITSM->callApi( + 'updateIncidence', + null, + $incidence, + $idIncidence, + 'PUT' + ); + return $incidence; + } + + + /** + * Get Status. + * + * @param ITSM $ITSM Object for callApi. + * + * @return array Return mode select. + */ + private function getStatus(ITSM $ITSM): array + { + $listStatus = $ITSM->callApi('listStatus'); + $result = []; + foreach ($listStatus['data'] as $status) { + $result[$status['idIncidenceStatus']] = $status['name']; + } + + return $result; + } + + + /** + * Draw list dashboards. + * + * @return void + */ + private function showDashboard() + { + global $config; + + View::render( + 'ITSM/ITSMDashboardView', + [ + 'ajaxController' => $this->ajaxController, + 'urlAjax' => \ui_get_full_url('ajax.php'), + ] + ); + } + + + /** + * Get list tickets and prepare data for datatable. + * + * @return void + */ + public function getListTickets() + { + global $config; + + // Init data. + $data = []; + // Catch post parameters. + $start = get_parameter('start', 0); + $length = get_parameter('length', $config['block_size']); + $order = get_datatable_order(true); + $filters = get_parameter('filter', []); + + try { + ob_start(); + $queryParams = array_merge( + [ + 'page' => $start, + 'sizePage' => $length, + ], + $order + ); + + $ITSM = new ITSM(); + $result = $ITSM->callApi( + 'listTickets', + $queryParams, + $filters + ); + + $data = array_reduce( + $result['data'], + function ($carry, $item) { + global $config; + // Transforms array of arrays $data into an array + // of objects, making a post-process of certain fields. + $tmp = (object) $item; + $new = (object) []; + $new->id = $tmp->idIncidence; + $new->title = $tmp->title; + $new->groupCompany = $tmp->idGroup.'/'.$tmp->idCompany; + $new->statusResolution = $tmp->status.'/'.$tmp->resolution; + $new->priority = $tmp->priority; + $new->updated = $tmp->updateDate; + $new->started = $tmp->startDate; + $new->creator = $tmp->idCreator; + $new->owner = $tmp->owner; + + $carry[] = $new; + return $carry; + } + ); + + echo json_encode( + [ + 'data' => $data, + 'recordsTotal' => $result['paginationData']['totalRegisters'], + 'recordsFiltered' => $result['paginationData']['totalRegisters'], + ] + ); + // Capture output. + $response = ob_get_clean(); + } catch (Throwable $e) { + echo json_encode(['error' => $e->getMessage()]); + exit; + } + + // If not valid, show error with issue. + json_decode($response); + if (json_last_error() === JSON_ERROR_NONE) { + // If valid dump. + echo $response; + } else { + echo json_encode( + ['error' => $response] + ); + } + + exit; + } + + + /** + * Get list tickets and prepare data for datatable. + * + * @return void + */ + public function getUserSelect() + { + global $config; + + try { + $ITSM = new ITSM(); + $result = $ITSM->callApi( + 'listUsers', + [ + 'page' => 0, + 'sizePage' => 0, + ], + ['freeSearch' => \get_parameter('search_term', '')] + ); + + $response = array_reduce( + $result['data'], + function ($carry, $user) { + $carry[$user['idUser']] = $user['fullName']; + return $carry; + } + ); + } catch (Throwable $e) { + echo json_encode(['error' => $e->getMessage()]); + exit; + } + + echo json_encode($response); + exit; + } + + +} diff --git a/pandora_console/operation/ITSM/itsm.php b/pandora_console/operation/ITSM/itsm.php new file mode 100644 index 0000000000..32aedf1781 --- /dev/null +++ b/pandora_console/operation/ITSM/itsm.php @@ -0,0 +1,73 @@ + '[ITSM]'.$e->getMessage() ]); + } else { + echo '[ITSM]'.$e->getMessage(); + } + + // Stop this execution, but continue 'globally'. + return; +} + +// AJAX controller. +if (is_ajax() === true) { + $method = get_parameter('method'); + + if (method_exists($cs, $method) === true) { + if ($cs->ajaxMethod($method) === true) { + $cs->{$method}(); + } else { + $cs->error('Unavailable method.'); + } + } else { + $cs->error('Method not found. ['.$method.']'); + } +} else { + // Run. + $cs->run(); +} diff --git a/pandora_console/operation/menu.php b/pandora_console/operation/menu.php index 96462b0eed..ad78de259b 100644 --- a/pandora_console/operation/menu.php +++ b/pandora_console/operation/menu.php @@ -687,6 +687,37 @@ if ($access_console_node === true) { $menu_operation['workspace']['sub'] = $sub; +if ($access_console_node === true) { + // ITSM. + $menu_operation['ITSM']['text'] = __('ITSM'); + $menu_operation['ITSM']['sec2'] = 'operation/ITSM/itsm'; + $menu_operation['ITSM']['id'] = 'oper-itsm'; + + $sub = []; + // ITSM Tickets. + $sub['manageTickets']['text'] = __('Tickets'); + $sub['manageTickets']['id'] = 'itsm-ticket'; + $sub['manageTickets']['refr'] = 0; + $sub['manageTickets']['type'] = 'direct'; + $sub['manageTickets']['subtype'] = 'nolink'; + + $sub2 = []; + $sub2['operation/ITSM/itsm&operation=list']['text'] = __('List'); + $sub2['operation/ITSM/itsm&operation=list']['id'] = 'itsm-ticket-list'; + + $sub2['operation/ITSM/itsm&operation=edit']['text'] = __('Edit'); + $sub2['operation/ITSM/itsm&operation=edit']['id'] = 'itsm-ticket-edit'; + + $sub['manageTickets']['sub2'] = $sub2; + + // ITSM Dashboard. + $sub['operation/ITSM/itsm']['text'] = __('Dashboard'); + $sub['operation/ITSM/itsm']['id'] = 'itsm-dashboard'; + $sub['operation/ITSM/itsm']['refr'] = 0; + + $menu_operation['ITSM']['sub'] = $sub; +} + if ($access_console_node === true) { // Rest of options, all with AR privilege (or should events be with incidents?) // ~ if (check_acl ($config['id_user'], 0, "AR")) { diff --git a/pandora_console/views/ITSM/ITSMDashboardView.php b/pandora_console/views/ITSM/ITSMDashboardView.php new file mode 100644 index 0000000000..229267496b --- /dev/null +++ b/pandora_console/views/ITSM/ITSMDashboardView.php @@ -0,0 +1,65 @@ + 'index.php?sec=ITSM&sec2=operation/ITSM/itsm', + 'label' => __('ITSM'), + ], + [ + 'link' => 'index.php?sec=ITSM&sec2=operation/ITSM/itsm', + 'label' => __('ITSM Dashboard'), + ], + ] +); + +if (empty($incidences) === true) { + ui_print_info_message( + [ + 'no_close' => true, + 'message' => __('Wip...........................'), + ] + ); +} else { + echo 'WIP...'; +} diff --git a/pandora_console/views/ITSM/ITSMTicketEditView.php b/pandora_console/views/ITSM/ITSMTicketEditView.php new file mode 100644 index 0000000000..b1f0330fe6 --- /dev/null +++ b/pandora_console/views/ITSM/ITSMTicketEditView.php @@ -0,0 +1,294 @@ + 'index.php?sec=ITSM&sec2=operation/ITSM/itsm', + 'label' => __('ITSM'), + ], + [ + 'link' => 'index.php?sec=ITSM&sec2=operation/ITSM/itsm&operation=list', + 'label' => __('ITSM Tickets'), + ], + [ + 'link' => 'index.php?sec=ITSM&sec2=operation/ITSM/itsm&operation=edit', + 'label' => __('Edit'), + ], + ] +); + + +if (empty($error) === false) { + ui_print_error_message($error); +} + +if (empty($successfullyMsg) === false) { + ui_print_success_message($successfullyMsg); +} + +// Main table. +$table = new stdClass(); +$table->width = '100%'; +$table->id = 'edit-ticket-itms'; +$table->class = 'databox filter-table-adv'; +$table->head = []; +$table->data = []; +$table->size = []; +$table->size = []; +$table->colspan[0][0] = 2; +$table->colspan[4][0] = 3; +$table->colspan[6][0] = 3; + +$table->data[0][0] = html_print_label_input_block( + __('Title'), + html_print_input_text( + 'title', + ($incidence['title'] ?? ''), + __('Name'), + 30, + 100, + true, + false, + true, + '', + 'w100p' + ) +); + +$integria_logo = 'images/integria_logo_gray.png'; +if ($config['style'] === 'pandora_black' && !is_metaconsole()) { + $integria_logo = 'images/integria_logo.svg'; +} + +$table->data[0][2] = '
'.html_print_image( + $integria_logo, + true, + ['style' => 'width: -webkit-fill-available;'], + false +).'
'; +$table->data[1][0] = html_print_label_input_block( + __('Type'), + html_print_select( + $objectTypes, + 'idIncidenceType', + ($incidence['idIncidenceType'] ?? ''), + '', + __('Select'), + 0, + true, + false, + true, + '', + false, + 'width: 100%;' + ) +); + +$table->data[1][1] = html_print_label_input_block( + __('Group'), + html_print_select( + $groups, + 'idGroup', + ($incidence['idGroup'] ?? ''), + '', + '', + 0, + true, + false, + true, + '', + false, + 'width: 100%;' + ) +); + +$table->data[1][2] = html_print_label_input_block( + __('Priority'), + html_print_select( + $priorities, + 'priority', + ($incidence['priority'] ?? 0), + '', + '', + 1, + true, + false, + true, + '', + false, + 'width: 100%;' + ) +); + +$table->data[2][0] = html_print_label_input_block( + __('Status'), + html_print_select( + $status, + 'status', + ($incidence['status'] ?? 0), + '', + '', + 1, + true, + false, + true, + '', + false, + 'width: 100%;' + ) +); + +$table->data[2][1] = html_print_label_input_block( + __('Creator').ui_print_help_tip(__('This field corresponds to the Integria IMS user specified in Integria IMS setup'), true), + html_print_input_text( + 'idCreator', + $config['integria_user'], + '', + 0, + 100, + true, + true, + false, + '', + 'w100p' + ) +); + +$table->data[2][2] = html_print_label_input_block( + __('Owner').ui_print_help_tip(__('Type at least two characters to search the user.'), true), + html_print_autocomplete_users_from_integria( + 'owner', + ($incidence['owner'] ?? ''), + true, + 0, + false, + false, + 'w100p', + ) +); + +$table->data[3][0] = '' +); + +$table->data[4][0] = html_print_label_input_block( + __('Description').$help_macros, + html_print_textarea( + 'description', + 3, + 20, + ($incidence['description'] ?? ''), + '', + true + ) +); + +// $table->data[5][0] = html_print_label_input_block( +// __('File name'), +// html_print_input_file('userfile', true) +// ); +// +// $table->data[6][0] = html_print_label_input_block( +// __('Attachment description'), +// html_print_textarea( +// 'file_description', +// 3, +// 20, +// '', +// '', +// true +// ) +// ); +// Print forms and stuff. +echo '
'; +html_print_table($table); +$buttons = ''; +if (empty($idIncidence) === true) { + $buttons .= html_print_input_hidden('create_incidence', 1, true); + $buttons .= html_print_submit_button( + __('Create'), + 'accion', + false, + [ 'icon' => 'next' ], + true + ); +} else { + $buttons .= html_print_input_hidden('update_incidence', 1, true); + $buttons .= html_print_input_hidden('idIncidence', $idIncidence, true); + $buttons .= html_print_submit_button( + __('Update'), + 'accion', + false, + [ 'icon' => 'upd' ], + true + ); +} + +html_print_action_buttons($buttons); + +echo '
'; +?> + + \ No newline at end of file diff --git a/pandora_console/views/ITSM/ITSMTicketListView.php b/pandora_console/views/ITSM/ITSMTicketListView.php new file mode 100644 index 0000000000..f7babace3b --- /dev/null +++ b/pandora_console/views/ITSM/ITSMTicketListView.php @@ -0,0 +1,131 @@ + 'index.php?sec=ITSM&sec2=operation/ITSM/itsm', + 'label' => __('ITSM'), + ], + [ + 'link' => 'index.php?sec=ITSM&sec2=operation/ITSM/itsm&operation=list', + 'label' => __('ITSM Tickets'), + ], + ] +); + +/* + if (isset($resultDelete) === true) { + \ui_print_result_message( + $resultDelete, + __('Successfully deleted'), + __('Could not be deleted') + ); + } + + if (isset($resultCopy) === true) { + \ui_print_result_message( + $resultCopy, + __('Successfully duplicate'), + __('Could not be duplicate') + ); + } +*/ + + +try { + $columns = [ + 'id', + 'title', + 'groupCompany', + 'statusResolution', + 'priority', + 'updated', + 'started', + 'creator', + 'owner', + ]; + + $column_names = [ + __('ID'), + __('Title'), + __('Group').'/'.__('Company'), + __('Status').'/'.__('Resolution'), + __('Priority'), + __('Updated'), + __('Started'), + __('Creator'), + __('Owner'), + ]; + + ui_print_datatable( + [ + 'id' => 'itms_list_tickets', + 'class' => 'info_table', + 'style' => 'width: 99%', + 'columns' => $columns, + 'column_names' => $column_names, + 'ajax_url' => $ajaxController, + 'ajax_data' => ['method' => 'getListTickets'], + 'no_sortable_columns' => [ + 2, + 3, + ], + 'search_button_class' => 'sub filter float-right', + 'filter_main_class' => 'box-flat white_table_graph fixed_filter_bar', + ] + ); +} catch (Exception $e) { + echo $e->getMessage(); +} + +$input_button = ''; +$input_button = html_print_button( + __('Create'), + '', + false, + '', + ['icon' => 'next'], + true +); + +html_print_action_buttons($input_button); From d84299d3ab0c54b4e3cb3fd41c30a41550ea70e2 Mon Sep 17 00:00:00 2001 From: daniel Date: Tue, 20 Jun 2023 08:43:10 +0200 Subject: [PATCH 002/116] wip api integration pandora #1355 --- .../godmode/users/user_management.php | 1 - pandora_console/include/javascript/ITSM.js | 34 +++++ pandora_console/include/lib/ITSM/ITSM.php | 20 ++- pandora_console/include/lib/ITSM/Manager.php | 144 ++++++++++++++++-- .../include/styles/integriaims.css | 20 +++ .../views/ITSM/ITSMCustomFields.php | 101 ++++++++++++ .../views/ITSM/ITSMTicketEditView.php | 34 +++-- 7 files changed, 324 insertions(+), 30 deletions(-) create mode 100644 pandora_console/include/javascript/ITSM.js create mode 100644 pandora_console/views/ITSM/ITSMCustomFields.php diff --git a/pandora_console/godmode/users/user_management.php b/pandora_console/godmode/users/user_management.php index 21a05b6d02..30f783f9f7 100644 --- a/pandora_console/godmode/users/user_management.php +++ b/pandora_console/godmode/users/user_management.php @@ -811,7 +811,6 @@ if ($config['integria_enabled'] && $config['integria_user_level_conf']) { $row['control'] .= ''; $table_remote->data['integria_test'] = $row; - hd('Entra'); // echo '
'; $userManagementTable->colspan['pandoraitsm'] = 2; $userManagementTable->data['pandoraitsm'] = html_print_table($table_remote, true); diff --git a/pandora_console/include/javascript/ITSM.js b/pandora_console/include/javascript/ITSM.js new file mode 100644 index 0000000000..974af45a37 --- /dev/null +++ b/pandora_console/include/javascript/ITSM.js @@ -0,0 +1,34 @@ +/* global $ jQuery */ + +/* Function get custom fields incidences */ +// eslint-disable-next-line no-unused-vars +function getInputFieldsIncidenceType(idIncidenceType, fieldsData, ajaxUrl) { + console.log(idIncidenceType); + console.log(fieldsData); + console.log(ajaxUrl); + // Failed request handler. + var handleFail = function(jqXHR, textStatus, errorThrown) { + console.log(jqXHR, textStatus, errorThrown); + }; + + // Function which handle success case. + var handleSuccess = function(data) { + $(".object-type-fields").empty(); + $(".object-type-fields").append(data); + }; + + // Visual Console container request. + jQuery + .get( + ajaxUrl, + { + page: "operation/ITSM/itsm", + method: "getInputFieldsIncidenceType", + idIncidenceType: idIncidenceType, + fieldsData: fieldsData + }, + "html" + ) + .done(handleSuccess) + .fail(handleFail); +} diff --git a/pandora_console/include/lib/ITSM/ITSM.php b/pandora_console/include/lib/ITSM/ITSM.php index fddd63650c..8c9756ab06 100644 --- a/pandora_console/include/lib/ITSM/ITSM.php +++ b/pandora_console/include/lib/ITSM/ITSM.php @@ -45,7 +45,6 @@ class ITSM if ($this->userLevelConf === true) { $this->userBearer = $user_info['integria_user_level_pass']; } - } @@ -77,6 +76,8 @@ class ITSM $path = $this->pathAction($action, $queryParams, $id); $url = $this->url.$path; + // Debugger. + // hd($url, true); $ch = curl_init(); curl_setopt($ch, CURLOPT_HTTPHEADER, $headers); curl_setopt($ch, CURLOPT_URL, $url); @@ -85,15 +86,14 @@ class ITSM curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($postFields)); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_VERBOSE, true); - $result = curl_exec($ch); + $response = curl_exec($ch); - $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE); - - $result = json_decode($result, true); + $result = json_decode($response, true); if (json_last_error() !== JSON_ERROR_NONE) { - throw new \Exception(__('Invalid response')); + throw new \Exception(__('Invalid response').', '.$response); } + $http_status = curl_getinfo($ch, CURLINFO_HTTP_CODE); if ($http_status !== 200) { throw new \Exception($result['error']); } @@ -147,6 +147,14 @@ class ITSM $path = '/incidence/'.$id; break; + case 'incidenceTypeFields': + $path = '/incidencetype/'.$id.'/field/list'; + break; + + case 'incidence': + $path = '/incidence/'.$id; + break; + default: // Not posible. break; diff --git a/pandora_console/include/lib/ITSM/Manager.php b/pandora_console/include/lib/ITSM/Manager.php index 0fbe7bcd49..2431547dd8 100644 --- a/pandora_console/include/lib/ITSM/Manager.php +++ b/pandora_console/include/lib/ITSM/Manager.php @@ -26,6 +26,7 @@ class Manager public $AJAXMethods = [ 'getListTickets', 'getUserSelect', + 'getInputFieldsIncidenceType', ]; /** @@ -106,12 +107,14 @@ class Manager */ public function run() { + ui_require_css_file('integriaims'); switch ($this->operation) { case 'list': $this->showList(); break; case 'edit': + \ui_require_javascript_file('ITSM'); $this->showEdit(); break; @@ -150,19 +153,9 @@ class Manager $create_incidence = (bool) \get_parameter('create_incidence', 0); $update_incidence = (bool) \get_parameter('update_incidence', 0); $idIncidence = \get_parameter('idIncidence', 0); - $incidence = [ - 'title' => \get_parameter('title', ''), - 'idIncidenceType' => \get_parameter('idIncidenceType', 0), - 'idGroup' => \get_parameter('idGroup', 0), - 'priority' => 'LOW', - // \get_parameter('priority', 'LOW'), - 'status' => \get_parameter('status', 'NEW'), - 'idCreator' => \get_parameter('idCreator', ''), - 'owner' => \get_parameter('owner_hidden', ''), - 'resolution' => \get_parameter('resolution', null), - 'description' => \get_parameter('description', ''), - ]; + // Debugger. + // hd($_POST); $error = ''; $ITSM = new ITSM(); try { @@ -171,12 +164,47 @@ class Manager // $priorities = $ITSM->callApi('listPriorities'); $resolutions = $this->getResolutions($ITSM); $status = $this->getStatus($ITSM); + + if (empty($idIncidence) === false) { + $incidenceData = $this->getIncidence($ITSM, $idIncidence); + } } catch (\Throwable $th) { $error = $th->getMessage(); } + // TODO: END POINT priorities. + // \get_parameter('priority', 'LOW'). + $incidence = [ + 'title' => \get_parameter('title', ($incidenceData['title'] ?? '')), + 'idIncidenceType' => \get_parameter('idIncidenceType', ($incidenceData['idIncidenceType'] ?? 0)), + 'idGroup' => \get_parameter('idGroup', ($incidenceData['idGroup'] ?? 0)), + 'priority' => 'LOW', + 'status' => \get_parameter('status', ($incidenceData['status'] ?? 'NEW')), + 'idCreator' => \get_parameter('idCreator', ($incidenceData['idCreator'] ?? '')), + 'owner' => \get_parameter('owner_hidden', ''), + 'resolution' => \get_parameter('resolution', ($incidenceData['resolution'] ?? null)), + 'description' => \get_parameter('description', ($incidenceData['description'] ?? '')), + ]; + $successfullyMsg = ''; try { + if (empty($incidence['idIncidenceType']) === false + && ($create_incidence === true || $update_incidence === true) + ) { + $customFields = \get_parameter('custom-fields', []); + if (empty($customFields) === false) { + $typeFieldData = []; + foreach ($customFields as $idField => $data) { + $typeFieldData[] = [ + 'idIncidenceTypeField' => $idField, + 'data' => $data, + ]; + } + } + + $incidence['typeFieldData'] = $typeFieldData; + } + if ($create_incidence === true) { $incidence = $this->createIncidence($ITSM, $incidence); $idIncidence = $incidence['idIncidence']; @@ -325,6 +353,52 @@ class Manager } + /** + * Get Incidence. + * + * @param ITSM $ITSM Object for callApi. + * @param integer $idIncidence Incidence ID. + * + * @return array Data incidence + */ + private function getIncidence(ITSM $ITSM, int $idIncidence): array + { + $result = $ITSM->callApi( + 'incidence', + [], + [], + $idIncidence, + 'GET' + ); + + return $result; + } + + + /** + * Get fields incidence type. + * + * @param ITSM $ITSM Object for callApi. + * @param integer $idIncidenceType Incidence Type ID. + * + * @return array Fields array. + */ + private function getFieldsIncidenceType(ITSM $ITSM, int $idIncidenceType): array + { + $result = $ITSM->callApi( + 'incidenceTypeFields', + [ + 'page' => 0, + 'sizePage' => 0, + ], + [], + $idIncidenceType + ); + + return $result; + } + + /** * Draw list dashboards. * @@ -332,8 +406,6 @@ class Manager */ private function showDashboard() { - global $config; - View::render( 'ITSM/ITSMDashboardView', [ @@ -467,4 +539,48 @@ class Manager } + /** + * Get Input fields of type incidence. + * + * @return void + */ + public function getInputFieldsIncidenceType() + { + $idIncidenceType = (int) get_parameter('idIncidenceType', true); + $fieldsData = json_decode(io_safe_output(get_parameter('fieldsData', [])), true); + if (empty($fieldsData) === false) { + $fieldsData = array_reduce( + $fieldsData, + function ($carry, $user) { + $carry[$user['idIncidenceField']] = $user['data']; + return $carry; + } + ); + } else { + $fieldsData = []; + } + + $error = ''; + try { + $ITSM = new ITSM(); + $result = $this->getFieldsIncidenceType($ITSM, $idIncidenceType); + $customFields = $result['data']; + } catch (Throwable $e) { + $error = $e->getMessage(); + } + + View::render( + 'ITSM/ITSMCustomFields', + [ + 'ajaxController' => $this->ajaxController, + 'urlAjax' => \ui_get_full_url('ajax.php'), + 'customFields' => $customFields, + 'fieldsData' => $fieldsData, + 'error' => $error, + ] + ); + exit; + } + + } diff --git a/pandora_console/include/styles/integriaims.css b/pandora_console/include/styles/integriaims.css index bca6df5038..e55c992bbe 100644 --- a/pandora_console/include/styles/integriaims.css +++ b/pandora_console/include/styles/integriaims.css @@ -123,3 +123,23 @@ div.integria_details_description textarea { .comment_body { padding: 15px 20px 15px 20px; } + +/*---*/ +div.incidence-type-custom-fields { + display: flex; + flex-direction: row; + justify-content: center; + align-items: baseline; + flex-wrap: wrap; +} + +.incidence-type-custom-fields > div { + flex: 1 1 45%; + display: flex; + margin: 0px 20px; + flex-direction: column; +} + +.incidence-type-custom-fields > div.incidence-type-custom-fields-textarea { + flex: 1 1 100%; +} diff --git a/pandora_console/views/ITSM/ITSMCustomFields.php b/pandora_console/views/ITSM/ITSMCustomFields.php new file mode 100644 index 0000000000..6837ff43f4 --- /dev/null +++ b/pandora_console/views/ITSM/ITSMCustomFields.php @@ -0,0 +1,101 @@ + true, + 'message' => __('Incidence type not fields'), + ] + ); +} else { + $output = '
'; + foreach ($customFields as $field) { + $options = [ + 'name' => 'custom-fields['.$field['idIncidenceTypeField'].']', + 'required' => $field['isRequired'], + 'return' => true, + 'value' => ($fieldsData[$field['idIncidenceTypeField']] ?? null), + ]; + + $class = ''; + + switch ($field['type']) { + case 'COMBO': + $options['type'] = 'select'; + $options['fields'] = explode(',', $field['comboValue']); + break; + + case 'TEXT': + $options['type'] = 'text'; + break; + + case 'CHECKBOX': + $options['type'] = 'checkbox'; + break; + + case 'DATE': + $options['type'] = 'text'; + break; + + case 'NUMERIC': + $options['type'] = 'number'; + break; + + case 'TEXTAREA': + $options['type'] = 'textarea'; + $options['rows'] = 4; + $options['columns'] = 0; + $class = 'incidence-type-custom-fields-textarea'; + break; + + default: + // Not posible. + break; + } + + $output .= html_print_label_input_block( + $field['label'], + html_print_input($options), + ['div_class' => $class] + ); + } + + $output .= '
'; + + echo $output; +} diff --git a/pandora_console/views/ITSM/ITSMTicketEditView.php b/pandora_console/views/ITSM/ITSMTicketEditView.php index b1f0330fe6..7ebfaa69ad 100644 --- a/pandora_console/views/ITSM/ITSMTicketEditView.php +++ b/pandora_console/views/ITSM/ITSMTicketEditView.php @@ -69,12 +69,10 @@ $table = new stdClass(); $table->width = '100%'; $table->id = 'edit-ticket-itms'; $table->class = 'databox filter-table-adv'; -$table->head = []; $table->data = []; -$table->size = []; -$table->size = []; $table->colspan[0][0] = 2; -$table->colspan[4][0] = 3; +$table->colspan[2][0] = 3; +$table->colspan[5][0] = 3; $table->colspan[6][0] = 3; $table->data[0][0] = html_print_label_input_block( @@ -158,7 +156,9 @@ $table->data[1][2] = html_print_label_input_block( ) ); -$table->data[2][0] = html_print_label_input_block( +$table->data[2][0] = '
WIP...
'; + +$table->data[3][0] = html_print_label_input_block( __('Status'), html_print_select( $status, @@ -176,7 +176,7 @@ $table->data[2][0] = html_print_label_input_block( ) ); -$table->data[2][1] = html_print_label_input_block( +$table->data[3][1] = html_print_label_input_block( __('Creator').ui_print_help_tip(__('This field corresponds to the Integria IMS user specified in Integria IMS setup'), true), html_print_input_text( 'idCreator', @@ -192,7 +192,7 @@ $table->data[2][1] = html_print_label_input_block( ) ); -$table->data[2][2] = html_print_label_input_block( +$table->data[3][2] = html_print_label_input_block( __('Owner').ui_print_help_tip(__('Type at least two characters to search the user.'), true), html_print_autocomplete_users_from_integria( 'owner', @@ -205,7 +205,7 @@ $table->data[2][2] = html_print_label_input_block( ) ); -$table->data[3][0] = '