Quick fixes

- Usage of headerNewsTabs()
- Remove 'Login' button from newswire column
- Display front page correctly when not logged in
- Add multi/themed CSS to front page and edit profile page
- Show site banner on profile edit page
- Include edit profile in "user pages" list
alt-html-css
Admin 2020-12-12 19:38:38 +00:00
parent 0724c3468d
commit 7d60cdacb2
6 changed files with 158 additions and 63 deletions

View File

@ -306,7 +306,7 @@ def htmlLinksMobile(cssCache: {}, baseDir: str,
# Full row "navbar" # Full row "navbar"
if defaultTimeline == 'tlfeatures': if defaultTimeline == 'tlfeatures':
# Show "tab" links instead of standard "buttons" # Show "tab" links instead of standard "buttons"
htmlStr += headerNewsTabs('linksmobile', translate, usersPath, baseDir, userPages) htmlStr += headerNewsTabs('linksmobile', translate, usersPath, baseDir, authorized, userPages)
# Close banner div # Close banner div
htmlStr += '</div>\n' htmlStr += '</div>\n'

View File

@ -61,6 +61,7 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
if ':' in domain: if ':' in domain:
domain = domain.split(':') domain = domain.split(':')
publishButtonStr = None
if authorized: if authorized:
# only show the publish button if logged in, otherwise replace it with # only show the publish button if logged in, otherwise replace it with
# a login button # a login button
@ -70,15 +71,16 @@ def getRightColumnContent(baseDir: str, nickname: str, domainFull: str,
'title="' + translate['Publish a news article'] + '">' + \ 'title="' + translate['Publish a news article'] + '">' + \
'<button class="publishbtn">' + \ '<button class="publishbtn">' + \
translate['Publish'] + '</button></a>\n' translate['Publish'] + '</button></a>\n'
else: # NOTE: Removed from this fork as is handled by 'htmlFooter' in webapp_utils.py
# if not logged in then replace the publish button with # else:
# a login button # # if not logged in then replace the publish button with
publishButtonStr = \ # # a login button
' <a href="/login"><button class="publishbtn">' + \ # publishButtonStr = \
translate['Login'] + '</button></a>\n' # ' <a href="/login"><button class="publishbtn">' + \
# translate['Login'] + '</button></a>\n'
# show publish button at the top if needed # show publish button at the top if needed
if publishButtonAtTop: if publishButtonStr and publishButtonAtTop:
htmlStr += '<center>' + publishButtonStr + '</center>' htmlStr += '<center>' + publishButtonStr + '</center>'
editImageClass = '' editImageClass = ''
@ -477,7 +479,7 @@ def htmlNewswireMobile(cssCache: {}, baseDir: str, nickname: str,
# Full row "navbar" # Full row "navbar"
if defaultTimeline == 'tlfeatures': if defaultTimeline == 'tlfeatures':
# Show "tab" links instead of standard "buttons" # Show "tab" links instead of standard "buttons"
htmlStr += headerNewsTabs('newswiremobile', translate, usersPath, baseDir, userPages) htmlStr += headerNewsTabs('newswiremobile', translate, usersPath, baseDir, authorized, userPages)
# Close banner div # Close banner div
htmlStr += '</div>\n' htmlStr += '</div>\n'

View File

@ -599,7 +599,10 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
if defaultTimeline == 'tlfeatures': if defaultTimeline == 'tlfeatures':
# Show "tab" links instead of standard "buttons" # Show "tab" links instead of standard "buttons"
# NOTE: "inbox" is used as a generic boxName, as with 'User' pages # NOTE: "inbox" is used as a generic boxName, as with 'User' pages
newPostForm += headerNewsTabs('inbox', translate, usersPath, baseDir, userPages) # NOTE: It should be "safe" to assume that this code would not be running,
# unless the user was already deemed 'authorized',
# thus allowing us to pass True directly
newPostForm += headerNewsTabs('inbox', translate, usersPath, baseDir, True, userPages)
# Close banner div # Close banner div
newPostForm += '</div>\n' newPostForm += '</div>\n'
@ -798,7 +801,7 @@ def htmlNewPost(cssCache: {}, mediaInstance: bool, translate: {},
newPostForm += ' </div>\n' newPostForm += ' </div>\n'
newPostForm += '</form>\n' newPostForm += '</form>\n'
# Close "section" and "page" div # Close "main" and "page" div
newPostForm += '</div><!-- div main -->\n</div><!-- div page -->\n' newPostForm += '</div><!-- div main -->\n</div><!-- div page -->\n'
if not reportUrl: if not reportUrl:

View File

@ -9,12 +9,14 @@ __status__ = "Production"
import os import os
from utils import isSystemAccount from utils import isSystemAccount
from utils import getDomainFromActor from utils import getDomainFromActor
from utils import getConfigParam
from person import personBoxJson from person import personBoxJson
from webapp_utils import htmlHeaderWithExternalStyle from webapp_utils import htmlHeaderWithExternalStyles
from webapp_utils import htmlFooter from webapp_utils import htmlFooter
from webapp_utils import getBannerFile from webapp_utils import getBannerFile
from webapp_utils import htmlPostSeparator from webapp_utils import htmlPostSeparator
from webapp_utils import headerButtonsFrontScreen from webapp_utils import headerButtonsFrontScreen
from webapp_headerbuttons import headerNewsTabs
from webapp_column_left import getLeftColumnContent from webapp_column_left import getLeftColumnContent
from webapp_column_right import getRightColumnContent from webapp_column_right import getRightColumnContent
from webapp_post import individualPostAsHtml from webapp_post import individualPostAsHtml
@ -106,41 +108,61 @@ def htmlFrontScreen(rssIconAtTop: bool,
if port: if port:
domainFull = domain + ':' + str(port) domainFull = domain + ':' + str(port)
loginButton = headerButtonsFrontScreen(translate, nickname,
'features', authorized,
iconsAsButtons)
# If this is the news account then show a different banner # If this is the news account then show a different banner
bannerFile, bannerFilename = \ bannerFile, bannerFilename = getBannerFile(baseDir, nickname, domain)
getBannerFile(baseDir, nickname, domain, theme)
profileHeaderStr = \
'<img loading="lazy" class="timeline-banner" ' + \
'src="/users/' + nickname + '/' + bannerFile + '" />\n'
if loginButton:
profileHeaderStr += '<center>' + loginButton + '</center>\n'
profileHeaderStr += '<table class="timeline">\n' profileHeaderStr = '<div class="header">\n'
profileHeaderStr += ' <colgroup>\n'
profileHeaderStr += ' <col span="1" class="column-left">\n' # TODO: News instances should ignore personalised banners
profileHeaderStr += ' <col span="1" class="column-center">\n' # Currently uses the 'news' actor banner - as it remains unchanged
profileHeaderStr += ' <col span="1" class="column-right">\n' profileHeaderStr += (f"\t<a class=\"timeline-banner hidden-text\" href=\"/users/{nickname}/tlfeatures\">"
profileHeaderStr += ' </colgroup>\n' f"{translate['Features']}</a>\n"
profileHeaderStr += ' <tbody>\n' f"\t<div class=\"title\">\n"
profileHeaderStr += ' <tr>\n' f"\t\t<span>#IndymediaBack</span>\n"
profileHeaderStr += ' <td valign="top" class="col-left">\n' f"\t</div>\n")
profileHeaderStr += \
# Show "tab" links instead of standard "buttons"
profileHeaderStr += headerNewsTabs('tlfeatures', translate, '/users/news', baseDir, authorized, None)
# Close banner div
profileHeaderStr += '</div>\n'
# TODO: Should probably use a more generic class, easier to re-use and help simplify CSS
# NOTE: Related also to class "page" added to 'webapp_create_post.py'
profileHeaderStr += '<div class="timeline">\n'
iconsPath = getIconsWebPath(baseDir)
leftColumnStr = \
getLeftColumnContent(baseDir, 'news', domainFull, getLeftColumnContent(baseDir, 'news', domainFull,
httpPrefix, translate, httpPrefix, translate,
False, False, None, rssIconAtTop, True, iconsPath, False,
True, theme) False, None, rssIconAtTop, True,
profileHeaderStr += ' </td>\n' True)
profileHeaderStr += ' <td valign="top" class="col-center">\n' profileHeaderStr += ' <div class="section links">\n' + \
leftColumnStr + ' </div>\n'
profileStr = profileHeaderStr profileStr = profileHeaderStr
cssFilename = baseDir + '/epicyon-profile.css' cssFiles = []
# TODO: Clean up - default load only one base css file
# default css
cssFiles.append(baseDir + '/epicyon-profile.css')
if os.path.isfile(baseDir + '/epicyon.css'): if os.path.isfile(baseDir + '/epicyon.css'):
cssFilename = baseDir + '/epicyon.css' cssFiles[0] = baseDir + '/epicyon.css'
# TODO: Clean up and remove this override
cssFiles[0] = 'base.css'
# Get theme-specific css if exists - must be named '<theme-name>.css'
themeName = getConfigParam(baseDir, 'theme')
themePath = f'{baseDir}/theme/{themeName}.css'
if os.path.isfile(themePath):
cssFiles.append('theme/' + themeName + '.css')
# center column containing posts
profileStr += ' <div class="section main">\n'
licenseStr = '' licenseStr = ''
bannerFile, bannerFilename = \ bannerFile, bannerFilename = \
@ -156,21 +178,27 @@ def htmlFrontScreen(rssIconAtTop: bool,
showPublishedDateOnly, showPublishedDateOnly,
peertubeInstances) + licenseStr peertubeInstances) + licenseStr
# end of div main
profileStr += ' </div>\n'
# Footer which is only used for system accounts # Footer which is only used for system accounts
profileFooterStr = ' </td>\n'
profileFooterStr += ' <td valign="top" class="col-right">\n' iconsPath = getIconsWebPath(baseDir)
profileFooterStr += \ rightColumnStr = \
getRightColumnContent(baseDir, 'news', domainFull, getRightColumnContent(baseDir, 'news', domainFull,
httpPrefix, translate, httpPrefix, translate,
False, False, newswire, False, False, False, newswire, False,
False, None, False, False, False, None, False, False,
False, True, authorized, True, theme) False, True, authorized, True)
profileFooterStr += ' </td>\n'
profileFooterStr += ' </tr>\n' profileFooterStr = ' <div class="section newswire">' + \
profileFooterStr += ' </tbody>\n' rightColumnStr + ' </div>\n'
profileFooterStr += '</table>\n'
# Close div page
profileFooterStr += '</div>\n'
profileStr = \ profileStr = \
htmlHeaderWithExternalStyle(cssFilename) + \ htmlHeaderWithExternalStyles(cssFiles) + \
profileStr + profileFooterStr + htmlFooter() profileStr + profileFooterStr + htmlFooter()
return profileStr return profileStr

View File

@ -27,6 +27,7 @@ from session import getJson
from posts import parseUserFeed from posts import parseUserFeed
from posts import getUserUrl from posts import getUserUrl
from posts import getPersonBox from posts import getPersonBox
from posts import isModerator
from donate import getDonationUrl from donate import getDonationUrl
from xmpp import getXmppAddress from xmpp import getXmppAddress
from matrix import getMatrixAddress from matrix import getMatrixAddress
@ -42,7 +43,8 @@ from follow import isFollowerOfPerson
from webapp_frontscreen import htmlFrontScreen from webapp_frontscreen import htmlFrontScreen
from webapp_utils import scheduledPostsExist from webapp_utils import scheduledPostsExist
from webapp_utils import getPersonAvatarUrl from webapp_utils import getPersonAvatarUrl
from webapp_utils import htmlHeaderWithExternalStyle from webapp_utils import getIconsWebPath
from webapp_utils import htmlHeaderWithExternalStyle, htmlHeaderWithExternalStyles
from webapp_utils import htmlFooter from webapp_utils import htmlFooter
from webapp_utils import addEmojiToDisplayName from webapp_utils import addEmojiToDisplayName
from webapp_utils import getBannerFile from webapp_utils import getBannerFile
@ -50,6 +52,7 @@ from webapp_utils import htmlPostSeparator
from webapp_utils import getBlogAddress from webapp_utils import getBlogAddress
from webapp_post import individualPostAsHtml from webapp_post import individualPostAsHtml
from webapp_timeline import htmlIndividualShare from webapp_timeline import htmlIndividualShare
from webapp_headerbuttons import headerButtonsTimeline, headerNewsTabs
def htmlProfileAfterSearch(cssCache: {}, def htmlProfileAfterSearch(cssCache: {},
@ -1046,9 +1049,22 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
'class="slider" name="skillValue' + \ 'class="slider" name="skillValue' + \
str(skillCtr) + '" value="50"></p>' str(skillCtr) + '" value="50"></p>'
cssFilename = baseDir + '/epicyon-profile.css' cssFiles = []
# the css filename
cssFiles.append(baseDir + '/epicyon-profile.css')
if os.path.isfile(baseDir + '/epicyon.css'): if os.path.isfile(baseDir + '/epicyon.css'):
cssFilename = baseDir + '/epicyon.css' cssFiles[0] = baseDir + '/epicyon.css'
# TODO: Clean up and remove this override
cssFiles[0] = 'base.css'
# Get theme-specific css if exists - must be named '<theme-name>.css'
themeName = getConfigParam(baseDir, 'theme')
themePath = f'{baseDir}/theme/{themeName}.css'
if os.path.isfile(themePath):
cssFiles.append('theme/' + themeName + '.css')
moderatorsStr = '' moderatorsStr = ''
themesDropdown = '' themesDropdown = ''
@ -1186,15 +1202,60 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
'style="height:200px">' + peertubeInstancesStr + \ 'style="height:200px">' + peertubeInstancesStr + \
'</textarea>\n' '</textarea>\n'
editProfileForm = htmlHeaderWithExternalStyle(cssFilename) editProfileForm = htmlHeaderWithExternalStyles(cssFiles)
usersPath = '/users/' + nickname
# top banner # top banner
editProfileForm += '<div class="header">\n'
if not defaultTimeline == 'tlfeatures':
editProfileForm += (f"\t<a class=\"timeline-banner hidden-text\" href=\"/users/{nickname}/{defaultTimeline}\" "
f"style=\"background-image: url('{usersPath}/{bannerFile}');\">"
f"{translate['Switch to timeline view']}</a>\n")
else:
# TODO: News instances should ignore personalised banners
# Currently uses the 'news' actor banner - as it remains unchanged
editProfileForm += (f"\t<a class=\"timeline-banner hidden-text\" href=\"/users/{nickname}/tlfeatures\">"
f"{translate['Features']}</a>\n"
f"\t<div class=\"title\">\n"
f"\t\t<span>#IndymediaBack</span>\n"
f"\t</div>\n")
# Certain Epciyon pages should only be accessible via the 'User' page for News instances
userPages = ['inbox', 'outbox', 'dm', 'tlreplies', 'tlblogs', 'tlmedia', 'tlshares', \
'tlsaves', 'tlevents', 'tlbookmarks', 'moderation', 'search', \
'followers', 'newfollowers', 'newdm', 'newpost', 'newblog', 'newevent', 'editprofile']
# Full row "navbar"
if defaultTimeline == 'tlfeatures':
# Show "tab" links instead of standard "buttons"
# NOTE: It should be "safe" to assume that this code would not be running,
# unless the user was already deemed 'authorized',
# thus allowing us to pass True directly
editProfileForm += headerNewsTabs('editprofile', translate, usersPath, baseDir, True, userPages)
# Close banner div
editProfileForm += '</div>\n'
# TODO: Place form inside a "page" div for 'News' instances
# NOTE: Duplicate of code from webapp_create_post.py
editProfileForm += '<div class="page">\n'
moderator = isModerator(baseDir, nickname)
# TODO: Add "User" links
if defaultTimeline == 'tlfeatures':
# TODO: Determine if "editprofile" is the appropriate 'boxName'
editProfileForm += \ editProfileForm += \
'<a href="/users/' + nickname + '/' + defaultTimeline + '" title="' + \ headerButtonsTimeline(defaultTimeline, 'editprofile', 1,
translate['Switch to timeline view'] + '" alt="' + \ translate, usersPath,
translate['Switch to timeline view'] + '">\n' False, moderator,
editProfileForm += '<img loading="lazy" class="timeline-banner" src="' + \ False,
'/users/' + nickname + '/' + bannerFile + '" /></a>\n' baseDir, nickname,
domain, None,
True, userPages)
editProfileForm += '<div class="section main">\n'
editProfileForm += \ editProfileForm += \
'<form enctype="multipart/form-data" method="POST" ' + \ '<form enctype="multipart/form-data" method="POST" ' + \
@ -1494,6 +1555,10 @@ def htmlEditProfile(cssCache: {}, translate: {}, baseDir: str, path: str,
editProfileForm += ' </div>\n' editProfileForm += ' </div>\n'
editProfileForm += ' </div>\n' editProfileForm += ' </div>\n'
editProfileForm += '</form>\n' editProfileForm += '</form>\n'
# Close "main" and "page" div
editProfileForm += '</div><!-- div main -->\n</div><!-- div page -->\n'
editProfileForm += htmlFooter() editProfileForm += htmlFooter()
return editProfileForm return editProfileForm

View File

@ -162,19 +162,16 @@ def htmlTimeline(cssCache: {}, defaultTimeline: str,
f"\t</div>\n") f"\t</div>\n")
# TODO: Include '/editprofile' link on 'User' page for 'News' instances
# Certain Epciyon pages should only be accessible via the 'User' page for News instances # Certain Epciyon pages should only be accessible via the 'User' page for News instances
# TODO: The 'new...' pages appear to require handling elsewhere # TODO: The 'new...' pages appear to require handling elsewhere
userPages = ['inbox', 'outbox', 'dm', 'tlreplies', 'tlblogs', 'tlmedia', 'tlshares', \ userPages = ['inbox', 'outbox', 'dm', 'tlreplies', 'tlblogs', 'tlmedia', 'tlshares', \
'tlsaves', 'tlevents', 'tlbookmarks', 'moderation', 'search', \ 'tlsaves', 'tlevents', 'tlbookmarks', 'moderation', 'search', \
'followers', 'newfollowers', 'newdm', 'newpost', 'newblog', 'newevent'] 'followers', 'newfollowers', 'newdm', 'newpost', 'newblog', 'newevent', 'editprofile']
# Full row "navbar" # Full row "navbar"
if defaultTimeline == 'tlfeatures': if defaultTimeline == 'tlfeatures':
# Show "tab" links instead of standard "buttons" # Show "tab" links instead of standard "buttons"
tlStr += headerNewsTabs(boxName, translate, usersPath, baseDir, userPages) tlStr += headerNewsTabs(boxName, translate, usersPath, baseDir, authorized, userPages)
# Close banner div # Close banner div
tlStr += '</div>\n' tlStr += '</div>\n'