diff --git a/app/docker/components/datatables/tasks-datatable/tasksDatatable.html b/app/docker/components/datatables/tasks-datatable/tasksDatatable.html deleted file mode 100644 index fed57be91..000000000 --- a/app/docker/components/datatables/tasks-datatable/tasksDatatable.html +++ /dev/null @@ -1,133 +0,0 @@ -
- - -
-
-
- -
- {{ $ctrl.titleText }} -
- -
-
- - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - - - Actions - - - - - -
{{ item.Status.State }} - {{ item.ServiceName }}{{ item.Slot ? '.' + item.Slot : '' }}{{ '.' + item.Id }} - {{ item.ServiceName }}{{ item.Slot ? '.' + item.Slot : '' }}{{ '.' + item.Id }} - - - - {{ item.Slot ? item.Slot : '-' }}{{ item.NodeId | tasknodename: $ctrl.nodes }}{{ item.Updated | getisodate }}
Loading...
No task available.
-
- -
-
-
diff --git a/app/docker/components/datatables/tasks-datatable/tasksDatatable.js b/app/docker/components/datatables/tasks-datatable/tasksDatatable.js deleted file mode 100644 index 4bdbda8c6..000000000 --- a/app/docker/components/datatables/tasks-datatable/tasksDatatable.js +++ /dev/null @@ -1,16 +0,0 @@ -angular.module('portainer.docker').component('tasksDatatable', { - templateUrl: './tasksDatatable.html', - controller: 'TasksDatatableController', - bindings: { - titleText: '@', - titleIcon: '@', - dataset: '<', - tableKey: '@', - orderBy: '@', - reverseOrder: '<', - nodes: '<', - showSlotColumn: '<', - showLogsButton: '<', - agentProxy: '<', - }, -}); diff --git a/app/docker/components/datatables/tasks-datatable/tasksDatatableController.js b/app/docker/components/datatables/tasks-datatable/tasksDatatableController.js deleted file mode 100644 index 38c3098f9..000000000 --- a/app/docker/components/datatables/tasks-datatable/tasksDatatableController.js +++ /dev/null @@ -1,49 +0,0 @@ -angular.module('portainer.docker').controller('TasksDatatableController', [ - '$scope', - '$controller', - 'DatatableService', - function ($scope, $controller, DatatableService) { - angular.extend(this, $controller('GenericDatatableController', { $scope: $scope })); - - this.state = Object.assign(this.state, { - showQuickActionStats: true, - showQuickActionLogs: true, - showQuickActionExec: true, - showQuickActionInspect: true, - showQuickActionAttach: false, - }); - - this.$onInit = function () { - this.setDefaults(); - this.prepareTableFromDataset(); - - this.state.orderBy = this.orderBy; - var storedOrder = DatatableService.getDataTableOrder(this.tableKey); - if (storedOrder !== null) { - this.state.reverseOrder = storedOrder.reverse; - this.state.orderBy = storedOrder.orderBy; - } - - var textFilter = DatatableService.getDataTableTextFilters(this.tableKey); - if (textFilter !== null) { - this.state.textFilter = textFilter; - this.onTextFilterChange(); - } - - var storedFilters = DatatableService.getDataTableFilters(this.tableKey); - if (storedFilters !== null) { - this.filters = storedFilters; - } - if (this.filters && this.filters.state) { - this.filters.state.open = false; - } - - var storedSettings = DatatableService.getDataTableSettings(this.tableKey); - if (storedSettings !== null) { - this.settings = storedSettings; - this.settings.open = false; - } - this.onSettingsRepeaterChange(); - }; - }, -]); diff --git a/app/docker/react/components/index.ts b/app/docker/react/components/index.ts index a76d7e2a8..34e2a4d25 100644 --- a/app/docker/react/components/index.ts +++ b/app/docker/react/components/index.ts @@ -3,7 +3,6 @@ import angular from 'angular'; import { r2a } from '@/react-tools/react2angular'; import { withControlledInput } from '@/react-tools/withControlledInput'; import { StackContainersDatatable } from '@/react/common/stacks/ItemView/StackContainersDatatable'; -import { ContainerQuickActions } from '@/react/docker/containers/components/ContainerQuickActions'; import { TemplateListDropdownAngular } from '@/react/docker/app-templates/TemplateListDropdown'; import { TemplateListSortAngular } from '@/react/docker/app-templates/TemplateListSort'; import { withCurrentUser } from '@/react-tools/withCurrentUser'; @@ -40,15 +39,6 @@ const ngModule = angular ]) .component('dockerfileDetails', r2a(DockerfileDetails, ['image'])) .component('dockerHealthStatus', r2a(HealthStatus, ['health'])) - .component( - 'containerQuickActions', - r2a(withUIRouter(withCurrentUser(ContainerQuickActions)), [ - 'containerId', - 'nodeName', - 'state', - 'status', - ]) - ) .component('templateListDropdown', TemplateListDropdownAngular) .component('templateListSort', TemplateListSortAngular) .component( diff --git a/app/docker/react/components/services.ts b/app/docker/react/components/services.ts index 046095038..ebac9b128 100644 --- a/app/docker/react/components/services.ts +++ b/app/docker/react/components/services.ts @@ -2,22 +2,18 @@ import angular from 'angular'; import { r2a } from '@/react-tools/react2angular'; import { withUIRouter } from '@/react-tools/withUIRouter'; -import { TasksDatatable } from '@/react/docker/services/ListView/ServicesDatatable/TasksDatatable'; import { withCurrentUser } from '@/react-tools/withCurrentUser'; -import { TaskTableQuickActions } from '@/react/docker/services/common/TaskTableQuickActions'; import { ServicesDatatable } from '@/react/docker/services/ListView/ServicesDatatable'; +import { TasksDatatable } from '@/react/docker/services/ItemView/TasksDatatable'; export const servicesModule = angular .module('portainer.docker.react.components.services', []) .component( 'dockerServiceTasksDatatable', - r2a(withUIRouter(withCurrentUser(TasksDatatable)), ['dataset', 'search']) - ) - .component( - 'dockerTaskTableQuickActions', - r2a(withUIRouter(withCurrentUser(TaskTableQuickActions)), [ - 'state', - 'taskId', + r2a(withUIRouter(withCurrentUser(TasksDatatable)), [ + 'serviceName', + 'dataset', + 'isSlotColumnVisible', ]) ) .component( diff --git a/app/docker/views/services/edit/includes/tasks.html b/app/docker/views/services/edit/includes/tasks.html index 18d5ab105..8a64277d4 100644 --- a/app/docker/views/services/edit/includes/tasks.html +++ b/app/docker/views/services/edit/includes/tasks.html @@ -1,14 +1,6 @@ -
- -
+ diff --git a/app/docker/views/services/edit/service.html b/app/docker/views/services/edit/service.html index dc341ca70..712c9da19 100644 --- a/app/docker/views/services/edit/service.html +++ b/app/docker/views/services/edit/service.html @@ -253,6 +253,7 @@
-
+ +
diff --git a/app/react/docker/services/ItemView/.keep b/app/react/docker/services/ItemView/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/app/react/docker/services/ItemView/TasksDatatable/TasksDatatable.tsx b/app/react/docker/services/ItemView/TasksDatatable/TasksDatatable.tsx new file mode 100644 index 000000000..f2c0334f0 --- /dev/null +++ b/app/react/docker/services/ItemView/TasksDatatable/TasksDatatable.tsx @@ -0,0 +1,37 @@ +import { List } from 'lucide-react'; + +import { Datatable } from '@@/datatables'; +import { createPersistedStore } from '@@/datatables/types'; +import { useTableState } from '@@/datatables/useTableState'; +import { withMeta } from '@@/datatables/extend-options/withMeta'; + +import { useColumns } from './columns'; +import { DecoratedTask } from './types'; + +const storageKey = 'docker-service-tasks'; +const store = createPersistedStore(storageKey); + +export function TasksDatatable({ + dataset, + isSlotColumnVisible, + serviceName, +}: { + dataset: DecoratedTask[]; + isSlotColumnVisible: boolean; + serviceName: string; +}) { + const tableState = useTableState(store, storageKey); + const columns = useColumns(isSlotColumnVisible); + + return ( + + ); +} diff --git a/app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/columns/actions.tsx b/app/react/docker/services/ItemView/TasksDatatable/columns/actions.tsx similarity index 97% rename from app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/columns/actions.tsx rename to app/react/docker/services/ItemView/TasksDatatable/columns/actions.tsx index fe672dc74..1f153c5f2 100644 --- a/app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/columns/actions.tsx +++ b/app/react/docker/services/ItemView/TasksDatatable/columns/actions.tsx @@ -24,7 +24,7 @@ function Cell({ return null; } const state: QuickActionsState = { - showQuickActionAttach: true, + showQuickActionAttach: false, showQuickActionExec: true, showQuickActionInspect: true, showQuickActionLogs: true, diff --git a/app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/columns/helper.ts b/app/react/docker/services/ItemView/TasksDatatable/columns/helper.ts similarity index 100% rename from app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/columns/helper.ts rename to app/react/docker/services/ItemView/TasksDatatable/columns/helper.ts diff --git a/app/react/docker/services/ItemView/TasksDatatable/columns/index.ts b/app/react/docker/services/ItemView/TasksDatatable/columns/index.ts new file mode 100644 index 000000000..cf6b1f5e3 --- /dev/null +++ b/app/react/docker/services/ItemView/TasksDatatable/columns/index.ts @@ -0,0 +1,24 @@ +import { useMemo } from 'react'; +import _ from 'lodash'; + +import { actions } from './actions'; +import { node } from './node'; +import { slot } from './slot'; +import { status } from './status'; +import { task } from './task'; +import { updated } from './updated'; + +export function useColumns(isSlotColumnsVisible = true) { + return useMemo( + () => + _.compact([ + status, + task, + actions, + isSlotColumnsVisible && slot, + node, + updated, + ]), + [isSlotColumnsVisible] + ); +} diff --git a/app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/columns/node.tsx b/app/react/docker/services/ItemView/TasksDatatable/columns/node.tsx similarity index 100% rename from app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/columns/node.tsx rename to app/react/docker/services/ItemView/TasksDatatable/columns/node.tsx diff --git a/app/react/docker/services/ItemView/TasksDatatable/columns/slot.tsx b/app/react/docker/services/ItemView/TasksDatatable/columns/slot.tsx new file mode 100644 index 000000000..dd0916475 --- /dev/null +++ b/app/react/docker/services/ItemView/TasksDatatable/columns/slot.tsx @@ -0,0 +1,5 @@ +import { columnHelper } from './helper'; + +export const slot = columnHelper.accessor((item) => item.Slot || '-', { + header: 'Slot', +}); diff --git a/app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/columns/status.tsx b/app/react/docker/services/ItemView/TasksDatatable/columns/status.tsx similarity index 100% rename from app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/columns/status.tsx rename to app/react/docker/services/ItemView/TasksDatatable/columns/status.tsx diff --git a/app/react/docker/services/ItemView/TasksDatatable/columns/task.tsx b/app/react/docker/services/ItemView/TasksDatatable/columns/task.tsx new file mode 100644 index 000000000..5defb3116 --- /dev/null +++ b/app/react/docker/services/ItemView/TasksDatatable/columns/task.tsx @@ -0,0 +1,51 @@ +import { CellContext } from '@tanstack/react-table'; + +import { useCurrentEnvironment } from '@/react/hooks/useCurrentEnvironment'; +import { isAgentEnvironment } from '@/react/portainer/environments/utils'; + +import { Link } from '@@/Link'; + +import { DecoratedTask } from '../types'; +import { getTableMeta } from '../meta'; + +import { columnHelper } from './helper'; + +export const task = columnHelper.accessor('Id', { + header: 'Id', + cell: Cell, +}); + +function Cell({ + getValue, + row: { original: item }, + table: { + options: { meta }, + }, +}: CellContext) { + const environmentQuery = useCurrentEnvironment(); + + if (!environmentQuery.data) { + return null; + } + + const { serviceName } = getTableMeta(meta); + + const value = getValue(); + const isAgent = isAgentEnvironment(environmentQuery.data.Type); + + const name = `${serviceName}${item.Slot ? `.${item.Slot}` : ''}.${value}`; + + return isAgent && item.Container ? ( + + {name} + + ) : ( + + {name} + + ); +} diff --git a/app/react/docker/services/ItemView/TasksDatatable/columns/updated.tsx b/app/react/docker/services/ItemView/TasksDatatable/columns/updated.tsx new file mode 100644 index 000000000..026efc658 --- /dev/null +++ b/app/react/docker/services/ItemView/TasksDatatable/columns/updated.tsx @@ -0,0 +1,8 @@ +import { isoDate } from '@/portainer/filters/filters'; + +import { columnHelper } from './helper'; + +export const updated = columnHelper.accessor('Updated', { + header: 'Last Update', + cell: ({ getValue }) => isoDate(getValue()), +}); diff --git a/app/react/docker/services/ItemView/TasksDatatable/index.ts b/app/react/docker/services/ItemView/TasksDatatable/index.ts new file mode 100644 index 000000000..f95acf3ac --- /dev/null +++ b/app/react/docker/services/ItemView/TasksDatatable/index.ts @@ -0,0 +1 @@ +export { TasksDatatable } from './TasksDatatable'; diff --git a/app/react/docker/services/ItemView/TasksDatatable/meta.ts b/app/react/docker/services/ItemView/TasksDatatable/meta.ts new file mode 100644 index 000000000..08ac07861 --- /dev/null +++ b/app/react/docker/services/ItemView/TasksDatatable/meta.ts @@ -0,0 +1,17 @@ +type TableMeta = { + serviceName: string; + table: 'tasks'; +}; + +export function getTableMeta(meta: unknown): TableMeta { + return isTableMeta(meta) ? meta : { table: 'tasks', serviceName: '' }; +} + +function isTableMeta(meta: unknown): meta is TableMeta { + return ( + !!meta && + typeof meta === 'object' && + 'table' in meta && + meta.table === 'tasks' + ); +} diff --git a/app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/types.ts b/app/react/docker/services/ItemView/TasksDatatable/types.ts similarity index 100% rename from app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/types.ts rename to app/react/docker/services/ItemView/TasksDatatable/types.ts diff --git a/app/react/docker/services/ListView/ServicesDatatable/ServicesDatatable.tsx b/app/react/docker/services/ListView/ServicesDatatable/ServicesDatatable.tsx index 843b70292..776397533 100644 --- a/app/react/docker/services/ListView/ServicesDatatable/ServicesDatatable.tsx +++ b/app/react/docker/services/ListView/ServicesDatatable/ServicesDatatable.tsx @@ -19,6 +19,8 @@ import { getColumnVisibilityState } from '@@/datatables/ColumnVisibilityMenu'; import { mergeOptions } from '@@/datatables/extend-options/mergeOptions'; import { withGlobalFilter } from '@@/datatables/extend-options/withGlobalFilter'; +import { DecoratedTask } from '../../ItemView/TasksDatatable/types'; + import { useColumns } from './columns'; import { TasksDatatable } from './TasksDatatable'; import { TableActions } from './TableActions'; @@ -72,7 +74,10 @@ export function ServicesDatatable({ - + } + search={tableState.search} + /> )} diff --git a/app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/TasksDatatable.tsx b/app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/TasksDatatable.tsx index 8f1e906fd..ce264eba2 100644 --- a/app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/TasksDatatable.tsx +++ b/app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/TasksDatatable.tsx @@ -1,7 +1,15 @@ +import { DecoratedTask } from '@/react/docker/services/ItemView/TasksDatatable/types'; +import { status } from '@/react/docker/services/ItemView/TasksDatatable/columns/status'; +import { actions } from '@/react/docker/services/ItemView/TasksDatatable/columns/actions'; +import { slot } from '@/react/docker/services/ItemView/TasksDatatable/columns/slot'; +import { node } from '@/react/docker/services/ItemView/TasksDatatable/columns/node'; +import { updated } from '@/react/docker/services/ItemView/TasksDatatable/columns/updated'; + import { NestedDatatable } from '@@/datatables/NestedDatatable'; -import { columns } from './columns'; -import { DecoratedTask } from './types'; +import { task } from './task-column'; + +const columns = [status, task, actions, slot, node, updated]; export function TasksDatatable({ dataset, diff --git a/app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/columns/index.ts b/app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/columns/index.ts deleted file mode 100644 index aaca2fa3f..000000000 --- a/app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/columns/index.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { isoDate } from '@/portainer/filters/filters'; - -import { actions } from './actions'; -import { columnHelper } from './helper'; -import { node } from './node'; -import { status } from './status'; -import { task } from './task'; - -export const columns = [ - status, - task, - actions, - columnHelper.accessor((item) => item.Slot || '-', { header: 'Slot' }), - node, - columnHelper.accessor('Updated', { - header: 'Last Update', - cell: ({ getValue }) => isoDate(getValue()), - }), -]; diff --git a/app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/columns/task.tsx b/app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/task-column.tsx similarity index 84% rename from app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/columns/task.tsx rename to app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/task-column.tsx index 1a94f5947..8a3db86d7 100644 --- a/app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/columns/task.tsx +++ b/app/react/docker/services/ListView/ServicesDatatable/TasksDatatable/task-column.tsx @@ -2,13 +2,11 @@ import { CellContext } from '@tanstack/react-table'; import { useCurrentEnvironment } from '@/react/hooks/useCurrentEnvironment'; import { isAgentEnvironment } from '@/react/portainer/environments/utils'; +import { DecoratedTask } from '@/react/docker/services/ItemView/TasksDatatable/types'; +import { columnHelper } from '@/react/docker/services/ItemView/TasksDatatable/columns/helper'; import { Link } from '@@/Link'; -import { DecoratedTask } from '../types'; - -import { columnHelper } from './helper'; - export const task = columnHelper.accessor('Id', { header: 'Task', cell: Cell,