diff --git a/Builder/IISMainHandler/build.txt b/Builder/IISMainHandler/build.txt index 4f36264..1c34b96 100644 --- a/Builder/IISMainHandler/build.txt +++ b/Builder/IISMainHandler/build.txt @@ -1 +1 @@ -360 \ No newline at end of file +377 \ No newline at end of file diff --git a/Builder/IISUploadHandler/build.txt b/Builder/IISUploadHandler/build.txt index 69226f7..6d58c4e 100644 --- a/Builder/IISUploadHandler/build.txt +++ b/Builder/IISUploadHandler/build.txt @@ -1 +1 @@ -92 \ No newline at end of file +109 \ No newline at end of file diff --git a/Common/Common.csproj b/Common/Common.csproj index b2c3365..e14444c 100644 --- a/Common/Common.csproj +++ b/Common/Common.csproj @@ -53,6 +53,7 @@ + @@ -70,6 +71,7 @@ + diff --git a/Common/UBBParser.cs b/Common/UBBParser.cs new file mode 100644 index 0000000..c6f2259 --- /dev/null +++ b/Common/UBBParser.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace FLocal.Common { + public static class UBBParser { + + public static string UBBToIntermediate(string UBB) { + return UBB; + } + + public static string ShallerToUBB(string shaller) { + return shaller; + } + + } +} diff --git a/Common/actions/ChangeSet.cs b/Common/actions/ChangeSet.cs index 63f47e6..e9d3dee 100644 --- a/Common/actions/ChangeSet.cs +++ b/Common/actions/ChangeSet.cs @@ -24,6 +24,7 @@ namespace FLocal.Common.actions { dataobjects.Board.TableSpec.TABLE, dataobjects.Thread.TableSpec.TABLE, dataobjects.Post.TableSpec.TABLE, + dataobjects.Post.RevisionTableSpec.TABLE, dataobjects.Board.ReadMarkerTableSpec.TABLE, dataobjects.Thread.ReadMarkerTableSpec.TABLE, dataobjects.Session.TableSpec.TABLE, @@ -94,11 +95,17 @@ namespace FLocal.Common.actions { public void Dispose() { //if(!this.isProcessed) throw new CriticalException("ChangeSet is not processed yet"); - foreach(KeyValuePair> kvp in this.changesByTable) { - foreach(AbstractChange change in kvp.Value) { - if(change.getId().HasValue) { - change.tableSpec.refreshSqlObject(change.getId().Value); - } //otherwise we're disposing because of sql error or something, so we should show real cause of problem, not "id is null" + if(this.isProcessed) { + foreach(KeyValuePair> kvp in this.changesByTable) { + foreach(AbstractChange change in kvp.Value) { + if(change.getId().HasValue) { + try { + change.tableSpec.refreshSqlObject(change.getId().Value); + } catch(NotFoundInDBException) { + //it seems something broken earlier; transaction rollback etc... + } + } //otherwise we're disposing because of sql error or something, so we should show real cause of problem, not "id is null" + } } } } diff --git a/Common/actions/ReferenceFieldValue.cs b/Common/actions/ReferenceFieldValue.cs index a8b5fac..3022bb6 100644 --- a/Common/actions/ReferenceFieldValue.cs +++ b/Common/actions/ReferenceFieldValue.cs @@ -16,7 +16,7 @@ namespace FLocal.Common.actions { return this.referenced.getId().Value.ToString(); } public override string getStringRepresentation(string oldInfo) { - return this.referenced.getId().Value.ToString(); + return this.getStringRepresentation(); } } diff --git a/Common/actions/TwoWayReferenceFieldValue.cs b/Common/actions/TwoWayReferenceFieldValue.cs new file mode 100644 index 0000000..97efc60 --- /dev/null +++ b/Common/actions/TwoWayReferenceFieldValue.cs @@ -0,0 +1,28 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace FLocal.Common.actions { + + class TwoWayReferenceFieldValue : ReferenceFieldValue { + + public delegate string Calculator(string old, string reference); + + private Calculator calculator; + + public TwoWayReferenceFieldValue(AbstractChange referenced, Calculator calculator) + : base(referenced) { + this.calculator = calculator; + } + + public override string getStringRepresentation() { + throw new NotSupportedException(); + } + + public override string getStringRepresentation(string oldInfo) { + return this.calculator(oldInfo, base.getStringRepresentation()); + } + + } +} diff --git a/Common/dataobjects/Post.cs b/Common/dataobjects/Post.cs index 4ea6512..5b04b65 100644 --- a/Common/dataobjects/Post.cs +++ b/Common/dataobjects/Post.cs @@ -5,6 +5,8 @@ using System.Text; using System.Xml.Linq; using FLocal.Core; using FLocal.Core.DB; +using FLocal.Common; +using FLocal.Common.actions; namespace FLocal.Common.dataobjects { public class Post : SqlObject { @@ -16,7 +18,7 @@ namespace FLocal.Common.dataobjects { public const string FIELD_POSTDATE = "PostDate"; public const string FIELD_LASTCHANGEDATE = "LastChangeDate"; public const string FIELD_REVISION = "Revision"; - public const string FIELD_LAYER = "Layer"; + public const string FIELD_LAYERID = "LayerId"; public const string FIELD_TITLE = "Title"; public const string FIELD_BODY = "Body"; public const string FIELD_THREADID = "ThreadId"; @@ -27,6 +29,20 @@ namespace FLocal.Common.dataobjects { public void refreshSqlObject(int id) { Refresh(id); } } + public class RevisionTableSpec : ISqlObjectTableSpec { + public const string TABLE = "Revisions"; + public const string FIELD_ID = "Id"; + public const string FIELD_POSTID = "PostId"; + public const string FIELD_CHANGEDATE = "ChangeDate"; + public const string FIELD_TITLE = "Title"; + public const string FIELD_BODY = "Body"; + public const string FIELD_NUMBER = "Number"; + public static readonly RevisionTableSpec instance = new RevisionTableSpec(); + public string name { get { return TABLE; } } + public string idName { get { return FIELD_ID; } } + public void refreshSqlObject(int id) { } + } + protected override ISqlObjectTableSpec table { get { return TableSpec.instance; } } private int _posterId; @@ -67,11 +83,11 @@ namespace FLocal.Common.dataobjects { } } - private int _layer; - public int layer { + private int _layerId; + public int layerId { get { this.LoadIfNotLoaded(); - return this._layer; + return this._layerId; } } @@ -127,7 +143,7 @@ namespace FLocal.Common.dataobjects { this._postDate = new DateTime(long.Parse(data[TableSpec.FIELD_POSTDATE])); this._lastChangeDate = Util.ParseDateTimeFromTimestamp(data[TableSpec.FIELD_LASTCHANGEDATE]); this._revision = int.Parse(data[TableSpec.FIELD_REVISION]); - this._layer = int.Parse(data[TableSpec.FIELD_LAYER]); + this._layerId = int.Parse(data[TableSpec.FIELD_LAYERID]); this._title = data[TableSpec.FIELD_TITLE]; this._body = data[TableSpec.FIELD_BODY]; this._threadId = int.Parse(data[TableSpec.FIELD_THREADID]); @@ -149,7 +165,7 @@ namespace FLocal.Common.dataobjects { new XElement("postDate", this.postDate.ToXml()), new XElement("lastChangeDate", this.postDate.ToXml()), new XElement("revision", this.revision), - new XElement("layer", this.layer), + new XElement("layerId", this.layerId), new XElement("title", this.title), new XElement("body", context.outputParams.preprocessBodyIntermediate(this.body)), new XElement("bodyShort", this.bodyShort), @@ -166,5 +182,100 @@ namespace FLocal.Common.dataobjects { return result; } + public Post Reply(User poster, string title, string body, int desiredLayerId) { + + if(this.thread.isLocked) { + throw new FLocalException("thread locked"); + } + + int actualLayerId = Math.Max(poster.getMinAllowedLayer(this.thread.board), desiredLayerId); + AbstractChange postInsert = new InsertChange( + TableSpec.instance, + new Dictionary { + { TableSpec.FIELD_THREADID, new ScalarFieldValue(this.thread.id.ToString()) }, + { TableSpec.FIELD_PARENTPOSTID, new ScalarFieldValue(this.id.ToString()) }, + { TableSpec.FIELD_POSTERID, new ScalarFieldValue(poster.id.ToString()) }, + { TableSpec.FIELD_POSTDATE, new ScalarFieldValue(DateTime.Now.ToUTCString()) }, + { TableSpec.FIELD_REVISION, new ScalarFieldValue("0") }, + { TableSpec.FIELD_LASTCHANGEDATE, new ScalarFieldValue(DateTime.Now.ToUTCString()) }, + { TableSpec.FIELD_LAYERID, new ScalarFieldValue(layerId.ToString()) }, + { TableSpec.FIELD_TITLE, new ScalarFieldValue(title) }, + { TableSpec.FIELD_BODY, new ScalarFieldValue(UBBParser.UBBToIntermediate(body)) }, + } + ); + AbstractChange revisionInsert = new InsertChange( + RevisionTableSpec.instance, + new Dictionary { + { RevisionTableSpec.FIELD_POSTID, new ReferenceFieldValue(postInsert) }, + { RevisionTableSpec.FIELD_NUMBER, new ScalarFieldValue("0") }, + { RevisionTableSpec.FIELD_CHANGEDATE, new ScalarFieldValue(DateTime.Now.ToUTCString()) }, + { RevisionTableSpec.FIELD_TITLE, new ScalarFieldValue(title) }, + { RevisionTableSpec.FIELD_BODY, new ScalarFieldValue(body) }, + } + ); + AbstractChange threadUpdate = new UpdateChange( + Thread.TableSpec.instance, + new Dictionary { + { Thread.TableSpec.FIELD_LASTPOSTDATE, new ScalarFieldValue(DateTime.Now.ToUTCString()) }, + { Thread.TableSpec.FIELD_TOTALPOSTS, new IncrementFieldValue() }, + { + Thread.TableSpec.FIELD_LASTPOSTID, + new TwoWayReferenceFieldValue( + postInsert, + (oldStringId, newStringId) => { + int oldId = int.Parse(oldStringId); + int newId = int.Parse(newStringId); + return Math.Max(oldId, newId).ToString(); + } + ) + } + }, + this.thread.id + ); + AbstractChange userUpdate = new UpdateChange( + User.TableSpec.instance, + new Dictionary { + { User.TableSpec.FIELD_TOTALPOSTS, new IncrementFieldValue() }, + }, + poster.id + ); + List changes = new List { + postInsert, + revisionInsert, + threadUpdate, + userUpdate, + }; + + int? boardId = thread.boardId; + do { + Board board = Board.LoadById(boardId.Value); + changes.Add( + new UpdateChange( + Board.TableSpec.instance, + new Dictionary { + { Board.TableSpec.FIELD_TOTALPOSTS, new IncrementFieldValue() }, + { + Board.TableSpec.FIELD_LASTPOSTID, + new TwoWayReferenceFieldValue( + postInsert, + (oldStringId, newStringId) => { + int oldId = int.Parse(oldStringId); + int newId = int.Parse(newStringId); + return Math.Max(oldId, newId).ToString(); + } + ) + } + }, + board.id + ) + ); + boardId = board.parentBoardId; + } while(boardId.HasValue); + + ChangeSetUtil.ApplyChanges(changes.ToArray()); + + return Post.LoadById(postInsert.getId().Value); + } + } } diff --git a/Common/dataobjects/User.cs b/Common/dataobjects/User.cs index c2d0ed9..96987b2 100644 --- a/Common/dataobjects/User.cs +++ b/Common/dataobjects/User.cs @@ -192,5 +192,9 @@ namespace FLocal.Common.dataobjects { ); } + public int getMinAllowedLayer(Board board) { + return 1; + } + } } diff --git a/IISMainHandler/HandlersFactory.cs b/IISMainHandler/HandlersFactory.cs index 96b5fa7..5e3c3e6 100644 --- a/IISMainHandler/HandlersFactory.cs +++ b/IISMainHandler/HandlersFactory.cs @@ -31,7 +31,15 @@ namespace FLocal.IISHandler { case "thread": return new handlers.ThreadHandler(); case "post": - return new handlers.PostHandler(); + if(context.requestParts.Length < 2) { + return new handlers.WrongUrlHandler(); + } + switch(context.requestParts[2].ToLower()) { + case "reply": + return new handlers.response.ReplyHandler(); + default: + return new handlers.PostHandler(); + } case "login": return new handlers.response.LoginHandler(); case "migrateaccount": @@ -67,6 +75,8 @@ namespace FLocal.IISHandler { return new handlers.request.LogoutHandler(); case "migrateaccount": return new handlers.request.MigrateAccountHandler(); + case "reply": + return new handlers.request.ReplyHandler(); default: return new handlers.WrongUrlHandler(); } diff --git a/IISMainHandler/IISMainHandler.csproj b/IISMainHandler/IISMainHandler.csproj index 800fb43..28ea5e3 100644 --- a/IISMainHandler/IISMainHandler.csproj +++ b/IISMainHandler/IISMainHandler.csproj @@ -58,15 +58,19 @@ + + + + diff --git a/IISMainHandler/handlers/PostHandler.cs b/IISMainHandler/handlers/PostHandler.cs index 4dcf6ad..510399a 100644 --- a/IISMainHandler/handlers/PostHandler.cs +++ b/IISMainHandler/handlers/PostHandler.cs @@ -28,6 +28,7 @@ namespace FLocal.IISHandler.handlers { XElement[] result = new XElement[] { new XElement("currentLocation", post.exportToXmlSimpleWithParent(context)), + post.thread.exportToXml(context, false), new XElement("posts", post.exportToXmlWithoutThread(context, true, new XElement("isUnread", (post.id > lastReadId).ToPlainString()))) }; diff --git a/IISMainHandler/handlers/ThreadHandler.cs b/IISMainHandler/handlers/ThreadHandler.cs index 2b788a1..6f2fda9 100644 --- a/IISMainHandler/handlers/ThreadHandler.cs +++ b/IISMainHandler/handlers/ThreadHandler.cs @@ -57,6 +57,7 @@ namespace FLocal.IISHandler.handlers { XElement[] result = new XElement[] { new XElement("currentLocation", thread.exportToXmlSimpleWithParent(context)), + thread.exportToXml(context, false), new XElement("posts", from post in posts select post.exportToXmlWithoutThread(context, true, new XElement("isUnread", (post.id > lastReadId).ToPlainString())), pageOuter.exportToXml(2, 5, 2) diff --git a/IISMainHandler/handlers/request/AbstractNewMessageHandler.cs b/IISMainHandler/handlers/request/AbstractNewMessageHandler.cs new file mode 100644 index 0000000..e7b3b9e --- /dev/null +++ b/IISMainHandler/handlers/request/AbstractNewMessageHandler.cs @@ -0,0 +1,27 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using FLocal.Core; + +namespace FLocal.IISHandler.handlers.request { + abstract class AbstractNewMessageHandler : AbstractPostHandler { + + protected string getTitle(WebContext context) { + string title = context.httprequest.Form["title"].Trim(); + if(title == "") { + throw new FLocalException("Title is empty"); + } + return title; + } + + protected string getBody(WebContext context) { + string body = context.httprequest.Form["body"].Trim(); + if(body == "") { + throw new FLocalException("Body is empty"); + } + return body; + } + + } +} diff --git a/IISMainHandler/handlers/request/CreateThreadHandler.cs b/IISMainHandler/handlers/request/CreateThreadHandler.cs new file mode 100644 index 0000000..1d03ca1 --- /dev/null +++ b/IISMainHandler/handlers/request/CreateThreadHandler.cs @@ -0,0 +1,20 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; + +namespace FLocal.IISHandler.handlers.request { + class CreateThreadHandler : AbstractNewMessageHandler { + + protected override string templateName { + get { + throw new NotImplementedException(); + } + } + + protected override XElement[] Do(WebContext context) { + throw new NotImplementedException(); + } + } +} diff --git a/IISMainHandler/handlers/request/ReplyHandler.cs b/IISMainHandler/handlers/request/ReplyHandler.cs new file mode 100644 index 0000000..50a4a36 --- /dev/null +++ b/IISMainHandler/handlers/request/ReplyHandler.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Xml.Linq; +using FLocal.Common.dataobjects; + +namespace FLocal.IISHandler.handlers.request { + class ReplyHandler : AbstractNewMessageHandler { + + protected override string templateName { + get { + return "result/MessageCreated.xslt"; + } + } + + protected override XElement[] Do(WebContext context) { +// Post post = Post.LoadById(int.Parse(context.httprequest.Form["parent"])); + //int desiredLayerId = Math.Min(context.session.account.user.getMinAllowedLayer(post.thread.board), int.Parse(context.httprequest.Form["layer"])); + + Post newPost = Post.LoadById( + int.Parse(context.httprequest.Form["parent"]) + ).Reply( + context.session.account.user, + this.getTitle(context), + this.getBody(context), + int.Parse(context.httprequest.Form["layerId"]) + ); + + newPost.thread.markAsRead(context.session.account, newPost, newPost); + + return new XElement[] { newPost.exportToXmlWithoutThread(context, false) }; + } + + } +} diff --git a/IISMainHandler/handlers/response/ReplyHandler.cs b/IISMainHandler/handlers/response/ReplyHandler.cs new file mode 100644 index 0000000..04b2d11 --- /dev/null +++ b/IISMainHandler/handlers/response/ReplyHandler.cs @@ -0,0 +1,32 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Web; +using System.Xml.Linq; +using FLocal.Core; +using FLocal.Common; +using FLocal.Common.dataobjects; + +namespace FLocal.IISHandler.handlers.response { + + class ReplyHandler : AbstractGetHandler { + + override protected string templateName { + get { + return "PostReply.xslt"; + } + } + + override protected XElement[] getSpecificData(WebContext context) { + Post post = Post.LoadById(int.Parse(context.requestParts[1])); + + return new XElement[] { + post.thread.board.exportToXml(context, false), + post.thread.exportToXml(context, false), + post.exportToXmlWithoutThread(context, false), + }; + } + } + +} \ No newline at end of file diff --git a/static/css/coffeehaus.css b/static/css/coffeehaus.css index ee9af64..e88a796 100644 --- a/static/css/coffeehaus.css +++ b/static/css/coffeehaus.css @@ -1,6 +1,12 @@ /* File Version 6.5.1 */ -a:link { +[pseudolink] { + color: #303030; + background: none; + text-decoration: underline; +} + +a:link { color: #303030; background: none; } diff --git a/static/css/global.css b/static/css/global.css index 4ae9c2e..0d61d36 100644 --- a/static/css/global.css +++ b/static/css/global.css @@ -70,4 +70,8 @@ pre } .navigation { margin:3px; +} + +[pseudolink] { + cursor:hand; } \ No newline at end of file diff --git a/static/js/textEditor.js b/static/js/textEditor.js new file mode 100644 index 0000000..9056ada Binary files /dev/null and b/static/js/textEditor.js differ diff --git a/templates/Full/Login.xslt b/templates/Full/Login.xslt index bdfd4be..9cd8510 100644 --- a/templates/Full/Login.xslt +++ b/templates/Full/Login.xslt @@ -15,7 +15,7 @@ Ââåäèòå âàøå èìÿ ïîëüçîâàòåëÿ è ïàðîëü äëÿ ðåãèñòðàöèè â ôîðóìå.
- Åñëè âû åù¸ íå ïîëüçîâàëèñü ýòèì ôîðóìîì, íî ïðèøëè ñî ñòàðîãî ôîðóì.ëîêàëà – âû ìîæåòå ñîçäàòü ïàðîëü â ôîðìå ìèãðàöèè. + Åñëè âû åù¸ íå ïîëüçîâàëèñü ýòèì ôîðóìîì, íî ïðèøëè ñî ñòàðîãî ôîðóì.ëîêàëà – âû ìîæåòå ñîçäàòü ïàðîëü â ôîðìå ìèãðàöèè. @@ -45,7 +45,7 @@ - Åñëè âû ïðèøëè ñî ñòàðîãî ôîðóì.ëîêàëà – ââåäèòå ñâîé ëîãèí. + Åñëè âû ïðèøëè ñî ñòàðîãî ôîðóì.ëîêàëà – ââåäèòå ñâîé ëîãèí. diff --git a/templates/Full/Post.xslt b/templates/Full/Post.xslt index f2cd876..1b49c50 100644 --- a/templates/Full/Post.xslt +++ b/templates/Full/Post.xslt @@ -9,7 +9,9 @@ - + + +
diff --git a/templates/Full/PostReply.xslt b/templates/Full/PostReply.xslt new file mode 100644 index 0000000..2da3a4c --- /dev/null +++ b/templates/Full/PostReply.xslt @@ -0,0 +1,107 @@ + + + + + + + + + +
+ + + + + + + + + + +
+ Îòâåò íà ñîîáùåíèå ( + + ) +
+ Çàïîëíèòå ïðèâåäåííóþ íèæå ôîðìó äëÿ îòïðàâêè ñîîáùåíèÿ â ôîðóì. HTML îòêëþ÷åí. UBBCode âêëþ÷åí, è âû ìîæåòå èñïîëüçîâàòü UBBCode â âàøèõ ñîîáùåíèÿõ. Àíîíèìíûå ñîîáùåíèÿ ðàçðåøåíû, è âû ìîæåòå âûáðàòü ëþáîå íåçàðåãèñòðèðîâàííîå èìÿ. +
+
+ + + + Ïîëüçîâàòåëü: + +
+
+ Òåìà: +
+ + + + + + + + Re: + + + + + + Ñëîé ñîîáùåíèÿ: + +
+
+ +
+ + ß õî÷ó ïðåäâàðèòåëüíî ïðîñìîòðåòü ñîîáùåíèå ïåðåä îòïðàâêîé +
+
+ + Ïðîâåðèòü ïðàâîïèñàíèå +
+
+ + +
+
+ +
+ + + + + +
+ + + + + + + + + + +
+ Îòâåò íà ñîîáùåíèå +
+ + Àâòîð: + +
+ Òåìà: + +
+
+ +
+
+
+ +
\ No newline at end of file diff --git a/templates/Full/Thread.xslt b/templates/Full/Thread.xslt index e8a7eed..18f14ad 100644 --- a/templates/Full/Thread.xslt +++ b/templates/Full/Thread.xslt @@ -23,7 +23,9 @@ - + + + diff --git a/templates/Full/UploadNew.xslt b/templates/Full/UploadNew.xslt index bd2b232..7b2a81e 100644 --- a/templates/Full/UploadNew.xslt +++ b/templates/Full/UploadNew.xslt @@ -14,7 +14,8 @@ diff --git a/templates/Full/elems/PostInfo.xslt b/templates/Full/elems/PostInfo.xslt index b03b4e1..5b1c588 100644 --- a/templates/Full/elems/PostInfo.xslt +++ b/templates/Full/elems/PostInfo.xslt @@ -3,6 +3,7 @@ + true
Âûáåðèòå ôàéë äëÿ çàãðóçêè - Ìàêñèìàëüíûé ðàçìåð ôàéëà – 1ÌÁ, äîïóñòèìûå ðàçðåøåíèÿ: gif, jpg, png +
+ Ìàêñèìàëüíûé ðàçìåð ôàéëà – 1ÌÁ, äîïóñòèìûå ðàçðåøåíèÿ: gif, jpg, png
@@ -54,7 +55,9 @@ diff --git a/templates/Full/elems/TextEditor.xslt b/templates/Full/elems/TextEditor.xslt new file mode 100644 index 0000000..f44e16f --- /dev/null +++ b/templates/Full/elems/TextEditor.xslt @@ -0,0 +1,245 @@ + + + + + + + Ñîîáùåíèå +
+ +
+
+ + +
+ + + + + + + + + + +
ÑìàéëèêèUBBCodeØðèôò
+ + smile + +   + + frown + +   + + blush + +   + + laugh + +   + + wink + +   + + tongue + +
+ + cool + +   + + crazy + +   + + mad + +   + + shocked + +   + + smirk + +   + + grin + +
+ + ooo + +   + + confused + +   + + More! + +   + + Upload + +   + + Mix + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ URL + + Êîä + + Êàðòèíêà +
+ Íà÷àëî ñïèñêà + + Ýë-ò ñïèñêà + + Êîíåö ñïèñêà +
+ Íà÷àëî
ãîëîñîâàíèÿ
+
+ Âàðèàíò
ãîëîñîâàíèÿ
+
+ Êîíåö
ãîëîñîâàíèÿ
+
+ Æèðíûé + + Íàêëîí + + Öèòàòà +
+ Ïîëüçîâàòåëü + + Òàáëèöà + + Ecode +
+ YouTube + + Math +
+
+ + + + + + + +
+ +
+ +
+ + + + + + + + + + + + + + + + + + + +
+     + +     + +     + +     +
+     + +     + +     + +     +
+     + +     + +     + + ? +
+
+ + + + \ No newline at end of file diff --git a/templates/Full/result/MessageCreated.xslt b/templates/Full/result/MessageCreated.xslt new file mode 100644 index 0000000..0e640b9 --- /dev/null +++ b/templates/Full/result/MessageCreated.xslt @@ -0,0 +1,30 @@ + + + + + + + + +
+ + + + + + + +
+ Íîâîå ñîîáùåíèå +
+ Âàøå ñîîáùåíèå áûëî óñïåøíî ñîçäàíî +
+ + /Thread//p + Ïðîñìîòðåòü ñîîáùåíèå + +
+
+
+ +
\ No newline at end of file