বিষয়বস্তুতে চলুন

ব্যবহারকারী:Abazizfahad/খেলাঘর/মডিউল

উইকিপিডিয়া, মুক্ত বিশ্বকোষ থেকে

মডিউল:কর্ম-পরিকল্পনা ছক -- -- এই মডিউলটি টেমপ্লেট:কর্ম-পরিকল্পনা ছক–এর উপকরণ -- local getArgs = require('মডিউল:Arguments').getArgs local TableTools = require('মডিউল:টেবিল সরঞ্জাম') local p = {}

function addTemplates(frame, data, args) -- adds additional template to the top of the page, above the infobox local page_template -- local tmplt_args = {} local template_div = mw.html.create('div')

	for k,v in pairs(data.templates) do -- if there is a matching arg, and it has a table of template possibilities
		if (args[k] and string.len(args[k]) > 0 and type(data.templates[k]) == "table") then --convert args to lowercase before checking them against cats
			for tmplt_key, tmplt_val in pairs(data.templates[k]) do

if data.templates.passArg == true then template_div :cssText("") :wikitext(frame:expandTemplate{title=data.templates[k][tmplt_key], args={status = stringFirstCharToUpper(args[k])}}) --status is special casing. need to pass generic arg keys :done() break elseif (stringToLowerCase(args[k]) == tmplt_key and mw.title.new("Template:" .. tmplt_val).exists) then

                       template_div
                           :cssText("margin-bottom:1em;")
                           :wikitext(frame:expandTemplate{title=tmplt_val, args={}})
                           :done()
               end
                   --convert args to lowercase and subs spaces for underscores
                   --make sure specified template exists
                   -- if (type(tmplt_val) == "string" and stringToLowerCase(args[k]) == tmplt_key and mw.title.new("Template:" .. tmplt_val).exists) then 

end end

	end	
	page_template = tostring(template_div)		

return page_template end

function addCategories(data, args, open_roles) -- will also look for numbered categories local cat_list = {} local base_cat = data.categories.base -- table.insert(cat_list, base_cat) --always need a base category -- -- adding role categories if data.categories.default then table.insert(cat_list, data.categories.default) end if data.categories.roles then role_cat = data.categories.roles for k,v in pairs(open_roles) do table.insert(cat_list, base_cat .. k:gsub("^%l", string.upper) .. role_cat) end end

	for k,v in pairs(data.categories) do -- if there is a matching arg, and it has a table of category possibilities
		if (args[k] and string.len(args[k]) > 0) then --convert args to lowercase before checking them against cats
			if type(data.categories[k]) == "table" then

for cat_key, cat_val in pairs(data.categories[k]) do if stringSpacesToUnderscores(stringToLowerCase(args[k])) == cat_key then --convert args to lowercase and subs spaces for underscores before checking them against cats table.insert(cat_list, base_cat .. cat_val) break end end elseif type(data.categories[k]) == "string" then --concat the value of the cat field with the default cat directly table.insert(cat_list, base_cat .. data.categories[k]) end end

	end	
	local page_categories = " " .. tostring(table.concat(cat_list, " ")) .. ""

return page_categories end

function makeTextField(field, field_div) -- makes a formatted text field for output, based on parameter -- values or on default values provided for that field -- type in the stylesheet field_div:cssText(field.style) if field.vtype2 == "body" then field_div :tag('span') :cssText(field.style2)--inconsistent use of styles 2/3 here :wikitext(field.title)--we probably aren't using this for most things now, after Heather's redesign :done() :tag('span') :cssText(field.style3) :wikitext(field.values[1]) :done() elseif field.vtype2 == "title" then field_div :tag('span') :cssText(field.style3) :wikitext(field.values[1]) :done() elseif field.vtype2 == "link" then field_div :tag('span') :cssText(field.style3) :wikitext("[[" .. field.values[1] .. "|" .. field.title .."]]") :done() end field_div:done() return field_div end

function makeImageField(field, field_div) -- makes a formatted image field for output, based on parameter values -- provided in the calling template or its parent template, or on default -- values provided in the stylesheet field_div:cssText(field.style) field_div :tag('span') :cssText(field.style3) if field.vtype2 == "thumb" then field_div :wikitext("[[" .. field.values[1] .. "|right|" .. field.width .."]]") elseif field.vtype2 == "link" then field_div :wikitext("[[" .. field.values[1] .. "|" .. field.alignment .. "|" .. field.width .."|link=" .. field.link .. "]]") elseif field.vtype2 == "badge" then if mw.ustring.find( field.values[1], "http", 1, true ) then field_div :wikitext("" .. field.alignment .. "|" .. field.width .."|link=" .. field.values[1] .. " " .. "[" .. field.values[1] .. " " .. field.title .. "]") end elseif field.vtype2 == "ui_button" then field_div :addClass(field.class) :wikitext(field.title) :done() end field_div:done() return field_div end

