Laid the foundations for better reply attachments.
The attachment manager introduced in the previous patch is now properly localised. Repurposed AttachmentStore.CountInTopic as a more general CountIn method. Added an & entity in attachment URLs so that the characters don't get mutated into something weird. Tried to make the linebreaks a little glitchy in the inline editor, we have a better solution in a mind soon! Fixed a bug where replies used .ContentHTML instead of .Content which led to a lot of HTML getting in the way of reply edits. Fixed a bug where reply attachments used the topicID rather than the replyID for their originID entries. Fixed a bug where the topic attachment counts weren't getting incremented. Added the topic.select_button_test, topic.copy_button_test and topic.upload_button_test phrases. Added the attachCount column to the replies table. This commit requires you to run the patcher / updater.
This commit is contained in:
parent
6c42df3091
commit
bf2af0ae96
@ -247,6 +247,7 @@ func createTables(adapter qgen.Adapter) error {
|
|||||||
tblColumn{"lastUpdated", "datetime", 0, false, false, ""},
|
tblColumn{"lastUpdated", "datetime", 0, false, false, ""},
|
||||||
tblColumn{"ipaddress", "varchar", 200, false, false, "0.0.0.0.0"},
|
tblColumn{"ipaddress", "varchar", 200, false, false, "0.0.0.0.0"},
|
||||||
tblColumn{"likeCount", "int", 0, false, false, "0"},
|
tblColumn{"likeCount", "int", 0, false, false, "0"},
|
||||||
|
tblColumn{"attachCount", "int", 0, false, false, "0"},
|
||||||
tblColumn{"words", "int", 0, false, false, "1"}, // ? - replies has a default of 1 and topics has 0? why?
|
tblColumn{"words", "int", 0, false, false, "1"}, // ? - replies has a default of 1 and topics has 0? why?
|
||||||
tblColumn{"actionType", "varchar", 20, false, false, "''"},
|
tblColumn{"actionType", "varchar", 20, false, false, "''"},
|
||||||
tblColumn{"poll", "int", 0, false, false, "0"},
|
tblColumn{"poll", "int", 0, false, false, "0"},
|
||||||
|
@ -26,31 +26,31 @@ type AttachmentStore interface {
|
|||||||
MiniTopicGet(id int) (alist []*MiniAttachment, err error)
|
MiniTopicGet(id int) (alist []*MiniAttachment, err error)
|
||||||
Add(sectionID int, sectionTable string, originID int, originTable string, uploadedBy int, path string) (int, error)
|
Add(sectionID int, sectionTable string, originID int, originTable string, uploadedBy int, path string) (int, error)
|
||||||
GlobalCount() int
|
GlobalCount() int
|
||||||
CountInTopic(tid int) int
|
CountIn(originTable string, oid int) int
|
||||||
CountInPath(path string) int
|
CountInPath(path string) int
|
||||||
Delete(aid int) error
|
Delete(aid int) error
|
||||||
}
|
}
|
||||||
|
|
||||||
type DefaultAttachmentStore struct {
|
type DefaultAttachmentStore struct {
|
||||||
get *sql.Stmt
|
get *sql.Stmt
|
||||||
getByTopic *sql.Stmt
|
getByTopic *sql.Stmt
|
||||||
add *sql.Stmt
|
add *sql.Stmt
|
||||||
count *sql.Stmt
|
count *sql.Stmt
|
||||||
countInTopic *sql.Stmt
|
countIn *sql.Stmt
|
||||||
countInPath *sql.Stmt
|
countInPath *sql.Stmt
|
||||||
delete *sql.Stmt
|
delete *sql.Stmt
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewDefaultAttachmentStore() (*DefaultAttachmentStore, error) {
|
func NewDefaultAttachmentStore() (*DefaultAttachmentStore, error) {
|
||||||
acc := qgen.NewAcc()
|
acc := qgen.NewAcc()
|
||||||
return &DefaultAttachmentStore{
|
return &DefaultAttachmentStore{
|
||||||
get: acc.Select("attachments").Columns("originID, sectionID, uploadedBy, path").Where("attachID = ?").Prepare(),
|
get: acc.Select("attachments").Columns("originID, sectionID, uploadedBy, path").Where("attachID = ?").Prepare(),
|
||||||
getByTopic: acc.Select("attachments").Columns("attachID, sectionID, uploadedBy, path").Where("originTable = 'topics' AND originID = ?").Prepare(),
|
getByTopic: acc.Select("attachments").Columns("attachID, sectionID, uploadedBy, path").Where("originTable = 'topics' AND originID = ?").Prepare(),
|
||||||
add: acc.Insert("attachments").Columns("sectionID, sectionTable, originID, originTable, uploadedBy, path").Fields("?,?,?,?,?,?").Prepare(),
|
add: acc.Insert("attachments").Columns("sectionID, sectionTable, originID, originTable, uploadedBy, path").Fields("?,?,?,?,?,?").Prepare(),
|
||||||
count: acc.Count("attachments").Prepare(),
|
count: acc.Count("attachments").Prepare(),
|
||||||
countInTopic: acc.Count("attachments").Where("originTable = 'topics' and originID = ?").Prepare(),
|
countIn: acc.Count("attachments").Where("originTable = ? and originID = ?").Prepare(),
|
||||||
countInPath: acc.Count("attachments").Where("path = ?").Prepare(),
|
countInPath: acc.Count("attachments").Where("path = ?").Prepare(),
|
||||||
delete: acc.Delete("attachments").Where("attachID = ?").Prepare(),
|
delete: acc.Delete("attachments").Where("attachID = ?").Prepare(),
|
||||||
}, acc.FirstError()
|
}, acc.FirstError()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,8 +107,8 @@ func (store *DefaultAttachmentStore) GlobalCount() (count int) {
|
|||||||
return count
|
return count
|
||||||
}
|
}
|
||||||
|
|
||||||
func (store *DefaultAttachmentStore) CountInTopic(tid int) (count int) {
|
func (store *DefaultAttachmentStore) CountIn(originTable string, oid int) (count int) {
|
||||||
err := store.countInTopic.QueryRow(tid).Scan(&count)
|
err := store.countIn.QueryRow(originTable, oid).Scan(&count)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
LogError(err)
|
LogError(err)
|
||||||
}
|
}
|
||||||
|
@ -587,7 +587,7 @@ func ParseMessage(msg string, sectionID int, sectionType string /*, user User*/)
|
|||||||
|
|
||||||
// TODO: Reduce the amount of code duplication
|
// TODO: Reduce the amount of code duplication
|
||||||
if media.Type == "attach" {
|
if media.Type == "attach" {
|
||||||
addImage(media.URL + "?sectionID=" + strconv.Itoa(sectionID) + "§ionType=" + sectionType)
|
addImage(media.URL + "?sectionID=" + strconv.Itoa(sectionID) + "&sectionType=" + sectionType)
|
||||||
continue
|
continue
|
||||||
} else if media.Type == "image" {
|
} else if media.Type == "image" {
|
||||||
addImage(media.URL)
|
addImage(media.URL)
|
||||||
|
@ -376,6 +376,10 @@
|
|||||||
"topic.report_button_text":"Report",
|
"topic.report_button_text":"Report",
|
||||||
"topic.flag_button_text":"Flag",
|
"topic.flag_button_text":"Flag",
|
||||||
|
|
||||||
|
"topic.select_button_text":"Select",
|
||||||
|
"topic.copy_button_text":"Copy",
|
||||||
|
"topic.upload_button_text":"Upload",
|
||||||
|
|
||||||
"panel_rank_admins":"Admins",
|
"panel_rank_admins":"Admins",
|
||||||
"panel_rank_mods":"Mods",
|
"panel_rank_mods":"Mods",
|
||||||
"panel_rank_banned":"Banned",
|
"panel_rank_banned":"Banned",
|
||||||
|
@ -22,6 +22,7 @@ func init() {
|
|||||||
addPatch(8, patch8)
|
addPatch(8, patch8)
|
||||||
addPatch(9, patch9)
|
addPatch(9, patch9)
|
||||||
addPatch(10, patch10)
|
addPatch(10, patch10)
|
||||||
|
addPatch(11, patch11)
|
||||||
}
|
}
|
||||||
|
|
||||||
func patch0(scanner *bufio.Scanner) (err error) {
|
func patch0(scanner *bufio.Scanner) (err error) {
|
||||||
@ -29,7 +30,6 @@ func patch0(scanner *bufio.Scanner) (err error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = execStmt(qgen.Builder.DropTable("menu_items"))
|
err = execStmt(qgen.Builder.DropTable("menu_items"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -400,7 +400,6 @@ func patch10(scanner *bufio.Scanner) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// We could probably do something more efficient, but as there shouldn't be too many sites right now, we can probably cheat a little, otherwise it'll take forever to get things done
|
|
||||||
err = acc().Select("topics").Cols("tid").EachInt(func(tid int) error {
|
err = acc().Select("topics").Cols("tid").EachInt(func(tid int) error {
|
||||||
stid := itoa(tid)
|
stid := itoa(tid)
|
||||||
|
|
||||||
@ -430,3 +429,41 @@ func patch10(scanner *bufio.Scanner) error {
|
|||||||
_, err = acc().Insert("updates").Columns("dbVersion").Fields("0").Exec()
|
_, err = acc().Insert("updates").Columns("dbVersion").Fields("0").Exec()
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func patch11(scanner *bufio.Scanner) error {
|
||||||
|
err := execStmt(qgen.Builder.AddColumn("replies", tblColumn{"attachCount", "int", 0, false, false, "0"}))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Attachments for replies got the topicID rather than the replyID for a while in error, so we want to separate these out
|
||||||
|
_, err = acc().Update("attachments").Set("originTable = 'freplies'").Where("originTable = 'replies'").Exec()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// We could probably do something more efficient, but as there shouldn't be too many sites right now, we can probably cheat a little, otherwise it'll take forever to get things done
|
||||||
|
return acc().Select("topics").Cols("tid").EachInt(func(tid int) error {
|
||||||
|
stid := itoa(tid)
|
||||||
|
|
||||||
|
count, err := acc().Count("attachments").Where("originTable = 'topics' and originID = " + stid).Total()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = acc().Update("topics").Set("attachCount = ?").Where("tid = " + stid).Exec(count)
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
|
||||||
|
/*return acc().Select("replies").Cols("rid").EachInt(func(rid int) error {
|
||||||
|
srid := itoa(rid)
|
||||||
|
|
||||||
|
count, err := acc().Count("attachments").Where("originTable = 'replies' and originID = " + srid).Total()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = acc().Update("replies").Set("attachCount = ?").Where("rid = " + srid).Exec(count)
|
||||||
|
return err
|
||||||
|
})*/
|
||||||
|
}
|
||||||
|
@ -380,7 +380,7 @@ function mainInit(){
|
|||||||
$(".topic_name").html(topicNameInput);
|
$(".topic_name").html(topicNameInput);
|
||||||
$(".topic_name").attr(topicNameInput);
|
$(".topic_name").attr(topicNameInput);
|
||||||
let topicContentInput = $('.topic_content_input').val();
|
let topicContentInput = $('.topic_content_input').val();
|
||||||
$(".topic_content").html(topicContentInput.replace(/(\n)+/g,"<br />"));
|
$(".topic_content").html(topicContentInput.replace("\n","<br><br>"));
|
||||||
let topicStatusInput = $('.topic_status_input').val();
|
let topicStatusInput = $('.topic_status_input').val();
|
||||||
$(".topic_status_e:not(.open_edit)").html(topicStatusInput);
|
$(".topic_status_e:not(.open_edit)").html(topicStatusInput);
|
||||||
|
|
||||||
@ -410,18 +410,25 @@ function mainInit(){
|
|||||||
|
|
||||||
$(".edit_item").click(function(event){
|
$(".edit_item").click(function(event){
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let blockParent = $(this).closest('.editable_parent');
|
let blockParent = this.closest('.editable_parent');
|
||||||
let block = blockParent.find('.editable_block').eq(0);
|
let srcNode = blockParent.querySelector(".edit_source");
|
||||||
block.html("<textarea style='width: 99%;' name='edit_item'>" + block.html() + "</textarea><br /><a href='" + $(this).closest('a').attr("href") + "'><button class='submit_edit' type='submit'>Update</button></a>");
|
let block = blockParent.querySelector('.editable_block');
|
||||||
|
block.classList.add("in_edit");
|
||||||
|
let source = "";
|
||||||
|
if(srcNode!=null) source = srcNode.innerText;
|
||||||
|
else source = block.innerHTML;
|
||||||
|
// TODO: Add a client template for this
|
||||||
|
block.innerHTML = "<textarea style='width: 99%;' name='edit_item'>" + source + "</textarea><br /><a href='" + this.closest('a').getAttribute("href") + "'><button class='submit_edit' type='submit'>Update</button></a>";
|
||||||
|
|
||||||
$(".submit_edit").click(function(event){
|
$(".submit_edit").click(function(event){
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
let blockParent = $(this).closest('.editable_parent');
|
block.classList.remove("in_edit");
|
||||||
let block = blockParent.find('.editable_block').eq(0);
|
let newContent = block.querySelector('textarea').value;
|
||||||
let newContent = block.find('textarea').eq(0).val();
|
block.innerHTML = newContent.replace("\n","<br><br>");
|
||||||
block.html(newContent);
|
if(srcNode!=null) srcNode.innerText = newContent;
|
||||||
|
|
||||||
var formAction = $(this).closest('a').attr("href");
|
let formAction = this.closest('a').getAttribute("href");
|
||||||
|
// TODO: Bounce the parsed post back and set innerHTML to it?
|
||||||
$.ajax({ url: formAction, type: "POST", error: ajaxError, dataType: "json", data: { isJs: "1", edit_item: newContent }
|
$.ajax({ url: formAction, type: "POST", error: ajaxError, dataType: "json", data: { isJs: "1", edit_item: newContent }
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -8,8 +8,26 @@ import (
|
|||||||
|
|
||||||
"github.com/Azareal/Gosora/common"
|
"github.com/Azareal/Gosora/common"
|
||||||
"github.com/Azareal/Gosora/common/counters"
|
"github.com/Azareal/Gosora/common/counters"
|
||||||
|
"github.com/Azareal/Gosora/query_gen"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ReplyStmts struct {
|
||||||
|
updateAttachs *sql.Stmt
|
||||||
|
}
|
||||||
|
|
||||||
|
var replyStmts ReplyStmts
|
||||||
|
|
||||||
|
// TODO: Move this statement somewhere else
|
||||||
|
func init() {
|
||||||
|
common.DbInits.Add(func(acc *qgen.Accumulator) error {
|
||||||
|
replyStmts = ReplyStmts{
|
||||||
|
// TODO: Less race-y attachment count updates
|
||||||
|
updateAttachs: acc.Update("replies").Set("attachCount = ?").Where("rid = ?").Prepare(),
|
||||||
|
}
|
||||||
|
return acc.FirstError()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func CreateReplySubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
func CreateReplySubmit(w http.ResponseWriter, r *http.Request, user common.User) common.RouteError {
|
||||||
tid, err := strconv.Atoi(r.PostFormValue("tid"))
|
tid, err := strconv.Atoi(r.PostFormValue("tid"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -35,15 +53,6 @@ func CreateReplySubmit(w http.ResponseWriter, r *http.Request, user common.User)
|
|||||||
return common.NoPermissions(w, r, user)
|
return common.NoPermissions(w, r, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Handle the file attachments
|
|
||||||
// TODO: Stop duplicating this code
|
|
||||||
if user.Perms.UploadFiles {
|
|
||||||
_, rerr := uploadAttachment(w, r, user, topic.ParentID, "forums", tid, "replies")
|
|
||||||
if rerr != nil {
|
|
||||||
return rerr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
content := common.PreparseMessage(r.PostFormValue("reply-content"))
|
content := common.PreparseMessage(r.PostFormValue("reply-content"))
|
||||||
// TODO: Fully parse the post and put that in the parsed column
|
// TODO: Fully parse the post and put that in the parsed column
|
||||||
rid, err := common.Rstore.Create(topic, content, user.LastIP, user.ID)
|
rid, err := common.Rstore.Create(topic, content, user.LastIP, user.ID)
|
||||||
@ -55,6 +64,16 @@ func CreateReplySubmit(w http.ResponseWriter, r *http.Request, user common.User)
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return common.LocalError("Unable to load the reply", w, r, user)
|
return common.LocalError("Unable to load the reply", w, r, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Handle the file attachments
|
||||||
|
// TODO: Stop duplicating this code
|
||||||
|
if user.Perms.UploadFiles {
|
||||||
|
_, rerr := uploadAttachment(w, r, user, topic.ParentID, "forums", rid, "replies")
|
||||||
|
if rerr != nil {
|
||||||
|
return rerr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if r.PostFormValue("has_poll") == "1" {
|
if r.PostFormValue("has_poll") == "1" {
|
||||||
var maxPollOptions = 10
|
var maxPollOptions = 10
|
||||||
var pollInputItems = make(map[int]string)
|
var pollInputItems = make(map[int]string)
|
||||||
|
@ -599,6 +599,7 @@ func deleteAttachment(w http.ResponseWriter, r *http.Request, user common.User,
|
|||||||
|
|
||||||
// TODO: Stop duplicating this code
|
// TODO: Stop duplicating this code
|
||||||
// TODO: Use a transaction here
|
// TODO: Use a transaction here
|
||||||
|
// TODO: Move this function to neutral ground
|
||||||
func uploadAttachment(w http.ResponseWriter, r *http.Request, user common.User, sid int, sectionTable string, oid int, originTable string) (pathMap map[string]string, rerr common.RouteError) {
|
func uploadAttachment(w http.ResponseWriter, r *http.Request, user common.User, sid int, sectionTable string, oid int, originTable string) (pathMap map[string]string, rerr common.RouteError) {
|
||||||
pathMap = make(map[string]string)
|
pathMap = make(map[string]string)
|
||||||
files, rerr := uploadFilesWithHash(w, r, user, "./attachs/")
|
files, rerr := uploadFilesWithHash(w, r, user, "./attachs/")
|
||||||
@ -619,9 +620,9 @@ func uploadAttachment(w http.ResponseWriter, r *http.Request, user common.User,
|
|||||||
pathMap[filename] = strconv.Itoa(aid)
|
pathMap[filename] = strconv.Itoa(aid)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch sectionTable {
|
switch originTable {
|
||||||
case "topics":
|
case "topics":
|
||||||
_, err = topicStmts.updateAttachs.Exec(common.Attachments.CountInTopic(oid), oid)
|
_, err = topicStmts.updateAttachs.Exec(common.Attachments.CountIn(originTable,oid), oid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, common.InternalError(err, w, r)
|
return nil, common.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
@ -629,6 +630,11 @@ func uploadAttachment(w http.ResponseWriter, r *http.Request, user common.User,
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, common.InternalError(err, w, r)
|
return nil, common.InternalError(err, w, r)
|
||||||
}
|
}
|
||||||
|
case "replies":
|
||||||
|
_, err = replyStmts.updateAttachs.Exec(common.Attachments.CountIn(originTable,oid), oid)
|
||||||
|
if err != nil {
|
||||||
|
return nil, common.InternalError(err, w, r)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@ CREATE TABLE [replies] (
|
|||||||
[lastUpdated] datetime not null,
|
[lastUpdated] datetime not null,
|
||||||
[ipaddress] nvarchar (200) DEFAULT '0.0.0.0.0' not null,
|
[ipaddress] nvarchar (200) DEFAULT '0.0.0.0.0' not null,
|
||||||
[likeCount] int DEFAULT 0 not null,
|
[likeCount] int DEFAULT 0 not null,
|
||||||
|
[attachCount] int DEFAULT 0 not null,
|
||||||
[words] int DEFAULT 1 not null,
|
[words] int DEFAULT 1 not null,
|
||||||
[actionType] nvarchar (20) DEFAULT '' not null,
|
[actionType] nvarchar (20) DEFAULT '' not null,
|
||||||
[poll] int DEFAULT 0 not null,
|
[poll] int DEFAULT 0 not null,
|
||||||
|
@ -10,6 +10,7 @@ CREATE TABLE `replies` (
|
|||||||
`lastUpdated` datetime not null,
|
`lastUpdated` datetime not null,
|
||||||
`ipaddress` varchar(200) DEFAULT '0.0.0.0.0' not null,
|
`ipaddress` varchar(200) DEFAULT '0.0.0.0.0' not null,
|
||||||
`likeCount` int DEFAULT 0 not null,
|
`likeCount` int DEFAULT 0 not null,
|
||||||
|
`attachCount` int DEFAULT 0 not null,
|
||||||
`words` int DEFAULT 1 not null,
|
`words` int DEFAULT 1 not null,
|
||||||
`actionType` varchar(20) DEFAULT '' not null,
|
`actionType` varchar(20) DEFAULT '' not null,
|
||||||
`poll` int DEFAULT 0 not null,
|
`poll` int DEFAULT 0 not null,
|
||||||
|
@ -10,6 +10,7 @@ CREATE TABLE "replies" (
|
|||||||
`lastUpdated` timestamp not null,
|
`lastUpdated` timestamp not null,
|
||||||
`ipaddress` varchar (200) DEFAULT '0.0.0.0.0' not null,
|
`ipaddress` varchar (200) DEFAULT '0.0.0.0.0' not null,
|
||||||
`likeCount` int DEFAULT 0 not null,
|
`likeCount` int DEFAULT 0 not null,
|
||||||
|
`attachCount` int DEFAULT 0 not null,
|
||||||
`words` int DEFAULT 1 not null,
|
`words` int DEFAULT 1 not null,
|
||||||
`actionType` varchar (20) DEFAULT '' not null,
|
`actionType` varchar (20) DEFAULT '' not null,
|
||||||
`poll` int DEFAULT 0 not null,
|
`poll` int DEFAULT 0 not null,
|
||||||
|
@ -82,17 +82,17 @@
|
|||||||
{{if .Topic.Attachments}}<div class="show_on_edit attach_edit_bay" tid="{{.Topic.ID}}">
|
{{if .Topic.Attachments}}<div class="show_on_edit attach_edit_bay" tid="{{.Topic.ID}}">
|
||||||
{{range .Topic.Attachments}}
|
{{range .Topic.Attachments}}
|
||||||
<div class="attach_item{{if .Image}} attach_image_holder{{end}}">
|
<div class="attach_item{{if .Image}} attach_image_holder{{end}}">
|
||||||
{{if .Image}}<img src="//{{$.Header.Site.URL}}/attachs/{{.Path}}?sectionID={{.SectionID}}§ionType=forums" height="24" width="24" />{{end}}
|
{{if .Image}}<img src="//{{$.Header.Site.URL}}/attachs/{{.Path}}?sectionID={{.SectionID}}§ionType=forums" height=24 width=24 />{{end}}
|
||||||
<span class="attach_item_path" aid="{{.ID}}" fullPath="//{{$.Header.Site.URL}}/attachs/{{.Path}}">{{.Path}}</span>
|
<span class="attach_item_path" aid="{{.ID}}" fullPath="//{{$.Header.Site.URL}}/attachs/{{.Path}}">{{.Path}}</span>
|
||||||
<button class="attach_item_select">Select</button>
|
<button class="attach_item_select">{{lang "topic.select_button_text"}}</button>
|
||||||
<button class="attach_item_copy">Copy</button>
|
<button class="attach_item_copy">{{lang "topic.copy_button_text"}}</button>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
<div class="attach_item attach_item_buttons">
|
<div class="attach_item attach_item_buttons">
|
||||||
{{if .CurrentUser.Perms.UploadFiles}}
|
{{if .CurrentUser.Perms.UploadFiles}}
|
||||||
<input name="upload_files" id="upload_files_op" multiple type="file" style="display: none;" />
|
<input name="upload_files" id="upload_files_op" multiple type="file" style="display: none;" />
|
||||||
<label for="upload_files_op" class="formbutton add_file_button">Upload</label>{{end}}
|
<label for="upload_files_op" class="formbutton add_file_button">{{lang "topic.upload_button_text"}}</label>{{end}}
|
||||||
<button class="attach_item_delete">Delete</button>
|
<button class="attach_item_delete">{{lang "topic.delete_button_text"}}</button>
|
||||||
</div>
|
</div>
|
||||||
</div>{{end}}
|
</div>{{end}}
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
<span class="action_icon" style="font-size: 18px;padding-right: 5px;" aria-hidden="true">{{.ActionIcon}}</span>
|
<span class="action_icon" style="font-size: 18px;padding-right: 5px;" aria-hidden="true">{{.ActionIcon}}</span>
|
||||||
<span itemprop="text">{{.ActionType}}</span>
|
<span itemprop="text">{{.ActionType}}</span>
|
||||||
{{else}}
|
{{else}}
|
||||||
{{/** TODO: We might end up with <br>s in the inline editor, fix this **/}}
|
<div class="edit_source auto_hide">{{.Content}}</div>
|
||||||
<div class="editable_block user_content" itemprop="text">{{.ContentHtml}}</div>
|
<div class="editable_block user_content" itemprop="text">{{.ContentHtml}}</div>
|
||||||
<div class="controls button_container{{if .LikeCount}} has_likes{{end}}">
|
<div class="controls button_container{{if .LikeCount}} has_likes{{end}}">
|
||||||
<div class="action_button_left">
|
<div class="action_button_left">
|
||||||
|
@ -710,6 +710,23 @@ button, .formbutton, .panel_right_button:not(.has_inner_button) {
|
|||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
padding: 16px;
|
padding: 16px;
|
||||||
}
|
}
|
||||||
|
.user_content.in_edit {
|
||||||
|
padding: 0px;
|
||||||
|
background: none;
|
||||||
|
}
|
||||||
|
.user_content textarea {
|
||||||
|
resize: vertical;
|
||||||
|
height: 150px;
|
||||||
|
width: 100% !important;
|
||||||
|
padding: 16px;
|
||||||
|
}
|
||||||
|
.user_content.in_edit a {
|
||||||
|
display: flex;
|
||||||
|
background-color: #444444;
|
||||||
|
border-radius: 4px;
|
||||||
|
margin-top: 4px; /*8 without <br>*/
|
||||||
|
padding: 6px;
|
||||||
|
}
|
||||||
.post_item .button_container {
|
.post_item .button_container {
|
||||||
display: flex;
|
display: flex;
|
||||||
margin-top: 8px;
|
margin-top: 8px;
|
||||||
@ -1014,10 +1031,7 @@ input[type=checkbox]:checked + label .sel {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@media(max-width: 500px) {
|
@media(max-width: 500px) {
|
||||||
.sidebar {
|
.sidebar, .topic_view_count {
|
||||||
display: none;
|
|
||||||
}
|
|
||||||
.topic_view_count {
|
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user