Browse Source

Simple theme template editor

Vova Tkach 5 years ago
parent
commit
8239615285

+ 23 - 1
assets/cp.scripts.js

@@ -3456,7 +3456,9 @@
 			if(form.hasClass('prev-data-lost')) {
 				form.find('input, textarea, select').on('input', function() {
 					if(!FormDataWasChanged) {
-						FormDataWasChanged = true;
+						if(!$(this).hasClass('ignore-lost-data')) {
+							FormDataWasChanged = true;
+						}
 					}
 				});
 			}
@@ -3597,6 +3599,25 @@
 			});
 		};
 
+		function MakeTextAreasNotReactOnTab() {
+			$('textarea.use-tab-key').each(function() {
+				$(this).keydown(function(e) {
+					if(e.keyCode === 9) {
+						var start = this.selectionStart;
+						var end = this.selectionEnd;
+						var $this = $(this);
+						var value = $this.val();
+						$this.val(value.substring(0, start) + "\t" + value.substring(end));
+						this.selectionStart = this.selectionEnd = start + 1;
+						e.preventDefault();
+						if(!FormDataWasChanged) {
+							FormDataWasChanged = true;
+						}
+					}
+				});
+			});
+		};
+
 		function Initialize() {
 			// Check if jQuery was loaded
 			if(typeof $ == 'function') {
@@ -3604,6 +3625,7 @@
 				BindWindowBeforeUnload();
 				MakeTextAreasAutoSized();
 				MakeTextAreasWysiwyg();
+				MakeTextAreasNotReactOnTab();
 			} else {
 				console.log('Error: jQuery is not loaded!');
 			}

File diff suppressed because it is too large
+ 0 - 0
assets/cp.scripts.js.go


+ 1 - 1
consts/consts.go

@@ -5,7 +5,7 @@ import (
 )
 
 const AssetsPath = "assets"
-const AssetsVersion = "30"
+const AssetsVersion = "31"
 const DirIndexFile = "index.html"
 
 // Bootstrap resources

+ 9 - 9
hosts/localhost/template/404.html

@@ -1,10 +1,10 @@
-{{template "header.html" .}}
-<div class="card mb-4">
-	<div class="card-body">
-		<h2 class="card-title">Error 404</h2>
-		<div class="page-content">
-			The page what you looking for "<b>{{$.Data.RequestURL}}</b>" is not found
-		</div>
-	</div>
-</div>
+{{template "header.html" .}}
+<div class="card mb-4">
+	<div class="card-body">
+		<h2 class="card-title">Error 404</h2>
+		<div class="page-content">
+			The page what you looking for "<b>{{$.Data.RequestURL}}</b>" is not found
+		</div>
+	</div>
+</div>
 {{template "footer.html" .}}

+ 57 - 57
hosts/localhost/template/blog-category.html

@@ -1,58 +1,58 @@
-{{template "header.html" .}}
-<div class="card mb-4">
-	<div class="post">
-		<div class="card-body">
-			<b>Category author:</b> {{$.Data.Blog.Category.User.FirstName}} {{$.Data.Blog.Category.User.LastName}}
-		</div>
-	</div>
-</div>
-<div class="card mb-4">
-	{{if $.Data.Blog.HavePosts}}
-		{{range $.Data.Blog.Posts}}
-			<div class="post">
-				<div class="card-body">
-					<h2 class="card-title">
-						<a href="{{.Permalink}}">
-							{{.Name}}
-						</a>
-					</h2>
-					<div class="post-content">
-						{{.Briefly}}
-					</div>
-					<div class="post-date">
-						<div><small>Published on {{.DateTimeFormat "02/01/2006, 15:04:05"}}</small></div>
-						<div>Author: {{.User.FirstName}} {{.User.LastName}}</div>
-					</div>
-				</div>
-			</div>
-		{{end}}
-	{{else}}
-		<div class="card-body">
-			Sorry, no posts matched your criteria
-		</div>
-	{{end}}
-</div>
-{{if $.Data.Blog.HavePosts}}
-	{{if gt $.Data.Blog.PostsMaxPage 1 }}
-		<nav>
-			<ul class="pagination mb-4">
-				{{if $.Data.Blog.PaginationPrev}}
-					<li class="page-item{{if $.Data.Blog.PaginationPrev.Current}} disabled{{end}}">
-						<a class="page-link" href="{{$.Data.Blog.PaginationPrev.Link}}">Previous</a>
-					</li>
-				{{end}}
-				{{range $.Data.Blog.Pagination}}
-					<li class="page-item{{if .Current}} active{{end}}">
-						<a class="page-link" href="{{.Link}}">{{.Num}}</a>
-					</li>
-				{{end}}
-				{{if $.Data.Blog.PaginationNext}}
-					<li class="page-item{{if $.Data.Blog.PaginationNext.Current}} disabled{{end}}">
-						<a class="page-link" href="{{$.Data.Blog.PaginationNext.Link}}">Next</a>
-					</li>
-				{{end}}
-			</ul>
-		</nav>
-	{{end}}
-{{end}}
+{{template "header.html" .}}
+<div class="card mb-4">
+	<div class="post">
+		<div class="card-body">
+			<b>Category author:</b> {{$.Data.Blog.Category.User.FirstName}} {{$.Data.Blog.Category.User.LastName}}
+		</div>
+	</div>
+</div>
+<div class="card mb-4">
+	{{if $.Data.Blog.HavePosts}}
+		{{range $.Data.Blog.Posts}}
+			<div class="post">
+				<div class="card-body">
+					<h2 class="card-title">
+						<a href="{{.Permalink}}">
+							{{.Name}}
+						</a>
+					</h2>
+					<div class="post-content">
+						{{.Briefly}}
+					</div>
+					<div class="post-date">
+						<div><small>Published on {{.DateTimeFormat "02/01/2006, 15:04:05"}}</small></div>
+						<div>Author: {{.User.FirstName}} {{.User.LastName}}</div>
+					</div>
+				</div>
+			</div>
+		{{end}}
+	{{else}}
+		<div class="card-body">
+			Sorry, no posts matched your criteria
+		</div>
+	{{end}}
+</div>
+{{if $.Data.Blog.HavePosts}}
+	{{if gt $.Data.Blog.PostsMaxPage 1 }}
+		<nav>
+			<ul class="pagination mb-4">
+				{{if $.Data.Blog.PaginationPrev}}
+					<li class="page-item{{if $.Data.Blog.PaginationPrev.Current}} disabled{{end}}">
+						<a class="page-link" href="{{$.Data.Blog.PaginationPrev.Link}}">Previous</a>
+					</li>
+				{{end}}
+				{{range $.Data.Blog.Pagination}}
+					<li class="page-item{{if .Current}} active{{end}}">
+						<a class="page-link" href="{{.Link}}">{{.Num}}</a>
+					</li>
+				{{end}}
+				{{if $.Data.Blog.PaginationNext}}
+					<li class="page-item{{if $.Data.Blog.PaginationNext.Current}} disabled{{end}}">
+						<a class="page-link" href="{{$.Data.Blog.PaginationNext.Link}}">Next</a>
+					</li>
+				{{end}}
+			</ul>
+		</nav>
+	{{end}}
+{{end}}
 {{template "footer.html" .}}

+ 14 - 14
hosts/localhost/template/blog-post.html

@@ -1,15 +1,15 @@
-{{template "header.html" .}}
-<div class="card mb-4">
-	<div class="card-body">
-		<h2 class="card-title">{{$.Data.Blog.Post.Name}}</h2>
-		<div class="page-content">
-			{{$.Data.Blog.Post.Briefly}}
-			{{$.Data.Blog.Post.Content}}
-		</div>
-	</div>
-	<div class="card-footer text-muted">
-		<div>Published on {{$.Data.Blog.Post.DateTimeFormat "02/01/2006, 15:04:05"}}</div>
-		<div>Author: {{$.Data.Blog.Post.User.FirstName}} {{$.Data.Blog.Post.User.LastName}}</div>
-	</div>
-</div>
+{{template "header.html" .}}
+<div class="card mb-4">
+	<div class="card-body">
+		<h2 class="card-title">{{$.Data.Blog.Post.Name}}</h2>
+		<div class="page-content">
+			{{$.Data.Blog.Post.Briefly}}
+			{{$.Data.Blog.Post.Content}}
+		</div>
+	</div>
+	<div class="card-footer text-muted">
+		<div>Published on {{$.Data.Blog.Post.DateTimeFormat "02/01/2006, 15:04:05"}}</div>
+		<div>Author: {{$.Data.Blog.Post.User.FirstName}} {{$.Data.Blog.Post.User.LastName}}</div>
+	</div>
+</div>
 {{template "footer.html" .}}

+ 54 - 54
hosts/localhost/template/blog.html

@@ -1,55 +1,55 @@
-{{template "header.html" .}}
-<div class="card mb-4">
-	{{if $.Data.Blog.HavePosts}}
-		{{range $.Data.Blog.Posts}}
-			<div class="post">
-				<div class="card-body">
-					<h2 class="card-title">
-						<a href="{{.Permalink}}">
-							{{.Name}}
-						</a>
-					</h2>
-					<div class="post-content">
-						{{.Briefly}}
-					</div>
-					<div class="post-date">
-						<div><small>Published on {{.DateTimeFormat "02/01/2006, 15:04:05"}}</small></div>
-						<div>Author: {{.User.FirstName}} {{.User.LastName}}</div>
-					</div>
-				</div>
-			</div>
-		{{end}}
-	{{else}}
-		<div class="card-body">
-			Sorry, no posts matched your criteria
-		</div>
-	{{end}}
-</div>
-{{if $.Data.Blog.HavePosts}}
-	{{if gt $.Data.Blog.PostsMaxPage 1 }}
-		<nav>
-			<ul class="pagination mb-4">
-				{{if $.Data.Blog.PaginationPrev}}
-					<li class="page-item{{if $.Data.Blog.PaginationPrev.Current}} disabled{{end}}">
-						<a class="page-link" href="{{$.Data.Blog.PaginationPrev.Link}}">Previous</a>
-					</li>
-				{{end}}
-				{{range $.Data.Blog.Pagination}}
-					{{if .Dots}}
-						<li class="page-item disabled"><a class="page-link" href="">...</a></li>
-					{{else}}
-						<li class="page-item{{if .Current}} active{{end}}">
-							<a class="page-link" href="{{.Link}}">{{.Num}}</a>
-						</li>
-					{{end}}
-				{{end}}
-				{{if $.Data.Blog.PaginationNext}}
-					<li class="page-item{{if $.Data.Blog.PaginationNext.Current}} disabled{{end}}">
-						<a class="page-link" href="{{$.Data.Blog.PaginationNext.Link}}">Next</a>
-					</li>
-				{{end}}
-			</ul>
-		</nav>
-	{{end}}
-{{end}}
+{{template "header.html" .}}
+<div class="card mb-4">
+	{{if $.Data.Blog.HavePosts}}
+		{{range $.Data.Blog.Posts}}
+			<div class="post">
+				<div class="card-body">
+					<h2 class="card-title">
+						<a href="{{.Permalink}}">
+							{{.Name}}
+						</a>
+					</h2>
+					<div class="post-content">
+						{{.Briefly}}
+					</div>
+					<div class="post-date">
+						<div><small>Published on {{.DateTimeFormat "02/01/2006, 15:04:05"}}</small></div>
+						<div>Author: {{.User.FirstName}} {{.User.LastName}}</div>
+					</div>
+				</div>
+			</div>
+		{{end}}
+	{{else}}
+		<div class="card-body">
+			Sorry, no posts matched your criteria
+		</div>
+	{{end}}
+</div>
+{{if $.Data.Blog.HavePosts}}
+	{{if gt $.Data.Blog.PostsMaxPage 1 }}
+		<nav>
+			<ul class="pagination mb-4">
+				{{if $.Data.Blog.PaginationPrev}}
+					<li class="page-item{{if $.Data.Blog.PaginationPrev.Current}} disabled{{end}}">
+						<a class="page-link" href="{{$.Data.Blog.PaginationPrev.Link}}">Previous</a>
+					</li>
+				{{end}}
+				{{range $.Data.Blog.Pagination}}
+					{{if .Dots}}
+						<li class="page-item disabled"><a class="page-link" href="">...</a></li>
+					{{else}}
+						<li class="page-item{{if .Current}} active{{end}}">
+							<a class="page-link" href="{{.Link}}">{{.Num}}</a>
+						</li>
+					{{end}}
+				{{end}}
+				{{if $.Data.Blog.PaginationNext}}
+					<li class="page-item{{if $.Data.Blog.PaginationNext.Current}} disabled{{end}}">
+						<a class="page-link" href="{{$.Data.Blog.PaginationNext.Link}}">Next</a>
+					</li>
+				{{end}}
+			</ul>
+		</nav>
+	{{end}}
+{{end}}
 {{template "footer.html" .}}

+ 25 - 25
hosts/localhost/template/footer.html

@@ -1,26 +1,26 @@
-						</div>
-						<div class="col-md-4">
-							{{template "sidebar-right.html" .}}
-						</div>
-					</div>
-				</div>
-			</div>
-		</div>
-		<footer class="bg-light py-4">
-			<div class="container">
-				<p class="m-0 text-center text-black">
-					Copyright © Your Website {{if eq ($.Data.DateTimeFormat "2006") "2019"}}
-						{{$.Data.DateTimeFormat "2006"}}
-					{{else}}
-						2019-{{$.Data.DateTimeFormat "2006"}}
-					{{end}}
-				</p>
-			</div>
-		</footer>
-		<!-- Optional JavaScript -->
-		<!-- jQuery first, then Popper.js, then Bootstrap JS -->
-		<script src="{{$.System.PathJsJquery}}"></script>
-		<script src="{{$.System.PathJsPopper}}"></script>
-		<script src="{{$.System.PathJsBootstrap}}"></script>
-	</body>
+						</div>
+						<div class="col-md-4">
+							{{template "sidebar-right.html" .}}
+						</div>
+					</div>
+				</div>
+			</div>
+		</div>
+		<footer class="bg-light py-4">
+			<div class="container">
+				<p class="m-0 text-center text-black">
+					Copyright © Your Website {{if eq ($.Data.DateTimeFormat "2006") "2019"}}
+						{{$.Data.DateTimeFormat "2006"}}
+					{{else}}
+						2019-{{$.Data.DateTimeFormat "2006"}}
+					{{end}}
+				</p>
+			</div>
+		</footer>
+		<!-- Optional JavaScript -->
+		<!-- jQuery first, then Popper.js, then Bootstrap JS -->
+		<script src="{{$.System.PathJsJquery}}"></script>
+		<script src="{{$.System.PathJsPopper}}"></script>
+		<script src="{{$.System.PathJsBootstrap}}"></script>
+	</body>
 </html>

+ 95 - 95
hosts/localhost/template/header.html

@@ -1,96 +1,96 @@
-<!doctype html>
-<html lang="en">
-	<head>
-		<!-- Required meta tags -->
-		<meta charset="utf-8">
-		<meta name="theme-color" content="#205081" />
-		<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
-
-		<!-- Bootstrap CSS -->
-		<link rel="stylesheet" href="{{$.System.PathCssBootstrap}}">
-
-		<title>
-			{{if not (eq $.Data.Module "404")}}
-				{{if eq $.Data.Module "index"}}
-					{{$.Data.Page.Name}}
-				{{else if or (eq $.Data.Module "blog") (eq $.Data.Module "blog-post") (eq $.Data.Module "blog-category")}}
-					{{if eq $.Data.Module "blog-category"}}
-						Posts of category "{{$.Data.Blog.Category.Name}}" | Blog
-					{{else if eq $.Data.Module "blog-post"}}
-						{{$.Data.Blog.Post.Name}} | Blog
-					{{else}}
-						Latest posts | Blog
-					{{end}}
-				{{end}}
-			{{else}}
-				Error 404
-			{{end}}
-		</title>
-		<meta name="keywords" content="{{$.Data.Page.MetaKeywords}}" />
-		<meta name="description" content="{{$.Data.Page.MetaDescription}}" />
-		<link rel="shortcut icon" href="{{$.System.PathIcoFav}}" type="image/x-icon" />
-
-		<!-- Template CSS file from template folder -->
-		<link rel="stylesheet" href="{{$.System.PathThemeStyles}}?v=1">
-
-		<!-- Template JavaScript file from template folder -->
-		<script src="{{$.System.PathThemeScripts}}?v=1"></script>
-	</head>
-	<body class="fixed-top-bar1">
-		<div id="wrap">
-			<nav class="navbar navbar-expand-lg navbar-light bg-light">
-				<div class="container">
-					<a class="navbar-brand" href="/">Fave {{$.System.InfoVersion}}</a>
-					<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
-						<span class="navbar-toggler-icon"></span>
-					</button>
-					<div class="collapse navbar-collapse" id="navbarResponsive">
-						<ul class="navbar-nav ml-auto">
-							<li class="nav-item{{if eq $.Data.Page.Alias "/"}} active{{end}}">
-								<a class="nav-link" href="/">Home</a>
-							</li>
-							<li class="nav-item">
-								<a class="nav-link{{if eq $.Data.Page.Alias "/another/"}} active{{end}}" href="/another/">Another</a>
-							</li>
-							<li class="nav-item">
-								<a class="nav-link{{if eq $.Data.Page.Alias "/about/"}} active{{end}}" href="/about/">About</a>
-							</li>
-							<li class="nav-item">
-								<a class="nav-link{{if or (eq $.Data.Module "blog") (eq $.Data.Module "blog-post") (eq $.Data.Module "blog-category")}} active{{end}}" href="/blog/">Blog</a>
-							</li>
-							<li class="nav-item">
-								<a class="nav-link{{if eq $.Data.Module "404"}} active{{end}}" href="/not-existent-page/">404</a>
-							</li>
-						</ul>
-					</div>
-				</div>
-			</nav>
-			<div id="main">
-				<div class="bg-fave">
-					<div class="container">
-						<h1 class="text-left text-white m-0 p-0 py-5">
-							{{if not (eq $.Data.Module "404")}}
-								{{if eq $.Data.Module "index"}}
-									{{if eq $.Data.Page.Alias "/"}}
-										Welcome to home page
-									{{else}}
-										Welcome to some another page
-									{{end}}
-								{{else if or (eq $.Data.Module "blog") (eq $.Data.Module "blog-post") (eq $.Data.Module "blog-category")}}
-									{{if eq $.Data.Module "blog-category"}}
-										Blog category
-									{{else if eq $.Data.Module "blog-post"}}
-										Blog post
-									{{else}}
-										Blog
-									{{end}}
-								{{end}}
-							{{else}}
-								Oops, page is not found...
-							{{end}}
-						</h1>
-					</div>
-				</div>
-				<div class="container clear-top">
-					<div class="row pt-4">
+<!doctype html>
+<html lang="en">
+	<head>
+		<!-- Required meta tags -->
+		<meta charset="utf-8">
+		<meta name="theme-color" content="#205081" />
+		<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+
+		<!-- Bootstrap CSS -->
+		<link rel="stylesheet" href="{{$.System.PathCssBootstrap}}">
+
+		<title>
+			{{if not (eq $.Data.Module "404")}}
+				{{if eq $.Data.Module "index"}}
+					{{$.Data.Page.Name}}
+				{{else if or (eq $.Data.Module "blog") (eq $.Data.Module "blog-post") (eq $.Data.Module "blog-category")}}
+					{{if eq $.Data.Module "blog-category"}}
+						Posts of category "{{$.Data.Blog.Category.Name}}" | Blog
+					{{else if eq $.Data.Module "blog-post"}}
+						{{$.Data.Blog.Post.Name}} | Blog
+					{{else}}
+						Latest posts | Blog
+					{{end}}
+				{{end}}
+			{{else}}
+				Error 404
+			{{end}}
+		</title>
+		<meta name="keywords" content="{{$.Data.Page.MetaKeywords}}" />
+		<meta name="description" content="{{$.Data.Page.MetaDescription}}" />
+		<link rel="shortcut icon" href="{{$.System.PathIcoFav}}" type="image/x-icon" />
+
+		<!-- Template CSS file from template folder -->
+		<link rel="stylesheet" href="{{$.System.PathThemeStyles}}?v=1">
+
+		<!-- Template JavaScript file from template folder -->
+		<script src="{{$.System.PathThemeScripts}}?v=1"></script>
+	</head>
+	<body class="fixed-top-bar1">
+		<div id="wrap">
+			<nav class="navbar navbar-expand-lg navbar-light bg-light">
+				<div class="container">
+					<a class="navbar-brand" href="/">Fave {{$.System.InfoVersion}}</a>
+					<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation">
+						<span class="navbar-toggler-icon"></span>
+					</button>
+					<div class="collapse navbar-collapse" id="navbarResponsive">
+						<ul class="navbar-nav ml-auto">
+							<li class="nav-item{{if eq $.Data.Page.Alias "/"}} active{{end}}">
+								<a class="nav-link" href="/">Home</a>
+							</li>
+							<li class="nav-item">
+								<a class="nav-link{{if eq $.Data.Page.Alias "/another/"}} active{{end}}" href="/another/">Another</a>
+							</li>
+							<li class="nav-item">
+								<a class="nav-link{{if eq $.Data.Page.Alias "/about/"}} active{{end}}" href="/about/">About</a>
+							</li>
+							<li class="nav-item">
+								<a class="nav-link{{if or (eq $.Data.Module "blog") (eq $.Data.Module "blog-post") (eq $.Data.Module "blog-category")}} active{{end}}" href="/blog/">Blog</a>
+							</li>
+							<li class="nav-item">
+								<a class="nav-link{{if eq $.Data.Module "404"}} active{{end}}" href="/not-existent-page/">404</a>
+							</li>
+						</ul>
+					</div>
+				</div>
+			</nav>
+			<div id="main">
+				<div class="bg-fave">
+					<div class="container">
+						<h1 class="text-left text-white m-0 p-0 py-5">
+							{{if not (eq $.Data.Module "404")}}
+								{{if eq $.Data.Module "index"}}
+									{{if eq $.Data.Page.Alias "/"}}
+										Welcome to home page
+									{{else}}
+										Welcome to some another page
+									{{end}}
+								{{else if or (eq $.Data.Module "blog") (eq $.Data.Module "blog-post") (eq $.Data.Module "blog-category")}}
+									{{if eq $.Data.Module "blog-category"}}
+										Blog category
+									{{else if eq $.Data.Module "blog-post"}}
+										Blog post
+									{{else}}
+										Blog
+									{{end}}
+								{{end}}
+							{{else}}
+								Oops, page is not found...
+							{{end}}
+						</h1>
+					</div>
+				</div>
+				<div class="container clear-top">
+					<div class="row pt-4">
 						<div class="col-md-8">

+ 13 - 13
hosts/localhost/template/index.html

@@ -1,14 +1,14 @@
-{{template "header.html" .}}
-<div class="card mb-4">
-	<div class="card-body">
-		<h2 class="card-title">{{$.Data.Page.Name}}</h2>
-		<div class="page-content">
-			{{$.Data.Page.Content}}
-		</div>
-	</div>
-	<div class="card-footer text-muted">
-		<div>Published on {{$.Data.Page.DateTimeFormat "02/01/2006, 15:04:05"}}</div>
-		<div>Author: {{$.Data.Page.User.FirstName}} {{$.Data.Page.User.LastName}}</div>
-	</div>
-</div>
+{{template "header.html" .}}
+<div class="card mb-4">
+	<div class="card-body">
+		<h2 class="card-title">{{$.Data.Page.Name}}</h2>
+		<div class="page-content">
+			{{$.Data.Page.Content}}
+		</div>
+	</div>
+	<div class="card-footer text-muted">
+		<div>Published on {{$.Data.Page.DateTimeFormat "02/01/2006, 15:04:05"}}</div>
+		<div>Author: {{$.Data.Page.User.FirstName}} {{$.Data.Page.User.LastName}}</div>
+	</div>
+</div>
 {{template "footer.html" .}}

+ 13 - 13
hosts/localhost/template/page.html

@@ -1,14 +1,14 @@
-{{template "header.html" .}}
-<div class="card mb-4">
-	<div class="card-body">
-		<h2 class="card-title">{{$.Data.Page.Name}}</h2>
-		<div class="page-content">
-			{{$.Data.Page.Content}}
-		</div>
-	</div>
-	<div class="card-footer text-muted">
-		<div>Published on {{$.Data.Page.DateTimeFormat "02/01/2006, 15:04:05"}}</div>
-		<div>Author: {{$.Data.Page.User.FirstName}} {{$.Data.Page.User.LastName}}</div>
-	</div>
-</div>
+{{template "header.html" .}}
+<div class="card mb-4">
+	<div class="card-body">
+		<h2 class="card-title">{{$.Data.Page.Name}}</h2>
+		<div class="page-content">
+			{{$.Data.Page.Content}}
+		</div>
+	</div>
+	<div class="card-footer text-muted">
+		<div>Published on {{$.Data.Page.DateTimeFormat "02/01/2006, 15:04:05"}}</div>
+		<div>Author: {{$.Data.Page.User.FirstName}} {{$.Data.Page.User.LastName}}</div>
+	</div>
+</div>
 {{template "footer.html" .}}

+ 20 - 20
hosts/localhost/template/sidebar-right.html

@@ -1,21 +1,21 @@
-<div class="card mb-4">
-	<h5 class="card-header">Categories</h5>
-	<div class="card-body">
-		<ul class="m-0 p-0 pl-4">
-			{{range $.Data.Blog.Categories 0}}
-				<li class="{{if and $.Data.Blog.Category (eq $.Data.Blog.Category.Id .Id)}}active{{end}}">
-					<a href="{{.Permalink}}">{{.Name}}</a>
-				</li>
-			{{end}}
-		</ul>
-	</div>
-</div>
-<div class="card mb-4">
-	<h5 class="card-header">Useful links</h5>
-	<div class="card-body">
-		<ul class="m-0 p-0 pl-4">
-			<li><a href="https://github.com/vladimirok5959/golang-fave" target="_blank">Project on GitHub</a></li>
-			<li><a href="https://github.com/vladimirok5959/golang-fave/wiki" target="_blank">Wiki on GitHub</a></li>
-		</ul>
-	</div>
+<div class="card mb-4">
+	<h5 class="card-header">Categories</h5>
+	<div class="card-body">
+		<ul class="m-0 p-0 pl-4">
+			{{range $.Data.Blog.Categories 0}}
+				<li class="{{if and $.Data.Blog.Category (eq $.Data.Blog.Category.Id .Id)}}active{{end}}">
+					<a href="{{.Permalink}}">{{.Name}}</a>
+				</li>
+			{{end}}
+		</ul>
+	</div>
+</div>
+<div class="card mb-4">
+	<h5 class="card-header">Useful links</h5>
+	<div class="card-body">
+		<ul class="m-0 p-0 pl-4">
+			<li><a href="https://github.com/vladimirok5959/golang-fave" target="_blank">Project on GitHub</a></li>
+			<li><a href="https://github.com/vladimirok5959/golang-fave/wiki" target="_blank">Wiki on GitHub</a></li>
+		</ul>
+	</div>
 </div>

+ 116 - 116
hosts/localhost/template/styles.css

@@ -1,117 +1,117 @@
-/* Fix bootstrap */
-@media (max-width: 991.98px) {
-	.navbar-expand-lg>.container,
-	.navbar-expand-lg>.container-fluid {
-		padding-right: 15px;
-		padding-left: 15px;
-	}
-}
-
-@media (max-width: 575px) {
-	.navbar-expand-lg>.container,
-	.navbar-expand-lg>.container-fluid {
-		padding-right: 0px;
-		padding-left: 0px;
-	}
-}
-
-@media (min-width: 992px) {
-	.navbar-expand-lg .navbar-nav {
-		margin-right: -.5rem;
-	}
-}
-
-/* Set base bootstrap width */
-@media (min-width: 1200px) {
-	.container {
-		max-width: 1000px;
-	}
-	.navbar-expand-lg .navbar-nav {
-		margin-right: -.5rem;
-	}
-}
-
-/* Base font and colors */
-body {
-	color: #444;
-	font-size: 1.0rem;
-	font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
-}
-
-.h1,
-.h2,
-.h3,
-.h4,
-.h5,
-.h6,
-h1,
-h2,
-h3,
-h4,
-h5,
-h6,
-footer {
-	color: #000;
-}
-
-.navbar-brand {
-	font-weight: bold;
-}
-
-h1 {
-	font-size: 250%;
-}
-
-/* Nice sticky footer */
-html,
-body {
-	height: 100%;
-}
-
-#wrap {
-	min-height: 100%;
-}
-
-#main {
-	overflow: auto;
-	padding-bottom: 4.5rem;
-}
-
-footer {
-	position: relative;
-	margin-top: -4.5rem;
-	height: 4.5rem;
-	clear: both;
-}
-
-/* Sticky top nav bar, body class "fixed-top-bar" */
-.fixed-top-bar .navbar {
-	position: fixed;
-	top: 0;
-	right: 0;
-	left: 0;
-	z-index: 1030;
-}
-
-.fixed-top-bar #main {
-	padding-top: 3.5rem;
-}
-
-/* Fave background */
-.bg-fave {
-	background: #205081 url(/assets/sys/bg.png) repeat 0 0;
-}
-
-/* Fix content marging */
-.page-content p:last-child {
-	margin-bottom: 0px;
-}
-
-/* Borders */
-.navbar {
-	border-bottom: 1px solid rgba(0, 0, 0, .125);
-}
-
-footer {
-	border-top: 1px solid rgba(0, 0, 0, .125);
+/* Fix bootstrap */
+@media (max-width: 991.98px) {
+	.navbar-expand-lg>.container,
+	.navbar-expand-lg>.container-fluid {
+		padding-right: 15px;
+		padding-left: 15px;
+	}
+}
+
+@media (max-width: 575px) {
+	.navbar-expand-lg>.container,
+	.navbar-expand-lg>.container-fluid {
+		padding-right: 0px;
+		padding-left: 0px;
+	}
+}
+
+@media (min-width: 992px) {
+	.navbar-expand-lg .navbar-nav {
+		margin-right: -.5rem;
+	}
+}
+
+/* Set base bootstrap width */
+@media (min-width: 1200px) {
+	.container {
+		max-width: 1000px;
+	}
+	.navbar-expand-lg .navbar-nav {
+		margin-right: -.5rem;
+	}
+}
+
+/* Base font and colors */
+body {
+	color: #444;
+	font-size: 1.0rem;
+	font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+
+.h1,
+.h2,
+.h3,
+.h4,
+.h5,
+.h6,
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+footer {
+	color: #000;
+}
+
+.navbar-brand {
+	font-weight: bold;
+}
+
+h1 {
+	font-size: 250%;
+}
+
+/* Nice sticky footer */
+html,
+body {
+	height: 100%;
+}
+
+#wrap {
+	min-height: 100%;
+}
+
+#main {
+	overflow: auto;
+	padding-bottom: 4.5rem;
+}
+
+footer {
+	position: relative;
+	margin-top: -4.5rem;
+	height: 4.5rem;
+	clear: both;
+}
+
+/* Sticky top nav bar, body class "fixed-top-bar" */
+.fixed-top-bar .navbar {
+	position: fixed;
+	top: 0;
+	right: 0;
+	left: 0;
+	z-index: 1030;
+}
+
+.fixed-top-bar #main {
+	padding-top: 3.5rem;
+}
+
+/* Fave background */
+.bg-fave {
+	background: #205081 url(/assets/sys/bg.png) repeat 0 0;
+}
+
+/* Fix content marging */
+.page-content p:last-child {
+	margin-bottom: 0px;
+}
+
+/* Borders */
+.navbar {
+	border-bottom: 1px solid rgba(0, 0, 0, .125);
+}
+
+footer {
+	border-top: 1px solid rgba(0, 0, 0, .125);
 }