function makeParticipantField(field, ftype) local field_div = mw.html.create('div') local title_span if field.icon then title_span = "left" .. "|18px " .. field.title else title_span = field.title end field_div :cssText(field.style) :tag('span') :cssText(field.style2) :wikitext(title_span) :done() if ftype == "filled" then local i = 1 for k,v in ipairs(field.values) do if (i > 1 and field.icon) then --only insert extra padding if has icon field.style3 = "padding-left:25px; display:block" end if field.vtype2 then --ideally all configs should at least have this field for participants. FIXME if field.vtype2 == "username" then v = "• " .. "" .. v .. "" elseif field.vtype2 == "email" then v = "• " .. v end else v = "• " .. "" .. v .. "" end field_div :tag('span') :cssText(field.style3) :wikitext(v) -- :wikitext("• " .. "" .. v .. "") :done() i = i + 1 end end field_div:allDone() return field_div end

function makeSectionDiv(sec_fields, sec_style) local sec_div = mw.html.create('div'):cssText(sec_style) sec_fields = TableTools.compressSparseArray(sec_fields) for findex, sec_field in ipairs(sec_fields) do -- should put this at the end of the function, and just append the other stuff sec_div:node(sec_field) end return sec_div end

function makeParticipantsSection(frame, args, data, filled_role_data, open_roles) local filled_role_fields = {} for role, val_table in pairs(filled_role_data) do local field = data.fields[role] field.title = mw.text.trim(frame:expandTemplate{title=args.translations, args={field.key}}) field.values = {} for val_num, val_text in ipairs(filled_role_data[role]) do field.values[#field.values + 1] = val_text end local filled_field_div = makeParticipantField(field, "filled")

       filled_role_fields[field.rank] = filled_field_div	

end local sec_div = makeSectionDiv(filled_role_fields, data.styles.section["participants"]) if (data.fields.more_participants and args.more_participants and stringToLowerCase(args.more_participants)) == "yes" then -- really need this here? -- if (args.portal == "Idealab" or args.portal == "Research") then -- beware, exceptions everywhere sec_div:tag('span'):cssText("font-style:italic; color: #888888"):wikitext(mw.text.trim(frame:expandTemplate{title=args.translations, args={data.fields.more_participants.key}})):done() -- elseif args.portal == "Patterns" then -- sec_div:tag('span'):cssText("font-style:italic; color: #888888"):wikitext("a learning pattern for..."):done() -- else for role, val in pairs(open_roles) do -- should make these ordered using compressSparseArray, as above local field = data.fields[role] field.title = mw.text.trim(frame:expandTemplate{title=args.translations, args={field.key}}) if field.icon then field.icon = field.icon_inactive end local open_field_div = makeParticipantField(field, "open") sec_div:node(open_field_div) end end sec_div:allDone() return sec_div end

function makeSectionFields(args, field) -- ui button is separate local field_div = mw.html.create('div'):cssText(field.style) --why declare this here? if field.vtype == "image" then if (field.isRequired == true or (args[field.arg] and string.len(args[field.arg]) > 0)) then --should move this up, may not just apply to images field_div = makeImageField(field, field_div) end elseif field.vtype == "text" then field_div = makeTextField(field, field_div) else end return field_div -- make sure div is 'done' end

function makeSection(frame, args, data, box_sec) -- return a div for a section of the box including child divs -- for each content field in that section -- local sec_div = mw.html.create('div'):cssText(data.styles.section[box_sec]) local sec_fields = {} for k,v in pairs(data.fields) do if data.fields[k].section == box_sec then local field = data.fields[k] field.title = mw.text.trim(frame:expandTemplate{title=args.translations, args={field.key}}) field.values = {} if (args[k] and string.len(args[k]) > 0) then field.values[1] = args[k] --does not accept numbered args if field.toLowerCase == true then -- special casing to make IEG status=SELECTED to display in lowercase field.values[1] = stringToLowerCase(field.values[1]) end local field_div = makeSectionFields(args, field) sec_fields[field.rank] = field_div elseif field.isRequired == true then if field.vtype == "text" then field.values[1] = mw.text.trim(frame:expandTemplate{title=args.translations, args={field.default}}) else field.values[1] = field.default end local field_div = makeSectionFields(args, field) sec_fields[field.rank] = field_div else --don't make a section for this field end end end local sec_div = makeSectionDiv(sec_fields, data.styles.section[box_sec]) return sec_div end

function makeInfobox(frame, args, data, filled_role_data, open_roles) -- builds the infobox. Some content sections are required, others -- are optional. Optional sections are defined in the stylesheet. local box = mw.html.create('div'):cssText(data.styles.box.outer) local inner_box = mw.html.create('div'):cssText(data.styles.box.inner) if data.sections.above == true then local sec_top = makeSection(frame, args, data, "above") box:node(sec_top) end if data.sections.nav == true then local sec_nav = makeSection(frame, args, data, "nav") box:node(sec_nav) end local sec_head = makeSection(frame, args, data, "head") inner_box:node(sec_head) local sec_main = makeSection(frame, args, data, "main") inner_box:node(sec_main) if data.sections.participants == true then local sec_participants = makeParticipantsSection(frame, args, data, filled_role_data, open_roles) inner_box:node(sec_participants) end if data.sections.cta == true then local sec_cta = makeSection(frame, args, data, "cta") inner_box:node(sec_cta) inner_box:tag('div'):cssText("clear:both"):done() --clears buttons in the cta sections end inner_box:allDone() box:node(inner_box) if data.sections.below == true then local sec_bottom = makeSection(frame, args, data, "below") box:node(sec_bottom) end box:allDone() return box end

function orderStringtoNumber(array, val, num)

   if num > table.getn(array) then
       array[#array+1] = val
   else
       table.insert(array, num, val)
   end  
   return array

end

function isJoinable(args, data) if args.more_participants == "NO" then data.fields.join = nil data.fields.endorse.style = "display:inline; float:right;" end return data end

function deepCopyTable(data) -- the deep copy is a workaround step to avoid the restrictions placed on -- tables imported through loadData if type(data) ~= 'table' then return data end local res = {} for k,v in pairs(data) do if type(v) == 'table' then v = deepCopyTable(v) end res[k] = v end return res end

function getPortalData(args) -- loads the relevant stylesheet, if a sub-template was called with a portal -- argument and a stylesheet exists with the same name. For example, calling -- স্ক্রিপ্ট ত্রুটি: "Probox/Idealab" নামক কোনো মডিউল নেই। would load the -- Module:Probox/Idealab stylesheet local data_readOnly = {} local data_writable = {} if (args.portal and mw.title.makeTitle( 'Module', 'Probox/' .. args.portal).exists) then data_readOnly = mw.loadData("Module:Probox/" .. args.portal) else data_readOnly = mw.loadData("Module:Probox/Default") end -- data_writable = TableTools.shallowClone(data_readOnly) data_writable = deepCopyTable(data_readOnly) return data_writable end

function string.starts(String,Start)

 return string.sub(String,1,string.len(Start))==Start

end

function stringToLowerCase(value) return mw.ustring.lower(value) end

function stringSpacesToUnderscores(value) return mw.ustring.gsub(value, " ", "_") end

function stringFirstCharToUpper(str)

   return (str:gsub("^%l", string.upper))

end

function TCTlookup(args) local tct_path = tostring(args.translations) --mw.log(mw.title.getCurrentTitle().subpageText) local tct_subpage = mw.title.getCurrentTitle().subpageText if tct_subpage == "en" then tct_path = tct_path .. "/" .. tct_subpage elseif (mw.title.new("Template:" .. args.translations .. "/" .. tct_subpage).exists and mw.language.isSupportedLanguage(tct_subpage)) then tct_path = tct_path .. "/" .. tct_subpage else tct_path = tct_path .. "/" .. "en" end -- mw.log(tct_path) return tct_path end

function getRoleArgs(args, available_roles)

   -- returns:
   -- 1) a table of ordered values for valid role params, 
   -- even if numbered nonsequentially
   -- 2) a table of all roles with at least 1 empty param, 
   -- plus the default volunteer role
   local filled_role_data = {}
   local open_roles = {}
   if available_roles.default then -- some boxes have default role to join
   	open_roles[available_roles.default] = true
   end	

