mirror of https://github.com/portainer/portainer
refactor(docker/containers): migrate inspect view to react [EE-2190] (#11005)
parent
de473fc10e
commit
2100155ab5
@ -1,27 +0,0 @@
|
||||
angular.module('portainer.docker').controller('ContainerInspectController', [
|
||||
'$scope',
|
||||
'$transition$',
|
||||
'Notifications',
|
||||
'ContainerService',
|
||||
'HttpRequestHelper',
|
||||
'endpoint',
|
||||
function ($scope, $transition$, Notifications, ContainerService, HttpRequestHelper, endpoint) {
|
||||
$scope.state = {
|
||||
DisplayTextView: false,
|
||||
};
|
||||
$scope.containerInfo = {};
|
||||
|
||||
function initView() {
|
||||
HttpRequestHelper.setPortainerAgentTargetHeader($transition$.params().nodeName);
|
||||
ContainerService.inspect(endpoint.Id, $transition$.params().id)
|
||||
.then(function success(d) {
|
||||
$scope.containerInfo = d;
|
||||
})
|
||||
.catch(function error(e) {
|
||||
Notifications.error('Failure', e, 'Unable to inspect container');
|
||||
});
|
||||
}
|
||||
|
||||
initView();
|
||||
},
|
||||
]);
|
@ -1,28 +0,0 @@
|
||||
<page-header
|
||||
title="'Container inspect'"
|
||||
breadcrumbs="[
|
||||
{ label:'Containers', link:'docker.containers' },
|
||||
{
|
||||
label:(containerInfo.Name | trimcontainername),
|
||||
link: 'docker.containers.container',
|
||||
linkParams: { id: containerInfo.Id },
|
||||
}, 'Inspect']"
|
||||
>
|
||||
</page-header>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-lg-12 col-md-12 col-xs-12">
|
||||
<rd-widget>
|
||||
<rd-widget-header icon="circle" title-text="Inspect">
|
||||
<span class="btn-group btn-group-sm">
|
||||
<label class="btn btn-light" ng-model="state.DisplayTextView" uib-btn-radio="false"><pr-icon icon="'code'"></pr-icon>Tree</label>
|
||||
<label class="btn btn-light" ng-model="state.DisplayTextView" uib-btn-radio="true"><pr-icon icon="'file'"></pr-icon>Text</label>
|
||||
</span>
|
||||
</rd-widget-header>
|
||||
<rd-widget-body>
|
||||
<pre ng-show="state.DisplayTextView">{{ containerInfo | json: 4 }}</pre>
|
||||
<json-tree ng-hide="state.DisplayTextView" object="containerInfo" root-name="containerInfo.Id" start-expanded="true"></json-tree>
|
||||
</rd-widget-body>
|
||||
</rd-widget>
|
||||
</div>
|
||||
</div>
|
@ -1,30 +1,25 @@
|
||||
/* json-tree override */
|
||||
.json-tree,
|
||||
json-tree {
|
||||
.json-tree {
|
||||
font-size: 13px;
|
||||
color: var(--blue-5);
|
||||
}
|
||||
|
||||
.json-tree .key,
|
||||
json-tree .key {
|
||||
.json-tree .key {
|
||||
color: var(--text-json-tree-color);
|
||||
padding-right: 4px;
|
||||
}
|
||||
|
||||
json-tree .key {
|
||||
padding-right: 5px;
|
||||
.json-tree .chevronIcon {
|
||||
color: var(--text-json-tree-color);
|
||||
}
|
||||
|
||||
.json-tree .branch-preview,
|
||||
json-tree .branch-preview {
|
||||
.json-tree .branch-preview {
|
||||
color: var(--text-json-tree-branch-preview-color);
|
||||
font-style: normal;
|
||||
font-size: 11px;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.json-tree .leaf-value,
|
||||
json-tree .leaf-value {
|
||||
.json-tree .leaf-value {
|
||||
color: var(--text-json-tree-leaf-color);
|
||||
}
|
||||
|
||||
/* !json-tree override */
|
@ -0,0 +1,79 @@
|
||||
import { useCurrentStateAndParams } from '@uirouter/react';
|
||||
import { Circle, Code as CodeIcon, File } from 'lucide-react';
|
||||
import { useState } from 'react';
|
||||
|
||||
import { trimContainerName } from '@/docker/filters/utils';
|
||||
import { useEnvironmentId } from '@/react/hooks/useEnvironmentId';
|
||||
|
||||
import { JsonTree } from '@@/JsonTree';
|
||||
import { PageHeader } from '@@/PageHeader';
|
||||
import { Widget } from '@@/Widget';
|
||||
import { ButtonSelector } from '@@/form-components/ButtonSelector/ButtonSelector';
|
||||
import { Code } from '@@/Code';
|
||||
|
||||
import { useContainerInspect } from '../queries/useContainerInspect';
|
||||
|
||||
export function InspectView() {
|
||||
const environmentId = useEnvironmentId();
|
||||
const {
|
||||
params: { id, nodeName },
|
||||
} = useCurrentStateAndParams();
|
||||
const inspectQuery = useContainerInspect(environmentId, id, { nodeName });
|
||||
const [viewType, setViewType] = useState<'tree' | 'text'>('tree');
|
||||
|
||||
if (!inspectQuery.data) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const containerInfo = inspectQuery.data;
|
||||
|
||||
return (
|
||||
<>
|
||||
<PageHeader
|
||||
title="Container inspect"
|
||||
breadcrumbs={[
|
||||
{ label: 'Containers', link: 'docker.containers' },
|
||||
{
|
||||
label: trimContainerName(containerInfo.Name),
|
||||
link: '^',
|
||||
// linkParams: { id: containerInfo.Id },
|
||||
},
|
||||
'Inspect',
|
||||
]}
|
||||
/>
|
||||
|
||||
<div className="row">
|
||||
<div className="col-lg-12 col-md-12 col-xs-12">
|
||||
<Widget>
|
||||
<Widget.Title icon={Circle} title="Inspect">
|
||||
<ButtonSelector<'tree' | 'text'>
|
||||
onChange={(value) => setViewType(value)}
|
||||
value={viewType}
|
||||
options={[
|
||||
{
|
||||
label: 'Tree',
|
||||
icon: CodeIcon,
|
||||
value: 'tree',
|
||||
},
|
||||
{
|
||||
label: 'Text',
|
||||
icon: File,
|
||||
value: 'text',
|
||||
},
|
||||
]}
|
||||
/>
|
||||
</Widget.Title>
|
||||
<Widget.Body>
|
||||
{viewType === 'text' && (
|
||||
<Code showCopyButton>
|
||||
{JSON.stringify(containerInfo, undefined, 4)}
|
||||
</Code>
|
||||
)}
|
||||
{viewType === 'tree' && <JsonTree data={containerInfo} />}
|
||||
</Widget.Body>
|
||||
</Widget>
|
||||
</div>
|
||||
</div>
|
||||
</>
|
||||
);
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
import { useQuery } from 'react-query';
|
||||
|
||||
import { EnvironmentId } from '@/react/portainer/environments/types';
|
||||
import axios, { parseAxiosError } from '@/portainer/services/axios';
|
||||
import { genericHandler } from '@/docker/rest/response/handlers';
|
||||
|
||||
import { ContainerId } from '../types';
|
||||
import { urlBuilder } from '../containers.service';
|
||||
import { addNodeName } from '../../proxy/addNodeName';
|
||||
|
||||
import { queryKeys } from './query-keys';
|
||||
import { ContainerJSON } from './container';
|
||||
|
||||
export function useContainerInspect(
|
||||
environmentId: EnvironmentId,
|
||||
id: ContainerId,
|
||||
params: { nodeName?: string } = {}
|
||||
) {
|
||||
return useQuery({
|
||||
queryKey: [...queryKeys.container(environmentId, id), params] as const,
|
||||
queryFn: () => inspectContainer(environmentId, id, params),
|
||||
});
|
||||
}
|
||||
|
||||
export async function inspectContainer(
|
||||
environmentId: EnvironmentId,
|
||||
id: ContainerId,
|
||||
{ nodeName }: { nodeName?: string } = {}
|
||||
) {
|
||||
try {
|
||||
const { data } = await axios.get<ContainerJSON>(
|
||||
urlBuilder(environmentId, id, 'json'),
|
||||
{ transformResponse: genericHandler, headers: addNodeName(nodeName) }
|
||||
);
|
||||
return data;
|
||||
} catch (e) {
|
||||
throw parseAxiosError(e, 'Failed starting container');
|
||||
}
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
import { RawAxiosRequestHeaders } from 'axios';
|
||||
|
||||
const AgentTargetHeader = 'X-PortainerAgent-Target';
|
||||
|
||||
export function addNodeName(
|
||||
nodeName?: string,
|
||||
headers: RawAxiosRequestHeaders = {}
|
||||
) {
|
||||
if (!nodeName) {
|
||||
return headers;
|
||||
}
|
||||
|
||||
return {
|
||||
...headers,
|
||||
[AgentTargetHeader]: nodeName,
|
||||
};
|
||||
}
|
Loading…
Reference in new issue