Enhance package management UI with selection functionality and batch actions
This commit is contained in:
@@ -16,25 +16,27 @@ local page = UI.Page {
|
|||||||
x = 2, ex = 14, y = 2, ey = -6,
|
x = 2, ex = 14, y = 2, ey = -6,
|
||||||
values = { },
|
values = { },
|
||||||
columns = {
|
columns = {
|
||||||
{ heading = 'Package', key = 'name' },
|
{ heading = ' Package', key = 'displayName' },
|
||||||
},
|
},
|
||||||
sortColumn = 'name',
|
sortColumn = 'name',
|
||||||
autospace = true,
|
autospace = true,
|
||||||
help = 'Select a package',
|
help = 'Space to select, Enter to toggle',
|
||||||
},
|
},
|
||||||
add = UI.Button {
|
installSelected = UI.Button {
|
||||||
x = 2, y = -3,
|
x = 2, y = -3,
|
||||||
text = ' + ',
|
text = ' + ',
|
||||||
event = 'action',
|
event = 'batch_action',
|
||||||
help = 'Install or update',
|
operation = 'install',
|
||||||
|
operationText = 'Install',
|
||||||
|
help = 'Install or update selected',
|
||||||
},
|
},
|
||||||
remove = UI.Button {
|
removeSelected = UI.Button {
|
||||||
x = 8, y = -3,
|
x = 8, y = -3,
|
||||||
text = ' - ',
|
text = ' - ',
|
||||||
event = 'action',
|
event = 'batch_action',
|
||||||
operation = 'uninstall',
|
operation = 'uninstall',
|
||||||
operationText = 'Remove',
|
operationText = 'Remove',
|
||||||
help = 'Remove',
|
help = 'Remove selected',
|
||||||
},
|
},
|
||||||
updateall = UI.Button {
|
updateall = UI.Button {
|
||||||
ex = -2, y = -3, width = 12,
|
ex = -2, y = -3, width = 12,
|
||||||
@@ -89,7 +91,9 @@ function page:loadPackages()
|
|||||||
end
|
end
|
||||||
table.insert(self.grid.values, {
|
table.insert(self.grid.values, {
|
||||||
installed = not not Packages:isInstalled(k),
|
installed = not not Packages:isInstalled(k),
|
||||||
|
selected = false,
|
||||||
name = k,
|
name = k,
|
||||||
|
displayName = k,
|
||||||
manifest = manifest,
|
manifest = manifest,
|
||||||
})
|
})
|
||||||
end
|
end
|
||||||
@@ -104,12 +108,62 @@ function page:loadPackages()
|
|||||||
end
|
end
|
||||||
|
|
||||||
function page.grid:getRowTextColor(row, selected)
|
function page.grid:getRowTextColor(row, selected)
|
||||||
|
if row.selected then
|
||||||
|
return colors.cyan
|
||||||
|
end
|
||||||
if row.installed then
|
if row.installed then
|
||||||
return colors.yellow
|
return colors.yellow
|
||||||
end
|
end
|
||||||
return UI.Grid.getRowTextColor(self, row, selected)
|
return UI.Grid.getRowTextColor(self, row, selected)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function page:getSelectedPackages()
|
||||||
|
local selected = { }
|
||||||
|
for _, row in pairs(self.grid.values) do
|
||||||
|
if row.selected then
|
||||||
|
table.insert(selected, row)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return selected
|
||||||
|
end
|
||||||
|
|
||||||
|
function page:getSelectedCount()
|
||||||
|
local count = 0
|
||||||
|
for _, row in pairs(self.grid.values) do
|
||||||
|
if row.selected then
|
||||||
|
count = count + 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return count
|
||||||
|
end
|
||||||
|
|
||||||
|
function page:toggleSelection(row)
|
||||||
|
row.selected = not row.selected
|
||||||
|
row.displayName = row.selected and ('\187 ' .. row.name) or row.name
|
||||||
|
self.grid:draw()
|
||||||
|
self:updateStatus()
|
||||||
|
end
|
||||||
|
|
||||||
|
function page:clearSelection()
|
||||||
|
for _, row in pairs(self.grid.values) do
|
||||||
|
row.selected = false
|
||||||
|
row.displayName = row.name
|
||||||
|
end
|
||||||
|
self.grid:draw()
|
||||||
|
end
|
||||||
|
|
||||||
|
function page:updateStatus()
|
||||||
|
local count = self:getSelectedCount()
|
||||||
|
if count > 0 then
|
||||||
|
self.statusBar:setStatus(count .. ' package(s) selected')
|
||||||
|
else
|
||||||
|
local focused = self.grid:getSelected()
|
||||||
|
if focused then
|
||||||
|
self.statusBar:setStatus(focused.installed and 'Installed' or '')
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
function page.action:show()
|
function page.action:show()
|
||||||
self.output.win:clear()
|
self.output.win:clear()
|
||||||
UI.SlideOut.show(self)
|
UI.SlideOut.show(self)
|
||||||
@@ -134,11 +188,7 @@ function page:run(operation, name)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function page:updateSelection(selected)
|
function page:updateSelection(selected)
|
||||||
self.add.operation = selected.installed and 'update' or 'install'
|
-- no-op: buttons are always active for batch operations
|
||||||
self.add.operationText = selected.installed and 'Update' or 'Install'
|
|
||||||
self.remove.inactive = not selected.installed
|
|
||||||
self.add:draw()
|
|
||||||
self.remove:draw()
|
|
||||||
end
|
end
|
||||||
|
|
||||||
function page:eventHandler(event)
|
function page:eventHandler(event)
|
||||||
@@ -152,7 +202,14 @@ function page:eventHandler(event)
|
|||||||
Ansi.yellow, manifest.title,
|
Ansi.yellow, manifest.title,
|
||||||
Ansi.white, manifest.description))
|
Ansi.white, manifest.description))
|
||||||
self.description:draw()
|
self.description:draw()
|
||||||
self:updateSelection(event.selected)
|
self:updateStatus()
|
||||||
|
|
||||||
|
elseif event.type == 'grid_select' then
|
||||||
|
-- Space or Enter toggles selection
|
||||||
|
local row = self.grid:getSelected()
|
||||||
|
if row then
|
||||||
|
self:toggleSelection(row)
|
||||||
|
end
|
||||||
|
|
||||||
elseif event.type == 'checkbox_change' then
|
elseif event.type == 'checkbox_change' then
|
||||||
config.compression = not config.compression
|
config.compression = not config.compression
|
||||||
@@ -160,34 +217,69 @@ function page:eventHandler(event)
|
|||||||
|
|
||||||
elseif event.type == 'updateall' then
|
elseif event.type == 'updateall' then
|
||||||
self.operation = 'updateall'
|
self.operation = 'updateall'
|
||||||
|
self.operationTargets = { }
|
||||||
self.action.button.text = ' Begin '
|
self.action.button.text = ' Begin '
|
||||||
self.action.button.event = 'begin'
|
self.action.button.event = 'begin'
|
||||||
self.action.titleBar.title = 'Update All'
|
self.action.titleBar.title = 'Update All'
|
||||||
self.action:show()
|
self.action:show()
|
||||||
|
|
||||||
elseif event.type == 'action' then
|
elseif event.type == 'batch_action' then
|
||||||
local selected = self.grid:getSelected()
|
local targets = self:getSelectedPackages()
|
||||||
if selected then
|
local operation = event.button.operation
|
||||||
self.operation = event.button.operation
|
|
||||||
self.action.button.text = event.button.operationText
|
-- fall back to focused row if nothing selected
|
||||||
self.action.titleBar.title = selected.manifest.title
|
if #targets == 0 then
|
||||||
self.action.button.text = ' Begin '
|
local focused = self.grid:getSelected()
|
||||||
self.action.button.event = 'begin'
|
if focused then
|
||||||
self.action:show()
|
targets = { focused }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if #targets == 0 then return end
|
||||||
|
|
||||||
|
-- for install: update already-installed packages, install new ones
|
||||||
|
if operation == 'install' then
|
||||||
|
self.operation = 'install'
|
||||||
|
else
|
||||||
|
-- filter to only installed packages for uninstall
|
||||||
|
local installed = { }
|
||||||
|
for _, t in ipairs(targets) do
|
||||||
|
if t.installed then
|
||||||
|
table.insert(installed, t)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
targets = installed
|
||||||
|
if #targets == 0 then return end
|
||||||
|
self.operation = 'uninstall'
|
||||||
|
end
|
||||||
|
|
||||||
|
self.operationTargets = targets
|
||||||
|
local title = #targets == 1
|
||||||
|
and targets[1].manifest.title
|
||||||
|
or (#targets .. ' packages')
|
||||||
|
self.action.button.text = ' Begin '
|
||||||
|
self.action.button.event = 'begin'
|
||||||
|
self.action.titleBar.title = string.format('%s %s',
|
||||||
|
operation == 'install' and 'Install/Update' or 'Remove', title)
|
||||||
|
self.action:show()
|
||||||
|
|
||||||
elseif event.type == 'hide-action' then
|
elseif event.type == 'hide-action' then
|
||||||
self.action:hide()
|
self.action:hide()
|
||||||
|
|
||||||
elseif event.type == 'begin' then
|
elseif event.type == 'begin' then
|
||||||
if self.operation == 'updateall' then
|
if self.operation == 'updateall' then
|
||||||
self:run(self.operation, '')
|
self:run('updateall', '')
|
||||||
else
|
else
|
||||||
local selected = self.grid:getSelected()
|
for _, target in ipairs(self.operationTargets) do
|
||||||
self:run(self.operation, selected.name)
|
local op = self.operation
|
||||||
selected.installed = Packages:isInstalled(selected.name)
|
if op == 'install' and target.installed then
|
||||||
|
op = 'update'
|
||||||
self:updateSelection(selected)
|
end
|
||||||
|
self:run(op, target.name)
|
||||||
|
target.installed = Packages:isInstalled(target.name)
|
||||||
|
end
|
||||||
|
self:clearSelection()
|
||||||
|
self:updateStatus()
|
||||||
end
|
end
|
||||||
|
|
||||||
self.action.button.text = ' Done '
|
self.action.button.text = ' Done '
|
||||||
|
|||||||
Reference in New Issue
Block a user