-- Modulo per implementare il template Cronologia valutazioni
-- copiato senza vergogna da modulo:Navbox
-- Configurazione
local cfg = mw.loadData("Modulo:Cronologia valutazioni/Configurazione")
local function dump(t, ...)
local args = {...}
for _, s in ipairs(args) do
table.insert(t, s)
end
end
local errors = {}
local we_got_error = false
local debug = false
-------------------------------------------------------------------------------
-- Funzioni di utilità
-------------------------------------------------------------------------------
-- Ritorna true se il nome dell'argomento è valido
local function isValidArg(name, validArgs)
local ret = cfg.HistoryBoxArgs[name] ~= nil
if not ret then
local _, _, base_name, id = mw.ustring.find(name, "^(%a+)(%d+)$")
if cfg.HistoryBoxNumberedArgs[base_name] and id then ret = tonumber(id) end
end
return ret
end
-- Ritorna gli argomenti passati al modulo, scartando quelli senza nome,
-- quelli contenenti stringhe vuote e i non riconosciuti.
local function getArgs(frame, isSubgroup)
local ret = {}
for k, v in pairs(frame:getParent().args) do
if type(k) == "string" and v ~= "" then
if isValidArg(k) then
ret[k] = v
else
dump(errors, "Argomento non riconosciuto: '" .. k .. "'")
end
end
end
return ret
end
-- Ritorna gli ID degli argomenti azioneN presenti
local function getListIds(args)
local ret = {}
for k, v in pairs(args) do
local id = k:match("^azione(%d+)$")
if id then table.insert(ret, tonumber(id)) end
end
table.sort(ret)
return ret
end
-- Verica se si verifica una condizione di errore
-- errors_check: lista di array con le condizioni da controllare, questi hanno la struttura:
----- condition: il valore (vero o falso) da controllare
----- checks: lista di stati da controllare
----- msg: messaggio di errore se gli stati hanno tutti il valore uguale a condition
-- restituisce nil se non ci sono errori, altrimenti una stringa con un errore per riga
local function checkErrors(errors_check, status, errors_msg)
if errors_check == nil then return end
for _, check in ipairs(errors_check) do
local check_result = true
for _, par_to_test in ipairs(check.checks) do
check_result = check_result and (status[par_to_test] == check.condition)
end
if check_result then errors_msg[#errors_msg+1] = check.msg end
end
end
local function wrap_errors(errors_msg)
if #errors_msg > 0 then
local errors = {}
for _, e in ipairs(errors_msg) do
errors[#errors+1] = '<div class="error">' .. e .. '</div>'
end
if #errors > 0 then we_got_error = true end
return table.concat(errors)
end
return ''
end
-------------------------------------------------------------------------------
-- Classe HistoryBox
-------------------------------------------------------------------------------
local HistoryBox = {}
function HistoryBox:new(args)
local self = {}
setmetatable(self, { __index = HistoryBox,
__tostring = function(t) return self:__tostring() end })
self.args = args
-- costruzione table
self.status = {}
self.actions = {}
self.counters = {}
self.categories = {}
self.avviso_sotto = "" -- da implementare
for k,v in pairs(cfg.status_toggle) do
self.status[k] = v
end
self.current_title = mw.title.getCurrentTitle()
self.name = self.args['debug_name'] or self.current_title.text
self.processedArgs = {}
self.listIds = getListIds(self.args)
self:__PreprocessArgs()
self:__SetupBaseNode()
self:__infoDiv()
if #self.listIds ~= 1 then
self:__RowContent() end
if self.current_title.namespace == 1 or debug then
self:__SetCategories()
end
return self
end
function HistoryBox:__tostring()
categorie = table.concat(self.categories)
if debug and categorie ~= '' and self.current_title.namespace ~= 1 then
categorie = '<br>Categorie: ' .. table.concat(self.categories, ", ")
end
ret = tostring(self.BaseNode) .. self.avviso_sotto .. wrap_errors(errors) .. categorie
if we_got_error and not(self.args['no_categoria_errore']) then
ret = ret .. '[[Categoria:Errori di compilazione del template Procedure]]'
end
return ret
end
function HistoryBox:__PreprocessArgs()
local currentTitle = mw.title.getCurrentTitle()
for _, Id in ipairs(self.listIds) do
local row = { }
local action = mw.ustring.upper(self.args['azione' .. Id] or '')
action = cfg.action_alias[action] or action
local row_action = cfg.actions[action]
if row_action == nil then
dump(errors, "Non riconosciuta 'azione" .. Id .. " = " .. action .. "'")
else
-- leggo i dati della riga
local date = self.args['data' .. Id]
local collegamento = self.args['collegamento' .. Id]
local codice = self.args['codice' .. Id]
local name = self.args['nome' .. Id] or self.name
local commento = self.args['commento' .. Id]
if commento then
row['comment'] = "'''commento''': ''" .. commento .. "''" end
local errors_msg = {}
local error_msg = checkErrors(row_action['check_errors'], self.status, errors_msg)
local msg, link_label
-- verifico che l'esito esista e lo gestisco
local result = mw.ustring.upper(self.args['esito' .. Id] or '')
if result == '' and row_action['default_result'] then
result = row_action['default_result']
elseif row_action['result_alias'] then
result = row_action.result_alias[result] or result
end
local row_result = row_action.valid_result[result]
if row_result then
-- controllo se le condizioni sono tutte soddisfatte
checkErrors(row_result['check_errors'], self.status, errors_msg)
-- setto le variabili relative all'azione
if row_result['set'] then
for _,to_set in ipairs(row_result.set) do
self.status[to_set[2]] = to_set[1]
end
end
msg = row_result['msg']
link_label = row_result['link_label']
row['icon'] = row_result['icon']
else
if not(row_action['no_result']) then
local default_result = row_action['default_result'] or 'xxx'
local list_result = {}
for kr,vr in pairs(row_action.valid_result) do
if kr == default_result then
list_result[#list_result+1] = "<b>" .. mw.ustring.lower(kr) .. "</b>"
else
list_result[#list_result+1] = mw.ustring.lower(kr)
end
end
dump(errors, "Esito '" .. result .. "' non riconosciuto, esiti validi: " .. table.concat(list_result, "/"))
end
row['result'] = '-'
end
msg = msg or row_action['msg']
link_label = link_label or row_action['link_label']
row['icon'] = row['icon'] or row_action['icon']
-- analizzo casi specifici
-- per le rimozioni da riconoscimento qualità è necessario indagare quale fosse il riconoscimento per cambiare i giusti "status"
if action == "RRQ" then
if result == "RIMOSSA" then
if self.status.is_vetrina then
self.status.is_vetrina = false
self.status.removed_vetrina = true
row['icon'] = 'VetrinaEsclusa'
elseif self.status.is_vdq then
self.status.is_vdq = false
self.status.removed_vdq = true
row['icon'] = 'VdqEsclusa'
end
elseif result == "MANTENUTA" or result == "ANNULLATA" then
if self.status.is_vetrina then
row['icon'] = 'Vetrina'
elseif self.status.is_vdq then
row['icon'] = 'Vdq'
end
end
end
-- per le valutazioni VdQ scadute generalmente non c'è pagina a cui linkare
if action == "OLDVDQ" and result == "SCADUTA" then
collegamento = collegamento or "no"
end
-- per le procedure di cancellazione aggiungo in automatico dettagli sul tipo di procedura
if action == "PDC" then
if (result == "MANTENUTA" or result=="CANCELLATA") then
local vote_yes = self.args['si' .. Id]
local vote_no = self.args['no' .. Id]
if vote_yes and vote_no then
msg = msg..' in seguito a voto della comunità con risultato <span style="color:green;">' .. vote_yes .. '</span> a <span style="color:red;">' .. vote_no .. '</span>.'
link_label = "votazione"
else
msg = msg..' in seguito a decisione consensuale.'
end
end
end
-- per le vecchie valutazioni per la vetrina si distinguono le votazioni dalle valutazioni in base alla data
if (action == "OLDSRQ" or action == "OLDRRQ") and date then
_, _, _, month, year = string.find(date, "^(%d?%d?) ?(%a*) ?(%d%d%d%d)$")
year = tonumber(year)
if year <= 2008 or (year == 2009 and (month == 'gennaio' or month == 'febbraio')) then
link_label = "votazione"
end
end
-- genero i dati di output rimanenti
-- link alla versione
if codice then
date = date or "versione " .. codice
row['date'] = '[' .. tostring(mw.uri.fullUrl( name, {oldid=codice} )) .. " " .. date .. "]"
else
row['date'] = date or "-"
end
-- aggiorno il counter associato all'azione
if collegamento ~= "no" then
if self.counters[row_action.counter] then
self.counters[row_action.counter] = self.counters[row_action.counter] + 1
else
self.counters[row_action.counter] = 1
end
end
-- Tenta di generare il link di default se collegamento non è definito
if collegamento == nil then
if row_action['default_position'] then
if row_action['use_date_for_position'] then
if date then
_, _, _, month, year = string.find(date, "^(%d?%d?) ?(%a+) (%d%d%d%d)$")
if month and year and tonumber(year) >= 2012 then
month = string.lower(month)
month = string.gsub(month, "^%l", string.upper)
collegamento = mw.message.newRawMessage( row_action.default_position,
{ name or self.name, month, year}
):plain()
elseif action == "LSC" then
row['consiglio']= "Le procedure prima del 2012 non venivano archiviate, perciò possono essere trovate solo nella [http://it.wikipedia.org/w/index.php?title=Wikipedia:Lo_sapevi_che/Valutazione&action=history cronologia] della pagina di valutazione."
end
-- per le valutazioni LSC non c'è collegamento automatico senza data, perciò il template aiuta l'utente a trovare la valutazione manualmente
else
if action == "LSC" then
row['consiglio']= "La procedura si può trovare nell'[[Wikipedia:Lo sapevi che/Valutazione/Archivio|archivio]], oppure nella [http://it.wikipedia.org/w/index.php?title=Wikipedia:Lo_sapevi_che/Valutazione&action=history cronologia] della pagina di valutazione."
end
end
else
if self.counters[row_action.counter] == 1 then
collegamento = mw.message.newRawMessage( row_action.default_position[1],
{ name or self.name} ):plain()
else
collegamento = mw.message.newRawMessage( row_action.default_position[2],
{ name or self.name,
self.counters[row_action.counter]
} ):plain()
end
end
end
elseif collegamento == "no" then
collegamento = nil
end
row['msg'] = msg
row['collegamento'] = collegamento
link_label = link_label or "discussione"
row['label'] = link_label
if #errors_msg>0 then
row['errors_msg'] = wrap_errors(errors_msg)
end
table.insert(self.processedArgs, row)
end
end
end
function HistoryBox:__SetupBaseNode()
self.BaseNode = mw.html.create("h2")
:cssText("border: none; margin-left: 8%; margin-bottom: 0.4em")
:done()
:tag("table")
:addClass("cronoval")
:addClass("noprint") -- serve a qualcosa? tanto va nelle discussioni
:cssText("margin: 5px 10%; border: thin solid #a7d7f9; background-color: #EAF7ED;")
if #self.listIds ~= 1 then
self.BaseNode:addClass("mw-collapsible") end
end
function HistoryBox:__infoDiv()
local stato_descriptor, commento, consiglio, icon = self:__getSummaryInfo()
self.BaseNode:tag("tr")
:addClass("cronoval_h")
:tag("td")
:addClass("avviso-immagine")
:cssText("width:52px;")
:wikitext("[[File:" .. (cfg.icons[icon] or cfg.icons['default']) .. "|40px]]")
:done()
:tag("td")
:addClass("avviso-testo")
:wikitext(stato_descriptor)
:tag ("div")
:cssText ("font-size: 90%;")
:wikitext (commento)
:done ()
:tag ("div")
:wikitext (consiglio)
end
function HistoryBox:__getSummaryInfo()
local ret = {}
if #self.processedArgs == 1 then
local row = self.processedArgs[1]
if row['date'] ~= "-" then
ret = {"In data "..row['date']} end
ret[#ret + 1] = mw.message.newRawMessage (row['msg'], {" la voce <b>"..mw.title.subjectNsText.."</b>"}):plain()
local ret_consiglio= ""
if row['collegamento'] then
ret_consiglio= "Consulta la '''[["..row['collegamento'].."|pagina della "..row['label'].."]]''' per eventuali pareri e suggerimenti."
elseif row['consiglio'] then
ret_consiglio= row['consiglio'] end
return table.concat(ret), row['comment'], ret_consiglio, row['icon']
else
local s = self.status
local c = self.counters
c['Vetrina'] = (c['OLDSRQ'] or 0) + (c['Vetrina'] or 0)
local incipit_done = true
local icon
ret[1] = '<b>$1</b>'
if s.is_vetrina then
ret[#ret+1] = ' è una [[Wikipedia:Vetrina|voce in vetrina]]'
icon = 'Vetrina'
elseif s.is_vdq then
ret[#ret+1] = ' è una [[Wikipedia:Voci di qualità|voce di qualità]]'
icon = 'Vdq'
if s.removed_vetrina then
ret[#ret+1] = ', in precedenza è stata in vetrina'
end
elseif s.removed_vetrina then
ret[#ret+1] = ' è stata una [[Wikipedia:Vetrina|voce in vetrina]]'
icon = 'VetrinaEsclusa'
elseif s.removed_vdq then
ret[#ret+1] = ' è stata una [[Wikipedia:Voci di qualità|voce di qualità]]'
icon = 'VdqEsclusa'
elseif c['SRQ'] then
ret[#ret+1] = ' è stata segnalata per un [[Wikipedia:Riconoscimenti di qualità/Segnalazioni|riconoscimento di qualità]]'
if c['SRQ'] + c['Vetrina'] + (c['Vdq'] or 0) == 1 then
ret[#ret+1] = ', ma non ha superato la valutazione'
else
ret[#ret+1] = ', ma non ha superato le valutazioni'
end
icon = 'QualitaEsclusa'
elseif c['Vetrina'] >= 1 and c['Vdq'] then
ret[#ret+1] = ' non ha superato le valutazioni per essere giudicata una [[Wikipedia:Vetrina|voce in vetrina]] o [[Wikipedia:Vetrina|di qualità]]'
icon = 'QualitaEsclusa'
elseif c['Vetrina'] >= 1 then
ret[#ret+1] = ' non ha superato la valutazione per essere inserita in [[Wikipedia:Vetrina|vetrina]]'
icon = 'VetrinaEsclusa'
elseif c['Vdq'] then
ret[#ret+1] = ' non ha superato la valutazione per essere giudicata una [[Wikipedia:Vetrina|voce di qualità]]'
icon = 'VdqEsclusa'
else
incipit_done = false
end
if c['Vaglio'] then
if incipit_done then
ret[#ret+1] = '. La voce'
end
ret[#ret+1] = ' è stata sottoposta a '
if c['Vaglio'] > 1 then
ret[#ret+1] = 'più procedure di [[Wikipedia:Vaglio|vaglio]]'
else
ret[#ret+1] = 'una procedura di [[Wikipedia:Vaglio|vaglio]]'
end
incipit_done = true
end
if c['Lo sapevi che'] then
if incipit_done then
ret[#ret+1] = '. La voce'
end
if s.was_LSC then
ret[#ret+1] = ' è comparsa nella rubrica [[Wikipedia:Lo sapevi che|Lo sapevi che]]'
icon = icon or "LoSapeviChe"
else
ret[#ret+1] = ' è stata proposta per la rubrica [[Wikipedia:Lo sapevi che|Lo sapevi che]], ma è stata respinta'
end
incipit_done = true
end
if c['Cancellazione'] then
if incipit_done then
ret[#ret+1] = '. La voce'
end
ret[#ret+1] = ' è stata sottoposta a'
if c['Cancellazione'] > 1 then
ret[#ret+1] = ' più procedure di [[Wikipedia:Pagine da cancellare|cancellazione]]'
else
ret[#ret+1] = ' una procedura di [[Wikipedia:Pagine da cancellare|cancellazione]]'
end
if s.was_deleted then
ret[#ret+1] = ', ma successivamente è stata ripristinata'
else
if c['Cancellazione'] > 1 then
ret[#ret+1] = ', che non sono state accolte'
else
ret[#ret+1] = ', che non è stata accolta'
end
end
incipit_done = true
end
if incipit_done then
ret[#ret+1] = '.'
return mw.message.newRawMessage(table.concat(ret), {self.name}):plain(), nil,
"Consulta le varie procedure di valutazione per eventuali pareri e suggerimenti", (icon or "default")
end
return ''
end
end
function HistoryBox:__RowContent()
local listIds, altStyle
-- crea la tabella che contiene i dati collassati
local dataTableContent =
self.BaseNode:tag("tr")
:tag("td")
:attr("colspan", "2")
:tag("table")
:addClass("cronoval_elenco")
:cssText("clear: both; width: 100% !important; border-collapse: collapse;") -- l'important è per la versione mobile
for row_number, row in ipairs(self.processedArgs) do
local row_element = dataTableContent:tag("tr")
:cssText("background-color: white; border: thin solid #D8D8D8;")
local icon = ''
if row['icon'] then
icon = '[[File:' .. cfg.icons[row.icon] .. "|20px]]"end
local conclusione= ""
if row.collegamento then
conclusione= " '''[[" .. row.collegamento .. "|Vedi " .. row.label .. "]]'''"
elseif row.consiglio then
conclusione= " " .. row.consiglio end
local data_element = row_element
:tag("td")
:cssText("width: 22px; padding:0 2px;")
:wikitext(icon)
:done()
:tag("td")
:addClass("plainlinks")
:cssText("text-align: right; padding-right: 0.3em; width: 10em; vertical-align: top;")
:wikitext(row.date..":")
:done()
:tag("td")
:wikitext(mw.message.newRawMessage (row.msg, {"la voce"}):plain() .. conclusione)
if row['comment'] then
data_element
:tag('div')
:cssText("font-size: 90%;")
:wikitext(row.comment)
end
if row['errors_msg'] then
data_element:tag("div"):wikitext(row['errors_msg'])
end
end
end
function HistoryBox:__SetCategories()
-- Aggiunge le categorie per la pagina secondo il suo stato
if self.status.tried_qualita then
self.categories[#self.categories+1] = '[[Categoria:Voci escluse da un riconoscimento di qualità]]'
end
if self.status.tried_vetrina then
self.categories[#self.categories+1] = '[[Categoria:Voci escluse dalla vetrina]]'
end
if self.status.tried_vdq then
self.categories[#self.categories+1] = '[[Categoria:Voci escluse dalle voci di qualità]]'
end
if self.status.tried_LSC then
self.categories[#self.categories+1] = '[[Categoria:Voci scartate nella rubrica Lo sapevi che]]'
end
if self.status.removed_vetrina then
self.categories[#self.categories+1] = '[[Categoria:Voci rimosse dalla vetrina]]'
end
if self.status.removed_vdq then
self.categories[#self.categories+1] = '[[Categoria:Voci rimosse dalle voci di qualità]]'
end
if self.status.scaduta_vdq then
self.categories[#self.categories+1] = '[[Categoria:Segnalazioni voci di qualità scadute]]'
end
if self.counters['Vaglio'] then
self.categories[#self.categories+1] = '[[Categoria:Voci vagliate]]'
end
if self.status.was_LSC then
self.categories[#self.categories+1] = '[[Categoria:Voci pubblicate nella rubrica Lo sapevi che]]'
end
if self.current_title.namespace ~= 1 then
for i,_ in ipairs(self.categories) do
self.categories[i] = self.categories[i]:gsub('%[%[', '')
self.categories[i] = self.categories[i]:gsub('%]%]', '')
end
end
end
function HistoryBox:__Status()
local ret = {}
for k,_ in pairs(cfg.status_toggle) do
ret[#ret+1] = k .. ': ' .. tostring(self.status[k])
end
return table.concat(ret, '; ')
end
-------------------------------------------------------------------------------
-- API
-------------------------------------------------------------------------------
local p = {}
-- Entry-point per {{HistoryBox}}
function p.historybox(frame)
return tostring(HistoryBox:new(getArgs(frame)))
end
-- Ritorna la tabella di configurazione
function p.actiontable(frame)
local tableNode = mw.html.create("table")
:addClass('wikitable')
:addClass('sortable')
tableNode:tag('tr')
:tag('th'):wikitext('Azione'):done()
:tag('th'):wikitext('Alias azione'):done()
:tag('th'):wikitext('Descrizione'):done()
:tag('th'):wikitext("Esiti<br /><small>In grassetto l'esito di default</small><br /><small>Tra parentesi gli alias</small>"):done()
:tag('th'):wikitext("Collegamento di default")
for kaction, vaction in pairs(cfg.actions) do
local table_row = tableNode:tag('tr')
table_row:tag('td')
:wikitext(kaction)
local alias_action = {}
for k, v in pairs(cfg.action_alias) do
if v == kaction then
alias_action[#alias_action+1] = mw.ustring.lower(k)
end
end
table_row:tag('td')
:wikitext(table.concat(alias_action, ',<br />'))
table_row:tag('td')
:wikitext(vaction['description'] or ' ')
local default_result = vaction['default_result'] or 'xxx'
local td_result = table_row:tag('td')
if vaction.valid_result then
local first_result = true
for kr,vr in pairs(vaction.valid_result) do
if first_result then
first_result = false
else
td_result:tag('br'):done()
end
if kr == default_result then
td_result:tag("b"):wikitext(mw.ustring.lower(kr))
else
td_result:wikitext(mw.ustring.lower(kr))
end
if vaction['result_alias'] then
local result_alias = {}
for ka, va in pairs(vaction.result_alias) do
if va == kr then result_alias[#result_alias+1] = mw.ustring.lower(ka) end
end
if #result_alias > 0 then td_result:wikitext(" (" .. table.concat(result_alias, ", ") .. ")" ) end
end
td_result:wikitext(' --> ' .. (vr['msg'] or '???') )
end
else
td_result = table_row:wikitext("-")
end
local default_position = ' '
if vaction['default_position'] then
if vaction['use_date_for_position'] then
default_position = mw.message.newRawMessage( vaction.default_position, { '<nome>', '<mese>', '<anno>'}):plain()
else
default_position = mw.message.newRawMessage( vaction.default_position[1] .. '<br />' .. vaction.default_position[2],
{ '<name>', '<n>'} ):plain()
end
end
table_row:tag('td'):wikitext(default_position)
end
return tostring(tableNode)
end
return p