diff --git a/app/controllers/ui_ansible_roles_controller.rb b/app/controllers/ui_ansible_roles_controller.rb
index 364bedc97..78bb4aaff 100644
--- a/app/controllers/ui_ansible_roles_controller.rb
+++ b/app/controllers/ui_ansible_roles_controller.rb
@@ -1,4 +1,7 @@
class UiAnsibleRolesController < ::Api::V2::BaseController
+
+ before_action :find_resource, :only => [:destroy]
+
def resource_name(resource = 'AnsibleRole')
super resource
end
@@ -7,6 +10,12 @@ def index
@ui_ansible_roles = resource_scope_for_index(:permission => :view_ansible_roles)
end
+ api :DELETE, '/ui_ansible_roles/:id', N_('Deletes Ansible role')
+ param :id, :identifier, :required => true
+ def destroy
+ AnsibleRole.find_by(id: params[:id]).destroy
+ end
+
# restore original method from find_common to ignore resource nesting
def resource_scope(**kwargs)
@resource_scope ||= scope_for(resource_class, **kwargs)
diff --git a/app/views/ansible_roles/index.html.erb b/app/views/ansible_roles/index.html.erb
index def0fd832..35dcda643 100644
--- a/app/views/ansible_roles/index.html.erb
+++ b/app/views/ansible_roles/index.html.erb
@@ -1,47 +1,9 @@
+<%= webpacked_plugins_js_for :foreman_ansible %>
+<%= webpacked_plugins_css_for :foreman_ansible %>
+
<% title _("Ansible Roles") %>
<% title_actions ansible_proxy_import(hash_for_import_ansible_roles_path),
documentation_button('#4.1ImportingRoles', :root_url => ansible_doc_url) %>
-
-
-
- <%= sort :name, :as => s_("Role|Name") %> |
- <%= _("Hostgroups") %> |
- <%= _("Hosts") %> |
- <%= _("Variables") %> |
- <%= sort :updated_at, :as => _("Imported at") %> |
- <%= _("Actions") %> |
-
-
-
- <% @ansible_roles.each do |role| %>
-
- <%= role.name %> |
- <%= link_to role.hostgroups.count, hostgroups_path(:search => "ansible_role = #{role.name}") %> |
- <%= link_to role.hosts.count, hosts_path(:search => "ansible_role = #{role.name}")%> |
- <%= link_to(role.ansible_variables.count, ansible_variables_path(:search => "ansible_role = #{role}")) %> |
- <%= import_time role %> |
-
- <%
- links = [
- link_to(
- _('Variables'),
- ansible_variables_path(:search => "ansible_role = #{role}")
- ),
- display_delete_if_authorized(
- hash_for_ansible_role_path(:id => role).
- merge(:auth_object => role, :authorizer => authorizer),
- :data => { :confirm => _("Delete %s?") % role.name },
- :action => :delete
- )
- ]
- %>
- <%= action_buttons(*links) %>
- |
-
- <% end %>
-
-
-
<%= will_paginate_with_info @ansible_roles %>
diff --git a/app/views/ui_ansible_roles/show.json.rabl b/app/views/ui_ansible_roles/show.json.rabl
index a90699275..441681175 100644
--- a/app/views/ui_ansible_roles/show.json.rabl
+++ b/app/views/ui_ansible_roles/show.json.rabl
@@ -1,3 +1,18 @@
object @ansible_role
-extends "api/v2/ansible_roles/show"
+attributes :id, :name
+code :hostgroupsCount do |role|
+ role.hostgroups.count
+end
+code :hostsCount do |role|
+ role.hosts.count
+end
+code :variablesCount do |role|
+ role.ansible_variables.count
+end
+code :importTime do |role|
+ import_time(role)
+end
+code :can_delete do |role|
+ authorized_for(:controller => UiAnsibleRolesController, :action => :destroy)
+end
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index 1a0431e4f..82a75d00e 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -60,7 +60,7 @@
end
end
- resources :ui_ansible_roles, :only => [:index]
+ resources :ui_ansible_roles, :only => [:index, :destroy]
resources :ansible_variables, :except => [:show] do
resources :lookup_values, :only => [:index, :create, :update, :destroy]
@@ -117,4 +117,5 @@
match '/ansible/hostgroups' => 'react#index', :via => [:get]
match '/ansible/hostgroups/*page' => 'react#index', :via => [:get]
+ match '/ansible/ansible_roles' => 'react#index', :via => [:get]
end
diff --git a/webpack/components/AnsibleRoles/AnsibleRolesPage.js b/webpack/components/AnsibleRoles/AnsibleRolesPage.js
new file mode 100644
index 000000000..93a634de1
--- /dev/null
+++ b/webpack/components/AnsibleRoles/AnsibleRolesPage.js
@@ -0,0 +1,34 @@
+import React from 'react';
+import TableIndexPage from 'foremanReact/components/PF4/TableIndexPage/TableIndexPage';
+import { translate as __ } from 'foremanReact/common/I18n';
+import { getDocsURL } from 'foremanReact/common/helpers';
+import { AnsibleRolesImportButton } from './components/AnsibleRolesImportButton';
+import { getActions } from '../AnsibleRoles/AnsibleRolesPageHelpers';
+
+export const AnsibleRolesPage = () => (
+ Primary
+ }
+ customHelpURL={getDocsURL(
+ 'Managing_Configurations_Ansible',
+ 'Importing_Ansible_Roles_and_Variables_ansible'
+ )}
+ rowKebabItems={getActions}
+ columns={{
+ importTime: { title: __('Imported at'), isSorted: true },
+ variablesCount: { title: __('Variables') },
+ hostsCount: { title: __('Hosts') },
+ hostgroupsCount: { title: __('Hostgroups') },
+ name: { title: __('Name'), isSorted: true },
+ }}
+ />
+);
diff --git a/webpack/components/AnsibleRoles/AnsibleRolesPageHelpers.js b/webpack/components/AnsibleRoles/AnsibleRolesPageHelpers.js
new file mode 100644
index 000000000..b8a263816
--- /dev/null
+++ b/webpack/components/AnsibleRoles/AnsibleRolesPageHelpers.js
@@ -0,0 +1,38 @@
+import React from 'react';
+import { translate as __ } from 'foremanReact/common/I18n';
+
+export const getActions = ({ id, name, canDelete, ...item }) => [
+ {
+ title: (
+
+ {__('View Hostgroups')}
+
+ ),
+ isDisabled: false,
+ },
+ {
+ title: (
+
+ {__('View Hosts')}
+
+ ),
+ isDisabled: false,
+ },
+ {
+ title: (
+
+ {__('View Variables')}
+
+ ),
+ isDisabled: false,
+ },
+];
+
+const hostgroupsUrl = roleName => `/hostgroups${searchString(roleName)}`;
+const hostsUrl = roleName => `/hosts${searchString(roleName)}`;
+const variablesUrl = roleName => `ansible_variables${searchString(roleName)}`;
+const searchString = roleName =>
+ `?search=${encodeURIComponent(`ansible_role = ${roleName}`)}`;
+
+export const importUrl = (proxyName, proxyId) =>
+ `ansible_roles/import?proxy=${encodeURIComponent(`${proxyId}-${proxyName}`)}`;
diff --git a/webpack/components/AnsibleRoles/components/AnsibleRolesImportButton.js b/webpack/components/AnsibleRoles/components/AnsibleRolesImportButton.js
new file mode 100644
index 000000000..ca77c79d8
--- /dev/null
+++ b/webpack/components/AnsibleRoles/components/AnsibleRolesImportButton.js
@@ -0,0 +1,68 @@
+import React from 'react';
+import { Dropdown, DropdownToggle, DropdownItem } from '@patternfly/react-core';
+import { translate as __ } from 'foremanReact/common/I18n';
+import { useAPI } from 'foremanReact/common/hooks/API/APIHooks';
+import { importUrl } from '../AnsibleRolesPageHelpers';
+
+export const AnsibleRolesImportButton = () => {
+ let dropdownItems;
+
+ const {
+ response: { results },
+ status,
+ } = useAPI('get', '/api/v2/smart_proxies');
+
+ const [isOpen, setIsOpen] = React.useState(false);
+ const onToggle = isToggleOpen => {
+ setIsOpen(isToggleOpen);
+ };
+ const onFocus = () => {
+ const element = document.getElementById('toggle-primary');
+ element.focus();
+ };
+ const onSelect = () => {
+ setIsOpen(false);
+ onFocus();
+ };
+
+ if (status !== 'RESOLVED') {
+ dropdownItems = [
+ {__('Loading...')},
+ ];
+ } else {
+ dropdownItems = results
+ .filter(result =>
+ result.features.some(feature =>
+ feature.capabilities.includes('ansible')
+ )
+ )
+ .map(proxy => (
+
+ {proxy.name}
+
+ ));
+ if (dropdownItems.length === 0) {
+ dropdownItems = [
+
+ {__('No Smart Proxies found')}
+ ,
+ ];
+ }
+ }
+ return (
+
+ {__('Import from')}
+
+ }
+ isOpen={isOpen}
+ dropdownItems={dropdownItems}
+ />
+ );
+};
diff --git a/webpack/routes/AnsibleRoles/index.js b/webpack/routes/AnsibleRoles/index.js
new file mode 100644
index 000000000..0b090504a
--- /dev/null
+++ b/webpack/routes/AnsibleRoles/index.js
@@ -0,0 +1,16 @@
+import React from 'react';
+import { Helmet } from 'react-helmet';
+import { translate as __ } from 'foremanReact/common/I18n';
+
+import { AnsibleRolesPage } from '../../components/AnsibleRoles/AnsibleRolesPage';
+
+const AnsibleRoles = () => (
+
+
+ {__('Ansible Roles')}
+
+
+
+);
+
+export default AnsibleRoles;
diff --git a/webpack/routes/routes.js b/webpack/routes/routes.js
index 6e996c06a..933734a60 100644
--- a/webpack/routes/routes.js
+++ b/webpack/routes/routes.js
@@ -1,5 +1,6 @@
import React from 'react';
import HostgroupJobs from './HostgroupJobs';
+import AnsibleRoles from './AnsibleRoles';
export default [
{
@@ -7,4 +8,9 @@ export default [
render: props => ,
exact: true,
},
+ {
+ path: '/ansible/ansible_roles',
+ render: props => ,
+ exact: true,
+ },
];