Порівняти коміти
5 Коміти
24121a1618
...
ece1144273
Автор | SHA1 | Дата | |
---|---|---|---|
ece1144273 | |||
af1734e7bf | |||
f160ac8102 | |||
aaa0f2f76a | |||
7c086e0d78 |
BIN
database/.sessiondaosqlite.cpp.kate-swp
Normal file
BIN
database/.sessiondaosqlite.cpp.kate-swp
Normal file
Бінарний файл не відображається.
@ -10,6 +10,7 @@ class SessionDao
|
|||||||
virtual void save(const Session &session) = 0;
|
virtual void save(const Session &session) = 0;
|
||||||
virtual std::optional<Session> find(std::string token) = 0;
|
virtual std::optional<Session> find(std::string token) = 0;
|
||||||
virtual void deleteSession(std::string token) = 0;
|
virtual void deleteSession(std::string token) = 0;
|
||||||
|
virtual std::vector<Session> fetch() = 0;
|
||||||
virtual ~SessionDao()
|
virtual ~SessionDao()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
63
database/sessiondaosqlite.cpp
Normal file → Executable file
63
database/sessiondaosqlite.cpp
Normal file → Executable file
@ -50,6 +50,29 @@ void SessionDaoSqlite::deleteSession(std::string token)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SessionDaoSqlite::fillSession(int userid, Session &sess)
|
||||||
|
{
|
||||||
|
if(userid > -1)
|
||||||
|
{
|
||||||
|
UserDaoSqlite userDao{this->db};
|
||||||
|
auto u = userDao.find(userid);
|
||||||
|
if(u)
|
||||||
|
{
|
||||||
|
sess.user = *u;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logger::error() << "Session for non existent user";
|
||||||
|
throw DatabaseQueryException("Session for non existent user");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sess.user = User::Anonymous();
|
||||||
|
}
|
||||||
|
sess.loggedIn = userid != -1;
|
||||||
|
}
|
||||||
|
|
||||||
std::optional<Session> SessionDaoSqlite::find(std::string token)
|
std::optional<Session> SessionDaoSqlite::find(std::string token)
|
||||||
{
|
{
|
||||||
Session result;
|
Session result;
|
||||||
@ -62,25 +85,7 @@ std::optional<Session> SessionDaoSqlite::find(std::string token)
|
|||||||
int userid;
|
int userid;
|
||||||
q >> std::tie(userid, result.token, result.csrf_token, result.creation_time);
|
q >> std::tie(userid, result.token, result.csrf_token, result.creation_time);
|
||||||
|
|
||||||
if(userid > -1)
|
fillSession(userid, result);
|
||||||
{
|
|
||||||
UserDaoSqlite userDao{this->db};
|
|
||||||
auto u = userDao.find(userid);
|
|
||||||
if(u)
|
|
||||||
{
|
|
||||||
result.user = *u;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Logger::error() << "Session for non existent user";
|
|
||||||
throw DatabaseQueryException("Session for non existent user");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result.user = User::Anonymous();
|
|
||||||
}
|
|
||||||
result.loggedIn = userid != -1;
|
|
||||||
}
|
}
|
||||||
catch(const sqlite::exceptions::no_rows &e)
|
catch(const sqlite::exceptions::no_rows &e)
|
||||||
{
|
{
|
||||||
@ -92,3 +97,23 @@ std::optional<Session> SessionDaoSqlite::find(std::string token)
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<Session> SessionDaoSqlite::fetch()
|
||||||
|
{
|
||||||
|
std::vector<Session> result;
|
||||||
|
|
||||||
|
*db << "SELECT userid, token, csrf_token, strftime('%s', creationtime) FROM session" >>
|
||||||
|
[this, &result](int userid, std::string token, std::string csrf_token, time_t creationtime)
|
||||||
|
{
|
||||||
|
Session tmp;
|
||||||
|
tmp.csrf_token = csrf_token;
|
||||||
|
tmp.token = token;
|
||||||
|
tmp.creation_time = creationtime;
|
||||||
|
|
||||||
|
fillSession(userid, tmp);
|
||||||
|
|
||||||
|
result.push_back(tmp);
|
||||||
|
};
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
@ -6,11 +6,15 @@
|
|||||||
|
|
||||||
class SessionDaoSqlite : public SessionDao, protected SqliteDao
|
class SessionDaoSqlite : public SessionDao, protected SqliteDao
|
||||||
{
|
{
|
||||||
|
private:
|
||||||
|
void fillSession(int userid, Session &sess);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
SessionDaoSqlite();
|
SessionDaoSqlite();
|
||||||
void save(const Session &session) override;
|
void save(const Session &session) override;
|
||||||
std::optional<Session> find(std::string token) override;
|
std::optional<Session> find(std::string token) override;
|
||||||
void deleteSession(std::string token) override;
|
void deleteSession(std::string token) override;
|
||||||
|
std::vector<Session> fetch() override;
|
||||||
using SqliteDao::SqliteDao;
|
using SqliteDao::SqliteDao;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
4
logger.h
4
logger.h
@ -7,8 +7,8 @@ class Logger
|
|||||||
private:
|
private:
|
||||||
class LogEntry
|
class LogEntry
|
||||||
{
|
{
|
||||||
bool headerSent;
|
bool headerSent = false;
|
||||||
std::ostream *out;
|
std::ostream *out = nullptr;
|
||||||
std::string prefix;
|
std::string prefix;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
32
qswiki.cpp
32
qswiki.cpp
@ -31,8 +31,8 @@ SOFTWARE.
|
|||||||
#include "handlers/handlerfactory.h"
|
#include "handlers/handlerfactory.h"
|
||||||
#include "database/databasefactory.h"
|
#include "database/databasefactory.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "template.h"
|
|
||||||
#include "session.h"
|
#include "session.h"
|
||||||
|
#include "template.h"
|
||||||
#include "logger.h"
|
#include "logger.h"
|
||||||
#include "urlprovider.h"
|
#include "urlprovider.h"
|
||||||
#include "requestworker.h"
|
#include "requestworker.h"
|
||||||
@ -74,6 +74,33 @@ std::unique_ptr<ICache> createCache(const ConfigVariableResolver &resolver)
|
|||||||
return std::make_unique<FsCache>(path);
|
return std::make_unique<FsCache>(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::thread background_worker;
|
||||||
|
void start_background_worker(Database &database, Config &config)
|
||||||
|
{
|
||||||
|
background_worker = std::thread(
|
||||||
|
[&database, &config]()
|
||||||
|
{
|
||||||
|
while(true)
|
||||||
|
{
|
||||||
|
Logger::log() << "Executing background worker";
|
||||||
|
|
||||||
|
auto sessionDao = database.createSessionDao();
|
||||||
|
auto sessionList = sessionDao->fetch();
|
||||||
|
time_t now = time(NULL);
|
||||||
|
|
||||||
|
for(Session &sess : sessionList)
|
||||||
|
{
|
||||||
|
if(now - sess.creation_time > config.session_max_lifetime)
|
||||||
|
{
|
||||||
|
sessionDao->deleteSession(sess.token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::this_thread::sleep_for(std::chrono::hours(1));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
|
|
||||||
@ -136,6 +163,7 @@ int main(int argc, char **argv)
|
|||||||
Logger::setStream(&logstream);
|
Logger::setStream(&logstream);
|
||||||
|
|
||||||
auto database = createDatabase(config);
|
auto database = createDatabase(config);
|
||||||
|
|
||||||
std::string socketPath = config.configVarResolver.getConfig("socketpath");
|
std::string socketPath = config.configVarResolver.getConfig("socketpath");
|
||||||
CLIHandler cliHandler(config, *database);
|
CLIHandler cliHandler(config, *database);
|
||||||
|
|
||||||
@ -158,6 +186,8 @@ int main(int argc, char **argv)
|
|||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
start_background_worker(*database.get(), config);
|
||||||
|
|
||||||
CLIServer cliServer{cliHandler};
|
CLIServer cliServer{cliHandler};
|
||||||
if(!cliServer.detachServer(socketPath))
|
if(!cliServer.detachServer(socketPath))
|
||||||
{
|
{
|
||||||
|
@ -42,6 +42,7 @@ std::string RevisionRenderer::renderContent(std::string content)
|
|||||||
{
|
{
|
||||||
dynamicVarsMap["pagetitle"] = parser.extractCommand("pagetitle", content);
|
dynamicVarsMap["pagetitle"] = parser.extractCommand("pagetitle", content);
|
||||||
dynamicVarsMap["createdon"] = utils::toISODate(time(NULL));
|
dynamicVarsMap["createdon"] = utils::toISODate(time(NULL));
|
||||||
|
dynamicVarsMap["modifydatetime"] = utils::toISODateTime(time(NULL));
|
||||||
|
|
||||||
std::string resolvedContent = parser.parseDynamics(content, std::bind(&RevisionRenderer::dynamicCallback, this, std::placeholders::_1, std::placeholders::_2));
|
std::string resolvedContent = parser.parseDynamics(content, std::bind(&RevisionRenderer::dynamicCallback, this, std::placeholders::_1, std::placeholders::_2));
|
||||||
|
|
||||||
@ -60,6 +61,7 @@ std::string RevisionRenderer::renderContent(const Revision &r, std::string_view
|
|||||||
|
|
||||||
dynamicVarsMap["createdon"] = utils::toISODate(firstRevision.value().timestamp);
|
dynamicVarsMap["createdon"] = utils::toISODate(firstRevision.value().timestamp);
|
||||||
dynamicVarsMap["pagetitle"] = customTitle;
|
dynamicVarsMap["pagetitle"] = customTitle;
|
||||||
|
dynamicVarsMap["modifydatetime"] = utils::toISODateTime(r.timestamp);
|
||||||
|
|
||||||
std::string resolvedContent = parser.parseDynamics(r.content, std::bind(&RevisionRenderer::dynamicCallback, this, std::placeholders::_1, std::placeholders::_2));
|
std::string resolvedContent = parser.parseDynamics(r.content, std::bind(&RevisionRenderer::dynamicCallback, this, std::placeholders::_1, std::placeholders::_2));
|
||||||
|
|
||||||
|
@ -4,8 +4,5 @@
|
|||||||
<li style="font-size: 10pt">Powered by qswiki</li>
|
<li style="font-size: 10pt">Powered by qswiki</li>
|
||||||
</ul>
|
</ul>
|
||||||
</footer>
|
</footer>
|
||||||
<script>
|
|
||||||
{qswiki:include:js_session_refresh}
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
@ -1,5 +0,0 @@
|
|||||||
function refreshSession()
|
|
||||||
{
|
|
||||||
fetch(new Request("{qswiki:config:refreshsessionurl}"));
|
|
||||||
}
|
|
||||||
setInterval(refreshSession, 60*2*1000);
|
|
@ -7,7 +7,6 @@
|
|||||||
</footer>
|
</footer>
|
||||||
<script src="{qswiki:config:highlightjspath}"></script>
|
<script src="{qswiki:config:highlightjspath}"></script>
|
||||||
<script>
|
<script>
|
||||||
{qswiki:include:js_session_refresh}
|
|
||||||
hljs.highlightAll();
|
hljs.highlightAll();
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
446
template/quitesimple/style2.css
Normal file
446
template/quitesimple/style2.css
Normal file
@ -0,0 +1,446 @@
|
|||||||
|
body
|
||||||
|
{
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
font-family: Verdana;
|
||||||
|
background-color: white;
|
||||||
|
display: grid;
|
||||||
|
min-height: 100vh;
|
||||||
|
grid-template-rows: auto 1fr auto;
|
||||||
|
grid-template-areas: "nav nav"
|
||||||
|
"main side"
|
||||||
|
"footer footer";
|
||||||
|
grid-template-columns: 1fr auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
header
|
||||||
|
{
|
||||||
|
margin: 0;
|
||||||
|
paddin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3
|
||||||
|
{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav
|
||||||
|
{
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
display: flex;
|
||||||
|
background-color: #062463;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
grid-area: nav;
|
||||||
|
|
||||||
|
}
|
||||||
|
nav ul
|
||||||
|
{
|
||||||
|
background-color: #062463;
|
||||||
|
color: white;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style-type: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
nav li
|
||||||
|
{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a, nav a:visited
|
||||||
|
{
|
||||||
|
padding: 10px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: white;
|
||||||
|
display: block;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 100%;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a:hover, nav a:focus
|
||||||
|
{
|
||||||
|
padding: 10px;
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: white;
|
||||||
|
color: #062463;
|
||||||
|
display: block;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
a, a:visited
|
||||||
|
{
|
||||||
|
color: #062463;;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover
|
||||||
|
{
|
||||||
|
background-color: #062463;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#content
|
||||||
|
{
|
||||||
|
padding: 15px;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 14pt;
|
||||||
|
flex: 1;
|
||||||
|
grid-area: main
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar
|
||||||
|
{
|
||||||
|
grid-area: side;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar ul
|
||||||
|
{
|
||||||
|
list-style-type: none;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar a, a:visited
|
||||||
|
{
|
||||||
|
color: #062463;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar a:hover
|
||||||
|
{
|
||||||
|
background-color: #062463;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content a, a:visited
|
||||||
|
{
|
||||||
|
color: #062463;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content a:hover
|
||||||
|
{
|
||||||
|
background-color: #062463;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
footer
|
||||||
|
{
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
color: white;
|
||||||
|
background-color: #062463;
|
||||||
|
font-weight: bold;
|
||||||
|
grid-area: footer;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer ul
|
||||||
|
{
|
||||||
|
background-color: #062463;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
footer li
|
||||||
|
{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 45px;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
//flex: 1 1 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a, a:visited
|
||||||
|
{
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
color: white;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a:hover, ul#nav a:focus
|
||||||
|
{
|
||||||
|
text-decoration: none;
|
||||||
|
color: #062463;
|
||||||
|
background-color: white;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cats
|
||||||
|
{
|
||||||
|
background-color: #062463;
|
||||||
|
}
|
||||||
|
|
||||||
|
.letter_search_result
|
||||||
|
{
|
||||||
|
text-decoration: underline;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
ol
|
||||||
|
{
|
||||||
|
counter-reset: item;
|
||||||
|
}
|
||||||
|
.indexlink
|
||||||
|
{
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.notexists
|
||||||
|
{
|
||||||
|
color: red !important;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
body
|
||||||
|
{
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
font-family: Verdana;
|
||||||
|
background-color: white;
|
||||||
|
display: grid;
|
||||||
|
min-height: 100vh;
|
||||||
|
grid-template-rows: auto 1fr auto;
|
||||||
|
grid-template-areas: "nav nav"
|
||||||
|
"main side"
|
||||||
|
"footer footer";
|
||||||
|
grid-template-columns: 1fr auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
header
|
||||||
|
{
|
||||||
|
margin: 0;
|
||||||
|
paddin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3
|
||||||
|
{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav
|
||||||
|
{
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
display: flex;
|
||||||
|
background-color: #062463;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
grid-area: nav;
|
||||||
|
|
||||||
|
}
|
||||||
|
nav ul
|
||||||
|
{
|
||||||
|
background-color: #062463;
|
||||||
|
color: white;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style-type: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
nav li
|
||||||
|
{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a, nav a:visited
|
||||||
|
{
|
||||||
|
padding: 10px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: white;
|
||||||
|
display: block;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 100%;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a:hover, nav a:focus
|
||||||
|
{
|
||||||
|
padding: 10px;
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: white;
|
||||||
|
color: #062463;
|
||||||
|
display: block;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
a, a:visited
|
||||||
|
{
|
||||||
|
color: #062463;;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover
|
||||||
|
{
|
||||||
|
background-color: #062463;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#content
|
||||||
|
{
|
||||||
|
padding: 15px;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 14pt;
|
||||||
|
flex: 1;
|
||||||
|
grid-area: main
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar
|
||||||
|
{
|
||||||
|
grid-area: side;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar ul
|
||||||
|
{
|
||||||
|
list-style-type: none;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar a, a:visited
|
||||||
|
{
|
||||||
|
color: #062463;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar a:hover
|
||||||
|
{
|
||||||
|
background-color: #062463;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content a, a:visited
|
||||||
|
{
|
||||||
|
color: #062463;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content a:hover
|
||||||
|
{
|
||||||
|
background-color: #062463;
|
||||||
|
color: white;
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
footer
|
||||||
|
{
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
color: white;
|
||||||
|
background-color: #062463;
|
||||||
|
font-weight: bold;
|
||||||
|
grid-area: footer;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer ul
|
||||||
|
{
|
||||||
|
background-color: #062463;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
footer li
|
||||||
|
{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 45px;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
//flex: 1 1 0;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a, a:visited
|
||||||
|
{
|
||||||
|
text-decoration: none;
|
||||||
|
|
||||||
|
color: white;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a:hover, ul#nav a:focus
|
||||||
|
{
|
||||||
|
text-decoration: none;
|
||||||
|
color: #062463;
|
||||||
|
background-color: white;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cats
|
||||||
|
{
|
||||||
|
background-color: #062463;
|
||||||
|
}
|
||||||
|
|
||||||
|
.letter_search_result
|
||||||
|
{
|
||||||
|
text-decoration: underline;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
ol
|
||||||
|
{
|
||||||
|
counter-reset: item;
|
||||||
|
}
|
||||||
|
.indexlink
|
||||||
|
{
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
.notexists
|
||||||
|
{
|
||||||
|
color: red !important;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (max-width: 768px)
|
||||||
|
{
|
||||||
|
#sidebar
|
||||||
|
{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer li:nth-child(-n+2)
|
||||||
|
{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer li:nth-of-type(3)
|
||||||
|
{
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
}
|
236
template/quitesimple/style3.css
Normal file
236
template/quitesimple/style3.css
Normal file
@ -0,0 +1,236 @@
|
|||||||
|
body
|
||||||
|
{
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
font-family: Verdana;
|
||||||
|
background-color: white;
|
||||||
|
display: grid;
|
||||||
|
min-height: 100vh;
|
||||||
|
grid-template-rows: auto 1fr auto;
|
||||||
|
grid-template-areas: "nav nav"
|
||||||
|
"main side"
|
||||||
|
"footer footer";
|
||||||
|
grid-template-columns: 1fr auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
header
|
||||||
|
{
|
||||||
|
margin: 0;
|
||||||
|
paddin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1, h2, h3
|
||||||
|
{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav
|
||||||
|
{
|
||||||
|
padding: 0px;
|
||||||
|
margin: 0px;
|
||||||
|
display: flex;
|
||||||
|
background-color: #062463;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
grid-area: nav;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
nav ul
|
||||||
|
{
|
||||||
|
background-color: #062463;
|
||||||
|
color: white;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
list-style-type: none;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav li
|
||||||
|
{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a, nav a:visited
|
||||||
|
{
|
||||||
|
padding: 10px;
|
||||||
|
text-decoration: none;
|
||||||
|
color: white;
|
||||||
|
display: block;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
line-height: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav a:hover, nav a:focus
|
||||||
|
{
|
||||||
|
padding: 10px;
|
||||||
|
text-decoration: none;
|
||||||
|
background-color: white;
|
||||||
|
color: #062463;
|
||||||
|
display: block;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
a, a:visited
|
||||||
|
{
|
||||||
|
color: #062463;;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover
|
||||||
|
{
|
||||||
|
background-color: #062463;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content
|
||||||
|
{
|
||||||
|
padding: 15px;
|
||||||
|
font-family: monospace;
|
||||||
|
font-size: 14pt;
|
||||||
|
flex: 1;
|
||||||
|
grid-area: main
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar
|
||||||
|
{
|
||||||
|
grid-area: side;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar ul
|
||||||
|
{
|
||||||
|
list-style-type: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar a, a:visited
|
||||||
|
{
|
||||||
|
color: #062463;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar a:hover
|
||||||
|
{
|
||||||
|
background-color: #062463;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content a, a:visited
|
||||||
|
{
|
||||||
|
color: #062463;
|
||||||
|
}
|
||||||
|
|
||||||
|
#content a:hover
|
||||||
|
{
|
||||||
|
background-color: #062463;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer
|
||||||
|
{
|
||||||
|
width: 100%;
|
||||||
|
display: block;
|
||||||
|
color: white;
|
||||||
|
background-color: #062463;
|
||||||
|
font-weight: bold;
|
||||||
|
grid-area: footer;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer ul
|
||||||
|
{
|
||||||
|
background-color: #062463;
|
||||||
|
margin: 0px;
|
||||||
|
padding: 0px;
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer li
|
||||||
|
{
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: inline-block;
|
||||||
|
line-height: 45px;
|
||||||
|
color: white;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a, a:visited
|
||||||
|
{
|
||||||
|
text-decoration: none;
|
||||||
|
color: white;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
footer a:hover, ul#nav a:focus
|
||||||
|
{
|
||||||
|
text-decoration: none;
|
||||||
|
color: #062463;
|
||||||
|
background-color: white;
|
||||||
|
display: inline-block;
|
||||||
|
}
|
||||||
|
|
||||||
|
#cats
|
||||||
|
{
|
||||||
|
background-color: #062463;
|
||||||
|
}
|
||||||
|
|
||||||
|
.letter_search_result
|
||||||
|
{
|
||||||
|
text-decoration: underline;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
ol
|
||||||
|
{
|
||||||
|
counter-reset: item;
|
||||||
|
}
|
||||||
|
|
||||||
|
.indexlink
|
||||||
|
{
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.notexists
|
||||||
|
{
|
||||||
|
color: red !important;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchlink
|
||||||
|
{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (orientation: portrait)
|
||||||
|
{
|
||||||
|
#sidebar
|
||||||
|
{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer li:nth-child(-n+2)
|
||||||
|
{
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
#footer li:nth-of-type(3)
|
||||||
|
{
|
||||||
|
text-align: center;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchlink {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
#searchbar {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
Завантаження…
Посилання в новій задачі
Block a user