+ 128 - 0
modules/module_template.go

@@ -0,0 +1,128 @@
+package modules
+
+import (
+	"html"
+	"io/ioutil"
+	"net/url"
+	"os"
+	"strings"
+
+	"golang-fave/assets"
+	"golang-fave/consts"
+	"golang-fave/engine/builder"
+	"golang-fave/engine/wrapper"
+	"golang-fave/utils"
+)
+
+func (this *Modules) template_GetThemeFiles(wrap *wrapper.Wrapper) []string {
+	var result []string
+	files, err := ioutil.ReadDir(wrap.DTemplate)
+	if err == nil {
+		for _, file := range files {
+			if len(file.Name()) > 0 && file.Name()[0] == '.' {
+				continue
+			}
+			if len(file.Name()) > 0 && strings.ToLower(file.Name()) == "robots.txt" {
+				continue
+			}
+			result = append(result, file.Name())
+		}
+	}
+	return result
+}
+
+func (this *Modules) RegisterModule_Template() *Module {
+	return this.newModule(MInfo{
+		WantDB: false,
+		Mount:  "template",
+		Name:   "Template",
+		Order:  802,
+		System: true,
+		Icon:   assets.SysSvgIconGear,
+		Sub: &[]MISub{
+			{Mount: "default", Name: "Theme", Show: true, Icon: assets.SysSvgIconGear},
+		},
+	}, nil, func(wrap *wrapper.Wrapper) (string, string, string) {
+		content := ""
+		sidebar := ""
+		if wrap.CurrSubModule == "" || wrap.CurrSubModule == "default" {
+			content += this.getBreadCrumbs(wrap, &[]consts.BreadCrumb{
+				{Name: "Theme"},
+			})
+			files := this.template_GetThemeFiles(wrap)
+			if len(files) > 0 {
+				selected_file, _ := url.QueryUnescape(wrap.R.URL.Query().Get("file"))
+				if !(selected_file != "" && utils.InArrayString(files, selected_file)) {
+					selected_file = files[0]
+				}
+
+				list_of_files := ``
+				for _, file := range files {
+					selected := ""
+					if file == selected_file {
+						selected = " selected"
+					}
+					list_of_files += `<option value="` + html.EscapeString(file) +
+						`"` + selected + `>` + html.EscapeString(file) + `</option>`
+				}
+
+				fcont := []byte(``)
+				fcont, _ = ioutil.ReadFile(wrap.DTemplate + string(os.PathSeparator) + selected_file)
+
+				content += builder.DataForm(wrap, []builder.DataFormField{
+					{
+						Kind:  builder.DFKHidden,
+						Name:  "action",
+						Value: "template-edit-theme-file",
+					},
+					{
+						Kind:    builder.DFKText,
+						Caption: "Theme file",
+						Name:    "file",
+						Value:   "0",
+						CallBack: func(field *builder.DataFormField) string {
+							return `<div class="form-group n1">` +
+								`<div class="row">` +
+								`<div class="col-md-12">` +
+								`<div>` +
+								`<select class="form-control ignore-lost-data" id="lbl_file" name="file" onchange="setTimeout(function(){$('#lbl_file').val('` + selected_file + `')},500);document.location='/cp/` + wrap.CurrModule + `/?file='+encodeURI(this.value);">` +
+								list_of_files +
+								`</select>` +
+								`</div>` +
+								`</div>` +
+								`</div>` +
+								`</div>`
+						},
+					},
+					{
+						Kind: builder.DFKText,
+						CallBack: func(field *builder.DataFormField) string {
+							return `<div class="form-group last"><div class="row"><div class="col-12"><textarea class="form-control autosize use-tab-key" id="lbl_content" name="content" placeholder="" autocomplete="off">` + html.EscapeString(string(fcont)) + `</textarea></div></div></div>`
+						},
+					},
+					{
+						Kind: builder.DFKMessage,
+						CallBack: func(field *builder.DataFormField) string {
+							return `<div class="row"><div class="col-12"><div class="sys-messages"></div></div></div>`
+						},
+					},
+					{
+						Kind: builder.DFKSubmit,
+						CallBack: func(field *builder.DataFormField) string {
+							return `<div class="row d-lg-none"><div class="col-12"><button type="submit" class="btn btn-primary" data-target="add-edit-button">Save</button></div></div>`
+						},
+					},
+				})
+
+				sidebar += `<button class="btn btn-primary btn-sidebar" id="add-edit-button">Save</button>`
+			} else {
+				content += `<div class="sys-messages">
+					<div class="alert alert-warning" role="alert">
+						<strong>Error!</strong> No any file found in theme folder
+					</div>
+				</div>`
+			}
+		}
+		return this.getSidebarModules(wrap), content, sidebar
+	})
+}