for rd_key, rd_val in pairs(available_roles) do for a_key, a_val in pairs(args) do

   		if string.starts(a_key, rd_key) then
               if string.len(a_val) == 0 then
                   open_roles[rd_key] = true
               else   
                   if not filled_role_data[rd_key] then filled_role_data[rd_key] = {} end
                   local arg_num = tonumber(a_key:match('^' .. rd_key .. '([1-9]%d*)$'))
                   if arg_num then
                       filled_role_data[rd_key] = orderStringtoNumber(filled_role_data[rd_key], a_val, arg_num)
                   else
                       table.insert(filled_role_data[rd_key], 1, a_val)   
                   end
               end    
           end    

end end return filled_role_data, open_roles end

function p.main(frame) local args = getArgs(frame, {removeBlanks = false}) local data = getPortalData(args)

	data = isJoinable(args, data)

if not (args.translations and mw.title.new("Template:" .. args.translations).exists) then

		args.translations = "Probox/Default/Content"
	end
	-- mw.log(args.translations)
	-- if the TCT content index is under translation, check for translations in the subpage language
	if mw.title.new("Template:" .. args.translations .. "/en").exists then	
		args.translations = TCTlookup(args)
	end	
	if data.sections.cta == true then
		args.talk = tostring(mw.title.getCurrentTitle().talkPageTitle)  -- expensive
	end	
	local filled_role_data, open_roles = getRoleArgs(args, data.roles)

local box = makeInfobox(frame, args, data, filled_role_data, open_roles) local infobox = tostring(box) -- only add cats if not in Template or User ns if (data.categories and (mw.title.getCurrentTitle().nsText ~= "Template" and mw.title.getCurrentTitle().nsText ~= "User" and mw.title.getCurrentTitle().nsText ~= "Meta") and not args.noindex) then -- FIXME specify namespace in config, so that categories only appear if template is translcuded in that namespace page_categories = addCategories(data, args, open_roles) infobox = infobox .. page_categories end if data.templates then local top_template = addTemplates(frame, data, args) infobox = top_template .. infobox end return infobox end

return p