add start stop joplin client terminal
This commit is contained in:
parent
1f73faa7e4
commit
ff3011de69
39
code/Dockerfile
Normal file
39
code/Dockerfile
Normal file
@ -0,0 +1,39 @@
|
||||
# For more information, please refer to https://aka.ms/vscode-docker-python
|
||||
FROM python:3.9-alpine as compile-image
|
||||
# Install pip requirements
|
||||
COPY requirements.txt .
|
||||
RUN apk add --virtual .build-deps gcc libffi-dev musl-dev
|
||||
RUN pip install --user -r requirements.txt
|
||||
|
||||
|
||||
|
||||
FROM python:3.9-alpine
|
||||
|
||||
# add nginx
|
||||
EXPOSE 80
|
||||
RUN apk add --no-cache nginx
|
||||
RUN adduser -D -g 'www' www
|
||||
RUN mkdir /www
|
||||
RUN chown -R www:www /var/lib/nginx
|
||||
RUN chown -R www:www /www
|
||||
RUN mv /etc/nginx/nginx.conf /etc/nginx/nginx.conf.orig
|
||||
COPY settings/nginx.conf /etc/nginx/nginx.conf
|
||||
|
||||
# Keeps Python from generating .pyc files in the container
|
||||
ENV PYTHONDONTWRITEBYTECODE=1
|
||||
# Turns off buffering for easier container logging
|
||||
ENV PYTHONUNBUFFERED=1
|
||||
|
||||
COPY --from=compile-image /root/.local /root/.local
|
||||
ENV PATH=/root/.local/bin:$PATH
|
||||
WORKDIR /app
|
||||
COPY . /app
|
||||
|
||||
# Creates a non-root user with an explicit UID and adds permission to access the /app folder
|
||||
# For more info, please refer to https://aka.ms/vscode-docker-python-configure-containers
|
||||
#RUN adduser -u 5678 --disabled-password --gecos "" appuser && chown -R appuser /app
|
||||
#USER appuser
|
||||
|
||||
# During debugging, this entry point will be overridden. For more information, please refer to https://aka.ms/vscode-docker-python-debug
|
||||
RUN chmod +x /app/runserver.sh
|
||||
CMD ["/bin/sh", "/app/runserver.sh"]
|
@ -6,6 +6,7 @@
|
||||
# joplin_utils : procedure related joplin application
|
||||
#
|
||||
# --==--==--==--==--==--==--==--==--==--==--==--==--==--==--==-- #
|
||||
import os
|
||||
import net
|
||||
import times
|
||||
import osproc
|
||||
@ -15,8 +16,11 @@ import httpcore
|
||||
import strutils
|
||||
import strformat
|
||||
import std/options
|
||||
import std/httpclient
|
||||
import std/asyncdispatch
|
||||
|
||||
from os import sleep
|
||||
import std/[asyncdispatch, httpclient]
|
||||
from posix import read, write, fdatasync, close
|
||||
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
# TYPE : Setup joplin_ping data
|
||||
@ -56,6 +60,15 @@ type
|
||||
latitude*, longitude*, altitude*, order*:seq[float]
|
||||
req*: Request
|
||||
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
# TYPE : Setup process data structure
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
type
|
||||
program* = object
|
||||
pid*: int
|
||||
stdout*: string
|
||||
stderr*: string
|
||||
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
# DURATION : duration variables
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
@ -281,20 +294,35 @@ proc get_joplin_cli_token*(): string =
|
||||
|
||||
return flagValue
|
||||
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
# PROC : launch any program and get PID
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
proc launchProgram(app:string = "", workingPath:string = "", arguments:array[2, string]):int {.thread.} =
|
||||
|
||||
var p = startProcess(joinPath(workingPath,app), workingPath, arguments)
|
||||
let pid = p.processID()
|
||||
var outhdl = outputHandle(p)
|
||||
var inputhdl = inputHandle(p)
|
||||
var errhdl = errorHandle(p)
|
||||
return pid
|
||||
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
# PROC : start Joplin Terminal
|
||||
# PROC : Start joplin cli
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
proc joplin_cli_start*(): bool =
|
||||
var rc = false
|
||||
var result = execCmdEx("joplin server start &")
|
||||
proc joplin_cli_start*():int {.thread.} =
|
||||
|
||||
let joplinProcessId = launchProgram("joplin","/usr/bin/",["server","start"])
|
||||
return joplinProcessId
|
||||
|
||||
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
# PROC : stop Joplin Terminal
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
proc joplin_cli_stop*():int {.thread.} =
|
||||
let joplinProcessId = launchProgram("joplin","/usr/bin/",["server","stop"])
|
||||
return joplinProcessId
|
||||
|
||||
|
||||
if result.exitCode == 0:
|
||||
# echo result.output
|
||||
rc = true
|
||||
else:
|
||||
rc = false
|
||||
return rc
|
||||
|
||||
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
@ -305,26 +333,49 @@ proc joplin_cli_status*(): bool =
|
||||
var result = execCmdEx("joplin server status")
|
||||
|
||||
if result.exitCode == 0:
|
||||
# echo result.output
|
||||
rc = true
|
||||
if "Server is not running" in result.output :
|
||||
echo "Joplin Terminal cli status is down : ", result.output
|
||||
rc = false
|
||||
else:
|
||||
echo "Joplin Terminal cli status is up : ", result.output
|
||||
rc = true
|
||||
else:
|
||||
rc = false
|
||||
echo "Error validate joplin terminal status : ", result.output
|
||||
return rc
|
||||
|
||||
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
# PROC : start Joplin Terminal
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
# proc joplin_cli_start*(): bool =
|
||||
# var rc = false
|
||||
# startProcess("joplin","/usr/bin", @["server", "start"])
|
||||
# #var result = execCmdEx("ls -l /usr/bin/joplin")
|
||||
|
||||
# if joplin_cli_status() == true:
|
||||
# echo "Joplin Terminal started successfully : ",result.output
|
||||
# rc = true
|
||||
# else:
|
||||
# echo "Joplin Terminal didn't start : ",result.output
|
||||
# rc = false
|
||||
# return rc
|
||||
|
||||
|
||||
|
||||
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
# PROC : stop Joplin Terminal
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
proc joplin_cli_stop*(): bool =
|
||||
var rc = false
|
||||
var result = execCmdEx("joplin server stop")
|
||||
# proc joplin_cli_stop*(): bool =
|
||||
# var rc = false
|
||||
# var result = execCmdEx("joplin server stop")
|
||||
|
||||
if result.exitCode == 0:
|
||||
# echo result.output
|
||||
rc = true
|
||||
else:
|
||||
rc = false
|
||||
return rc
|
||||
# if result.exitCode == 0:
|
||||
# # echo result.output
|
||||
# rc = true
|
||||
# else:
|
||||
# rc = false
|
||||
# return rc
|
||||
|
||||
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
|
24
main.nim
24
main.nim
@ -73,6 +73,7 @@ type
|
||||
TData* = ref object of RootObj
|
||||
loggedIn*: bool
|
||||
userid, username*, userpass*, email*: string
|
||||
notification*: int
|
||||
req*: Request
|
||||
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
@ -84,6 +85,8 @@ proc init(c: var TData, cld: var ColomnLeftData) =
|
||||
c.username = ""
|
||||
c.userid = ""
|
||||
c.loggedIn = false
|
||||
c.notification = 0
|
||||
|
||||
|
||||
## default option
|
||||
# cld.option = notes
|
||||
@ -274,6 +277,18 @@ routes:
|
||||
echo @"msg"
|
||||
if c.loggedIn:
|
||||
|
||||
# Start joplin terminal cli if stropped
|
||||
if @"msg" == "startStopJoplin":
|
||||
if joplin_cli_status() == false:
|
||||
var isStart = joplin_cli_start()
|
||||
echo "Joplin client Terminal started: ",isStart
|
||||
# echo joplin_cli_status()
|
||||
if joplin_cli_status() == true:
|
||||
var isStart = joplin_cli_stop()
|
||||
echo "Joplin client Terminal stopped: ",isStart
|
||||
# echo joplin_cli_status()
|
||||
redirect("/secret")
|
||||
|
||||
# if Joplin application work
|
||||
var checkJoplin = waitFor ping_joplin(joplin_token)
|
||||
if checkJoplin.ping_status:
|
||||
@ -342,6 +357,15 @@ routes:
|
||||
logout(c)
|
||||
redirect("/")
|
||||
|
||||
# start_joplin route
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
# post "/start_joplin":
|
||||
# if joplin_cli_status() == false:
|
||||
# joplin_cli_start()
|
||||
|
||||
|
||||
|
||||
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
# # ROUTES TESTS SECTION ##
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
|
263
public/css/alertify-notif.css
Executable file
263
public/css/alertify-notif.css
Executable file
@ -0,0 +1,263 @@
|
||||
.alertify,
|
||||
.alertify-show,
|
||||
.alertify-log {
|
||||
-webkit-transition: all 500ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
-moz-transition: all 500ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
-ms-transition: all 500ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
-o-transition: all 500ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
transition: all 500ms cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
||||
/* easeOutBack */
|
||||
}
|
||||
|
||||
.alertify-hide {
|
||||
-webkit-transition: all 250ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
|
||||
-moz-transition: all 250ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
|
||||
-ms-transition: all 250ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
|
||||
-o-transition: all 250ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
|
||||
transition: all 250ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
|
||||
/* easeInBack */
|
||||
}
|
||||
|
||||
.alertify-log-hide {
|
||||
-webkit-transition: all 500ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
|
||||
-moz-transition: all 500ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
|
||||
-ms-transition: all 500ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
|
||||
-o-transition: all 500ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
|
||||
transition: all 500ms cubic-bezier(0.6, -0.28, 0.735, 0.045);
|
||||
/* easeInBack */
|
||||
}
|
||||
|
||||
.alertify-cover {
|
||||
position: fixed;
|
||||
z-index: 99999;
|
||||
top: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
background-color: white;
|
||||
filter: alpha(opacity=0);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.alertify-cover-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.alertify {
|
||||
position: fixed;
|
||||
z-index: 99999;
|
||||
top: 50px;
|
||||
left: 50%;
|
||||
width: 550px;
|
||||
margin-left: -275px;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.alertify-hidden {
|
||||
-webkit-transform: translate(0, -150px);
|
||||
-moz-transform: translate(0, -150px);
|
||||
-ms-transform: translate(0, -150px);
|
||||
-o-transform: translate(0, -150px);
|
||||
transform: translate(0, -150px);
|
||||
opacity: 0;
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* overwrite display: none; for everything except IE6-8 */
|
||||
:root * > .alertify-hidden {
|
||||
display: block;
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.alertify-logs {
|
||||
position: fixed;
|
||||
z-index: 5000;
|
||||
bottom: 10px;
|
||||
right: 10px;
|
||||
width: 300px;
|
||||
}
|
||||
|
||||
.alertify-logs-hidden {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.alertify-log {
|
||||
display: block;
|
||||
margin-top: 10px;
|
||||
position: relative;
|
||||
right: -300px;
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.alertify-log-show {
|
||||
right: 0;
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.alertify-log-hide {
|
||||
-webkit-transform: translate(300px, 0);
|
||||
-moz-transform: translate(300px, 0);
|
||||
-ms-transform: translate(300px, 0);
|
||||
-o-transform: translate(300px, 0);
|
||||
transform: translate(300px, 0);
|
||||
opacity: 0;
|
||||
}
|
||||
|
||||
.alertify-dialog {
|
||||
padding: 25px;
|
||||
}
|
||||
|
||||
.alertify-resetFocus {
|
||||
border: 0;
|
||||
clip: rect(0 0 0 0);
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
}
|
||||
|
||||
.alertify-inner {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.alertify-text {
|
||||
margin-bottom: 15px;
|
||||
width: 100%;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
font-size: 100%;
|
||||
}
|
||||
|
||||
.alertify-button,
|
||||
.alertify-button:hover,
|
||||
.alertify-button:active,
|
||||
.alertify-button:visited {
|
||||
background: none;
|
||||
text-decoration: none;
|
||||
border: none;
|
||||
/* line-height and font-size for input button */
|
||||
line-height: 1.5;
|
||||
font-size: 100%;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
@media only screen and (max-width: 680px) {
|
||||
.alertify,
|
||||
.alertify-logs {
|
||||
width: 90%;
|
||||
-webkit-box-sizing: border-box;
|
||||
-moz-box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.alertify {
|
||||
left: 5%;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Default Look and Feel
|
||||
*/
|
||||
.alertify,
|
||||
.alertify-log {
|
||||
font-family: sans-serif;
|
||||
}
|
||||
|
||||
.alertify {
|
||||
background: #FFF;
|
||||
border: 10px solid #333;
|
||||
/* browsers that don't support rgba */
|
||||
border: 10px solid rgba(0, 0, 0, 0.7);
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 3px 3px rgba(0, 0, 0, 0.3);
|
||||
-webkit-background-clip: padding;
|
||||
/* Safari 4? Chrome 6? */
|
||||
-moz-background-clip: padding;
|
||||
/* Firefox 3.6 */
|
||||
background-clip: padding-box;
|
||||
/* Firefox 4, Safari 5, Opera 10, IE 9 */
|
||||
}
|
||||
|
||||
.alertify-text {
|
||||
border: 1px solid #CCC;
|
||||
padding: 10px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
.alertify-button {
|
||||
border-radius: 4px;
|
||||
color: #FFF;
|
||||
font-weight: bold;
|
||||
padding: 6px 15px;
|
||||
text-decoration: none;
|
||||
text-shadow: 1px 1px 0 rgba(0, 0, 0, 0.5);
|
||||
box-shadow: inset 0 1px 0 0 rgba(255, 255, 255, 0.5);
|
||||
background-image: -webkit-linear-gradient(top, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0));
|
||||
background-image: -moz-linear-gradient(top, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0));
|
||||
background-image: -ms-linear-gradient(top, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0));
|
||||
background-image: -o-linear-gradient(top, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0));
|
||||
background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.3), rgba(255, 255, 255, 0));
|
||||
}
|
||||
|
||||
.alertify-button:hover,
|
||||
.alertify-button:focus {
|
||||
outline: none;
|
||||
background-image: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.1), transparent);
|
||||
background-image: -moz-linear-gradient(top, rgba(0, 0, 0, 0.1), transparent);
|
||||
background-image: -ms-linear-gradient(top, rgba(0, 0, 0, 0.1), transparent);
|
||||
background-image: -o-linear-gradient(top, rgba(0, 0, 0, 0.1), transparent);
|
||||
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0));
|
||||
}
|
||||
|
||||
.alertify-button:focus {
|
||||
box-shadow: 0 0 15px #2B72D5;
|
||||
}
|
||||
|
||||
.alertify-button:active {
|
||||
position: relative;
|
||||
box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.15), 0 1px 2px rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
|
||||
.alertify-button-cancel,
|
||||
.alertify-button-cancel:hover,
|
||||
.alertify-button-cancel:focus {
|
||||
background-color: #FE1A00;
|
||||
border: 1px solid #D83526;
|
||||
}
|
||||
|
||||
.alertify-button-ok,
|
||||
.alertify-button-ok:hover,
|
||||
.alertify-button-ok:focus {
|
||||
background-color: #5CB811;
|
||||
border: 1px solid #3B7808;
|
||||
}
|
||||
|
||||
.alertify-log {
|
||||
background: #1F1F1F;
|
||||
background: rgba(0, 0, 0, 0.9);
|
||||
padding: 15px;
|
||||
border-radius: 4px;
|
||||
color: #FFF;
|
||||
text-shadow: -1px -1px 0 rgba(0, 0, 0, 0.5);
|
||||
}
|
||||
|
||||
.alertify-log-error {
|
||||
background: #FE1A00;
|
||||
background: rgba(254, 26, 0, 0.9);
|
||||
}
|
||||
|
||||
.alertify-log-success {
|
||||
background: #5CB811;
|
||||
background: rgba(92, 184, 17, 0.9);
|
||||
}
|
||||
|
||||
/* button {
|
||||
min-width: 300px;
|
||||
outline: none;
|
||||
} */
|
||||
|
182
public/css/notif-bell.css
Executable file
182
public/css/notif-bell.css
Executable file
@ -0,0 +1,182 @@
|
||||
/* * {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
html {
|
||||
line-height: 1.2;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
*,
|
||||
*::after,
|
||||
*::before {
|
||||
box-sizing: inherit;
|
||||
}
|
||||
html,
|
||||
body {
|
||||
height: 100%;
|
||||
}
|
||||
body {
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
font-family: monospace, arial, sans-serif;
|
||||
font-size: 16px;
|
||||
background: linear-gradient(#160731 0%,#1B293C 100%);
|
||||
color: #333;
|
||||
overflow: hidden;
|
||||
} */
|
||||
/* .my-moon {
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
background-color: #fff;
|
||||
border-radius: 50%;
|
||||
box-shadow: 0 0 0 10px rgba(255,255,255,.04),
|
||||
0 0 0 20px rgba(255,255,255,.04),
|
||||
0 0 0 30px rgba(255,255,255,.04),
|
||||
0 0 50px 50px rgba(255,255,255,.02),
|
||||
0 0 100px 100px rgba(255,255,255,.02);
|
||||
-webkit-animation: moon-moving 30s both infinite;
|
||||
animation: moon-moving 30s both infinite;
|
||||
} */
|
||||
.notification-box {
|
||||
position: fixed;
|
||||
z-index: 99;
|
||||
top: 15px;
|
||||
right: 30px;
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
text-align: center;
|
||||
}
|
||||
.notification-bell {
|
||||
-webkit-animation: bell 1s 1s both infinite;
|
||||
animation: bell 1s 1s both infinite;
|
||||
}
|
||||
.notification-bell * {
|
||||
display: block;
|
||||
margin: 0 auto;
|
||||
/* background-color: #fff;
|
||||
box-shadow: 0px 0px 15px #fff; */
|
||||
background-color: rgb(9, 9, 9);
|
||||
box-shadow: 0px 0px 15px rgb(9, 9, 9);
|
||||
}
|
||||
.bell-top {
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 3px 3px 0 0;
|
||||
}
|
||||
.bell-middle {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
margin-top: -1px;
|
||||
border-radius: 12.5px 12.5px 0 0;
|
||||
}
|
||||
.bell-bottom {
|
||||
position: relative;
|
||||
z-index: 0;
|
||||
width: 32px;
|
||||
height: 2px;
|
||||
}
|
||||
.bell-bottom::before,
|
||||
.bell-bottom::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: -4px;
|
||||
}
|
||||
.bell-bottom::before {
|
||||
left: 1px;
|
||||
/* border-bottom: 4px solid #fff; */
|
||||
border-bottom: 4px solid rgb(9, 9, 9);
|
||||
border-right: 0 solid transparent;
|
||||
border-left: 4px solid transparent;
|
||||
}
|
||||
.bell-bottom::after {
|
||||
right: 1px;
|
||||
/* border-bottom: 4px solid #fff; */
|
||||
border-bottom: 4px solid rgb(9, 9, 9);
|
||||
border-right: 4px solid transparent;
|
||||
border-left: 0 solid transparent;
|
||||
}
|
||||
.bell-rad {
|
||||
width: 8px;
|
||||
height: 4px;
|
||||
margin-top: 2px;
|
||||
border-radius: 0 0 4px 4px;
|
||||
-webkit-animation: rad 1s 2s both infinite;
|
||||
animation: rad 1s 2s both infinite;
|
||||
}
|
||||
.notification-count {
|
||||
position: absolute;
|
||||
z-index: 1;
|
||||
top: -6px;
|
||||
right: -6px;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
line-height: 25px;
|
||||
font-size: 15px;
|
||||
border-radius: 50%;
|
||||
background-color: #ff4927;
|
||||
color: #fff;
|
||||
-webkit-animation: zoom 3s 3s both infinite;
|
||||
animation: zoom 3s 3s both infinite;
|
||||
}
|
||||
@-webkit-keyframes bell {
|
||||
0% { transform: rotate(0); }
|
||||
10% { transform: rotate(30deg); }
|
||||
20% { transform: rotate(0); }
|
||||
80% { transform: rotate(0); }
|
||||
90% { transform: rotate(-30deg); }
|
||||
100% { transform: rotate(0); }
|
||||
}
|
||||
@keyframes bell {
|
||||
0% { transform: rotate(0); }
|
||||
10% { transform: rotate(30deg); }
|
||||
20% { transform: rotate(0); }
|
||||
80% { transform: rotate(0); }
|
||||
90% { transform: rotate(-30deg); }
|
||||
100% { transform: rotate(0); }
|
||||
}
|
||||
@-webkit-keyframes rad {
|
||||
0% { transform: translateX(0); }
|
||||
10% { transform: translateX(6px); }
|
||||
20% { transform: translateX(0); }
|
||||
80% { transform: translateX(0); }
|
||||
90% { transform: translateX(-6px); }
|
||||
100% { transform: translateX(0); }
|
||||
}
|
||||
@keyframes rad {
|
||||
0% { transform: translateX(0); }
|
||||
10% { transform: translateX(6px); }
|
||||
20% { transform: translateX(0); }
|
||||
80% { transform: translateX(0); }
|
||||
90% { transform: translateX(-6px); }
|
||||
100% { transform: translateX(0); }
|
||||
}
|
||||
@-webkit-keyframes zoom {
|
||||
0% { opacity: 0; transform: scale(0); }
|
||||
10% { opacity: 1; transform: scale(1); }
|
||||
50% { opacity: 1; }
|
||||
51% { opacity: 0; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
@keyframes zoom {
|
||||
0% { opacity: 0; transform: scale(0); }
|
||||
10% { opacity: 1; transform: scale(1); }
|
||||
50% { opacity: 1; }
|
||||
51% { opacity: 0; }
|
||||
100% { opacity: 0; }
|
||||
}
|
||||
@-webkit-keyframes moon-moving {
|
||||
0% {
|
||||
transform: translate(-200%, 600%);
|
||||
}
|
||||
100% {
|
||||
transform: translate(800%, -200%);
|
||||
}
|
||||
}
|
||||
@keyframes moon-moving {
|
||||
0% {
|
||||
transform: translate(-200%, 600%);
|
||||
}
|
||||
100% {
|
||||
transform: translate(800%, -200%);
|
||||
}
|
||||
}
|
207
public/css/popupnotif.css
Normal file
207
public/css/popupnotif.css
Normal file
@ -0,0 +1,207 @@
|
||||
.alert>.start-icon {
|
||||
margin-right: 0;
|
||||
min-width: 20px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.alert>.start-icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.greencross
|
||||
{
|
||||
font-size:18px;
|
||||
color: #25ff0b;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.alert-simple.alert-success
|
||||
{
|
||||
border: 1px solid rgba(36, 241, 6, 0.46);
|
||||
background-color: rgba(7, 149, 66, 0.12156862745098039);
|
||||
box-shadow: 0px 0px 2px #259c08;
|
||||
color: #0ad406;
|
||||
text-shadow: 2px 1px #00040a;
|
||||
transition:0.5s;
|
||||
cursor:pointer;
|
||||
}
|
||||
.alert-success:hover{
|
||||
background-color: rgba(7, 149, 66, 0.35);
|
||||
transition:0.5s;
|
||||
}
|
||||
.alert-simple.alert-info
|
||||
{
|
||||
border: 1px solid rgba(6, 44, 241, 0.46);
|
||||
background-color: rgba(7, 73, 149, 0.12156862745098039);
|
||||
box-shadow: 0px 0px 2px #0396ff;
|
||||
color: #0396ff;
|
||||
text-shadow: 2px 1px #00040a;
|
||||
transition:0.5s;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.alert-info:hover
|
||||
{
|
||||
background-color: rgba(7, 73, 149, 0.35);
|
||||
transition:0.5s;
|
||||
}
|
||||
|
||||
.blue-cross
|
||||
{
|
||||
font-size: 18px;
|
||||
color: #0bd2ff;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.alert-simple.alert-warning
|
||||
{
|
||||
border: 1px solid rgba(241, 142, 6, 0.81);
|
||||
background-color: rgba(220, 128, 1, 0.16);
|
||||
box-shadow: 0px 0px 2px #ffb103;
|
||||
color: #ffb103;
|
||||
text-shadow: 2px 1px #00040a;
|
||||
transition:0.5s;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.alert-warning:hover{
|
||||
background-color: rgba(220, 128, 1, 0.33);
|
||||
transition:0.5s;
|
||||
}
|
||||
|
||||
.warning
|
||||
{
|
||||
font-size: 18px;
|
||||
color: #ffb40b;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.alert-simple.alert-danger
|
||||
{
|
||||
border: 1px solid rgba(241, 6, 6, 0.81);
|
||||
background-color: rgba(220, 17, 1, 0.16);
|
||||
box-shadow: 0px 0px 2px #ff0303;
|
||||
color: #ff0303;
|
||||
text-shadow: 2px 1px #00040a;
|
||||
transition:0.5s;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.alert-danger:hover
|
||||
{
|
||||
background-color: rgba(220, 17, 1, 0.33);
|
||||
transition:0.5s;
|
||||
}
|
||||
|
||||
.danger
|
||||
{
|
||||
font-size: 18px;
|
||||
color: #ff0303;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.alert-simple.alert-primary
|
||||
{
|
||||
border: 1px solid rgba(6, 241, 226, 0.81);
|
||||
background-color: rgba(1, 204, 220, 0.16);
|
||||
box-shadow: 0px 0px 2px #03fff5;
|
||||
color: #03d0ff;
|
||||
text-shadow: 2px 1px #00040a;
|
||||
transition:0.5s;
|
||||
cursor:pointer;
|
||||
}
|
||||
|
||||
.alert-primary:hover{
|
||||
background-color: rgba(1, 204, 220, 0.33);
|
||||
transition:0.5s;
|
||||
}
|
||||
|
||||
.alertprimary
|
||||
{
|
||||
font-size: 18px;
|
||||
color: #03d0ff;
|
||||
text-shadow: none;
|
||||
}
|
||||
|
||||
.square_box {
|
||||
position: absolute;
|
||||
-webkit-transform: rotate(45deg);
|
||||
-ms-transform: rotate(45deg);
|
||||
transform: rotate(45deg);
|
||||
border-top-left-radius: 45px;
|
||||
opacity: 0.302;
|
||||
}
|
||||
|
||||
.square_box.box_three {
|
||||
background-image: -moz-linear-gradient(-90deg, #290a59 0%, #3d57f4 100%);
|
||||
background-image: -webkit-linear-gradient(-90deg, #290a59 0%, #3d57f4 100%);
|
||||
background-image: -ms-linear-gradient(-90deg, #290a59 0%, #3d57f4 100%);
|
||||
opacity: 0.059;
|
||||
left: -80px;
|
||||
top: -60px;
|
||||
width: 500px;
|
||||
height: 500px;
|
||||
border-radius: 45px;
|
||||
}
|
||||
|
||||
.square_box.box_four {
|
||||
background-image: -moz-linear-gradient(-90deg, #290a59 0%, #3d57f4 100%);
|
||||
background-image: -webkit-linear-gradient(-90deg, #290a59 0%, #3d57f4 100%);
|
||||
background-image: -ms-linear-gradient(-90deg, #290a59 0%, #3d57f4 100%);
|
||||
opacity: 0.059;
|
||||
left: 150px;
|
||||
top: -25px;
|
||||
width: 550px;
|
||||
height: 550px;
|
||||
border-radius: 45px;
|
||||
}
|
||||
|
||||
.alert:before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
width: 0;
|
||||
height: calc(100% - 44px);
|
||||
border-left: 1px solid;
|
||||
border-right: 2px solid;
|
||||
border-bottom-right-radius: 3px;
|
||||
border-top-right-radius: 3px;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translate(0,-50%);
|
||||
height: 20px;
|
||||
}
|
||||
|
||||
.fa-times
|
||||
{
|
||||
-webkit-animation: blink-1 2s infinite both;
|
||||
animation: blink-1 2s infinite both;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* ----------------------------------------
|
||||
* animation blink-1
|
||||
* ----------------------------------------
|
||||
*/
|
||||
@-webkit-keyframes blink-1 {
|
||||
0%,
|
||||
50%,
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
25%,
|
||||
75% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
@keyframes blink-1 {
|
||||
0%,
|
||||
50%,
|
||||
100% {
|
||||
opacity: 1;
|
||||
}
|
||||
25%,
|
||||
75% {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
@ -58,7 +58,7 @@ a {
|
||||
--animation-timing-curve: ease-in-out;
|
||||
--blue-joplin-color: #0053b8;
|
||||
--light-blue-joplin-color: rgb(237, 241, 243);
|
||||
--header-height: 50px;
|
||||
--header-height: 55px;
|
||||
}
|
||||
|
||||
.header {
|
||||
@ -129,6 +129,12 @@ a {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.notifBell-btn {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.menu-icon {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
|
639
public/js/alertify_notif.js
Executable file
639
public/js/alertify_notif.js
Executable file
@ -0,0 +1,639 @@
|
||||
$(document).foundation();
|
||||
|
||||
/*global define*/
|
||||
(function (global, undefined) {
|
||||
"use strict";
|
||||
|
||||
var document = global.document,
|
||||
Alertify;
|
||||
|
||||
Alertify = function () {
|
||||
|
||||
var _alertify = {},
|
||||
dialogs = {},
|
||||
isopen = false,
|
||||
keys = { ENTER: 13, ESC: 27, SPACE: 32 },
|
||||
queue = [],
|
||||
$, btnCancel, btnOK, btnReset, btnResetBack, btnFocus, elCallee, elCover, elDialog, elLog, form, input, getTransitionEvent;
|
||||
|
||||
/**
|
||||
* Markup pieces
|
||||
* @type {Object}
|
||||
*/
|
||||
dialogs = {
|
||||
buttons : {
|
||||
holder : "<nav class=\"alertify-buttons\">{{buttons}}</nav>",
|
||||
submit : "<button type=\"submit\" class=\"alertify-button alertify-button-ok\" id=\"alertify-ok\">{{ok}}</button>",
|
||||
ok : "<button class=\"alertify-button alertify-button-ok\" id=\"alertify-ok\">{{ok}}</button>",
|
||||
cancel : "<button class=\"alertify-button alertify-button-cancel\" id=\"alertify-cancel\">{{cancel}}</button>"
|
||||
},
|
||||
input : "<div class=\"alertify-text-wrapper\"><input type=\"text\" class=\"alertify-text\" id=\"alertify-text\"></div>",
|
||||
message : "<p class=\"alertify-message\">{{message}}</p>",
|
||||
log : "<article class=\"alertify-log{{class}}\">{{message}}</article>"
|
||||
};
|
||||
|
||||
/**
|
||||
* Return the proper transitionend event
|
||||
* @return {String} Transition type string
|
||||
*/
|
||||
getTransitionEvent = function () {
|
||||
var t,
|
||||
type,
|
||||
supported = false,
|
||||
el = document.createElement("fakeelement"),
|
||||
transitions = {
|
||||
"WebkitTransition" : "webkitTransitionEnd",
|
||||
"MozTransition" : "transitionend",
|
||||
"OTransition" : "otransitionend",
|
||||
"transition" : "transitionend"
|
||||
};
|
||||
|
||||
for (t in transitions) {
|
||||
if (el.style[t] !== undefined) {
|
||||
type = transitions[t];
|
||||
supported = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type : type,
|
||||
supported : supported
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Shorthand for document.getElementById()
|
||||
*
|
||||
* @param {String} id A specific element ID
|
||||
* @return {Object} HTML element
|
||||
*/
|
||||
$ = function (id) {
|
||||
return document.getElementById(id);
|
||||
};
|
||||
|
||||
/**
|
||||
* Alertify private object
|
||||
* @type {Object}
|
||||
*/
|
||||
_alertify = {
|
||||
|
||||
/**
|
||||
* Labels object
|
||||
* @type {Object}
|
||||
*/
|
||||
labels : {
|
||||
ok : "OK",
|
||||
cancel : "Cancel"
|
||||
},
|
||||
|
||||
/**
|
||||
* Delay number
|
||||
* @type {Number}
|
||||
*/
|
||||
delay : 5000,
|
||||
|
||||
/**
|
||||
* Whether buttons are reversed (default is secondary/primary)
|
||||
* @type {Boolean}
|
||||
*/
|
||||
buttonReverse : false,
|
||||
|
||||
/**
|
||||
* Which button should be focused by default
|
||||
* @type {String} "ok" (default), "cancel", or "none"
|
||||
*/
|
||||
buttonFocus : "ok",
|
||||
|
||||
/**
|
||||
* Set the transition event on load
|
||||
* @type {[type]}
|
||||
*/
|
||||
transition : undefined,
|
||||
|
||||
/**
|
||||
* Set the proper button click events
|
||||
*
|
||||
* @param {Function} fn [Optional] Callback function
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
addListeners : function (fn) {
|
||||
var hasOK = (typeof btnOK !== "undefined"),
|
||||
hasCancel = (typeof btnCancel !== "undefined"),
|
||||
hasInput = (typeof input !== "undefined"),
|
||||
val = "",
|
||||
self = this,
|
||||
ok, cancel, common, key, reset;
|
||||
|
||||
// ok event handler
|
||||
ok = function (event) {
|
||||
if (typeof event.preventDefault !== "undefined") event.preventDefault();
|
||||
common(event);
|
||||
if (typeof input !== "undefined") val = input.value;
|
||||
if (typeof fn === "function") {
|
||||
if (typeof input !== "undefined") {
|
||||
fn(true, val);
|
||||
}
|
||||
else fn(true);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// cancel event handler
|
||||
cancel = function (event) {
|
||||
if (typeof event.preventDefault !== "undefined") event.preventDefault();
|
||||
common(event);
|
||||
if (typeof fn === "function") fn(false);
|
||||
return false;
|
||||
};
|
||||
|
||||
// common event handler (keyup, ok and cancel)
|
||||
common = function (event) {
|
||||
self.hide();
|
||||
self.unbind(document.body, "keyup", key);
|
||||
self.unbind(btnReset, "focus", reset);
|
||||
if (hasOK) self.unbind(btnOK, "click", ok);
|
||||
if (hasCancel) self.unbind(btnCancel, "click", cancel);
|
||||
};
|
||||
|
||||
// keyup handler
|
||||
key = function (event) {
|
||||
var keyCode = event.keyCode;
|
||||
if ((keyCode === keys.SPACE && !hasInput) || (hasInput && keyCode === keys.ENTER)) ok(event);
|
||||
if (keyCode === keys.ESC && hasCancel) cancel(event);
|
||||
};
|
||||
|
||||
// reset focus to first item in the dialog
|
||||
reset = function (event) {
|
||||
if (hasInput) input.focus();
|
||||
else if (!hasCancel || self.buttonReverse) btnOK.focus();
|
||||
else btnCancel.focus();
|
||||
};
|
||||
|
||||
// handle reset focus link
|
||||
// this ensures that the keyboard focus does not
|
||||
// ever leave the dialog box until an action has
|
||||
// been taken
|
||||
this.bind(btnReset, "focus", reset);
|
||||
this.bind(btnResetBack, "focus", reset);
|
||||
// handle OK click
|
||||
if (hasOK) this.bind(btnOK, "click", ok);
|
||||
// handle Cancel click
|
||||
if (hasCancel) this.bind(btnCancel, "click", cancel);
|
||||
// listen for keys, Cancel => ESC
|
||||
this.bind(document.body, "keyup", key);
|
||||
if (!this.transition.supported) {
|
||||
this.setFocus();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Bind events to elements
|
||||
*
|
||||
* @param {Object} el HTML Object
|
||||
* @param {Event} event Event to attach to element
|
||||
* @param {Function} fn Callback function
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
bind : function (el, event, fn) {
|
||||
if (typeof el.addEventListener === "function") {
|
||||
el.addEventListener(event, fn, false);
|
||||
} else if (el.attachEvent) {
|
||||
el.attachEvent("on" + event, fn);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Use alertify as the global error handler (using window.onerror)
|
||||
*
|
||||
* @return {boolean} success
|
||||
*/
|
||||
handleErrors : function () {
|
||||
if (typeof global.onerror !== "undefined") {
|
||||
var self = this;
|
||||
global.onerror = function (msg, url, line) {
|
||||
self.error("[" + msg + " on line " + line + " of " + url + "]", 0);
|
||||
};
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Append button HTML strings
|
||||
*
|
||||
* @param {String} secondary The secondary button HTML string
|
||||
* @param {String} primary The primary button HTML string
|
||||
*
|
||||
* @return {String} The appended button HTML strings
|
||||
*/
|
||||
appendButtons : function (secondary, primary) {
|
||||
return this.buttonReverse ? primary + secondary : secondary + primary;
|
||||
},
|
||||
|
||||
/**
|
||||
* Build the proper message box
|
||||
*
|
||||
* @param {Object} item Current object in the queue
|
||||
*
|
||||
* @return {String} An HTML string of the message box
|
||||
*/
|
||||
build : function (item) {
|
||||
var html = "",
|
||||
type = item.type,
|
||||
message = item.message,
|
||||
css = item.cssClass || "";
|
||||
|
||||
html += "<div class=\"alertify-dialog\">";
|
||||
html += "<a id=\"alertify-resetFocusBack\" class=\"alertify-resetFocus\" href=\"#\">Reset Focus</a>";
|
||||
|
||||
if (_alertify.buttonFocus === "none") html += "<a href=\"#\" id=\"alertify-noneFocus\" class=\"alertify-hidden\"></a>";
|
||||
|
||||
// doens't require an actual form
|
||||
if (type === "prompt") html += "<div id=\"alertify-form\">";
|
||||
|
||||
html += "<article class=\"alertify-inner\">";
|
||||
html += dialogs.message.replace("{{message}}", message);
|
||||
|
||||
if (type === "prompt") html += dialogs.input;
|
||||
|
||||
html += dialogs.buttons.holder;
|
||||
html += "</article>";
|
||||
|
||||
if (type === "prompt") html += "</div>";
|
||||
|
||||
html += "<a id=\"alertify-resetFocus\" class=\"alertify-resetFocus\" href=\"#\">Reset Focus</a>";
|
||||
html += "</div>";
|
||||
|
||||
switch (type) {
|
||||
case "confirm":
|
||||
html = html.replace("{{buttons}}", this.appendButtons(dialogs.buttons.cancel, dialogs.buttons.ok));
|
||||
html = html.replace("{{ok}}", this.labels.ok).replace("{{cancel}}", this.labels.cancel);
|
||||
break;
|
||||
case "prompt":
|
||||
html = html.replace("{{buttons}}", this.appendButtons(dialogs.buttons.cancel, dialogs.buttons.submit));
|
||||
html = html.replace("{{ok}}", this.labels.ok).replace("{{cancel}}", this.labels.cancel);
|
||||
break;
|
||||
case "alert":
|
||||
html = html.replace("{{buttons}}", dialogs.buttons.ok);
|
||||
html = html.replace("{{ok}}", this.labels.ok);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
elDialog.className = "alertify alertify-" + type + " " + css;
|
||||
elCover.className = "alertify-cover";
|
||||
return html;
|
||||
},
|
||||
|
||||
/**
|
||||
* Close the log messages
|
||||
*
|
||||
* @param {Object} elem HTML Element of log message to close
|
||||
* @param {Number} wait [optional] Time (in ms) to wait before automatically hiding the message, if 0 never hide
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
close : function (elem, wait) {
|
||||
// Unary Plus: +"2" === 2
|
||||
var timer = (wait && !isNaN(wait)) ? +wait : this.delay,
|
||||
self = this,
|
||||
hideElement, transitionDone;
|
||||
|
||||
// set click event on log messages
|
||||
this.bind(elem, "click", function () {
|
||||
hideElement(elem);
|
||||
});
|
||||
// Hide the dialog box after transition
|
||||
// This ensure it doens't block any element from being clicked
|
||||
transitionDone = function (event) {
|
||||
event.stopPropagation();
|
||||
// unbind event so function only gets called once
|
||||
self.unbind(this, self.transition.type, transitionDone);
|
||||
// remove log message
|
||||
elLog.removeChild(this);
|
||||
if (!elLog.hasChildNodes()) elLog.className += " alertify-logs-hidden";
|
||||
};
|
||||
// this sets the hide class to transition out
|
||||
// or removes the child if css transitions aren't supported
|
||||
hideElement = function (el) {
|
||||
// ensure element exists
|
||||
if (typeof el !== "undefined" && el.parentNode === elLog) {
|
||||
// whether CSS transition exists
|
||||
if (self.transition.supported) {
|
||||
self.bind(el, self.transition.type, transitionDone);
|
||||
el.className += " alertify-log-hide";
|
||||
} else {
|
||||
elLog.removeChild(el);
|
||||
if (!elLog.hasChildNodes()) elLog.className += " alertify-logs-hidden";
|
||||
}
|
||||
}
|
||||
};
|
||||
// never close (until click) if wait is set to 0
|
||||
if (wait === 0) return;
|
||||
// set timeout to auto close the log message
|
||||
setTimeout(function () { hideElement(elem); }, timer);
|
||||
},
|
||||
|
||||
/**
|
||||
* Create a dialog box
|
||||
*
|
||||
* @param {String} message The message passed from the callee
|
||||
* @param {String} type Type of dialog to create
|
||||
* @param {Function} fn [Optional] Callback function
|
||||
* @param {String} placeholder [Optional] Default value for prompt input field
|
||||
* @param {String} cssClass [Optional] Class(es) to append to dialog box
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
dialog : function (message, type, fn, placeholder, cssClass) {
|
||||
// set the current active element
|
||||
// this allows the keyboard focus to be resetted
|
||||
// after the dialog box is closed
|
||||
elCallee = document.activeElement;
|
||||
// check to ensure the alertify dialog element
|
||||
// has been successfully created
|
||||
var check = function () {
|
||||
if ((elLog && elLog.scrollTop !== null) && (elCover && elCover.scrollTop !== null)) return;
|
||||
else check();
|
||||
};
|
||||
// error catching
|
||||
if (typeof message !== "string") throw new Error("message must be a string");
|
||||
if (typeof type !== "string") throw new Error("type must be a string");
|
||||
if (typeof fn !== "undefined" && typeof fn !== "function") throw new Error("fn must be a function");
|
||||
// initialize alertify if it hasn't already been done
|
||||
this.init();
|
||||
check();
|
||||
|
||||
queue.push({ type: type, message: message, callback: fn, placeholder: placeholder, cssClass: cssClass });
|
||||
if (!isopen) this.setup();
|
||||
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Extend the log method to create custom methods
|
||||
*
|
||||
* @param {String} type Custom method name
|
||||
*
|
||||
* @return {Function}
|
||||
*/
|
||||
extend : function (type) {
|
||||
if (typeof type !== "string") throw new Error("extend method must have exactly one paramter");
|
||||
return function (message, wait) {
|
||||
this.log(message, type, wait);
|
||||
return this;
|
||||
};
|
||||
},
|
||||
|
||||
/**
|
||||
* Hide the dialog and rest to defaults
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
hide : function () {
|
||||
var transitionDone,
|
||||
self = this;
|
||||
// remove reference from queue
|
||||
queue.splice(0,1);
|
||||
// if items remaining in the queue
|
||||
if (queue.length > 0) this.setup(true);
|
||||
else {
|
||||
isopen = false;
|
||||
// Hide the dialog box after transition
|
||||
// This ensure it doens't block any element from being clicked
|
||||
transitionDone = function (event) {
|
||||
event.stopPropagation();
|
||||
// unbind event so function only gets called once
|
||||
self.unbind(elDialog, self.transition.type, transitionDone);
|
||||
};
|
||||
// whether CSS transition exists
|
||||
if (this.transition.supported) {
|
||||
this.bind(elDialog, this.transition.type, transitionDone);
|
||||
elDialog.className = "alertify alertify-hide alertify-hidden";
|
||||
} else {
|
||||
elDialog.className = "alertify alertify-hide alertify-hidden alertify-isHidden";
|
||||
}
|
||||
elCover.className = "alertify-cover alertify-cover-hidden";
|
||||
// set focus to the last element or body
|
||||
// after the dialog is closed
|
||||
elCallee.focus();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Initialize Alertify
|
||||
* Create the 2 main elements
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
init : function () {
|
||||
// ensure legacy browsers support html5 tags
|
||||
document.createElement("nav");
|
||||
document.createElement("article");
|
||||
document.createElement("section");
|
||||
// cover
|
||||
if ($("alertify-cover") == null) {
|
||||
elCover = document.createElement("div");
|
||||
elCover.setAttribute("id", "alertify-cover");
|
||||
elCover.className = "alertify-cover alertify-cover-hidden";
|
||||
document.body.appendChild(elCover);
|
||||
}
|
||||
// main element
|
||||
if ($("alertify") == null) {
|
||||
isopen = false;
|
||||
queue = [];
|
||||
elDialog = document.createElement("section");
|
||||
elDialog.setAttribute("id", "alertify");
|
||||
elDialog.className = "alertify alertify-hidden";
|
||||
document.body.appendChild(elDialog);
|
||||
}
|
||||
// log element
|
||||
if ($("alertify-logs") == null) {
|
||||
elLog = document.createElement("section");
|
||||
elLog.setAttribute("id", "alertify-logs");
|
||||
elLog.className = "alertify-logs alertify-logs-hidden";
|
||||
document.body.appendChild(elLog);
|
||||
}
|
||||
// set tabindex attribute on body element
|
||||
// this allows script to give it focus
|
||||
// after the dialog is closed
|
||||
document.body.setAttribute("tabindex", "0");
|
||||
// set transition type
|
||||
this.transition = getTransitionEvent();
|
||||
},
|
||||
|
||||
/**
|
||||
* Show a new log message box
|
||||
*
|
||||
* @param {String} message The message passed from the callee
|
||||
* @param {String} type [Optional] Optional type of log message
|
||||
* @param {Number} wait [Optional] Time (in ms) to wait before auto-hiding the log
|
||||
*
|
||||
* @return {Object}
|
||||
*/
|
||||
log : function (message, type, wait) {
|
||||
// check to ensure the alertify dialog element
|
||||
// has been successfully created
|
||||
var check = function () {
|
||||
if (elLog && elLog.scrollTop !== null) return;
|
||||
else check();
|
||||
};
|
||||
// initialize alertify if it hasn't already been done
|
||||
this.init();
|
||||
check();
|
||||
|
||||
elLog.className = "alertify-logs";
|
||||
this.notify(message, type, wait);
|
||||
return this;
|
||||
},
|
||||
|
||||
/**
|
||||
* Add new log message
|
||||
* If a type is passed, a class name "alertify-log-{type}" will get added.
|
||||
* This allows for custom look and feel for various types of notifications.
|
||||
*
|
||||
* @param {String} message The message passed from the callee
|
||||
* @param {String} type [Optional] Type of log message
|
||||
* @param {Number} wait [Optional] Time (in ms) to wait before auto-hiding
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
notify : function (message, type, wait) {
|
||||
var log = document.createElement("article");
|
||||
log.className = "alertify-log" + ((typeof type === "string" && type !== "") ? " alertify-log-" + type : "");
|
||||
log.innerHTML = message;
|
||||
// append child
|
||||
elLog.appendChild(log);
|
||||
// triggers the CSS animation
|
||||
setTimeout(function() { log.className = log.className + " alertify-log-show"; }, 50);
|
||||
this.close(log, wait);
|
||||
},
|
||||
|
||||
/**
|
||||
* Set properties
|
||||
*
|
||||
* @param {Object} args Passing parameters
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
set : function (args) {
|
||||
var k;
|
||||
// error catching
|
||||
if (typeof args !== "object" && args instanceof Array) throw new Error("args must be an object");
|
||||
// set parameters
|
||||
for (k in args) {
|
||||
if (args.hasOwnProperty(k)) {
|
||||
this[k] = args[k];
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Common place to set focus to proper element
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
setFocus : function () {
|
||||
if (input) {
|
||||
input.focus();
|
||||
input.select();
|
||||
}
|
||||
else btnFocus.focus();
|
||||
},
|
||||
|
||||
/**
|
||||
* Initiate all the required pieces for the dialog box
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
setup : function (fromQueue) {
|
||||
var item = queue[0],
|
||||
self = this,
|
||||
transitionDone;
|
||||
|
||||
// dialog is open
|
||||
isopen = true;
|
||||
// Set button focus after transition
|
||||
transitionDone = function (event) {
|
||||
event.stopPropagation();
|
||||
self.setFocus();
|
||||
// unbind event so function only gets called once
|
||||
self.unbind(elDialog, self.transition.type, transitionDone);
|
||||
};
|
||||
// whether CSS transition exists
|
||||
if (this.transition.supported && !fromQueue) {
|
||||
this.bind(elDialog, this.transition.type, transitionDone);
|
||||
}
|
||||
// build the proper dialog HTML
|
||||
elDialog.innerHTML = this.build(item);
|
||||
// assign all the common elements
|
||||
btnReset = $("alertify-resetFocus");
|
||||
btnResetBack = $("alertify-resetFocusBack");
|
||||
btnOK = $("alertify-ok") || undefined;
|
||||
btnCancel = $("alertify-cancel") || undefined;
|
||||
btnFocus = (_alertify.buttonFocus === "cancel") ? btnCancel : ((_alertify.buttonFocus === "none") ? $("alertify-noneFocus") : btnOK),
|
||||
input = $("alertify-text") || undefined;
|
||||
form = $("alertify-form") || undefined;
|
||||
// add placeholder value to the input field
|
||||
if (typeof item.placeholder === "string" && item.placeholder !== "") input.value = item.placeholder;
|
||||
if (fromQueue) this.setFocus();
|
||||
this.addListeners(item.callback);
|
||||
},
|
||||
|
||||
/**
|
||||
* Unbind events to elements
|
||||
*
|
||||
* @param {Object} el HTML Object
|
||||
* @param {Event} event Event to detach to element
|
||||
* @param {Function} fn Callback function
|
||||
*
|
||||
* @return {undefined}
|
||||
*/
|
||||
unbind : function (el, event, fn) {
|
||||
if (typeof el.removeEventListener === "function") {
|
||||
el.removeEventListener(event, fn, false);
|
||||
} else if (el.detachEvent) {
|
||||
el.detachEvent("on" + event, fn);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
return {
|
||||
alert : function (message, fn, cssClass) { _alertify.dialog(message, "alert", fn, "", cssClass); return this; },
|
||||
confirm : function (message, fn, cssClass) { _alertify.dialog(message, "confirm", fn, "", cssClass); return this; },
|
||||
extend : _alertify.extend,
|
||||
init : _alertify.init,
|
||||
log : function (message, type, wait) { _alertify.log(message, type, wait); return this; },
|
||||
prompt : function (message, fn, placeholder, cssClass) { _alertify.dialog(message, "prompt", fn, placeholder, cssClass); return this; },
|
||||
success : function (message, wait) { _alertify.log(message, "success", wait); return this; },
|
||||
error : function (message, wait) { _alertify.log(message, "error", wait); return this; },
|
||||
set : function (args) { _alertify.set(args); },
|
||||
labels : _alertify.labels,
|
||||
debug : _alertify.handleErrors
|
||||
};
|
||||
};
|
||||
|
||||
// AMD and window support
|
||||
if (typeof define === "function") {
|
||||
define([], function () { return new Alertify(); });
|
||||
} else if (typeof global.alertify === "undefined") {
|
||||
global.alertify = new Alertify();
|
||||
}
|
||||
|
||||
}(this));
|
||||
|
||||
|
||||
$('button.success').click(function() {
|
||||
alertify.set({ delay: 1700 });
|
||||
alertify.success("Success notification");
|
||||
});
|
||||
|
||||
$('button.alert').click(function() {
|
||||
alertify.set({ delay: 1700 });
|
||||
alertify.error("Error notification");
|
||||
});
|
@ -1,6 +1,16 @@
|
||||
const menuIconButton = document.querySelector("[data-menu-icon-btn]")
|
||||
const notifBellButton = document.querySelector("[data-notifBell-btn]")
|
||||
const sidebar = document.querySelector("[data-sidebar]")
|
||||
|
||||
menuIconButton.addEventListener("click", () => {
|
||||
sidebar.classList.toggle("open")
|
||||
})
|
||||
|
||||
|
||||
notifBellButton.addEventListener(
|
||||
"click", () => {
|
||||
alertify.set({ delay: 1700 });
|
||||
alertify.success("Success notification");
|
||||
}
|
||||
|
||||
)
|
||||
|
92
public/test_notif.html
Normal file
92
public/test_notif.html
Normal file
@ -0,0 +1,92 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Test Notification Popup</title>
|
||||
<link rel="stylesheet" href="css/styles.css">
|
||||
<link rel="stylesheet" href="css/popupnotif.css">
|
||||
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.1.3/css/bootstrap.min.css'>
|
||||
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.11.2/css/all.min.css'>
|
||||
<link rel='stylesheet' href='https://cdnjs.cloudflare.com/ajax/libs/font-awesome-animation/0.2.1/font-awesome-animation.min.css'>
|
||||
</head>
|
||||
<body>
|
||||
<section>
|
||||
<div class="square_box box_three"></div>
|
||||
<div class="square_box box_four"></div>
|
||||
<div class="container mt-5">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-sm-12">
|
||||
<div class="alert fade alert-simple alert-success alert-dismissible text-left font__family-montserrat font__size-16 font__weight-light brk-library-rendered rendered show">
|
||||
<button type="button" class="close font__size-18" data-dismiss="alert">
|
||||
<span aria-hidden="true"><a>
|
||||
<i class="fa fa-times greencross"></i>
|
||||
</a></span>
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
<i class="start-icon far fa-check-circle faa-tada animated"></i>
|
||||
<strong class="font__weight-semibold">Well done!</strong> You successfullyread this important.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12">
|
||||
<div class="alert fade alert-simple alert-info alert-dismissible text-left font__family-montserrat font__size-16 font__weight-light brk-library-rendered rendered show" role="alert" data-brk-library="component__alert">
|
||||
<button type="button" class="close font__size-18" data-dismiss="alert">
|
||||
<span aria-hidden="true">
|
||||
<i class="fa fa-times blue-cross"></i>
|
||||
</span>
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
<i class="start-icon fa fa-info-circle faa-shake animated"></i>
|
||||
<strong class="font__weight-semibold">Heads up!</strong> This alert needs your attention, but it's not super important.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12">
|
||||
<div class="alert fade alert-simple alert-warning alert-dismissible text-left font__family-montserrat font__size-16 font__weight-light brk-library-rendered rendered show" role="alert" data-brk-library="component__alert">
|
||||
<button type="button" class="close font__size-18" data-dismiss="alert">
|
||||
<span aria-hidden="true">
|
||||
<i class="fa fa-times warning"></i>
|
||||
</span>
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
<i class="start-icon fa fa-exclamation-triangle faa-flash animated"></i>
|
||||
<strong class="font__weight-semibold">Warning!</strong> Better check yourself, you're not looking too good.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12">
|
||||
<div class="alert fade alert-simple alert-danger alert-dismissible text-left font__family-montserrat font__size-16 font__weight-light brk-library-rendered rendered show" role="alert" data-brk-library="component__alert">
|
||||
<button type="button" class="close font__size-18" data-dismiss="alert">
|
||||
<span aria-hidden="true">
|
||||
<i class="fa fa-times danger "></i>
|
||||
</span>
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
<i class="start-icon far fa-times-circle faa-pulse animated"></i>
|
||||
<strong class="font__weight-semibold">Oh snap!</strong> Change a few things up and try submitting again.
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-sm-12">
|
||||
<div class="alert fade alert-simple alert-primary alert-dismissible text-left font__family-montserrat font__size-16 font__weight-light brk-library-rendered rendered show" role="alert" data-brk-library="component__alert">
|
||||
<button type="button" class="close font__size-18" data-dismiss="alert">
|
||||
<span aria-hidden="true"><i class="fa fa-times alertprimary"></i></span>
|
||||
<span class="sr-only">Close</span>
|
||||
</button>
|
||||
<i class="start-icon fa fa-thumbs-up faa-bounce animated"></i>
|
||||
<strong class="font__weight-semibold">Well done!</strong> You successfullyread this important.
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
@ -8,6 +8,22 @@ proc templ_title* (title: string): string = tmpli html"""
|
||||
<h2>$title</h2>
|
||||
"""
|
||||
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
# HTML : Show notification Bell
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
proc show_notification_bell* (nb_notif: int): string = tmpli html"""
|
||||
<div class="notification-box">
|
||||
<span class="notification-count">$nb_notif</span>
|
||||
<div class="notification-bell">
|
||||
<span class="bell-top"></span>
|
||||
<span class="bell-middle"></span>
|
||||
<span class="bell-bottom"></span>
|
||||
<span class="bell-rad"></span>
|
||||
</div>
|
||||
</div>
|
||||
"""
|
||||
|
||||
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
# SVG : Status Joplin green icon
|
||||
# --==--==--==--==--==--==--==--==--==--==-- #
|
||||
@ -49,3 +65,7 @@ proc NEED_joplinSyncro_icon* (): string = tmpli html"""
|
||||
proc InProgress_joplinSyncro_icon* (): string = tmpli html"""
|
||||
|
||||
"""
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -24,8 +24,9 @@
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Document</title>
|
||||
<link rel="stylesheet" href="css/styles.css">
|
||||
<link rel="stylesheet" href="css/progress.css">
|
||||
<link rel="stylesheet" href="css/notif-bell.css">
|
||||
<script src="js/script.js" defer></script>
|
||||
|
||||
</head>
|
||||
|
||||
<body>
|
||||
@ -35,7 +36,14 @@
|
||||
# var icon_menu = Menu_icon()
|
||||
${icon_menu}
|
||||
|
||||
|
||||
|
||||
</button>
|
||||
<button class="notifBell-btn" data-notifBell-btn>
|
||||
# var notifBell = show_notification_bell(1)
|
||||
${notifBell}
|
||||
</button>
|
||||
|
||||
</header>
|
||||
<div class="container">
|
||||
<aside class="sidebar" data-sidebar>
|
||||
@ -161,12 +169,13 @@
|
||||
</a>
|
||||
</li>
|
||||
<li class="sidebar-list-item ">
|
||||
<a href="#" class="sidebar-link">
|
||||
|
||||
# if columnLeftInfo.j_status:
|
||||
<a href="/secret?msg=startStopJoplin" class="sidebar-link">
|
||||
# var status_green = status_joplin_green()
|
||||
${status_green}
|
||||
# else:
|
||||
<a href="/secret?msg=startStopJoplin" class="sidebar-link">
|
||||
# var status_red = status_joplin_red()
|
||||
${status_red}
|
||||
# end if
|
||||
@ -256,6 +265,13 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script
|
||||
src="https://code.jquery.com/jquery-2.2.4.min.js"
|
||||
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
|
||||
crossorigin="anonymous">
|
||||
</script>
|
||||
<script src='https://cdnjs.cloudflare.com/ajax/libs/foundation/5.5.0/js/foundation.min.js'></script>
|
||||
<script src="js/alertify_notif.js" defer></script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
Loading…
Reference in New Issue
Block a user