VideoGallery: Difference between revisions
From Dune Awakening DB
Created page with "-- Module:VideoGallery -- Handles video gallery display with database integration local p = {} -- Database connection function local function getDB() return mw.ext.LuaSQLite.open('duneawakening') end -- Convert seconds to MM:SS format local function formatDuration(seconds) if not seconds or seconds == 0 then return "" end local minutes = math.floor(seconds / 60) local secs = seconds % 60 return string.format("%d:%02d", minutes, secs) en..." |
mNo edit summary |
||
| (One intermediate revision by the same user not shown) | |||
| Line 1: | Line 1: | ||
-- Module:VideoGallery | -- Module:VideoGallery | ||
-- | -- Lua module for rendering video gallery sections | ||
local p = {} | local p = {} | ||
-- | -- Helper function to escape quotes | ||
local function | local function escapeQuotes(str) | ||
return | if not str then return '' end | ||
return str:gsub('"', '"'):gsub("'", ''') | |||
end | end | ||
-- | -- Helper function to format duration | ||
local function formatDuration(seconds) | local function formatDuration(seconds) | ||
if not seconds or seconds == 0 then | if not seconds or seconds == 0 then return '' end | ||
local minutes = math.floor(seconds / 60) | local minutes = math.floor(seconds / 60) | ||
local secs = seconds % 60 | local secs = seconds % 60 | ||
| Line 19: | Line 18: | ||
end | end | ||
-- | -- Render videos for a specific category | ||
function p.renderCategoryVideos(frame) | |||
local category = frame.args.category or 'Featured' | |||
local html = '' | |||
local | |||
-- | -- Get unique purposes for this category | ||
local purposes = mw.ext.externalData.getExternalData{ | |||
source = 'externaldb', | |||
from = 'data_videos', | |||
data = 'purpose=purpose', | |||
where = "primary_tag='" .. category .. "' AND visibility='public' AND purpose IS NOT NULL", | |||
group_by = 'purpose', | |||
order_by = 'purpose' | |||
local | |||
} | } | ||
-- Loop through each purpose and create a section | |||
if purposes and purposes.purpose then | |||
-- | for i, purpose in ipairs(purposes.purpose) do | ||
html = html .. '<div class="video-section">\n' | |||
html = html .. ' <div class="video-section-header">\n' | |||
html = html .. ' <h3 class="section-title">' .. purpose .. '</h3>\n' | |||
html = html .. ' </div>\n' | |||
html = html .. ' <div class="video-grid">\n' | |||
-- Get videos for this purpose | |||
local videos = mw.ext.externalData.getExternalData{ | |||
source = 'externaldb', | |||
from = 'data_videos', | |||
data = 'video_id=video_id,youtube_id=youtube_id,title=title,channel_title=channel_title,channel_id=channel_id,author=author,published_at=published_at,duration_sec=duration_sec,purpose=purpose,primary_tag=primary_tag,secondary_tag=secondary_tag,description=description,video_notes=video_notes,video_internal_link=video_internal_link', | |||
where = "primary_tag='" .. category .. "' AND purpose='" .. purpose .. "' AND visibility='public'", | |||
order_by = 'published_at DESC' | |||
} | |||
videos | |||
-- Render video | -- Render each video card | ||
for | if videos and videos.video_id then | ||
for j, video_id in ipairs(videos.video_id) do | |||
local duration = formatDuration(tonumber(videos.duration_sec[j] or 0)) | |||
html = html .. ' <div class="video-card" ' | |||
html = html .. 'data-video-id="' .. video_id .. '" ' | |||
html = html .. 'data-youtube-id="' .. (videos.youtube_id[j] or '') .. '" ' | |||
html = html .. 'data-title="' .. escapeQuotes(videos.title[j] or '') .. '" ' | |||
html = html .. 'data-channel="' .. escapeQuotes(videos.channel_title[j] or '') .. '" ' | |||
html = html .. 'data-channel-id="' .. (videos.channel_id[j] or '') .. '" ' | |||
html = html .. 'data-author="' .. escapeQuotes(videos.author[j] or '') .. '" ' | |||
html = html .. 'data-published="' .. (videos.published_at[j] or '') .. '" ' | |||
html = html .. 'data-duration="' .. (videos.duration_sec[j] or '') .. '" ' | |||
html = html .. 'data-purpose="' .. escapeQuotes(videos.purpose[j] or '') .. '" ' | |||
html = html .. 'data-primary-tag="' .. (videos.primary_tag[j] or '') .. '" ' | |||
html = html .. 'data-secondary-tag="' .. (videos.secondary_tag[j] or '') .. '" ' | |||
html = html .. 'data-description="' .. escapeQuotes(videos.description[j] or '') .. '" ' | |||
html = html .. 'data-notes="' .. escapeQuotes(videos.video_notes[j] or '') .. '" ' | |||
html = html .. 'data-internal-link="' .. escapeQuotes(videos.video_internal_link[j] or '') .. '">\n' | |||
html = html .. ' <div class="video-thumbnail" style="background-image: url(\'https://img.youtube.com/vi/' .. (videos.youtube_id[j] or '') .. '/mqdefault.jpg\');">\n' | |||
if duration ~= '' then | |||
html = html .. ' <span class="video-duration">' .. duration .. '</span>\n' | |||
end | |||
html = html .. ' </div>\n' | |||
html = html .. ' <div class="video-info">\n' | |||
html = html .. ' <div class="video-title">' .. (videos.title[j] or '') .. '</div>\n' | |||
html = html .. ' <div class="video-channel">' .. (videos.channel_title[j] or '') .. '</div>\n' | |||
html = html .. ' </div>\n' | |||
html = html .. ' </div>\n' | |||
end | |||
end | end | ||
html = html .. ' </div>\n' | |||
html = html .. '</div>\n' | |||
</div> | |||
end | end | ||
end | end | ||
return html | |||
end | end | ||
-- | -- Render featured videos (shows videos from all categories) | ||
function p. | function p.renderFeaturedVideos(frame) | ||
local | local html = '' | ||
local | -- Get unique purposes from all categories | ||
local purposes = mw.ext.externalData.getExternalData{ | |||
source = 'externaldb', | |||
from = 'data_videos', | |||
data = 'purpose=purpose', | |||
where = "visibility='public' AND purpose IS NOT NULL", | |||
group_by = 'purpose', | |||
order_by = 'purpose', | |||
limit = 10 -- Limit featured to first 10 purposes | |||
} | |||
-- Loop through each purpose and create a section | |||
if purposes and purposes.purpose then | |||
for i, purpose in ipairs(purposes.purpose) do | |||
html = html .. '<div class="video-section">\n' | |||
html = html .. ' <div class="video-section-header">\n' | |||
html = html .. ' <h3 class="section-title">' .. purpose .. '</h3>\n' | |||
html = html .. ' </div>\n' | |||
html = html .. ' <div class="video-grid">\n' | |||
-- Get videos for this purpose | |||
local videos = mw.ext.externalData.getExternalData{ | |||
source = 'externaldb', | |||
from = 'data_videos', | |||
data = 'video_id=video_id,youtube_id=youtube_id,title=title,channel_title=channel_title,channel_id=channel_id,author=author,published_at=published_at,duration_sec=duration_sec,purpose=purpose,primary_tag=primary_tag,secondary_tag=secondary_tag,description=description,video_notes=video_notes,video_internal_link=video_internal_link', | |||
where = "purpose='" .. purpose .. "' AND visibility='public'", | |||
order_by = 'published_at DESC', | |||
limit = 4 -- Limit to 4 videos per purpose in featured | |||
} | |||
-- Render each video card | |||
if videos and videos.video_id then | |||
for j, video_id in ipairs(videos.video_id) do | |||
local duration = formatDuration(tonumber(videos.duration_sec[j] or 0)) | |||
html = html .. ' <div class="video-card" ' | |||
html = html .. 'data-video-id="' .. video_id .. '" ' | |||
html = html .. 'data-youtube-id="' .. (videos.youtube_id[j] or '') .. '" ' | |||
html = html .. 'data-title="' .. escapeQuotes(videos.title[j] or '') .. '" ' | |||
html = html .. 'data-channel="' .. escapeQuotes(videos.channel_title[j] or '') .. '" ' | |||
html = html .. 'data-channel-id="' .. (videos.channel_id[j] or '') .. '" ' | |||
html = html .. 'data-author="' .. escapeQuotes(videos.author[j] or '') .. '" ' | |||
html = html .. 'data-published="' .. (videos.published_at[j] or '') .. '" ' | |||
html = html .. 'data-duration="' .. (videos.duration_sec[j] or '') .. '" ' | |||
html = html .. 'data-purpose="' .. escapeQuotes(videos.purpose[j] or '') .. '" ' | |||
html = html .. 'data-primary-tag="' .. (videos.primary_tag[j] or '') .. '" ' | |||
html = html .. 'data-secondary-tag="' .. (videos.secondary_tag[j] or '') .. '" ' | |||
html = html .. 'data-description="' .. escapeQuotes(videos.description[j] or '') .. '" ' | |||
html = html .. 'data-notes="' .. escapeQuotes(videos.video_notes[j] or '') .. '" ' | |||
html = html .. 'data-internal-link="' .. escapeQuotes(videos.video_internal_link[j] or '') .. '">\n' | |||
html = html .. ' <div class="video-thumbnail" style="background-image: url(\'https://img.youtube.com/vi/' .. (videos.youtube_id[j] or '') .. '/mqdefault.jpg\');">\n' | |||
if duration ~= '' then | |||
html = html .. ' <span class="video-duration">' .. duration .. '</span>\n' | |||
end | |||
html = html .. ' </div>\n' | |||
html = html .. ' <div class="video-info">\n' | |||
html = html .. ' <div class="video-title">' .. (videos.title[j] or '') .. '</div>\n' | |||
html = html .. ' <div class="video-channel">' .. (videos.channel_title[j] or '') .. '</div>\n' | |||
html = html .. ' </div>\n' | |||
html = html .. ' </div>\n' | |||
end | |||
end | end | ||
html = html .. ' </div>\n' | |||
html = html .. '</div>\n' | |||
end | end | ||
end | end | ||
return html | |||
return | |||
end | end | ||
return p | return p | ||
Latest revision as of 17:43, 2 June 2025
Documentation for this module may be created at Module:VideoGallery/doc
-- Module:VideoGallery
-- Lua module for rendering video gallery sections
local p = {}
-- Helper function to escape quotes
local function escapeQuotes(str)
if not str then return '' end
return str:gsub('"', '"'):gsub("'", ''')
end
-- Helper function to format duration
local function formatDuration(seconds)
if not seconds or seconds == 0 then return '' end
local minutes = math.floor(seconds / 60)
local secs = seconds % 60
return string.format("%d:%02d", minutes, secs)
end
-- Render videos for a specific category
function p.renderCategoryVideos(frame)
local category = frame.args.category or 'Featured'
local html = ''
-- Get unique purposes for this category
local purposes = mw.ext.externalData.getExternalData{
source = 'externaldb',
from = 'data_videos',
data = 'purpose=purpose',
where = "primary_tag='" .. category .. "' AND visibility='public' AND purpose IS NOT NULL",
group_by = 'purpose',
order_by = 'purpose'
}
-- Loop through each purpose and create a section
if purposes and purposes.purpose then
for i, purpose in ipairs(purposes.purpose) do
html = html .. '<div class="video-section">\n'
html = html .. ' <div class="video-section-header">\n'
html = html .. ' <h3 class="section-title">' .. purpose .. '</h3>\n'
html = html .. ' </div>\n'
html = html .. ' <div class="video-grid">\n'
-- Get videos for this purpose
local videos = mw.ext.externalData.getExternalData{
source = 'externaldb',
from = 'data_videos',
data = 'video_id=video_id,youtube_id=youtube_id,title=title,channel_title=channel_title,channel_id=channel_id,author=author,published_at=published_at,duration_sec=duration_sec,purpose=purpose,primary_tag=primary_tag,secondary_tag=secondary_tag,description=description,video_notes=video_notes,video_internal_link=video_internal_link',
where = "primary_tag='" .. category .. "' AND purpose='" .. purpose .. "' AND visibility='public'",
order_by = 'published_at DESC'
}
-- Render each video card
if videos and videos.video_id then
for j, video_id in ipairs(videos.video_id) do
local duration = formatDuration(tonumber(videos.duration_sec[j] or 0))
html = html .. ' <div class="video-card" '
html = html .. 'data-video-id="' .. video_id .. '" '
html = html .. 'data-youtube-id="' .. (videos.youtube_id[j] or '') .. '" '
html = html .. 'data-title="' .. escapeQuotes(videos.title[j] or '') .. '" '
html = html .. 'data-channel="' .. escapeQuotes(videos.channel_title[j] or '') .. '" '
html = html .. 'data-channel-id="' .. (videos.channel_id[j] or '') .. '" '
html = html .. 'data-author="' .. escapeQuotes(videos.author[j] or '') .. '" '
html = html .. 'data-published="' .. (videos.published_at[j] or '') .. '" '
html = html .. 'data-duration="' .. (videos.duration_sec[j] or '') .. '" '
html = html .. 'data-purpose="' .. escapeQuotes(videos.purpose[j] or '') .. '" '
html = html .. 'data-primary-tag="' .. (videos.primary_tag[j] or '') .. '" '
html = html .. 'data-secondary-tag="' .. (videos.secondary_tag[j] or '') .. '" '
html = html .. 'data-description="' .. escapeQuotes(videos.description[j] or '') .. '" '
html = html .. 'data-notes="' .. escapeQuotes(videos.video_notes[j] or '') .. '" '
html = html .. 'data-internal-link="' .. escapeQuotes(videos.video_internal_link[j] or '') .. '">\n'
html = html .. ' <div class="video-thumbnail" style="background-image: url(\'https://img.youtube.com/vi/' .. (videos.youtube_id[j] or '') .. '/mqdefault.jpg\');">\n'
if duration ~= '' then
html = html .. ' <span class="video-duration">' .. duration .. '</span>\n'
end
html = html .. ' </div>\n'
html = html .. ' <div class="video-info">\n'
html = html .. ' <div class="video-title">' .. (videos.title[j] or '') .. '</div>\n'
html = html .. ' <div class="video-channel">' .. (videos.channel_title[j] or '') .. '</div>\n'
html = html .. ' </div>\n'
html = html .. ' </div>\n'
end
end
html = html .. ' </div>\n'
html = html .. '</div>\n'
end
end
return html
end
-- Render featured videos (shows videos from all categories)
function p.renderFeaturedVideos(frame)
local html = ''
-- Get unique purposes from all categories
local purposes = mw.ext.externalData.getExternalData{
source = 'externaldb',
from = 'data_videos',
data = 'purpose=purpose',
where = "visibility='public' AND purpose IS NOT NULL",
group_by = 'purpose',
order_by = 'purpose',
limit = 10 -- Limit featured to first 10 purposes
}
-- Loop through each purpose and create a section
if purposes and purposes.purpose then
for i, purpose in ipairs(purposes.purpose) do
html = html .. '<div class="video-section">\n'
html = html .. ' <div class="video-section-header">\n'
html = html .. ' <h3 class="section-title">' .. purpose .. '</h3>\n'
html = html .. ' </div>\n'
html = html .. ' <div class="video-grid">\n'
-- Get videos for this purpose
local videos = mw.ext.externalData.getExternalData{
source = 'externaldb',
from = 'data_videos',
data = 'video_id=video_id,youtube_id=youtube_id,title=title,channel_title=channel_title,channel_id=channel_id,author=author,published_at=published_at,duration_sec=duration_sec,purpose=purpose,primary_tag=primary_tag,secondary_tag=secondary_tag,description=description,video_notes=video_notes,video_internal_link=video_internal_link',
where = "purpose='" .. purpose .. "' AND visibility='public'",
order_by = 'published_at DESC',
limit = 4 -- Limit to 4 videos per purpose in featured
}
-- Render each video card
if videos and videos.video_id then
for j, video_id in ipairs(videos.video_id) do
local duration = formatDuration(tonumber(videos.duration_sec[j] or 0))
html = html .. ' <div class="video-card" '
html = html .. 'data-video-id="' .. video_id .. '" '
html = html .. 'data-youtube-id="' .. (videos.youtube_id[j] or '') .. '" '
html = html .. 'data-title="' .. escapeQuotes(videos.title[j] or '') .. '" '
html = html .. 'data-channel="' .. escapeQuotes(videos.channel_title[j] or '') .. '" '
html = html .. 'data-channel-id="' .. (videos.channel_id[j] or '') .. '" '
html = html .. 'data-author="' .. escapeQuotes(videos.author[j] or '') .. '" '
html = html .. 'data-published="' .. (videos.published_at[j] or '') .. '" '
html = html .. 'data-duration="' .. (videos.duration_sec[j] or '') .. '" '
html = html .. 'data-purpose="' .. escapeQuotes(videos.purpose[j] or '') .. '" '
html = html .. 'data-primary-tag="' .. (videos.primary_tag[j] or '') .. '" '
html = html .. 'data-secondary-tag="' .. (videos.secondary_tag[j] or '') .. '" '
html = html .. 'data-description="' .. escapeQuotes(videos.description[j] or '') .. '" '
html = html .. 'data-notes="' .. escapeQuotes(videos.video_notes[j] or '') .. '" '
html = html .. 'data-internal-link="' .. escapeQuotes(videos.video_internal_link[j] or '') .. '">\n'
html = html .. ' <div class="video-thumbnail" style="background-image: url(\'https://img.youtube.com/vi/' .. (videos.youtube_id[j] or '') .. '/mqdefault.jpg\');">\n'
if duration ~= '' then
html = html .. ' <span class="video-duration">' .. duration .. '</span>\n'
end
html = html .. ' </div>\n'
html = html .. ' <div class="video-info">\n'
html = html .. ' <div class="video-title">' .. (videos.title[j] or '') .. '</div>\n'
html = html .. ' <div class="video-channel">' .. (videos.channel_title[j] or '') .. '</div>\n'
html = html .. ' </div>\n'
html = html .. ' </div>\n'
end
end
html = html .. ' </div>\n'
html = html .. '</div>\n'
end
end
return html
end
return p
