Added the theme system.
You can now switch between themes in the Control Panel. The Alternate Post Layout teased in various screenshots and bits of inaccessible code is now the Tempra Conflux theme, while the original post layout is the Tempa Simple theme. Dramatically increased the speed at which the static files are served. Added a benchmark for static files. Eliminated the name parameter in various custom page structs. Added the TopicsPage struct for the /topics/ route. Added the ForumPage struct for the /forum/{id} route. Added the ForumsPage struct for the /forums/ route. The static file route now serves 404s when a file doesn't exist instead of nearly crashing the server. Reduced the number of unnecessary allocations on some of the routes. Added gradients to Tempra Conflux. Added position: sticky; to the userinfo blocks in Tempra Conflux. Added a notice on the generated template files.
18
data.sql
|
@ -99,8 +99,15 @@ CREATE TABLE `plugins`(
|
||||||
unique(`uname`)
|
unique(`uname`)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
CREATE TABLE `themes`(
|
||||||
|
`uname` varchar(200) not null,
|
||||||
|
`default` tinyint DEFAULT 0 not null,
|
||||||
|
unique(`uname`)
|
||||||
|
);
|
||||||
|
|
||||||
INSERT INTO settings(`name`,`content`,`type`) VALUES ('url_tags','1','bool');
|
INSERT INTO settings(`name`,`content`,`type`) VALUES ('url_tags','1','bool');
|
||||||
INSERT INTO settings(`name`,`content`,`type`,`constraints`) VALUES ('activation_type','1','list','1-3',);
|
INSERT INTO settings(`name`,`content`,`type`,`constraints`) VALUES ('activation_type','1','list','1-3',);
|
||||||
|
INSERT INTO themes(`uname`,`default`) VALUES ('tempra-simple',1);
|
||||||
|
|
||||||
INSERT INTO users(`name`,`email`,`group`,`is_super_admin`,`createdAt`,`lastActiveAt`,`message`)
|
INSERT INTO users(`name`,`email`,`group`,`is_super_admin`,`createdAt`,`lastActiveAt`,`message`)
|
||||||
VALUES ('Admin','admin@localhost',1,1,NOW(),NOW(),'');
|
VALUES ('Admin','admin@localhost',1,1,NOW(),NOW(),'');
|
||||||
|
@ -118,6 +125,7 @@ EditUserGroupSuperMod
|
||||||
EditUserGroupAdmin
|
EditUserGroupAdmin
|
||||||
ManageForums
|
ManageForums
|
||||||
EditSettings
|
EditSettings
|
||||||
|
ManageThemes
|
||||||
ManagePlugins
|
ManagePlugins
|
||||||
ViewIPs
|
ViewIPs
|
||||||
|
|
||||||
|
@ -132,11 +140,11 @@ PinTopic
|
||||||
CloseTopic
|
CloseTopic
|
||||||
*/
|
*/
|
||||||
|
|
||||||
INSERT INTO users_groups(`name`,`permissions`,`active`,`is_mod`,`is_admin`,`tag`) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManagePlugins":true,"ViewIPs":true,"ViewTopic":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}',1,1,1,"Admin");
|
INSERT INTO users_groups(`name`,`permissions`,`active`,`is_mod`,`is_admin`,`tag`) VALUES ('Administrator','{"BanUsers":true,"ActivateUsers":true,"EditUser":true,"EditUserEmail":true,"EditUserPassword":true,"EditUserGroup":true,"EditUserGroupSuperMod":true,"EditUserGroupAdmin":false,"ManageForums":true,"EditSettings":true,"ManageThemes":true,"ManagePlugins":true,"ViewIPs":true,"ViewTopic":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}',1,1,1,"Admin");
|
||||||
INSERT INTO users_groups(`name`,`permissions`,`is_mod`,`tag`) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":true,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManagePlugins":false,"ViewIPs":true,"ViewTopic":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}',1,"Mod");
|
INSERT INTO users_groups(`name`,`permissions`,`is_mod`,`tag`) VALUES ('Moderator','{"BanUsers":true,"ActivateUsers":false,"EditUser":true,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":true,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManageThemes":false,"ManagePlugins":false,"ViewIPs":true,"ViewTopic":true,"CreateTopic":true,"EditTopic":true,"DeleteTopic":true,"CreateReply":true,"EditReply":true,"DeleteReply":true,"PinTopic":true,"CloseTopic":true}',1,"Mod");
|
||||||
INSERT INTO users_groups(`name`,`permissions`) VALUES ('Member','{"BanUsers":false,"ActivateUsers":false,"EditUser":false,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":false,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManagePlugins":false,"ViewIPs":false,"ViewTopic":true,"CreateTopic":true,"EditTopic":false,"DeleteTopic":false,"CreateReply":true,"EditReply":false,"DeleteReply":false,"PinTopic":false,"CloseTopic":false}');
|
INSERT INTO users_groups(`name`,`permissions`) VALUES ('Member','{"BanUsers":false,"ActivateUsers":false,"EditUser":false,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":false,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManageThemes":false,"ManagePlugins":false,"ViewIPs":false,"ViewTopic":true,"CreateTopic":true,"EditTopic":false,"DeleteTopic":false,"CreateReply":true,"EditReply":false,"DeleteReply":false,"PinTopic":false,"CloseTopic":false}');
|
||||||
INSERT INTO users_groups(`name`,`permissions`,`is_banned`) VALUES ('Banned','{"BanUsers":false,"ActivateUsers":false,"EditUser":false,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":false,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManagePlugins":false,"ViewIPs":false,"ViewTopic":true,"CreateTopic":false,"EditTopic":false,"DeleteTopic":false,"CreateReply":false,"EditReply":false,"DeleteReply":false,"PinTopic":false,"CloseTopic":false}',1);
|
INSERT INTO users_groups(`name`,`permissions`,`is_banned`) VALUES ('Banned','{"BanUsers":false,"ActivateUsers":false,"EditUser":false,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":false,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManageThemes":false,"ManagePlugins":false,"ViewIPs":false,"ViewTopic":true,"CreateTopic":false,"EditTopic":false,"DeleteTopic":false,"CreateReply":false,"EditReply":false,"DeleteReply":false,"PinTopic":false,"CloseTopic":false}',1);
|
||||||
INSERT INTO users_groups(`name`,`permissions`,`is_banned`) VALUES ('Awaiting Activation','{"BanUsers":false,"ActivateUsers":false,"EditUser":false,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":false,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManagePlugins":false,"ViewIPs":false,"ViewTopic":true,"CreateTopic":false,"EditTopic":false,"DeleteTopic":false,"CreateReply":false,"EditReply":false,"DeleteReply":false,"PinTopic":false,"CloseTopic":false}');
|
INSERT INTO users_groups(`name`,`permissions`,`is_banned`) VALUES ('Awaiting Activation','{"BanUsers":false,"ActivateUsers":false,"EditUser":false,"EditUserEmail":false,"EditUserPassword":false,"EditUserGroup":false,"EditUserGroupSuperMod":false,"EditUserGroupAdmin":false,"ManageForums":false,"EditSettings":false,"ManageThemes":false,"ManagePlugins":false,"ViewIPs":false,"ViewTopic":true,"CreateTopic":false,"EditTopic":false,"DeleteTopic":false,"CreateReply":false,"EditReply":false,"DeleteReply":false,"PinTopic":false,"CloseTopic":false}');
|
||||||
|
|
||||||
INSERT INTO forums(`name`,`lastTopicTime`) VALUES ('General',NOW());
|
INSERT INTO forums(`name`,`lastTopicTime`) VALUES ('General',NOW());
|
||||||
INSERT INTO topics(`title`,`content`,`createdAt`,`lastReplyAt`,`createdBy`,`parentID`)
|
INSERT INTO topics(`title`,`content`,`createdAt`,`lastReplyAt`,`createdBy`,`parentID`)
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
{
|
||||||
|
"Name": "tempra-simple",
|
||||||
|
"FriendlyName": "Tempra Simple",
|
||||||
|
"Version": "0.0.1",
|
||||||
|
"Creator": "Azareal",
|
||||||
|
"Settings": {
|
||||||
|
"PostLayout": {
|
||||||
|
"FriendlyName":"Post Layout",
|
||||||
|
"Options": ["Compact","Alternate"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Templates": [
|
||||||
|
{
|
||||||
|
"Name": "topic",
|
||||||
|
"Source": "topic_alt",
|
||||||
|
"When": "PostLayout=Alternate"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
<?xml version="1.0" ?>
|
||||||
|
<theme>
|
||||||
|
<name>tempra-simple</name>
|
||||||
|
<friendlyName>Tempra Simple</friendlyName>
|
||||||
|
<version>0.0.1</version>
|
||||||
|
<creator url="http://github.com/Azareal">Azareal</creator>
|
||||||
|
<settings>
|
||||||
|
<name>PostLayout</name>
|
||||||
|
<friendlyName>Post Layout</name>
|
||||||
|
<options>
|
||||||
|
<option>Compact</option>
|
||||||
|
<option>Alternate</option>
|
||||||
|
</options>
|
||||||
|
</settings>
|
||||||
|
<templates>
|
||||||
|
<template name="topic" src="topic_alt" when="PostLayout=Alternate"></template>
|
||||||
|
</templates>
|
||||||
|
</theme>
|
11
extend.go
|
@ -1,5 +1,6 @@
|
||||||
/* Copyright Azareal 2016 - 2017 */
|
/* Copyright Azareal 2016 - 2017 */
|
||||||
package main
|
package main
|
||||||
|
import "log"
|
||||||
|
|
||||||
var plugins map[string]Plugin = make(map[string]Plugin)
|
var plugins map[string]Plugin = make(map[string]Plugin)
|
||||||
var hooks map[string]func(interface{})interface{} = make(map[string]func(interface{})interface{})
|
var hooks map[string]func(interface{})interface{} = make(map[string]func(interface{})interface{})
|
||||||
|
@ -24,6 +25,16 @@ type Plugin struct
|
||||||
hooks[name] = handler
|
hooks[name] = handler
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
func init_plugins() {
|
||||||
|
for name, body := range plugins {
|
||||||
|
log.Print("Added plugin " + name)
|
||||||
|
if body.Active {
|
||||||
|
log.Print("Initialised plugin " + name)
|
||||||
|
plugins[name].Init()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func add_hook(name string, handler interface{}) {
|
func add_hook(name string, handler interface{}) {
|
||||||
switch h := handler.(type) {
|
switch h := handler.(type) {
|
||||||
case func(interface{})interface{}:
|
case func(interface{})interface{}:
|
||||||
|
|
|
@ -31,8 +31,8 @@ func BenchmarkTopicTemplate(b *testing.B) {
|
||||||
replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
||||||
replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
replyList = append(replyList, Reply{0,0,"Hey everyone!",template.HTML("Hey everyone!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
||||||
|
|
||||||
tpage := TopicPage{"Topic Blah","topic",user,noticeList,replyList,topic,false}
|
tpage := TopicPage{"Topic Blah",user,noticeList,replyList,topic,false}
|
||||||
tpage2 := TopicPage{"Topic Blah","topic",admin,noticeList,replyList,topic,false}
|
tpage2 := TopicPage{"Topic Blah",admin,noticeList,replyList,topic,false}
|
||||||
w := ioutil.Discard
|
w := ioutil.Discard
|
||||||
|
|
||||||
b.Run("compiled_useradmin", func(b *testing.B) {
|
b.Run("compiled_useradmin", func(b *testing.B) {
|
||||||
|
@ -65,7 +65,7 @@ func BenchmarkTopicsTemplate(b *testing.B) {
|
||||||
var noticeList map[int]string = make(map[int]string)
|
var noticeList map[int]string = make(map[int]string)
|
||||||
noticeList[0] = "test"
|
noticeList[0] = "test"
|
||||||
|
|
||||||
var topicList []interface{}
|
var topicList []TopicUser
|
||||||
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
||||||
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
||||||
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
||||||
|
@ -77,8 +77,8 @@ func BenchmarkTopicsTemplate(b *testing.B) {
|
||||||
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
||||||
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
topicList = append(topicList, TopicUser{0,"Hey everyone!",template.HTML("Hey everyone!"),0,false,false,"0000-00-00 00:00:00",1,"open","Admin","",no_css_tmpl,0,"Admin","","",""})
|
||||||
|
|
||||||
tpage := Page{"Topic Blah","topic",user,noticeList,topicList,0}
|
tpage := TopicsPage{"Topic Blah",user,noticeList,topicList,0}
|
||||||
tpage2 := Page{"Topic Blah","topic",admin,noticeList,topicList,0}
|
tpage2 := TopicsPage{"Topic Blah",admin,noticeList,topicList,0}
|
||||||
w := ioutil.Discard
|
w := ioutil.Discard
|
||||||
|
|
||||||
b.Run("compiled_useradmin", func(b *testing.B) {
|
b.Run("compiled_useradmin", func(b *testing.B) {
|
||||||
|
@ -138,6 +138,10 @@ func BenchmarkRoute(b *testing.B) {
|
||||||
forums_req_admin.AddCookie(&admin_session_cookie)
|
forums_req_admin.AddCookie(&admin_session_cookie)
|
||||||
forums_handler := http.HandlerFunc(route_forums)
|
forums_handler := http.HandlerFunc(route_forums)
|
||||||
|
|
||||||
|
static_w := httptest.NewRecorder()
|
||||||
|
static_req := httptest.NewRequest("get","/static/global.js",bytes.NewReader(nil))
|
||||||
|
static_handler := http.HandlerFunc(route_static)
|
||||||
|
|
||||||
debug = false
|
debug = false
|
||||||
nogrouplog = true
|
nogrouplog = true
|
||||||
|
|
||||||
|
@ -146,16 +150,18 @@ func BenchmarkRoute(b *testing.B) {
|
||||||
log.SetOutput(discard)
|
log.SetOutput(discard)
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
init_database(err);
|
init_database(err)
|
||||||
external_sites["YT"] = "https://www.youtube.com/"
|
external_sites["YT"] = "https://www.youtube.com/"
|
||||||
hooks["trow_assign"] = nil
|
hooks["trow_assign"] = nil
|
||||||
hooks["rrow_assign"] = nil
|
hooks["rrow_assign"] = nil
|
||||||
|
init_plugins()
|
||||||
|
|
||||||
for name, body := range plugins {
|
b.Run("static_files", func(b *testing.B) {
|
||||||
if body.Active {
|
for i := 0; i < b.N; i++ {
|
||||||
plugins[name].Init()
|
static_w.Body.Reset()
|
||||||
}
|
static_handler.ServeHTTP(static_w,static_req)
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
b.Run("topic_admin", func(b *testing.B) {
|
b.Run("topic_admin", func(b *testing.B) {
|
||||||
for i := 0; i < b.N; i++ {
|
for i := 0; i < b.N; i++ {
|
||||||
|
|
BIN
gosora.exe
2
group.go
|
@ -30,6 +30,7 @@ type Perms struct
|
||||||
EditUserGroupAdmin bool
|
EditUserGroupAdmin bool
|
||||||
ManageForums bool // This could be local, albeit limited for per-forum managers
|
ManageForums bool // This could be local, albeit limited for per-forum managers
|
||||||
EditSettings bool
|
EditSettings bool
|
||||||
|
ManageThemes bool
|
||||||
ManagePlugins bool
|
ManagePlugins bool
|
||||||
ViewIPs bool
|
ViewIPs bool
|
||||||
|
|
||||||
|
@ -86,6 +87,7 @@ func init() {
|
||||||
EditUserGroupAdmin: true,
|
EditUserGroupAdmin: true,
|
||||||
ManageForums: true,
|
ManageForums: true,
|
||||||
EditSettings: true,
|
EditSettings: true,
|
||||||
|
ManageThemes: true,
|
||||||
ManagePlugins: true,
|
ManagePlugins: true,
|
||||||
ViewIPs: true,
|
ViewIPs: true,
|
||||||
|
|
||||||
|
|
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 68 KiB |
After Width: | Height: | Size: 216 KiB |
After Width: | Height: | Size: 161 KiB |
After Width: | Height: | Size: 33 KiB |
53
main.go
|
@ -31,52 +31,54 @@ var external_sites map[string]string = make(map[string]string)
|
||||||
var groups map[int]Group = make(map[int]Group)
|
var groups map[int]Group = make(map[int]Group)
|
||||||
var forums map[int]Forum = make(map[int]Forum)
|
var forums map[int]Forum = make(map[int]Forum)
|
||||||
var static_files map[string]SFile = make(map[string]SFile)
|
var static_files map[string]SFile = make(map[string]SFile)
|
||||||
var ctemplates []string
|
|
||||||
var template_topic_handle func(TopicPage,io.Writer) = nil
|
var template_topic_handle func(TopicPage,io.Writer) = nil
|
||||||
|
var template_topic_origin_handle func(TopicPage,io.Writer) = nil
|
||||||
var template_topic_alt_handle func(TopicPage,io.Writer) = nil
|
var template_topic_alt_handle func(TopicPage,io.Writer) = nil
|
||||||
var template_topics_handle func(Page,io.Writer) = nil
|
var template_topics_handle func(TopicsPage,io.Writer) = nil
|
||||||
var template_forum_handle func(Page,io.Writer) = nil
|
var template_forum_handle func(ForumPage,io.Writer) = nil
|
||||||
var template_forums_handle func(Page,io.Writer) = nil
|
var template_forums_handle func(ForumsPage,io.Writer) = nil
|
||||||
var template_profile_handle func(ProfilePage,io.Writer) = nil
|
var template_profile_handle func(ProfilePage,io.Writer) = nil
|
||||||
|
|
||||||
func compile_templates() {
|
func compile_templates() {
|
||||||
var c CTemplateSet
|
var c CTemplateSet
|
||||||
user := User{0,"","compiler@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","",""}
|
user := User{62,"","compiler@localhost",0,false,false,false,false,false,false,GuestPerms,"",false,"","","","",""}
|
||||||
var noticeList map[int]string = make(map[int]string)
|
var noticeList map[int]string = make(map[int]string)
|
||||||
noticeList[0] = "test"
|
noticeList[0] = "test"
|
||||||
|
|
||||||
log.Print("Compiling the templates")
|
log.Print("Compiling the templates")
|
||||||
|
|
||||||
topic := TopicUser{0,"",template.HTML(""),0,false,false,"",0,"","","",no_css_tmpl,0,"","","",""}
|
topic := TopicUser{1,"Blah",template.HTML("Hey there!"),0,false,false,"",0,"","","",no_css_tmpl,0,"","","",""}
|
||||||
var replyList []Reply
|
var replyList []Reply
|
||||||
replyList = append(replyList, Reply{0,0,"",template.HTML(""),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
replyList = append(replyList, Reply{0,0,"",template.HTML("Yo!"),0,"","",0,0,"",no_css_tmpl,0,"","","",""})
|
||||||
|
|
||||||
var varList map[string]VarItem = make(map[string]VarItem)
|
var varList map[string]VarItem = make(map[string]VarItem)
|
||||||
tpage := TopicPage{"Title","name",user,noticeList,replyList,topic,false}
|
tpage := TopicPage{"Title",user,noticeList,replyList,topic,false}
|
||||||
topic_id_tmpl := c.compile_template("topic.html","templates/","TopicPage", tpage, varList)
|
topic_id_tmpl := c.compile_template("topic.html","templates/","TopicPage", tpage, varList)
|
||||||
topic_id_alt_tmpl := c.compile_template("topic_alt.html","templates/","TopicPage", tpage, varList)
|
topic_id_alt_tmpl := c.compile_template("topic_alt.html","templates/","TopicPage", tpage, varList)
|
||||||
|
|
||||||
varList = make(map[string]VarItem)
|
varList = make(map[string]VarItem)
|
||||||
ppage := ProfilePage{"Title",user,noticeList,replyList,user,false}
|
ppage := ProfilePage{"User 526",user,noticeList,replyList,user,false}
|
||||||
profile_tmpl := c.compile_template("profile.html","templates/","ProfilePage", ppage, varList)
|
profile_tmpl := c.compile_template("profile.html","templates/","ProfilePage", ppage, varList)
|
||||||
|
|
||||||
var forumList []interface{}
|
var forumList []Forum
|
||||||
for _, forum := range forums {
|
for _, forum := range forums {
|
||||||
if forum.Active {
|
if forum.Active {
|
||||||
forumList = append(forumList, forum)
|
forumList = append(forumList, forum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
varList = make(map[string]VarItem)
|
varList = make(map[string]VarItem)
|
||||||
pi := Page{"Forum List","forums",user,noticeList,forumList,0}
|
forums_page := ForumsPage{"Forum List",user,noticeList,forumList,0}
|
||||||
forums_tmpl := c.compile_template("forums.html","templates/","Page", pi, varList)
|
forums_tmpl := c.compile_template("forums.html","templates/","ForumsPage", forums_page, varList)
|
||||||
|
|
||||||
var topicList []interface{}
|
var topicList []TopicUser
|
||||||
topicList = append(topicList, TopicUser{1,"Topic Title","The topic content.",1,false,false,"",1,"open","Admin","","",0,"","","",""})
|
topicList = append(topicList, TopicUser{1,"Topic Title","The topic content.",1,false,false,"",1,"open","Admin","","",0,"","","",""})
|
||||||
pi = Page{"Topic List","topics",user,noticeList,topicList,""}
|
topics_page := TopicsPage{"Topic List",user,noticeList,topicList,""}
|
||||||
topics_tmpl := c.compile_template("topics.html","templates/","Page", pi, varList)
|
topics_tmpl := c.compile_template("topics.html","templates/","TopicsPage", topics_page, varList)
|
||||||
|
//topics_tmpl := c.compile_template("topics.html","templates/","Page", pi, varList)
|
||||||
|
|
||||||
pi = Page{"General Forum","forum",user,noticeList,topicList,"There aren't any topics in this forum yet."}
|
forum_page := ForumPage{"General Forum",user,noticeList,topicList,"There aren't any topics in this forum yet."}
|
||||||
forum_tmpl := c.compile_template("forum.html","templates/","Page", pi, varList)
|
forum_tmpl := c.compile_template("forum.html","templates/","ForumPage", forum_page, varList)
|
||||||
|
|
||||||
log.Print("Writing the templates")
|
log.Print("Writing the templates")
|
||||||
write_template("topic", topic_id_tmpl)
|
write_template("topic", topic_id_tmpl)
|
||||||
|
@ -102,8 +104,9 @@ func write_template(name string, content string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func main(){
|
func main(){
|
||||||
|
init_themes()
|
||||||
var err error
|
var err error
|
||||||
init_database(err);
|
init_database(err)
|
||||||
compile_templates()
|
compile_templates()
|
||||||
|
|
||||||
log.Print("Loading the static files.")
|
log.Print("Loading the static files.")
|
||||||
|
@ -132,19 +135,11 @@ func main(){
|
||||||
hooks["rrow_assign"] = nil
|
hooks["rrow_assign"] = nil
|
||||||
templates.ParseGlob("pages/*")
|
templates.ParseGlob("pages/*")
|
||||||
|
|
||||||
for name, body := range plugins {
|
init_plugins()
|
||||||
log.Print("Added plugin " + name)
|
|
||||||
if body.Active {
|
|
||||||
log.Print("Initialised plugin " + name)
|
|
||||||
plugins[name].Init()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// In a directory to stop it clashing with the other paths
|
// In a directory to stop it clashing with the other paths
|
||||||
http.HandleFunc("/static/", route_static)
|
http.HandleFunc("/static/", route_static)
|
||||||
//http.HandleFunc("/static/", route_fstatic)
|
|
||||||
//fs_p := http.FileServer(http.Dir("./public"))
|
|
||||||
//http.Handle("/static/", http.StripPrefix("/static/",fs_p))
|
|
||||||
fs_u := http.FileServer(http.Dir("./uploads"))
|
fs_u := http.FileServer(http.Dir("./uploads"))
|
||||||
http.Handle("/uploads/", http.StripPrefix("/uploads/",fs_u))
|
http.Handle("/uploads/", http.StripPrefix("/uploads/",fs_u))
|
||||||
|
|
||||||
|
@ -205,6 +200,8 @@ func main(){
|
||||||
http.HandleFunc("/panel/settings/", route_panel_settings)
|
http.HandleFunc("/panel/settings/", route_panel_settings)
|
||||||
http.HandleFunc("/panel/settings/edit/", route_panel_setting)
|
http.HandleFunc("/panel/settings/edit/", route_panel_setting)
|
||||||
http.HandleFunc("/panel/settings/edit/submit/", route_panel_setting_edit)
|
http.HandleFunc("/panel/settings/edit/submit/", route_panel_setting_edit)
|
||||||
|
http.HandleFunc("/panel/themes/", route_panel_themes)
|
||||||
|
http.HandleFunc("/panel/themes/default/", route_panel_themes_default)
|
||||||
http.HandleFunc("/panel/plugins/", route_panel_plugins)
|
http.HandleFunc("/panel/plugins/", route_panel_plugins)
|
||||||
http.HandleFunc("/panel/plugins/activate/", route_panel_plugins_activate)
|
http.HandleFunc("/panel/plugins/activate/", route_panel_plugins_activate)
|
||||||
http.HandleFunc("/panel/plugins/deactivate/", route_panel_plugins_deactivate)
|
http.HandleFunc("/panel/plugins/deactivate/", route_panel_plugins_deactivate)
|
||||||
|
|
|
@ -42,8 +42,6 @@ func route_edit_topic(w http.ResponseWriter, r *http.Request) {
|
||||||
var is_closed bool
|
var is_closed bool
|
||||||
if topic_status == "closed" {
|
if topic_status == "closed" {
|
||||||
is_closed = true
|
is_closed = true
|
||||||
} else {
|
|
||||||
is_closed = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
topic_content := html.EscapeString(r.PostFormValue("topic_content"))
|
topic_content := html.EscapeString(r.PostFormValue("topic_content"))
|
||||||
|
@ -910,7 +908,6 @@ func route_panel_plugins_activate(w http.ResponseWriter, r *http.Request){
|
||||||
NoPermissions(w,r,user)
|
NoPermissions(w,r,user)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if r.FormValue("session") != user.Session {
|
if r.FormValue("session") != user.Session {
|
||||||
SecurityError(w,r,user)
|
SecurityError(w,r,user)
|
||||||
return
|
return
|
||||||
|
@ -1243,3 +1240,95 @@ func route_panel_groups(w http.ResponseWriter, r *http.Request){
|
||||||
pi := Page{"Group Manager","panel-groups",user,noticeList,groupList,0}
|
pi := Page{"Group Manager","panel-groups",user,noticeList,groupList,0}
|
||||||
templates.ExecuteTemplate(w,"panel-groups.html", pi)
|
templates.ExecuteTemplate(w,"panel-groups.html", pi)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func route_panel_themes(w http.ResponseWriter, r *http.Request){
|
||||||
|
user, noticeList, ok := SessionCheck(w,r)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !user.Is_Super_Mod || !user.Perms.ManageThemes {
|
||||||
|
NoPermissions(w,r,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var themeList []interface{}
|
||||||
|
for _, theme := range themes {
|
||||||
|
themeList = append(themeList, theme)
|
||||||
|
}
|
||||||
|
|
||||||
|
pi := Page{"Theme Manager","panel-themes",user,noticeList,themeList,0}
|
||||||
|
templates.ExecuteTemplate(w,"panel-themes.html", pi)
|
||||||
|
}
|
||||||
|
|
||||||
|
func route_panel_themes_default(w http.ResponseWriter, r *http.Request){
|
||||||
|
user, ok := SimpleSessionCheck(w,r)
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !user.Is_Super_Mod || !user.Perms.ManageThemes {
|
||||||
|
NoPermissions(w,r,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if r.FormValue("session") != user.Session {
|
||||||
|
SecurityError(w,r,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
uname := r.URL.Path[len("/panel/themes/default/"):]
|
||||||
|
theme, ok := themes[uname]
|
||||||
|
if !ok {
|
||||||
|
LocalError("The theme isn't registered in the system",w,r,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var isDefault bool
|
||||||
|
err := db.QueryRow("SELECT `default` from `themes` where `uname` = ?", uname).Scan(&isDefault)
|
||||||
|
if err != nil && err != sql.ErrNoRows {
|
||||||
|
InternalError(err,w,r,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
has_theme := err != sql.ErrNoRows
|
||||||
|
if has_theme {
|
||||||
|
if isDefault {
|
||||||
|
LocalError("The theme is already active",w,r,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
_, err = update_theme_stmt.Exec(1, uname)
|
||||||
|
if err != nil {
|
||||||
|
InternalError(err,w,r,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
_, err := add_theme_stmt.Exec(uname,1)
|
||||||
|
if err != nil {
|
||||||
|
InternalError(err,w,r,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = update_theme_stmt.Exec(0, defaultTheme)
|
||||||
|
if err != nil {
|
||||||
|
InternalError(err,w,r,user)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Print("Setting theme '" + theme.Name + "' as the default theme")
|
||||||
|
theme.Active = true
|
||||||
|
themes[uname] = theme
|
||||||
|
|
||||||
|
dTheme, ok := themes[defaultTheme]
|
||||||
|
if !ok {
|
||||||
|
log.Fatal("The default theme is missing")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dTheme.Active = false
|
||||||
|
themes[defaultTheme] = dTheme
|
||||||
|
|
||||||
|
defaultTheme = uname
|
||||||
|
reset_template_overrides()
|
||||||
|
add_theme_static_files(uname)
|
||||||
|
map_theme_templates(theme)
|
||||||
|
|
||||||
|
http.Redirect(w,r,"/panel/themes/",http.StatusSeeOther)
|
||||||
|
}
|
||||||
|
|
52
mysql.go
|
@ -42,6 +42,8 @@ var update_setting_stmt *sql.Stmt
|
||||||
var add_plugin_stmt *sql.Stmt
|
var add_plugin_stmt *sql.Stmt
|
||||||
var update_plugin_stmt *sql.Stmt
|
var update_plugin_stmt *sql.Stmt
|
||||||
var update_user_stmt *sql.Stmt
|
var update_user_stmt *sql.Stmt
|
||||||
|
var add_theme_stmt *sql.Stmt
|
||||||
|
var update_theme_stmt *sql.Stmt
|
||||||
|
|
||||||
func init_database(err error) {
|
func init_database(err error) {
|
||||||
if(dbpassword != ""){
|
if(dbpassword != ""){
|
||||||
|
@ -253,6 +255,18 @@ func init_database(err error) {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Print("Preparing add_theme statement.")
|
||||||
|
add_theme_stmt, err = db.Prepare("INSERT INTO `themes`(`uname`,`default`) VALUES(?,?)")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Print("Preparing update_theme statement.")
|
||||||
|
update_theme_stmt, err = db.Prepare("UPDATE `themes` SET `default` = ? WHERE `uname` = ?")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
log.Print("Preparing update_user statement.")
|
log.Print("Preparing update_user statement.")
|
||||||
update_user_stmt, err = db.Prepare("UPDATE `users` SET `name` = ?, `email` = ?, `group` = ? WHERE `uid` = ?")
|
update_user_stmt, err = db.Prepare("UPDATE `users` SET `name` = ?, `email` = ?, `group` = ? WHERE `uid` = ?")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -381,4 +395,42 @@ func init_database(err error) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Print("Loading the themes.")
|
||||||
|
rows, err = db.Query("SELECT `uname`, `default` FROM `themes`")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
defer rows.Close()
|
||||||
|
|
||||||
|
var defaultThemeSwitch bool
|
||||||
|
for rows.Next() {
|
||||||
|
err := rows.Scan(&uname, &defaultThemeSwitch)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Was the theme deleted at some point?
|
||||||
|
theme, ok := themes[uname]
|
||||||
|
if !ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if defaultThemeSwitch {
|
||||||
|
log.Print("Loading the theme '" + theme.Name + "'")
|
||||||
|
theme.Active = true
|
||||||
|
defaultTheme = uname
|
||||||
|
add_theme_static_files(uname)
|
||||||
|
map_theme_templates(theme)
|
||||||
|
} else {
|
||||||
|
theme.Active = false
|
||||||
|
}
|
||||||
|
themes[uname] = theme
|
||||||
|
}
|
||||||
|
err = rows.Err()
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
29
pages.go
|
@ -15,7 +15,6 @@ type Page struct
|
||||||
type TopicPage struct
|
type TopicPage struct
|
||||||
{
|
{
|
||||||
Title string
|
Title string
|
||||||
Name string
|
|
||||||
CurrentUser User
|
CurrentUser User
|
||||||
NoticeList map[int]string
|
NoticeList map[int]string
|
||||||
ItemList []Reply
|
ItemList []Reply
|
||||||
|
@ -23,6 +22,33 @@ type TopicPage struct
|
||||||
ExtData interface{}
|
ExtData interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type TopicsPage struct
|
||||||
|
{
|
||||||
|
Title string
|
||||||
|
CurrentUser User
|
||||||
|
NoticeList map[int]string
|
||||||
|
ItemList []TopicUser
|
||||||
|
ExtData interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ForumPage struct
|
||||||
|
{
|
||||||
|
Title string
|
||||||
|
CurrentUser User
|
||||||
|
NoticeList map[int]string
|
||||||
|
ItemList []TopicUser
|
||||||
|
ExtData interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ForumsPage struct
|
||||||
|
{
|
||||||
|
Title string
|
||||||
|
CurrentUser User
|
||||||
|
NoticeList map[int]string
|
||||||
|
ItemList []Forum
|
||||||
|
ExtData interface{}
|
||||||
|
}
|
||||||
|
|
||||||
type ProfilePage struct
|
type ProfilePage struct
|
||||||
{
|
{
|
||||||
Title string
|
Title string
|
||||||
|
@ -36,7 +62,6 @@ type ProfilePage struct
|
||||||
type PageSimple struct
|
type PageSimple struct
|
||||||
{
|
{
|
||||||
Title string
|
Title string
|
||||||
Name string
|
|
||||||
Something interface{}
|
Something interface{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
After Width: | Height: | Size: 146 KiB |
108
routes.go
|
@ -24,18 +24,27 @@ var nList map[int]string
|
||||||
// GET functions
|
// GET functions
|
||||||
func route_static(w http.ResponseWriter, r *http.Request){
|
func route_static(w http.ResponseWriter, r *http.Request){
|
||||||
//name := r.URL.Path[len("/static/"):]
|
//name := r.URL.Path[len("/static/"):]
|
||||||
if t, err := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && static_files[r.URL.Path].Info.ModTime().Before(t.Add(1*time.Second)) {
|
//log.Print("Outputting static file '" + r.URL.Path + "'")
|
||||||
|
|
||||||
|
file, ok := static_files[r.URL.Path]
|
||||||
|
if !ok {
|
||||||
|
w.WriteHeader(http.StatusNotFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Surely, there's a more efficient way of doing this?
|
||||||
|
if t, err := time.Parse(http.TimeFormat, r.Header.Get("If-Modified-Since")); err == nil && file.Info.ModTime().Before(t.Add(1 * time.Second)) {
|
||||||
w.WriteHeader(http.StatusNotModified)
|
w.WriteHeader(http.StatusNotModified)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
h := w.Header()
|
h := w.Header()
|
||||||
h.Set("Last-Modified", static_files[r.URL.Path].FormattedModTime)
|
h.Set("Last-Modified", file.FormattedModTime)
|
||||||
h.Set("Content-Type", static_files[r.URL.Path].Mimetype)
|
h.Set("Content-Type", file.Mimetype)
|
||||||
h.Set("Content-Length", strconv.FormatInt(static_files[r.URL.Path].Length, 10))
|
h.Set("Content-Length", strconv.FormatInt(file.Length, 10)) // Avoid doing a type conversion every time?
|
||||||
//http.ServeContent(w,r,r.URL.Path,static_files[r.URL.Path].Info.ModTime(),static_files[r.URL.Path])
|
//http.ServeContent(w,r,r.URL.Path,file.Info.ModTime(),file)
|
||||||
//w.Write(static_files[r.URL.Path].Data)
|
//w.Write(file.Data)
|
||||||
io.Copy(w, bytes.NewReader(static_files[r.URL.Path].Data))
|
io.Copy(w, bytes.NewReader(file.Data)) // Use w.Write instead?
|
||||||
//io.CopyN(w, bytes.NewReader(static_files[r.URL.Path].Data), static_files[r.URL.Path].Length)
|
//io.CopyN(w, bytes.NewReader(file.Data), static_files[r.URL.Path].Length)
|
||||||
}
|
}
|
||||||
|
|
||||||
func route_fstatic(w http.ResponseWriter, r *http.Request){
|
func route_fstatic(w http.ResponseWriter, r *http.Request){
|
||||||
|
@ -83,21 +92,7 @@ func route_topics(w http.ResponseWriter, r *http.Request){
|
||||||
return
|
return
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
var(
|
var topicList []TopicUser
|
||||||
topicList []interface{}
|
|
||||||
tid int
|
|
||||||
title string
|
|
||||||
content string
|
|
||||||
createdBy int
|
|
||||||
is_closed bool
|
|
||||||
sticky bool
|
|
||||||
createdAt string
|
|
||||||
parentID int
|
|
||||||
status string
|
|
||||||
name string
|
|
||||||
avatar string
|
|
||||||
)
|
|
||||||
|
|
||||||
rows, err := get_topic_list_stmt.Query()
|
rows, err := get_topic_list_stmt.Query()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
InternalError(err,w,r,user)
|
InternalError(err,w,r,user)
|
||||||
|
@ -105,27 +100,27 @@ func route_topics(w http.ResponseWriter, r *http.Request){
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
|
topicItem := TopicUser{ID: 0,}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
err := rows.Scan(&tid, &title, &content, &createdBy, &is_closed, &sticky, &createdAt, &parentID, &name, &avatar)
|
err := rows.Scan(&topicItem.ID, &topicItem.Title, &topicItem.Content, &topicItem.CreatedBy, &topicItem.Is_Closed, &topicItem.Sticky, &topicItem.CreatedAt, &topicItem.ParentID, &topicItem.CreatedByName, &topicItem.Avatar)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
InternalError(err,w,r,user)
|
InternalError(err,w,r,user)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_closed {
|
if topicItem.Is_Closed {
|
||||||
status = "closed"
|
topicItem.Status = "shut"
|
||||||
} else {
|
} else {
|
||||||
status = "open"
|
topicItem.Status = "open"
|
||||||
}
|
}
|
||||||
if avatar != "" {
|
if topicItem.Avatar != "" {
|
||||||
if avatar[0] == '.' {
|
if topicItem.Avatar[0] == '.' {
|
||||||
avatar = "/uploads/avatar_" + strconv.Itoa(createdBy) + avatar
|
topicItem.Avatar = "/uploads/avatar_" + strconv.Itoa(topicItem.CreatedBy) + topicItem.Avatar
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(createdBy),1)
|
topicItem.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(topicItem.CreatedBy),1)
|
||||||
}
|
}
|
||||||
|
|
||||||
topicItem := TopicUser{tid,title,content,createdBy,is_closed,sticky, createdAt,parentID,status,name,avatar,"",0,"","","",""}
|
|
||||||
if hooks["trow_assign"] != nil {
|
if hooks["trow_assign"] != nil {
|
||||||
topicItem = run_hook("trow_assign", topicItem).(TopicUser)
|
topicItem = run_hook("trow_assign", topicItem).(TopicUser)
|
||||||
}
|
}
|
||||||
|
@ -137,7 +132,7 @@ func route_topics(w http.ResponseWriter, r *http.Request){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
pi := Page{"Topic List","topics",user,noticeList,topicList,0}
|
pi := TopicsPage{"Topic List",user,noticeList,topicList,0}
|
||||||
if template_topics_handle != nil {
|
if template_topics_handle != nil {
|
||||||
template_topics_handle(pi,w)
|
template_topics_handle(pi,w)
|
||||||
} else {
|
} else {
|
||||||
|
@ -154,20 +149,7 @@ func route_forum(w http.ResponseWriter, r *http.Request){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var(
|
var topicList []TopicUser
|
||||||
topicList []interface{}
|
|
||||||
tid int
|
|
||||||
title string
|
|
||||||
content string
|
|
||||||
createdBy int
|
|
||||||
is_closed bool
|
|
||||||
sticky bool
|
|
||||||
createdAt string
|
|
||||||
parentID int
|
|
||||||
status string
|
|
||||||
name string
|
|
||||||
avatar string
|
|
||||||
)
|
|
||||||
|
|
||||||
fid, err := strconv.Atoi(r.URL.Path[len("/forum/"):])
|
fid, err := strconv.Atoi(r.URL.Path[len("/forum/"):])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -192,27 +174,27 @@ func route_forum(w http.ResponseWriter, r *http.Request){
|
||||||
}
|
}
|
||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
|
|
||||||
|
topicItem := TopicUser{ID: 0}
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
err := rows.Scan(&tid, &title, &content, &createdBy, &is_closed, &sticky, &createdAt, &parentID, &name, &avatar)
|
err := rows.Scan(&topicItem.ID, &topicItem.Title, &topicItem.Content, &topicItem.CreatedBy, &topicItem.Is_Closed, &topicItem.Sticky, &topicItem.CreatedAt, &topicItem.ParentID, &topicItem.CreatedByName, &topicItem.Avatar)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
InternalError(err,w,r,user)
|
InternalError(err,w,r,user)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if is_closed {
|
if topicItem.Is_Closed {
|
||||||
status = "closed"
|
topicItem.Status = "shut"
|
||||||
} else {
|
} else {
|
||||||
status = "open"
|
topicItem.Status = "open"
|
||||||
}
|
}
|
||||||
if avatar != "" {
|
if topicItem.Avatar != "" {
|
||||||
if avatar[0] == '.' {
|
if topicItem.Avatar[0] == '.' {
|
||||||
avatar = "/uploads/avatar_" + strconv.Itoa(createdBy) + avatar
|
topicItem.Avatar = "/uploads/avatar_" + strconv.Itoa(topicItem.CreatedBy) + topicItem.Avatar
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(createdBy),1)
|
topicItem.Avatar = strings.Replace(noavatar,"{id}",strconv.Itoa(topicItem.CreatedBy),1)
|
||||||
}
|
}
|
||||||
|
|
||||||
topicItem := TopicUser{tid,title,content,createdBy,is_closed,sticky,createdAt,parentID,status,name,avatar,"",0,"","","",""}
|
|
||||||
if hooks["trow_assign"] != nil {
|
if hooks["trow_assign"] != nil {
|
||||||
topicItem = run_hook("trow_assign", topicItem).(TopicUser)
|
topicItem = run_hook("trow_assign", topicItem).(TopicUser)
|
||||||
}
|
}
|
||||||
|
@ -224,7 +206,7 @@ func route_forum(w http.ResponseWriter, r *http.Request){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
pi := Page{forums[fid].Name,"forum",user,noticeList,topicList,0}
|
pi := ForumPage{forums[fid].Name,user,noticeList,topicList,0}
|
||||||
if template_forum_handle != nil {
|
if template_forum_handle != nil {
|
||||||
template_forum_handle(pi,w)
|
template_forum_handle(pi,w)
|
||||||
} else {
|
} else {
|
||||||
|
@ -241,14 +223,14 @@ func route_forums(w http.ResponseWriter, r *http.Request){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
var forumList []interface{}
|
var forumList []Forum
|
||||||
for _, forum := range forums {
|
for _, forum := range forums {
|
||||||
if forum.Active {
|
if forum.Active {
|
||||||
forumList = append(forumList, forum)
|
forumList = append(forumList, forum)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pi := Page{"Forum List","forums",user,noticeList,forumList,0}
|
pi := ForumsPage{"Forum List",user,noticeList,forumList,0}
|
||||||
if template_forums_handle != nil {
|
if template_forums_handle != nil {
|
||||||
template_forums_handle(pi,w)
|
template_forums_handle(pi,w)
|
||||||
} else {
|
} else {
|
||||||
|
@ -315,7 +297,7 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){
|
||||||
topic.ContentLines = strings.Count(content,"\n")
|
topic.ContentLines = strings.Count(content,"\n")
|
||||||
|
|
||||||
if topic.Is_Closed {
|
if topic.Is_Closed {
|
||||||
topic.Status = "closed"
|
topic.Status = "shut"
|
||||||
|
|
||||||
// We don't want users posting in locked topics...
|
// We don't want users posting in locked topics...
|
||||||
if !user.Is_Mod {
|
if !user.Is_Mod {
|
||||||
|
@ -407,9 +389,9 @@ func route_topic_id(w http.ResponseWriter, r *http.Request){
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
tpage := TopicPage{topic.Title,"topic",user,noticeList,replyList,topic,0}
|
tpage := TopicPage{topic.Title,user,noticeList,replyList,topic,0}
|
||||||
if template_topic_handle != nil { //if template_topic_alt_handle != nil {
|
if template_topic_handle != nil {
|
||||||
template_topic_handle(tpage,w) //template_topic_alt_handle(tpage,w)
|
template_topic_handle(tpage,w)
|
||||||
} else {
|
} else {
|
||||||
err = templates.ExecuteTemplate(w,"topic.html", tpage)
|
err = templates.ExecuteTemplate(w,"topic.html", tpage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
|
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
||||||
package main
|
package main
|
||||||
import "io"
|
import "io"
|
||||||
import "strconv"
|
import "strconv"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
template_forum_handle = template_forum
|
template_forum_handle = template_forum
|
||||||
|
//o_template_forum_handle = template_forum
|
||||||
|
ctemplates = append(ctemplates,"forum")
|
||||||
|
tmpl_ptr_map["forum"] = &template_forum_handle
|
||||||
|
tmpl_ptr_map["o_forum"] = template_forum
|
||||||
}
|
}
|
||||||
|
|
||||||
func template_forum(tmpl_forum_vars Page, w io.Writer) {
|
func template_forum(tmpl_forum_vars ForumPage, w io.Writer) {
|
||||||
w.Write([]byte(`<!doctype html>
|
w.Write([]byte(`<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
@ -68,20 +73,20 @@ w.Write([]byte(`
|
||||||
if len(tmpl_forum_vars.ItemList) != 0 {
|
if len(tmpl_forum_vars.ItemList) != 0 {
|
||||||
for _, item := range tmpl_forum_vars.ItemList {
|
for _, item := range tmpl_forum_vars.ItemList {
|
||||||
w.Write([]byte(`<div class="rowitem passive" style="`))
|
w.Write([]byte(`<div class="rowitem passive" style="`))
|
||||||
if item.(TopicUser).Avatar != "" {
|
if item.Avatar != "" {
|
||||||
w.Write([]byte(`background-image: url(` + item.(TopicUser).Avatar + `);background-position: left;background-repeat: no-repeat;background-size: 64px;padding-left: 72px;`))
|
w.Write([]byte(`background-image: url(` + item.Avatar + `);background-position: left;background-repeat: no-repeat;background-size: 64px;padding-left: 72px;`))
|
||||||
}
|
}
|
||||||
if item.(TopicUser).Sticky {
|
if item.Sticky {
|
||||||
w.Write([]byte(`background-color: #FFFFCC;`))
|
w.Write([]byte(`background-color: #FFFFCC;`))
|
||||||
} else {
|
} else {
|
||||||
if item.(TopicUser).Is_Closed {
|
if item.Is_Closed {
|
||||||
w.Write([]byte(`background-color: #eaeaea;`))
|
w.Write([]byte(`background-color: #eaeaea;`))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.Write([]byte(`">
|
w.Write([]byte(`">
|
||||||
<a href="/topic/` + strconv.Itoa(item.(TopicUser).ID) + `">` + item.(TopicUser).Title + `</a> `))
|
<a href="/topic/` + strconv.Itoa(item.ID) + `">` + item.Title + `</a> `))
|
||||||
if item.(TopicUser).Is_Closed {
|
if item.Is_Closed {
|
||||||
w.Write([]byte(`<span class="username topic_status_e topic_status_closed" style="float: right;">closed</span>
|
w.Write([]byte(`<span class="username topic_status_e topic_status_closed" style="float: right;">shut</span>
|
||||||
`))
|
`))
|
||||||
} else {
|
} else {
|
||||||
w.Write([]byte(`<span class="username hide_on_micro topic_status_e topic_status_open" style="float: right;">open</span>`))
|
w.Write([]byte(`<span class="username hide_on_micro topic_status_e topic_status_open" style="float: right;">open</span>`))
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
|
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
||||||
package main
|
package main
|
||||||
import "io"
|
import "io"
|
||||||
import "strconv"
|
import "strconv"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
template_forums_handle = template_forums
|
template_forums_handle = template_forums
|
||||||
|
//o_template_forums_handle = template_forums
|
||||||
|
ctemplates = append(ctemplates,"forums")
|
||||||
|
tmpl_ptr_map["forums"] = &template_forums_handle
|
||||||
|
tmpl_ptr_map["o_forums"] = template_forums
|
||||||
}
|
}
|
||||||
|
|
||||||
func template_forums(tmpl_forums_vars Page, w io.Writer) {
|
func template_forums(tmpl_forums_vars ForumsPage, w io.Writer) {
|
||||||
w.Write([]byte(`<!doctype html>
|
w.Write([]byte(`<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
@ -65,8 +70,8 @@ w.Write([]byte(`
|
||||||
if len(tmpl_forums_vars.ItemList) != 0 {
|
if len(tmpl_forums_vars.ItemList) != 0 {
|
||||||
for _, item := range tmpl_forums_vars.ItemList {
|
for _, item := range tmpl_forums_vars.ItemList {
|
||||||
w.Write([]byte(`<div class="rowitem">
|
w.Write([]byte(`<div class="rowitem">
|
||||||
<a href="/forum/` + strconv.Itoa(item.(Forum).ID) + `" style="font-size: 20px;position:relative;top: -2px;font-weight: normal;text-transform: none;">` + item.(Forum).Name + `</a>
|
<a href="/forum/` + strconv.Itoa(item.ID) + `" style="font-size: 20px;position:relative;top: -2px;font-weight: normal;text-transform: none;">` + item.Name + `</a>
|
||||||
<a href="/topic/` + strconv.Itoa(item.(Forum).LastTopicID) + `" style="font-weight: normal;text-transform: none;float: right;">` + item.(Forum).LastTopic + ` <small style="font-size: 12px;">` + item.(Forum).LastTopicTime + `</small></a>
|
<a href="/topic/` + strconv.Itoa(item.LastTopicID) + `" style="font-weight: normal;text-transform: none;float: right;">` + item.LastTopic + ` <small style="font-size: 12px;">` + item.LastTopicTime + `</small></a>
|
||||||
</div>
|
</div>
|
||||||
`))
|
`))
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
|
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
||||||
package main
|
package main
|
||||||
import "strconv"
|
|
||||||
import "io"
|
import "io"
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
template_profile_handle = template_profile
|
template_profile_handle = template_profile
|
||||||
|
//o_template_profile_handle = template_profile
|
||||||
|
ctemplates = append(ctemplates,"profile")
|
||||||
|
tmpl_ptr_map["profile"] = &template_profile_handle
|
||||||
|
tmpl_ptr_map["o_profile"] = template_profile
|
||||||
}
|
}
|
||||||
|
|
||||||
func template_profile(tmpl_profile_vars ProfilePage, w io.Writer) {
|
func template_profile(tmpl_profile_vars ProfilePage, w io.Writer) {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
||||||
package main
|
package main
|
||||||
import "io"
|
import "io"
|
||||||
import "strconv"
|
import "strconv"
|
||||||
|
@ -5,6 +6,10 @@ import "html/template"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
template_topic_handle = template_topic
|
template_topic_handle = template_topic
|
||||||
|
//o_template_topic_handle = template_topic
|
||||||
|
ctemplates = append(ctemplates,"topic")
|
||||||
|
tmpl_ptr_map["topic"] = &template_topic_handle
|
||||||
|
tmpl_ptr_map["o_topic"] = template_topic
|
||||||
}
|
}
|
||||||
|
|
||||||
func template_topic(tmpl_topic_vars TopicPage, w io.Writer) {
|
func template_topic(tmpl_topic_vars TopicPage, w io.Writer) {
|
||||||
|
@ -91,7 +96,7 @@ w.Write([]byte(`
|
||||||
<input class='show_on_edit topic_name_input' name="topic_name" value='` + tmpl_topic_vars.Topic.Title + `' type="text" />
|
<input class='show_on_edit topic_name_input' name="topic_name" value='` + tmpl_topic_vars.Topic.Title + `' type="text" />
|
||||||
<select name="topic_status" class='show_on_edit topic_status_input' style='float: right;'>
|
<select name="topic_status" class='show_on_edit topic_status_input' style='float: right;'>
|
||||||
<option>open</option>
|
<option>open</option>
|
||||||
<option>closed</option>
|
<option>shut</option>
|
||||||
</select>
|
</select>
|
||||||
<button name="topic-button" class="formbutton show_on_edit submit_edit">Update</button>
|
<button name="topic-button" class="formbutton show_on_edit submit_edit">Update</button>
|
||||||
`))
|
`))
|
||||||
|
|
|
@ -1,10 +1,15 @@
|
||||||
|
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
||||||
package main
|
package main
|
||||||
import "strconv"
|
|
||||||
import "html/template"
|
import "html/template"
|
||||||
import "io"
|
import "io"
|
||||||
|
import "strconv"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
template_topic_alt_handle = template_topic_alt
|
template_topic_alt_handle = template_topic_alt
|
||||||
|
//o_template_topic_alt_handle = template_topic_alt
|
||||||
|
ctemplates = append(ctemplates,"topic_alt")
|
||||||
|
tmpl_ptr_map["topic_alt"] = &template_topic_alt_handle
|
||||||
|
tmpl_ptr_map["o_topic_alt"] = template_topic_alt
|
||||||
}
|
}
|
||||||
|
|
||||||
func template_topic_alt(tmpl_topic_alt_vars TopicPage, w io.Writer) {
|
func template_topic_alt(tmpl_topic_alt_vars TopicPage, w io.Writer) {
|
||||||
|
@ -63,15 +68,17 @@ w.Write([]byte(`<div class="alert">` + item + `</div>`))
|
||||||
w.Write([]byte(`
|
w.Write([]byte(`
|
||||||
<div class="rowblock">
|
<div class="rowblock">
|
||||||
<form action='/topic/edit/submit/` + strconv.Itoa(tmpl_topic_alt_vars.Topic.ID) + `' method="post">
|
<form action='/topic/edit/submit/` + strconv.Itoa(tmpl_topic_alt_vars.Topic.ID) + `' method="post">
|
||||||
<div class="rowitem"`))
|
<div class="rowitem" style="`))
|
||||||
if tmpl_topic_alt_vars.Topic.Sticky {
|
if tmpl_topic_alt_vars.Topic.Sticky {
|
||||||
w.Write([]byte(` style="background-color: #FFFFEA;"`))
|
w.Write([]byte(`background-color: #FFFFEA;background: linear-gradient(to bottom, hsl(60, 70%, 96%), hsl(60, 70%, 89%)), url('/static/fabric-base-simple-alpha.png');`))
|
||||||
} else {
|
} else {
|
||||||
if tmpl_topic_alt_vars.Topic.Is_Closed {
|
if tmpl_topic_alt_vars.Topic.Is_Closed {
|
||||||
w.Write([]byte(` style="background-color: #eaeaea;"`))
|
w.Write([]byte(`background-color: #eaeaea;background: linear-gradient(to bottom, #eaeaea, hsl(0,0%,79%));`))
|
||||||
|
} else {
|
||||||
|
w.Write([]byte(`background: linear-gradient(to bottom, white, hsl(0, 0%, 93%));`))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.Write([]byte(`>
|
w.Write([]byte(`">
|
||||||
<a class='topic_name hide_on_edit'>` + tmpl_topic_alt_vars.Topic.Title + `</a>
|
<a class='topic_name hide_on_edit'>` + tmpl_topic_alt_vars.Topic.Title + `</a>
|
||||||
<span class='username hide_on_micro topic_status_e topic_status_` + tmpl_topic_alt_vars.Topic.Status + ` hide_on_edit' style="font-weight:normal;float: right;">` + tmpl_topic_alt_vars.Topic.Status + `</span>
|
<span class='username hide_on_micro topic_status_e topic_status_` + tmpl_topic_alt_vars.Topic.Status + ` hide_on_edit' style="font-weight:normal;float: right;">` + tmpl_topic_alt_vars.Topic.Status + `</span>
|
||||||
<span class="username hide_on_micro" style="border-right: 0;font-weight: normal;float: right;">Status</span>
|
<span class="username hide_on_micro" style="border-right: 0;font-weight: normal;float: right;">Status</span>
|
||||||
|
@ -91,7 +98,7 @@ w.Write([]byte(`
|
||||||
<input class='show_on_edit topic_name_input' name="topic_name" value='` + tmpl_topic_alt_vars.Topic.Title + `' type="text" />
|
<input class='show_on_edit topic_name_input' name="topic_name" value='` + tmpl_topic_alt_vars.Topic.Title + `' type="text" />
|
||||||
<select name="topic_status" class='show_on_edit topic_status_input' style='float: right;'>
|
<select name="topic_status" class='show_on_edit topic_status_input' style='float: right;'>
|
||||||
<option>open</option>
|
<option>open</option>
|
||||||
<option>closed</option>
|
<option>shut</option>
|
||||||
</select>
|
</select>
|
||||||
<button name="topic-button" class="formbutton show_on_edit submit_edit">Update</button>
|
<button name="topic-button" class="formbutton show_on_edit submit_edit">Update</button>
|
||||||
`))
|
`))
|
||||||
|
@ -104,7 +111,7 @@ w.Write([]byte(`
|
||||||
<style type="text/css">.rowitem:last-child .content_container { margin-bottom: 5px !important; }</style>
|
<style type="text/css">.rowitem:last-child .content_container { margin-bottom: 5px !important; }</style>
|
||||||
<div class="rowblock post_container" style="border-top: none;">
|
<div class="rowblock post_container" style="border-top: none;">
|
||||||
<div class="rowitem passive deletable_block editable_parent post_item" style="background-color: #eaeaea;padding-top: 4px;padding-left: 5px;clear: both;border-bottom: none;padding-right: 4px;padding-bottom: 2px;">
|
<div class="rowitem passive deletable_block editable_parent post_item" style="background-color: #eaeaea;padding-top: 4px;padding-left: 5px;clear: both;border-bottom: none;padding-right: 4px;padding-bottom: 2px;">
|
||||||
<div class="userinfo" style="background: white;width: 132px;padding: 2px;margin-top: 2px;float: left;box-shadow:0 1px 2px rgba(0,0,0,.1);">
|
<div class="userinfo" style="background: white;width: 132px;padding: 2px;margin-top: 2px;float: left;position: sticky;top: 4px;box-shadow:0 1px 2px rgba(0,0,0,.1);">
|
||||||
<div class="avatar_item" style="background-image: url(` + tmpl_topic_alt_vars.Topic.Avatar + `), url(/static/white-dot.jpg);background-position: 0px -10px;background-repeat: no-repeat, repeat-y;background-size: 128px;width: 128px;height: 100%;min-height: 128px;border-style: solid;border-color: #eaeaea;border-width: 1px;"> </div>
|
<div class="avatar_item" style="background-image: url(` + tmpl_topic_alt_vars.Topic.Avatar + `), url(/static/white-dot.jpg);background-position: 0px -10px;background-repeat: no-repeat, repeat-y;background-size: 128px;width: 128px;height: 100%;min-height: 128px;border-style: solid;border-color: #eaeaea;border-width: 1px;"> </div>
|
||||||
<div class="the_name" style="margin-top: 3px;text-align: center;color: #505050;">` + tmpl_topic_alt_vars.Topic.CreatedByName + `</div>
|
<div class="the_name" style="margin-top: 3px;text-align: center;color: #505050;">` + tmpl_topic_alt_vars.Topic.CreatedByName + `</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -118,7 +125,7 @@ if len(tmpl_topic_alt_vars.ItemList) != 0 {
|
||||||
for _, item := range tmpl_topic_alt_vars.ItemList {
|
for _, item := range tmpl_topic_alt_vars.ItemList {
|
||||||
w.Write([]byte(`
|
w.Write([]byte(`
|
||||||
<div class="rowitem passive deletable_block editable_parent post_item" style="background-color: #eaeaea;padding-top: 4px;padding-left: 5px;clear: both;border-bottom: none;padding-right: 4px;padding-bottom: 2px;">
|
<div class="rowitem passive deletable_block editable_parent post_item" style="background-color: #eaeaea;padding-top: 4px;padding-left: 5px;clear: both;border-bottom: none;padding-right: 4px;padding-bottom: 2px;">
|
||||||
<div class="userinfo" style="background: white;width: 132px;padding: 2px;margin-top: 2px;float: left;box-shadow:0 1px 2px rgba(0,0,0,.1);">
|
<div class="userinfo" style="background: white;width: 132px;padding: 2px;margin-top: 2px;float: left;position: sticky;top: 4px;box-shadow:0 1px 2px rgba(0,0,0,.1);">
|
||||||
<div class="avatar_item" style="background-image: url(` + item.Avatar + `), url(/static/white-dot.jpg);background-position: 0px -10px;background-repeat: no-repeat, repeat-y;background-size: 128px;width: 128px;height: 100%;min-height: 128px;border-style: solid;border-color: #eaeaea;border-width: 1px;"> </div>
|
<div class="avatar_item" style="background-image: url(` + item.Avatar + `), url(/static/white-dot.jpg);background-position: 0px -10px;background-repeat: no-repeat, repeat-y;background-size: 128px;width: 128px;height: 100%;min-height: 128px;border-style: solid;border-color: #eaeaea;border-width: 1px;"> </div>
|
||||||
<div class="the_name" style="margin-top: 3px;text-align: center;color: #505050;">` + item.CreatedByName + `</div>
|
<div class="the_name" style="margin-top: 3px;text-align: center;color: #505050;">` + item.CreatedByName + `</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -146,7 +153,7 @@ w.Write([]byte(`</div>
|
||||||
`))
|
`))
|
||||||
if tmpl_topic_alt_vars.CurrentUser.Perms.CreateReply {
|
if tmpl_topic_alt_vars.CurrentUser.Perms.CreateReply {
|
||||||
w.Write([]byte(`
|
w.Write([]byte(`
|
||||||
<div class="rowblock">
|
<div class="rowblock" style="border-top: none;">
|
||||||
<form action="/reply/create/" method="post">
|
<form action="/reply/create/" method="post">
|
||||||
<input name="tid" value='` + strconv.Itoa(tmpl_topic_alt_vars.Topic.ID) + `' type="hidden" />
|
<input name="tid" value='` + strconv.Itoa(tmpl_topic_alt_vars.Topic.ID) + `' type="hidden" />
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
|
|
|
@ -1,12 +1,17 @@
|
||||||
|
/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */
|
||||||
package main
|
package main
|
||||||
import "io"
|
import "io"
|
||||||
import "strconv"
|
import "strconv"
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
template_topics_handle = template_topics
|
template_topics_handle = template_topics
|
||||||
|
//o_template_topics_handle = template_topics
|
||||||
|
ctemplates = append(ctemplates,"topics")
|
||||||
|
tmpl_ptr_map["topics"] = &template_topics_handle
|
||||||
|
tmpl_ptr_map["o_topics"] = template_topics
|
||||||
}
|
}
|
||||||
|
|
||||||
func template_topics(tmpl_topics_vars Page, w io.Writer) {
|
func template_topics(tmpl_topics_vars TopicsPage, w io.Writer) {
|
||||||
w.Write([]byte(`<!doctype html>
|
w.Write([]byte(`<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
|
@ -68,20 +73,20 @@ w.Write([]byte(`
|
||||||
if len(tmpl_topics_vars.ItemList) != 0 {
|
if len(tmpl_topics_vars.ItemList) != 0 {
|
||||||
for _, item := range tmpl_topics_vars.ItemList {
|
for _, item := range tmpl_topics_vars.ItemList {
|
||||||
w.Write([]byte(`<div class="rowitem passive" style="`))
|
w.Write([]byte(`<div class="rowitem passive" style="`))
|
||||||
if item.(TopicUser).Avatar != "" {
|
if item.Avatar != "" {
|
||||||
w.Write([]byte(`background-image: url(` + item.(TopicUser).Avatar + `);background-position: left;background-repeat: no-repeat;background-size: 64px;padding-left: 72px;`))
|
w.Write([]byte(`background-image: url(` + item.Avatar + `);background-position: left;background-repeat: no-repeat;background-size: 64px;padding-left: 72px;`))
|
||||||
}
|
}
|
||||||
if item.(TopicUser).Sticky {
|
if item.Sticky {
|
||||||
w.Write([]byte(`background-color: #FFFFCC;`))
|
w.Write([]byte(`background-color: #FFFFCC;`))
|
||||||
} else {
|
} else {
|
||||||
if item.(TopicUser).Is_Closed {
|
if item.Is_Closed {
|
||||||
w.Write([]byte(`background-color: #eaeaea;`))
|
w.Write([]byte(`background-color: #eaeaea;`))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
w.Write([]byte(`">
|
w.Write([]byte(`">
|
||||||
<a href="/topic/` + strconv.Itoa(item.(TopicUser).ID) + `">` + item.(TopicUser).Title + `</a> `))
|
<a href="/topic/` + strconv.Itoa(item.ID) + `">` + item.Title + `</a> `))
|
||||||
if item.(TopicUser).Is_Closed {
|
if item.Is_Closed {
|
||||||
w.Write([]byte(`<span class="username topic_status_e topic_status_closed" style="float: right;">closed</span>
|
w.Write([]byte(`<span class="username topic_status_e topic_status_closed" style="float: right;">shut</span>
|
||||||
`))
|
`))
|
||||||
} else {
|
} else {
|
||||||
w.Write([]byte(`<span class="username hide_on_micro topic_status_e topic_status_open" style="float: right;">open</span>`))
|
w.Write([]byte(`<span class="username hide_on_micro topic_status_e topic_status_open" style="float: right;">open</span>`))
|
||||||
|
|
19
templates.go
|
@ -8,6 +8,9 @@ import "path/filepath"
|
||||||
import "io/ioutil"
|
import "io/ioutil"
|
||||||
import "text/template/parse"
|
import "text/template/parse"
|
||||||
|
|
||||||
|
var ctemplates []string
|
||||||
|
var tmpl_ptr_map map[string]interface{} = make(map[string]interface{})
|
||||||
|
|
||||||
type VarItem struct
|
type VarItem struct
|
||||||
{
|
{
|
||||||
Name string
|
Name string
|
||||||
|
@ -76,7 +79,6 @@ func (c *CTemplateSet) compile_template(name string, dir string, expects string,
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if debug {
|
if debug {
|
||||||
fmt.Println(name)
|
fmt.Println(name)
|
||||||
}
|
}
|
||||||
|
@ -90,7 +92,6 @@ func (c *CTemplateSet) compile_template(name string, dir string, expects string,
|
||||||
if debug {
|
if debug {
|
||||||
fmt.Println(c.tlist)
|
fmt.Println(c.tlist)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.localVars = make(map[string]map[string]VarItemReflect)
|
c.localVars = make(map[string]map[string]VarItemReflect)
|
||||||
c.localVars[fname] = make(map[string]VarItemReflect)
|
c.localVars[fname] = make(map[string]VarItemReflect)
|
||||||
c.localVars[fname]["."] = VarItemReflect{".",varholder,holdreflect}
|
c.localVars[fname]["."] = VarItemReflect{".",varholder,holdreflect}
|
||||||
|
@ -126,11 +127,14 @@ func (c *CTemplateSet) compile_template(name string, dir string, expects string,
|
||||||
varString += "var " + varItem.Name + " " + varItem.Type + " = " + varItem.Destination + "\n"
|
varString += "var " + varItem.Name + " " + varItem.Type + " = " + varItem.Destination + "\n"
|
||||||
}
|
}
|
||||||
|
|
||||||
out = "package main\n" + importList + c.pVarList + "\nfunc init() {\ntemplate_" + fname +"_handle = template_" + fname + "\n}\n\nfunc template_" + fname + "(tmpl_" + fname + "_vars " + expects + ", w io.Writer) {\n" + varString + out + "}\n"
|
fout := "/* This file was automatically generated by the software. Please don't edit it as your changes may be overwritten at any moment. */\n"
|
||||||
|
fout += "package main\n" + importList + c.pVarList + "\n"
|
||||||
|
fout += "func init() {\n\ttemplate_" + fname +"_handle = template_" + fname + "\n\t//o_template_" + fname +"_handle = template_" + fname + "\n\tctemplates = append(ctemplates,\"" + fname + "\")\n\ttmpl_ptr_map[\"" + fname + "\"] = &template_" + fname + "_handle\n\ttmpl_ptr_map[\"o_" + fname + "\"] = template_" + fname + "\n}\n\n"
|
||||||
|
fout += "func template_" + fname + "(tmpl_" + fname + "_vars " + expects + ", w io.Writer) {\n" + varString + out + "}\n"
|
||||||
|
|
||||||
out = strings.Replace(out,`))
|
fout = strings.Replace(fout,`))
|
||||||
w.Write([]byte(`," + ",-1)
|
w.Write([]byte(`," + ",-1)
|
||||||
out = strings.Replace(out,"` + `","",-1)
|
fout = strings.Replace(fout,"` + `","",-1)
|
||||||
|
|
||||||
for index, count := range c.stats {
|
for index, count := range c.stats {
|
||||||
fmt.Println(index + ": " + strconv.Itoa(count))
|
fmt.Println(index + ": " + strconv.Itoa(count))
|
||||||
|
@ -139,9 +143,9 @@ w.Write([]byte(`," + ",-1)
|
||||||
|
|
||||||
if debug {
|
if debug {
|
||||||
fmt.Println("Output!")
|
fmt.Println("Output!")
|
||||||
fmt.Println(out)
|
fmt.Println(fout)
|
||||||
}
|
}
|
||||||
return out
|
return fout
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *CTemplateSet) compile_switch(varholder string, holdreflect reflect.Value, template_name string, node interface{}) (out string) {
|
func (c *CTemplateSet) compile_switch(varholder string, holdreflect reflect.Value, template_name string, node interface{}) (out string) {
|
||||||
|
@ -380,7 +384,6 @@ func (c *CTemplateSet) compile_varswitch(varholder string, holdreflect reflect.V
|
||||||
fmt.Println(n.String())
|
fmt.Println(n.String())
|
||||||
fmt.Println(n.Ident)
|
fmt.Println(n.Ident)
|
||||||
}
|
}
|
||||||
|
|
||||||
out, _ = c.compile_if_varsub(n.String(), varholder, template_name, holdreflect)
|
out, _ = c.compile_if_varsub(n.String(), varholder, template_name, holdreflect)
|
||||||
return out
|
return out
|
||||||
case *parse.NilNode:
|
case *parse.NilNode:
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="rowblock">
|
<div class="rowblock">
|
||||||
{{range .ItemList}}<div class="rowitem passive" style="{{ if .Avatar }}background-image: url({{ .Avatar }});background-position: left;background-repeat: no-repeat;background-size: 64px;padding-left: 72px;{{end}}{{ if .Sticky }}background-color: #FFFFCC;{{else if .Is_Closed}}background-color: #eaeaea;{{end}}">
|
{{range .ItemList}}<div class="rowitem passive" style="{{ if .Avatar }}background-image: url({{ .Avatar }});background-position: left;background-repeat: no-repeat;background-size: 64px;padding-left: 72px;{{end}}{{ if .Sticky }}background-color: #FFFFCC;{{else if .Is_Closed}}background-color: #eaeaea;{{end}}">
|
||||||
<a href="/topic/{{.ID}}">{{.Title}}</a> {{if .Is_Closed}}<span class="username topic_status_e topic_status_closed" style="float: right;">closed</span>
|
<a href="/topic/{{.ID}}">{{.Title}}</a> {{if .Is_Closed}}<span class="username topic_status_e topic_status_closed" style="float: right;">shut</span>
|
||||||
{{else}}<span class="username hide_on_micro topic_status_e topic_status_open" style="float: right;">open</span>{{end}}
|
{{else}}<span class="username hide_on_micro topic_status_e topic_status_open" style="float: right;">open</span>{{end}}
|
||||||
<span class="username hide_on_micro" style="border-right: 0;float: right;">Status</span>
|
<span class="username hide_on_micro" style="border-right: 0;float: right;">Status</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -4,9 +4,7 @@
|
||||||
<div class="rowitem passive"><a href="/panel/groups/">Groups</a></div>
|
<div class="rowitem passive"><a href="/panel/groups/">Groups</a></div>
|
||||||
{{if .CurrentUser.Perms.ManageForums}}<div class="rowitem passive"><a href="/panel/forums/">Forums</a></div>{{end}}
|
{{if .CurrentUser.Perms.ManageForums}}<div class="rowitem passive"><a href="/panel/forums/">Forums</a></div>{{end}}
|
||||||
{{if .CurrentUser.Perms.EditSettings}}<div class="rowitem passive"><a href="/panel/settings/">Settings</a></div>{{end}}
|
{{if .CurrentUser.Perms.EditSettings}}<div class="rowitem passive"><a href="/panel/settings/">Settings</a></div>{{end}}
|
||||||
|
{{if .CurrentUser.Perms.ManageThemes}}<div class="rowitem passive"><a href="/panel/themes/">Themes</a></div>{{end}}
|
||||||
{{if .CurrentUser.Perms.ManagePlugins}}<div class="rowitem passive"><a href="/panel/plugins/">Plugins</a></div>{{end}}
|
{{if .CurrentUser.Perms.ManagePlugins}}<div class="rowitem passive"><a href="/panel/plugins/">Plugins</a></div>{{end}}
|
||||||
<div class="rowitem passive"><a>Coming Soon</a></div>
|
|
||||||
<div class="rowitem passive"><a>Coming Soon</a></div>
|
|
||||||
<div class="rowitem passive"><a>Coming Soon</a></div>
|
|
||||||
<div class="rowitem passive"><a href="/forum/-1">Reported Content</a></div>
|
<div class="rowitem passive"><a href="/forum/-1">Reported Content</a></div>
|
||||||
</div>
|
</div>
|
|
@ -0,0 +1,20 @@
|
||||||
|
{{template "header.html" . }}
|
||||||
|
{{template "panel-menu.html" . }}
|
||||||
|
<style type="text/css">.rowitem::after {content:"";display:block;clear:both;}</style>
|
||||||
|
<div class="colblock_right">
|
||||||
|
<div class="rowitem"><a>Themes</a></div>
|
||||||
|
</div>
|
||||||
|
<div class="colblock_right">
|
||||||
|
{{range .ItemList}}
|
||||||
|
<div class="rowitem editable_parent" style="font-weight: normal;text-transform: none;">
|
||||||
|
<span style="float: left;">
|
||||||
|
<a href="/panel/themes/{{.Name}}" class="editable_block" style="font-size: 20px;">{{.FriendlyName}}</a><br />
|
||||||
|
<small style="margin-left: 2px;">Author: {{.Creator}}</small>
|
||||||
|
</span>
|
||||||
|
<span style="float: right;">
|
||||||
|
{{if .Active}}<span>Default</span>{{else}}<a href="/panel/themes/default/{{.Name}}?session={{$.CurrentUser.Session}}" class="username">Make Default</a>{{end}}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
</div>
|
||||||
|
{{template "footer.html" . }}
|
|
@ -13,7 +13,7 @@
|
||||||
<input class='show_on_edit topic_name_input' name="topic_name" value='{{.Topic.Title}}' type="text" />
|
<input class='show_on_edit topic_name_input' name="topic_name" value='{{.Topic.Title}}' type="text" />
|
||||||
<select name="topic_status" class='show_on_edit topic_status_input' style='float: right;'>
|
<select name="topic_status" class='show_on_edit topic_status_input' style='float: right;'>
|
||||||
<option>open</option>
|
<option>open</option>
|
||||||
<option>closed</option>
|
<option>shut</option>
|
||||||
</select>
|
</select>
|
||||||
<button name="topic-button" class="formbutton show_on_edit submit_edit">Update</button>
|
<button name="topic-button" class="formbutton show_on_edit submit_edit">Update</button>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
{{template "header.html" . }}
|
{{template "header.html" . }}
|
||||||
<div class="rowblock">
|
<div class="rowblock">
|
||||||
<form action='/topic/edit/submit/{{.Topic.ID}}' method="post">
|
<form action='/topic/edit/submit/{{.Topic.ID}}' method="post">
|
||||||
<div class="rowitem"{{ if .Topic.Sticky }} style="background-color: #FFFFEA;"{{else if .Topic.Is_Closed}} style="background-color: #eaeaea;"{{end}}>
|
<div class="rowitem" style="{{ if .Topic.Sticky }}background-color: #FFFFEA;background: linear-gradient(to bottom, hsl(60, 70%, 96%), hsl(60, 70%, 89%)), url('/static/fabric-base-simple-alpha.png');{{else if .Topic.Is_Closed}}background-color: #eaeaea;background: linear-gradient(to bottom, #eaeaea, hsl(0,0%,79%));{{else}}background: linear-gradient(to bottom, white, hsl(0, 0%, 93%));{{end}}">
|
||||||
<a class='topic_name hide_on_edit'>{{.Topic.Title}}</a>
|
<a class='topic_name hide_on_edit'>{{.Topic.Title}}</a>
|
||||||
<span class='username hide_on_micro topic_status_e topic_status_{{.Topic.Status}} hide_on_edit' style="font-weight:normal;float: right;">{{.Topic.Status}}</span>
|
<span class='username hide_on_micro topic_status_e topic_status_{{.Topic.Status}} hide_on_edit' style="font-weight:normal;float: right;">{{.Topic.Status}}</span>
|
||||||
<span class="username hide_on_micro" style="border-right: 0;font-weight: normal;float: right;">Status</span>
|
<span class="username hide_on_micro" style="border-right: 0;font-weight: normal;float: right;">Status</span>
|
||||||
|
@ -13,7 +13,7 @@
|
||||||
<input class='show_on_edit topic_name_input' name="topic_name" value='{{.Topic.Title}}' type="text" />
|
<input class='show_on_edit topic_name_input' name="topic_name" value='{{.Topic.Title}}' type="text" />
|
||||||
<select name="topic_status" class='show_on_edit topic_status_input' style='float: right;'>
|
<select name="topic_status" class='show_on_edit topic_status_input' style='float: right;'>
|
||||||
<option>open</option>
|
<option>open</option>
|
||||||
<option>closed</option>
|
<option>shut</option>
|
||||||
</select>
|
</select>
|
||||||
<button name="topic-button" class="formbutton show_on_edit submit_edit">Update</button>
|
<button name="topic-button" class="formbutton show_on_edit submit_edit">Update</button>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
@ -24,7 +24,7 @@
|
||||||
<style type="text/css">.rowitem:last-child .content_container { margin-bottom: 5px !important; }</style>
|
<style type="text/css">.rowitem:last-child .content_container { margin-bottom: 5px !important; }</style>
|
||||||
<div class="rowblock post_container" style="border-top: none;">
|
<div class="rowblock post_container" style="border-top: none;">
|
||||||
<div class="rowitem passive deletable_block editable_parent post_item" style="background-color: #eaeaea;padding-top: 4px;padding-left: 5px;clear: both;border-bottom: none;padding-right: 4px;padding-bottom: 2px;">
|
<div class="rowitem passive deletable_block editable_parent post_item" style="background-color: #eaeaea;padding-top: 4px;padding-left: 5px;clear: both;border-bottom: none;padding-right: 4px;padding-bottom: 2px;">
|
||||||
<div class="userinfo" style="background: white;width: 132px;padding: 2px;margin-top: 2px;float: left;box-shadow:0 1px 2px rgba(0,0,0,.1);">
|
<div class="userinfo" style="background: white;width: 132px;padding: 2px;margin-top: 2px;float: left;position: sticky;top: 4px;box-shadow:0 1px 2px rgba(0,0,0,.1);">
|
||||||
<div class="avatar_item" style="background-image: url({{.Topic.Avatar}}), url(/static/white-dot.jpg);background-position: 0px -10px;background-repeat: no-repeat, repeat-y;background-size: 128px;width: 128px;height: 100%;min-height: 128px;border-style: solid;border-color: #eaeaea;border-width: 1px;"> </div>
|
<div class="avatar_item" style="background-image: url({{.Topic.Avatar}}), url(/static/white-dot.jpg);background-position: 0px -10px;background-repeat: no-repeat, repeat-y;background-size: 128px;width: 128px;height: 100%;min-height: 128px;border-style: solid;border-color: #eaeaea;border-width: 1px;"> </div>
|
||||||
<div class="the_name" style="margin-top: 3px;text-align: center;color: #505050;">{{.Topic.CreatedByName}}</div>
|
<div class="the_name" style="margin-top: 3px;text-align: center;color: #505050;">{{.Topic.CreatedByName}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -35,7 +35,7 @@
|
||||||
</div>
|
</div>
|
||||||
{{range .ItemList}}
|
{{range .ItemList}}
|
||||||
<div class="rowitem passive deletable_block editable_parent post_item" style="background-color: #eaeaea;padding-top: 4px;padding-left: 5px;clear: both;border-bottom: none;padding-right: 4px;padding-bottom: 2px;">
|
<div class="rowitem passive deletable_block editable_parent post_item" style="background-color: #eaeaea;padding-top: 4px;padding-left: 5px;clear: both;border-bottom: none;padding-right: 4px;padding-bottom: 2px;">
|
||||||
<div class="userinfo" style="background: white;width: 132px;padding: 2px;margin-top: 2px;float: left;box-shadow:0 1px 2px rgba(0,0,0,.1);">
|
<div class="userinfo" style="background: white;width: 132px;padding: 2px;margin-top: 2px;float: left;position: sticky;top: 4px;box-shadow:0 1px 2px rgba(0,0,0,.1);">
|
||||||
<div class="avatar_item" style="background-image: url({{.Avatar}}), url(/static/white-dot.jpg);background-position: 0px -10px;background-repeat: no-repeat, repeat-y;background-size: 128px;width: 128px;height: 100%;min-height: 128px;border-style: solid;border-color: #eaeaea;border-width: 1px;"> </div>
|
<div class="avatar_item" style="background-image: url({{.Avatar}}), url(/static/white-dot.jpg);background-position: 0px -10px;background-repeat: no-repeat, repeat-y;background-size: 128px;width: 128px;height: 100%;min-height: 128px;border-style: solid;border-color: #eaeaea;border-width: 1px;"> </div>
|
||||||
<div class="the_name" style="margin-top: 3px;text-align: center;color: #505050;">{{.CreatedByName}}</div>
|
<div class="the_name" style="margin-top: 3px;text-align: center;color: #505050;">{{.CreatedByName}}</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -50,7 +50,7 @@
|
||||||
</div>
|
</div>
|
||||||
{{end}}</div>
|
{{end}}</div>
|
||||||
{{if .CurrentUser.Perms.CreateReply}}
|
{{if .CurrentUser.Perms.CreateReply}}
|
||||||
<div class="rowblock">
|
<div class="rowblock" style="border-top: none;">
|
||||||
<form action="/reply/create/" method="post">
|
<form action="/reply/create/" method="post">
|
||||||
<input name="tid" value='{{.Topic.ID}}' type="hidden" />
|
<input name="tid" value='{{.Topic.ID}}' type="hidden" />
|
||||||
<div class="formrow">
|
<div class="formrow">
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="rowblock">
|
<div class="rowblock">
|
||||||
{{range .ItemList}}<div class="rowitem passive" style="{{if .Avatar}}background-image: url({{.Avatar}});background-position: left;background-repeat: no-repeat;background-size: 64px;padding-left: 72px;{{end}}{{if .Sticky}}background-color: #FFFFCC;{{else if .Is_Closed}}background-color: #eaeaea;{{end}}">
|
{{range .ItemList}}<div class="rowitem passive" style="{{if .Avatar}}background-image: url({{.Avatar}});background-position: left;background-repeat: no-repeat;background-size: 64px;padding-left: 72px;{{end}}{{if .Sticky}}background-color: #FFFFCC;{{else if .Is_Closed}}background-color: #eaeaea;{{end}}">
|
||||||
<a href="/topic/{{.ID}}">{{.Title}}</a> {{if .Is_Closed}}<span class="username topic_status_e topic_status_closed" style="float: right;">closed</span>
|
<a href="/topic/{{.ID}}">{{.Title}}</a> {{if .Is_Closed}}<span class="username topic_status_e topic_status_closed" style="float: right;">shut</span>
|
||||||
{{else}}<span class="username hide_on_micro topic_status_e topic_status_open" style="float: right;">open</span>{{end}}
|
{{else}}<span class="username hide_on_micro topic_status_e topic_status_open" style="float: right;">open</span>{{end}}
|
||||||
<span class="username hide_on_micro" style="border-right: 0;float: right;">Status</span>
|
<span class="username hide_on_micro" style="border-right: 0;float: right;">Status</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -0,0 +1,319 @@
|
||||||
|
/* Copyright Azareal 2016 - 2017 */
|
||||||
|
package main
|
||||||
|
|
||||||
|
import "fmt"
|
||||||
|
import "log"
|
||||||
|
import "io"
|
||||||
|
import "os"
|
||||||
|
import "strings"
|
||||||
|
import "mime"
|
||||||
|
import "io/ioutil"
|
||||||
|
import "path/filepath"
|
||||||
|
import "encoding/json"
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
var defaultTheme string
|
||||||
|
var themes map[string]Theme = make(map[string]Theme)
|
||||||
|
//var overriden_templates map[string]interface{} = make(map[string]interface{})
|
||||||
|
var overriden_templates map[string]bool = make(map[string]bool)
|
||||||
|
|
||||||
|
type Theme struct
|
||||||
|
{
|
||||||
|
Name string
|
||||||
|
FriendlyName string
|
||||||
|
Version string
|
||||||
|
Creator string
|
||||||
|
Settings map[string]ThemeSetting
|
||||||
|
Templates []TemplateMapping
|
||||||
|
|
||||||
|
// This variable should only be set and unset by the system, not the theme meta file
|
||||||
|
Active bool
|
||||||
|
}
|
||||||
|
|
||||||
|
type ThemeSetting struct
|
||||||
|
{
|
||||||
|
FriendlyName string
|
||||||
|
Options []string
|
||||||
|
}
|
||||||
|
|
||||||
|
type TemplateMapping struct
|
||||||
|
{
|
||||||
|
Name string
|
||||||
|
Source string
|
||||||
|
//When string
|
||||||
|
}
|
||||||
|
|
||||||
|
func init_themes() {
|
||||||
|
themeFiles, err := ioutil.ReadDir("./themes")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, themeFile := range themeFiles {
|
||||||
|
if !themeFile.IsDir() {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
themeName := themeFile.Name()
|
||||||
|
log.Print("Adding theme '" + themeName + "'")
|
||||||
|
themeFile, err := ioutil.ReadFile("./themes/" + themeName + "/theme.json")
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var theme Theme
|
||||||
|
json.Unmarshal(themeFile, &theme)
|
||||||
|
theme.Active = false // Set this to false, just in case someone explicitly overrode this value in the JSON file
|
||||||
|
|
||||||
|
themes[theme.Name] = theme
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func add_theme_static_files(themeName string) {
|
||||||
|
err := filepath.Walk("./themes/" + themeName + "/public", func(path string, f os.FileInfo, err error) error {
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if f.IsDir() {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
path = strings.Replace(path,"\\","/",-1)
|
||||||
|
|
||||||
|
log.Print("Attempting to add static file '" + path + "' for default theme '" + themeName + "'")
|
||||||
|
data, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
path = strings.TrimPrefix(path,"themes/" + themeName + "/public")
|
||||||
|
log.Print("Added the '" + path + "' static file for default theme " + themeName + ".")
|
||||||
|
|
||||||
|
static_files["/static" + path] = SFile{data,0,int64(len(data)),mime.TypeByExtension(filepath.Ext("/themes/" + themeName + "/public" + path)),f,f.ModTime().UTC().Format(http.TimeFormat)}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func map_theme_templates(theme Theme) {
|
||||||
|
if theme.Templates != nil {
|
||||||
|
for _, themeTmpl := range theme.Templates {
|
||||||
|
if themeTmpl.Name == "" {
|
||||||
|
log.Fatal("Invalid destination template name")
|
||||||
|
}
|
||||||
|
if themeTmpl.Source == "" {
|
||||||
|
log.Fatal("Invalid source template name")
|
||||||
|
}
|
||||||
|
|
||||||
|
// go generate is one possibility, but it would simply add another step of compilation
|
||||||
|
|
||||||
|
dest_tmpl_ptr, ok := tmpl_ptr_map[themeTmpl.Name]
|
||||||
|
if !ok {
|
||||||
|
log.Fatal("The destination template doesn't exist!")
|
||||||
|
}
|
||||||
|
source_tmpl_ptr, ok := tmpl_ptr_map[themeTmpl.Source]
|
||||||
|
if !ok {
|
||||||
|
log.Fatal("The source template doesn't exist!")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch d_tmpl_ptr := dest_tmpl_ptr.(type) {
|
||||||
|
case *func(TopicPage,io.Writer):
|
||||||
|
switch s_tmpl_ptr := source_tmpl_ptr.(type) {
|
||||||
|
case *func(TopicPage,io.Writer):
|
||||||
|
//overriden_templates[themeTmpl.Name] = d_tmpl_ptr
|
||||||
|
overriden_templates[themeTmpl.Name] = true
|
||||||
|
log.Print("Topic Handle")
|
||||||
|
fmt.Println(template_topic_handle)
|
||||||
|
log.Print("Before")
|
||||||
|
fmt.Println(d_tmpl_ptr)
|
||||||
|
fmt.Println(*d_tmpl_ptr)
|
||||||
|
log.Print("Source")
|
||||||
|
fmt.Println(s_tmpl_ptr)
|
||||||
|
fmt.Println(*s_tmpl_ptr)
|
||||||
|
*d_tmpl_ptr = *s_tmpl_ptr
|
||||||
|
log.Print("After")
|
||||||
|
fmt.Println(d_tmpl_ptr)
|
||||||
|
fmt.Println(*d_tmpl_ptr)
|
||||||
|
log.Print("Source")
|
||||||
|
fmt.Println(s_tmpl_ptr)
|
||||||
|
fmt.Println(*s_tmpl_ptr)
|
||||||
|
default:
|
||||||
|
log.Fatal("The source and destination templates are incompatible")
|
||||||
|
}
|
||||||
|
case *func(TopicsPage,io.Writer):
|
||||||
|
switch s_tmpl_ptr := source_tmpl_ptr.(type) {
|
||||||
|
case *func(TopicsPage,io.Writer):
|
||||||
|
//overriden_templates[themeTmpl.Name] = d_tmpl_ptr
|
||||||
|
overriden_templates[themeTmpl.Name] = true
|
||||||
|
*d_tmpl_ptr = *s_tmpl_ptr
|
||||||
|
default:
|
||||||
|
log.Fatal("The source and destination templates are incompatible")
|
||||||
|
}
|
||||||
|
case *func(ForumPage,io.Writer):
|
||||||
|
switch s_tmpl_ptr := source_tmpl_ptr.(type) {
|
||||||
|
case *func(ForumPage,io.Writer):
|
||||||
|
//overriden_templates[themeTmpl.Name] = d_tmpl_ptr
|
||||||
|
overriden_templates[themeTmpl.Name] = true
|
||||||
|
*d_tmpl_ptr = *s_tmpl_ptr
|
||||||
|
default:
|
||||||
|
log.Fatal("The source and destination templates are incompatible")
|
||||||
|
}
|
||||||
|
case *func(ForumsPage,io.Writer):
|
||||||
|
switch s_tmpl_ptr := source_tmpl_ptr.(type) {
|
||||||
|
case *func(ForumsPage,io.Writer):
|
||||||
|
//overriden_templates[themeTmpl.Name] = d_tmpl_ptr
|
||||||
|
overriden_templates[themeTmpl.Name] = true
|
||||||
|
*d_tmpl_ptr = *s_tmpl_ptr
|
||||||
|
default:
|
||||||
|
log.Fatal("The source and destination templates are incompatible")
|
||||||
|
}
|
||||||
|
case *func(ProfilePage,io.Writer):
|
||||||
|
switch s_tmpl_ptr := source_tmpl_ptr.(type) {
|
||||||
|
case *func(ProfilePage,io.Writer):
|
||||||
|
//overriden_templates[themeTmpl.Name] = d_tmpl_ptr
|
||||||
|
overriden_templates[themeTmpl.Name] = true
|
||||||
|
*d_tmpl_ptr = *s_tmpl_ptr
|
||||||
|
default:
|
||||||
|
log.Fatal("The source and destination templates are incompatible")
|
||||||
|
}
|
||||||
|
case *func(Page,io.Writer):
|
||||||
|
switch s_tmpl_ptr := source_tmpl_ptr.(type) {
|
||||||
|
case *func(Page,io.Writer):
|
||||||
|
//overriden_templates[themeTmpl.Name] = d_tmpl_ptr
|
||||||
|
overriden_templates[themeTmpl.Name] = true
|
||||||
|
*d_tmpl_ptr = *s_tmpl_ptr
|
||||||
|
default:
|
||||||
|
log.Fatal("The source and destination templates are incompatible")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Fatal("Unknown destination template type!")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func reset_template_overrides() {
|
||||||
|
log.Print("Resetting the template overrides")
|
||||||
|
|
||||||
|
for name, _ := range overriden_templates {
|
||||||
|
log.Print("Resetting '" + name + "' template override")
|
||||||
|
|
||||||
|
origin_pointer, ok := tmpl_ptr_map["o_" + name]
|
||||||
|
if !ok {
|
||||||
|
//log.Fatal("The origin template doesn't exist!")
|
||||||
|
log.Print("The origin template doesn't exist!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dest_tmpl_ptr, ok := tmpl_ptr_map[name]
|
||||||
|
if !ok {
|
||||||
|
//log.Fatal("The destination template doesn't exist!")
|
||||||
|
log.Print("The destination template doesn't exist!")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
switch o_ptr := origin_pointer.(type) {
|
||||||
|
case func(TopicPage,io.Writer):
|
||||||
|
switch d_ptr := dest_tmpl_ptr.(type) {
|
||||||
|
case *func(TopicPage,io.Writer):
|
||||||
|
log.Print("Topic Handle")
|
||||||
|
fmt.Println(template_topic_handle)
|
||||||
|
log.Print("Before")
|
||||||
|
fmt.Println(d_ptr)
|
||||||
|
fmt.Println(*d_ptr)
|
||||||
|
log.Print("Origin")
|
||||||
|
fmt.Println(o_ptr)
|
||||||
|
*d_ptr = o_ptr
|
||||||
|
log.Print("After")
|
||||||
|
fmt.Println(d_ptr)
|
||||||
|
fmt.Println(*d_ptr)
|
||||||
|
log.Print("Origin")
|
||||||
|
fmt.Println(o_ptr)
|
||||||
|
default:
|
||||||
|
log.Fatal("The origin and destination templates are incompatible")
|
||||||
|
}
|
||||||
|
case *func(TopicsPage,io.Writer):
|
||||||
|
switch d_ptr := dest_tmpl_ptr.(type) {
|
||||||
|
case *func(TopicsPage,io.Writer):
|
||||||
|
*d_ptr = o_ptr
|
||||||
|
default:
|
||||||
|
log.Fatal("The origin and destination templates are incompatible")
|
||||||
|
}
|
||||||
|
case *func(ForumPage,io.Writer):
|
||||||
|
switch d_ptr := dest_tmpl_ptr.(type) {
|
||||||
|
case *func(ForumPage,io.Writer):
|
||||||
|
*d_ptr = o_ptr
|
||||||
|
default:
|
||||||
|
log.Fatal("The origin and destination templates are incompatible")
|
||||||
|
}
|
||||||
|
case *func(ForumsPage,io.Writer):
|
||||||
|
switch d_ptr := dest_tmpl_ptr.(type) {
|
||||||
|
case *func(ForumsPage,io.Writer):
|
||||||
|
*d_ptr = o_ptr
|
||||||
|
default:
|
||||||
|
log.Fatal("The origin and destination templates are incompatible")
|
||||||
|
}
|
||||||
|
case *func(ProfilePage,io.Writer):
|
||||||
|
switch d_ptr := dest_tmpl_ptr.(type) {
|
||||||
|
case *func(ProfilePage,io.Writer):
|
||||||
|
*d_ptr = o_ptr
|
||||||
|
default:
|
||||||
|
log.Fatal("The origin and destination templates are incompatible")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Fatal("Unknown destination template type!")
|
||||||
|
}
|
||||||
|
log.Print("The template override was reset")
|
||||||
|
}
|
||||||
|
overriden_templates = make(map[string]bool)
|
||||||
|
log.Print("All of the template overrides have been reset")
|
||||||
|
|
||||||
|
/*for name, origin_pointer := range overriden_templates {
|
||||||
|
dest_tmpl_ptr, ok := tmpl_ptr_map[name]
|
||||||
|
if !ok {
|
||||||
|
log.Fatal("The destination template doesn't exist!")
|
||||||
|
}
|
||||||
|
|
||||||
|
switch o_ptr := origin_pointer.(type) {
|
||||||
|
case *func(TopicPage,io.Writer):
|
||||||
|
switch d_ptr := dest_tmpl_ptr.(type) {
|
||||||
|
case *func(TopicPage,io.Writer):
|
||||||
|
*d_ptr = *o_ptr
|
||||||
|
default:
|
||||||
|
log.Fatal("The origin and destination templates are incompatible")
|
||||||
|
}
|
||||||
|
case *func(TopicsPage,io.Writer):
|
||||||
|
switch d_ptr := dest_tmpl_ptr.(type) {
|
||||||
|
case *func(TopicsPage,io.Writer):
|
||||||
|
*d_ptr = *o_ptr
|
||||||
|
default:
|
||||||
|
log.Fatal("The origin and destination templates are incompatible")
|
||||||
|
}
|
||||||
|
case *func(ForumPage,io.Writer):
|
||||||
|
switch d_ptr := dest_tmpl_ptr.(type) {
|
||||||
|
case *func(ForumPage,io.Writer):
|
||||||
|
*d_ptr = *o_ptr
|
||||||
|
default:
|
||||||
|
log.Fatal("The origin and destination templates are incompatible")
|
||||||
|
}
|
||||||
|
case *func(ForumsPage,io.Writer):
|
||||||
|
switch d_ptr := dest_tmpl_ptr.(type) {
|
||||||
|
case *func(ForumsPage,io.Writer):
|
||||||
|
*d_ptr = *o_ptr
|
||||||
|
default:
|
||||||
|
log.Fatal("The origin and destination templates are incompatible")
|
||||||
|
}
|
||||||
|
case *func(ProfilePage,io.Writer):
|
||||||
|
switch d_ptr := dest_tmpl_ptr.(type) {
|
||||||
|
case *func(ProfilePage,io.Writer):
|
||||||
|
*d_ptr = *o_ptr
|
||||||
|
default:
|
||||||
|
log.Fatal("The origin and destination templates are incompatible")
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
log.Fatal("Unknown destination template type!")
|
||||||
|
}
|
||||||
|
delete(overriden_templates, name)
|
||||||
|
}*/
|
||||||
|
}
|
After Width: | Height: | Size: 136 KiB |
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"Name": "cosmo",
|
||||||
|
"FriendlyName": "AtomBB Cosmo",
|
||||||
|
"Version": "Coming Soon",
|
||||||
|
"Creator": "Azareal",
|
||||||
|
"Templates": [
|
||||||
|
{
|
||||||
|
"Name": "topic",
|
||||||
|
"Source": "topic_alt"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
{
|
||||||
|
"Name": "tempra-conflux",
|
||||||
|
"FriendlyName": "Tempra Conflux",
|
||||||
|
"Version": "0.0.1",
|
||||||
|
"Creator": "Azareal",
|
||||||
|
"Templates": [
|
||||||
|
{
|
||||||
|
"Name": "topic",
|
||||||
|
"Source": "topic_alt"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,409 @@
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
-moz-box-sizing: border-box;
|
||||||
|
-webkit-box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body
|
||||||
|
{
|
||||||
|
font-family: arial;
|
||||||
|
}
|
||||||
|
|
||||||
|
@font-face {
|
||||||
|
font-family: 'EmojiFont';
|
||||||
|
src: url('https://github.com/Ranks/emojione/raw/master/assets/fonts/emojione-svg.woff2') format('woff2'),
|
||||||
|
url('https://github.com/Ranks/emojione/raw/master/assets/fonts/emojione-svg.woff') format('woff'), local("arial");
|
||||||
|
}
|
||||||
|
|
||||||
|
@supports (-ms-ime-align:auto) {
|
||||||
|
.user_content
|
||||||
|
{
|
||||||
|
font-family: EmojiFont, arial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@-moz-document url-prefix() {
|
||||||
|
.user_content
|
||||||
|
{
|
||||||
|
font-family: EmojiFont, arial;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*.move_left{float: left;position: relative;left: 50%;}
|
||||||
|
.move_right{float: left;position: relative;left: -50%;}*/
|
||||||
|
ul
|
||||||
|
{
|
||||||
|
padding-left: 0px;
|
||||||
|
padding-right: 0px;
|
||||||
|
height: 28px;
|
||||||
|
list-style-type: none;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
li
|
||||||
|
{
|
||||||
|
height: 26px;
|
||||||
|
padding-left: 10px;
|
||||||
|
padding-top: 5px;
|
||||||
|
padding-bottom: 5px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
li:hover { background: rgb(250,250,250); }
|
||||||
|
li a
|
||||||
|
{
|
||||||
|
text-decoration: none;
|
||||||
|
color: #515151;
|
||||||
|
}
|
||||||
|
/*li a:hover { color: #7a7a7a; }*/
|
||||||
|
.menu_left
|
||||||
|
{
|
||||||
|
float: left;
|
||||||
|
border-right: 1px solid #ccc;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
.menu_right
|
||||||
|
{
|
||||||
|
float: right;
|
||||||
|
border-left: 1px solid #ccc;
|
||||||
|
padding-right: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.container
|
||||||
|
{
|
||||||
|
width: 90%;
|
||||||
|
padding: 0px;
|
||||||
|
margin-left: auto;
|
||||||
|
margin-right: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rowblock
|
||||||
|
{
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
width: 100%;
|
||||||
|
padding: 0px;
|
||||||
|
padding-top: 0px;
|
||||||
|
}
|
||||||
|
.rowblock:empty
|
||||||
|
{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.colblock_left
|
||||||
|
{
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
padding: 0px;
|
||||||
|
padding-top: 0px;
|
||||||
|
width: 30%;
|
||||||
|
float: left;
|
||||||
|
margin-right: 8px;
|
||||||
|
}
|
||||||
|
.colblock_right
|
||||||
|
{
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
padding: 0px;
|
||||||
|
padding-top: 0px;
|
||||||
|
width: 65%;
|
||||||
|
overflow: hidden;
|
||||||
|
word-wrap: break-word;
|
||||||
|
}
|
||||||
|
.colblock_left:empty
|
||||||
|
{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
.colblock_right:empty
|
||||||
|
{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.rowitem
|
||||||
|
{
|
||||||
|
width: 100%;
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 8px;
|
||||||
|
padding-top: 17px;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
.rowitem.passive
|
||||||
|
{
|
||||||
|
font-weight: normal;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
.rowitem:not(:last-child)
|
||||||
|
{
|
||||||
|
border-bottom: 1px dotted #ccc;
|
||||||
|
}
|
||||||
|
.rowitem a
|
||||||
|
{
|
||||||
|
text-decoration: none;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
.rowitem a:hover
|
||||||
|
{
|
||||||
|
color: silver;
|
||||||
|
}
|
||||||
|
|
||||||
|
.col_left
|
||||||
|
{
|
||||||
|
width: 30%;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
.col_right
|
||||||
|
{
|
||||||
|
width: 69%;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.colitem
|
||||||
|
{
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 8px;
|
||||||
|
padding-top: 17px;
|
||||||
|
padding-bottom: 12px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
.colitem.passive
|
||||||
|
{
|
||||||
|
font-weight: normal;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
.colitem a
|
||||||
|
{
|
||||||
|
text-decoration: none;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
.colitem a:hover
|
||||||
|
{
|
||||||
|
color: silver;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formrow
|
||||||
|
{
|
||||||
|
/*height: 40px;*/
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*Clearfix*/
|
||||||
|
.formrow:before,
|
||||||
|
.formrow:after {
|
||||||
|
content: " ";
|
||||||
|
display: table;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formrow:after {
|
||||||
|
clear: both;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formrow:not(:last-child)
|
||||||
|
{
|
||||||
|
border-bottom: 1px dotted #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formitem
|
||||||
|
{
|
||||||
|
float: left;
|
||||||
|
padding-left: 8px;
|
||||||
|
padding-right: 8px;
|
||||||
|
padding-top: 13px;
|
||||||
|
padding-bottom: 8px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formitem:first-child
|
||||||
|
{
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formitem:not(:last-child)
|
||||||
|
{
|
||||||
|
border-right: 1px dotted #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
.formitem.invisible_border
|
||||||
|
{
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mostly for textareas */
|
||||||
|
.formitem:only-child
|
||||||
|
{
|
||||||
|
width: 97%;
|
||||||
|
}
|
||||||
|
.formitem textarea
|
||||||
|
{
|
||||||
|
width: 100%;
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
|
.formitem:has-child()
|
||||||
|
{
|
||||||
|
margin: 0 auto;
|
||||||
|
float: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
button
|
||||||
|
{
|
||||||
|
background: white;
|
||||||
|
border: 1px solid #8e8e8e;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Topics */
|
||||||
|
.topic_status
|
||||||
|
{
|
||||||
|
text-transform: none;
|
||||||
|
margin-left: 8px;
|
||||||
|
padding-left: 2px;
|
||||||
|
padding-right: 2px;
|
||||||
|
padding-top: 2px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
background-color: #E8E8E8; /* 232,232,232. All three RGB colours being the same seems to create a shade of gray */
|
||||||
|
color: #505050; /* 80,80,80 */
|
||||||
|
border-radius: 2px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.topic_status:empty
|
||||||
|
{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.username
|
||||||
|
{
|
||||||
|
text-transform: none;
|
||||||
|
margin-left: 0px;
|
||||||
|
padding-left: 4px;
|
||||||
|
padding-right: 4px;
|
||||||
|
padding-top: 2px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
color: #505050; /* 80,80,80 */
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
border-style: dotted;
|
||||||
|
border-color: #505050; /* 232,232,232. All three RGB colours being the same seems to create a shade of gray */
|
||||||
|
border-width: 1px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
button.username
|
||||||
|
{
|
||||||
|
position: relative;
|
||||||
|
top: -0.25px;
|
||||||
|
}
|
||||||
|
.tag-mini
|
||||||
|
{
|
||||||
|
text-transform: none;
|
||||||
|
margin-left: 0px;
|
||||||
|
padding-left: 3px;
|
||||||
|
padding-right: 3px;
|
||||||
|
padding-top: 1.5px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
color: #505050; /* 80,80,80 */
|
||||||
|
background-color: #FFFFFF;
|
||||||
|
border-style: dotted;
|
||||||
|
border-color: #505050; /* 232,232,232. All three RGB colours being the same seems to create a shade of gray */
|
||||||
|
border-width: 1px;
|
||||||
|
font-size: 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.show_on_edit
|
||||||
|
{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert
|
||||||
|
{
|
||||||
|
display: block;
|
||||||
|
padding: 5px;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
.alert_success
|
||||||
|
{
|
||||||
|
display: block;
|
||||||
|
padding: 5px;
|
||||||
|
border: 1px solid A2FC00;
|
||||||
|
margin-bottom: 10px;
|
||||||
|
background-color: DAF7A6;
|
||||||
|
}
|
||||||
|
.alert_error
|
||||||
|
{
|
||||||
|
display: block;
|
||||||
|
padding: 5px;
|
||||||
|
border: 1px solid #FF004B;
|
||||||
|
margin-bottom: 8px;
|
||||||
|
background-color: #FEB7CC;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 880px) {
|
||||||
|
li
|
||||||
|
{
|
||||||
|
height: 25px;
|
||||||
|
font-size: 15px;
|
||||||
|
padding-left: 7px;
|
||||||
|
}
|
||||||
|
ul { height: 26px; margin-top: 8px; }
|
||||||
|
.menu_left { padding-right: 7px; }
|
||||||
|
.menu_right { padding-right: 7px; }
|
||||||
|
body { padding-left: 4px; padding-right: 4px; margin: 0px !important; width: 100% !important; height: 100% !important; overflow-x: hidden; }
|
||||||
|
.container { width: auto; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 810px) {
|
||||||
|
li
|
||||||
|
{
|
||||||
|
font-weight: normal;
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
.rowitem
|
||||||
|
{
|
||||||
|
text-transform: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 620px) {
|
||||||
|
li
|
||||||
|
{
|
||||||
|
padding-left: 5px;
|
||||||
|
padding-top: 2px;
|
||||||
|
padding-bottom: 2px;
|
||||||
|
height: 23px;
|
||||||
|
}
|
||||||
|
ul { height: 24px; }
|
||||||
|
.menu_left { padding-right: 5px; }
|
||||||
|
.menu_right { padding-right: 5px; }
|
||||||
|
.menu_create_topic { display: none;}
|
||||||
|
.hide_on_mobile { display: none; }
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (max-width: 470px) {
|
||||||
|
.menu_overview { display: none; }
|
||||||
|
.menu_profile { display: none; }
|
||||||
|
.hide_on_micro { display: none; }
|
||||||
|
.post_container {
|
||||||
|
overflow: visible !important;
|
||||||
|
}
|
||||||
|
.post_item {
|
||||||
|
background-position: 0px 2px !important;
|
||||||
|
background-size: 64px 64px !important;
|
||||||
|
padding-left: 2px !important;
|
||||||
|
min-height: 96px;
|
||||||
|
position: relative !important;
|
||||||
|
}
|
||||||
|
.post_item > .user_content {
|
||||||
|
margin-left: 75px !important;
|
||||||
|
width: 100% !important;
|
||||||
|
}
|
||||||
|
.post_item > .mod_button {
|
||||||
|
float: right !important;
|
||||||
|
margin-left: 2px !important;
|
||||||
|
position: relative;
|
||||||
|
top: -14px;
|
||||||
|
}
|
||||||
|
.post_item > .real_username {
|
||||||
|
position: absolute;
|
||||||
|
top: 70px;
|
||||||
|
float: left;
|
||||||
|
margin-top: 0px;
|
||||||
|
padding-top: 3px !important;
|
||||||
|
margin-right: 2px;
|
||||||
|
width: 60px;
|
||||||
|
font-size: 15px;
|
||||||
|
}
|
||||||
|
.container { width: 100% !important; }
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"Name": "tempra-simple",
|
||||||
|
"FriendlyName": "Tempra Simple",
|
||||||
|
"Version": "0.0.1",
|
||||||
|
"Creator": "Azareal"
|
||||||
|
}
|