diff --git a/Modules/History/lootHistory.lua b/Modules/History/lootHistory.lua index 6c849a71..5ff9f1c1 100644 --- a/Modules/History/lootHistory.lua +++ b/Modules/History/lootHistory.lua @@ -16,11 +16,13 @@ data[date][playerName] = { } } ]] -local selectedDate, selectedName, filterMenu, moreInfo, moreInfoData +local selectedDate, filterMenu, moreInfo, moreInfoData local rightClickMenu; local ROW_HEIGHT = 20; local NUM_ROWS = 15; local epochDates = {} -- [DateTime] = epoch +local searchList = {} +local searchType = "name"; local useClassFilters = false LootHistory.wowheadBaseUrl = "https://www.wowhead.com/item=" @@ -51,6 +53,12 @@ function LootHistory:OnInitialize() {name = L["Reason"], width = 220, comparesort = self.ResponseSort, defaultsort = 1, sortnext = 2}, -- Response aka the text supplied to lootDB...response {name = "", width = ROW_HEIGHT}, -- Delete button } + -- TODO localize tips + self.searchTypes = { + name = {name = "Name", tip = "Search by player name"}, + class = {name = "Class", tip = "Search by player class."}, + item = {name = "Item", tip = "Search by item name."}, + } filterMenu = _G.MSA_DropDownMenu_Create("RCLootCouncil_LootHistory_FilterMenu", UIParent) rightClickMenu = _G.MSA_DropDownMenu_Create("RCLootCouncil_LootHistory_RightclickMenu", UIParent) _G.MSA_DropDownMenu_Initialize(filterMenu, self.FilterMenu, "MENU") @@ -115,6 +123,75 @@ function LootHistory:GetLocalizedDate(date) -- date is "DD/MM/YY" return FormatShortDate(d, m, y) end +function LootHistory:ParseItemLink(item_link) + local _,_, find_item_link, item_color, item_id, item_name = string.find(item_link , "(|c(%w+).*item:(%d+):.*%[(.*)%]|h|r)") + if find_item_link then + return find_item_link, item_id, item_name, item_color + else + return nil, nil, nil, nil + end +end + +function LootHistory:ParseStringList(string_list) + -- parse a list of comma seperated values into a list + local list = {} + for value in string.gmatch(string_list, "[^,]+") do + trim_value = (value:gsub("^%s*(.-)%s*$", "%1")) + table.insert(list, trim_value) + end + return list +end + +function LootHistory:ParsePlayerName(full_name) + -- parse a full name to just the player's name (Villageburn-Skeram => Villageburn) + if not full_name then + return full_name + end + + partial_name = string.match(full_name, '(.*)-.*') + if partial_name then + return partial_name + else + return full_name + end +end + +function LootHistory:StringStartsWith(full_string, partical_string) + if not partical_string then + return false + end + return string.sub(string.lower(full_string),1,string.len(partical_string))==string.lower(partical_string) +end + +function LootHistory:StringContains(full_string, partical_string) + if not partical_string then + return false + end + + + local _,_,res = string.find(string.lower(full_string) , ".*(" .. string.lower(partical_string) .. ").*") + + return res ~= nil +end + +function LootHistory:ValueInListStartsWith(list, value) + for entry_key, entry_value in ipairs(list) do + if LootHistory:StringStartsWith(value, entry_value) then + return true + end + end + return false +end + +function LootHistory:ValueInListContains(list, value) + for entry_key, entry_value in ipairs(list) do + if LootHistory:StringContains(value, entry_value) then + return true + end + end + return false +end + function LootHistory:BuildData() addon:Debug("LootHistory:BuildData()") data = {} @@ -305,16 +382,31 @@ function LootHistory:DeleteEntriesOlderThanEpoch(epoch) end end -local function filterNameData (name, date) - local nameAndDate = true -- default to show everything - if selectedName and selectedDate then - nameAndDate = name == selectedName and date == selectedDate - elseif selectedName then - nameAndDate = name == selectedName - elseif selectedDate then - nameAndDate = date == selectedDate +local function filterNameData (name, date, num, class) + local dateMatch = (selectedDate and selectedDate == date) or not selectedDate + + local searchAndDate = true -- default to show everything + + if searchType == "class" and class then + + local classMatch = LootHistory:ValueInListStartsWith(searchList, class) or next(searchList) == nil + + searchAndDate = dateMatch and classMatch + + elseif searchType == "item" and num then + + local _, _, itemName, _ = LootHistory:ParseItemLink(lootDB[name][num].lootWon) + local itemMatch = LootHistory:ValueInListContains(searchList, itemName) or next(searchList) == nil + + searchAndDate = dateMatch and itemMatch + + elseif searchType == "name" then + + local nameMatch = LootHistory:ValueInListStartsWith(searchList, name) or next(searchList) == nil + searchAndDate = dateMatch and nameMatch end - return nameAndDate + + return searchAndDate end local function filterResponse (response, isAwardReason) @@ -339,7 +431,7 @@ end -- Filter function for Lib-ScrollingTable function LootHistory.FilterFunc(table, row) -- Name and Date filters: - local nameAndDate = filterNameData(row.name, row.date) + local nameAndDate = filterNameData(row.name, row.date, row.num, row.class) -- Response filters: if not db.modules["RCLootHistory"].filters then return nameAndDate end -- db hasn't been initialized @@ -353,7 +445,7 @@ end function LootHistory:FilterForLootDB (winner, entry) -- Name and Date filters: - local nameAndDate = filterNameData(winner, entry.date) + local nameAndDate = filterNameData(winner, entry.date, nil, nil) -- Response filters: if not db.modules["RCLootHistory"].filters then return nameAndDate end -- db hasn't been initialized @@ -748,9 +840,6 @@ local function IsFiltering() for k,v in pairs(db.modules["RCLootHistory"].filters) do if not v then return true end end - for _,v in pairs(db.modules["RCLootHistory"].filters.class) do - if v then return true end - end end function LootHistory:Update() @@ -798,23 +887,9 @@ function LootHistory:GetFrame() end }) - --Name selection - f.name = LibStub("ScrollingTable"):CreateST({{name = "", width = ROW_HEIGHT},{name = _G.NAME, width = 100, sort = 1}}, 5, ROW_HEIGHT, { ["r"] = 1.0, ["g"] = 0.9, ["b"] = 0.0, ["a"] = 0.5 }, f.content) - f.name.frame:SetPoint("TOPLEFT", f.date.frame, "TOPRIGHT", 20, 0) - f.name:EnableSelection(true) - f.name:RegisterEvents({ - ["OnClick"] = function(rowFrame, cellFrame, data, cols, row, realrow, column, table, button, ...) - if button == "LeftButton" and row then - selectedName = selectedName ~= data[realrow][column].name and data[realrow][column].name or nil - self:Update() - end - return false - end - }) - -- Abort button local b1 = addon:CreateButton(_G.CLOSE, f.content) - b1:SetPoint("TOPRIGHT", f, "TOPRIGHT", -10, -100) + b1:SetPoint("TOPRIGHT", f, "TOPRIGHT", -10, -50) b1:SetScript("OnClick", function() self:Disable() end) f.closeBtn = b1 @@ -894,11 +969,85 @@ function LootHistory:GetFrame() sel.frame:Show() f.moreInfoDropdown = sel + local searchTypeSel = AG:Create("Dropdown") + searchTypeSel:SetPoint("TOPLEFT", b4, "BOTTOMLEFT", 0, -10) + searchTypeSel:SetPoint("TOPRIGHT", b4, "BOTTOMRIGHT", 0, -10) + + local values = {} + for k, v in pairs(self.searchTypes) do + values[k] = v.name + end + searchTypeSel:SetList(values) + searchTypeSel:SetValue(searchType) + searchTypeSel:SetText(self.searchTypes[searchType].name) + + searchTypeSel:SetCallback("OnEnter", function() + addon:CreateTooltip(self.searchTypes[searchType].tip) + end) + searchTypeSel:SetCallback("OnLeave", function() + addon:HideTooltip() + end) + searchTypeSel:SetParent(f) + searchTypeSel.frame:Show() + + f.eb1 = CreateFrame("EditBox", "logEditBox", f.content, "InputBoxTemplate") + f.eb1:SetFrameStrata("DIALOG") + f.eb1:SetSize(300,25) + f.eb1:SetAutoFocus(false) + f.eb1:SetText(table.concat(searchList, ",")) + f.eb1:SetPoint("LEFT", searchTypeSel.frame, "RIGHT", 15, 0) + f.eb1:SetScript( "OnEnterPressed", function (char) + searchList = LootHistory:ParseStringList(f.eb1:GetText()) + self:Update() + end); + + searchTypeSel:SetCallback("OnValueChanged", function(_,_, key) + searchType = key + selectedDate = nil + searchList = {} + self.frame.eb1:SetText(table.concat(searchList, ",")) + self.frame.date:ClearSelection() + self.frame.name:ClearSelection() + + self:Update() + end) + + --Name selection + f.name = LibStub("ScrollingTable"):CreateST({{name = "", width = ROW_HEIGHT},{name = _G.NAME, width = 100, sort = 1}}, 5, ROW_HEIGHT, { ["r"] = 1.0, ["g"] = 0.9, ["b"] = 0.0, ["a"] = 0.5 }, f.content) + f.name.frame:SetPoint("TOPLEFT", f.date.frame, "TOPRIGHT", 20, 0) + f.name:EnableSelection(true) + f.name:RegisterEvents({ + ["OnClick"] = function(rowFrame, cellFrame, data, cols, row, realrow, column, table2, button, ...) + if button == "LeftButton" and row then + + local playerName = LootHistory:ParsePlayerName(data[realrow][column].name) + local nameInList = false + + for key, value in ipairs(searchList) do + if LootHistory:StringStartsWith(value, playerName) then + nameInList = true + table.remove(searchList, key) + end + end + + if not nameInList then + table.insert(searchList, playerName) + end + + f.eb1:SetText(table.concat(searchList, ",")) + self:Update() + end + return false + end + }) + -- Clear selection local b6 = addon:CreateButton(L["Clear Selection"], f.content) b6:SetPoint("RIGHT", sel.frame, "LEFT", -10, 0) b6:SetScript("OnClick", function() - selectedDate, selectedName = nil, nil + selectedDate = nil + searchList = {} + self.frame.eb1:SetText("") self.frame.date:ClearSelection() self.frame.name:ClearSelection() self:Update()