+ 56 - 0
modules/module_template_act_edit_theme_file.go

@@ -0,0 +1,56 @@
+package modules
+
+import (
+	"io/ioutil"
+	"os"
+
+	"golang-fave/engine/wrapper"
+	"golang-fave/utils"
+)
+
+func (this *Modules) RegisterAction_TemplateEditThemeFile() *Action {
+	return this.newAction(AInfo{
+		WantDB:    true,
+		Mount:     "template-edit-theme-file",
+		WantAdmin: true,
+	}, func(wrap *wrapper.Wrapper) {
+		pf_file := wrap.R.FormValue("file")
+		pf_content := wrap.R.FormValue("content")
+
+		if pf_file == "" {
+			wrap.MsgError(`Please specify file name`)
+			return
+		}
+
+		template_file := wrap.DTemplate + string(os.PathSeparator) + pf_file
+		if !utils.IsFileExists(template_file) {
+			wrap.MsgError(`File is not exists`)
+			return
+		}
+		if utils.IsDir(template_file) {
+			wrap.MsgError(`It's not regular file`)
+			return
+		}
+
+		files := this.template_GetThemeFiles(wrap)
+		if len(files) <= 0 {
+			wrap.MsgError(`No any file found in theme folder`)
+			return
+		}
+
+		if !utils.InArrayString(files, pf_file) {
+			wrap.MsgError(`File is not found`)
+			return
+		}
+
+		// Save content to file
+		err := ioutil.WriteFile(template_file, []byte(pf_content), 0664)
+		if err != nil {
+			wrap.MsgError(err.Error())
+			return
+		}
+
+		// Reload current page
+		wrap.Write(`window.location.reload(false);`)
+	})
+}

Some files were not shown because too many files changed in this diff