avancé de dev
3
venv/Lib/site-packages/baton/static/baton/app/.babelrc
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"presets": ["@babel/preset-env"]
|
||||
}
|
@@ -0,0 +1,2 @@
|
||||
node_modules/**
|
||||
dist/**
|
24
venv/Lib/site-packages/baton/static/baton/app/.eslintrc
Normal file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
"parser" : "babel-eslint",
|
||||
"extends" : [
|
||||
"standard"
|
||||
],
|
||||
"plugins" : [
|
||||
"flow-vars"
|
||||
],
|
||||
"env" : {
|
||||
"browser" : true
|
||||
},
|
||||
"globals" : {
|
||||
"Baton": {},
|
||||
"jQuery": {},
|
||||
"$": {},
|
||||
},
|
||||
"rules": {
|
||||
"semi" : [2, "never"],
|
||||
"max-len": [2, 120, 2],
|
||||
"comma-dangle": [2, "only-multiline"],
|
||||
"flow-vars/define-flow-type": 1,
|
||||
"flow-vars/use-flow-type": 1
|
||||
}
|
||||
}
|
13
venv/Lib/site-packages/baton/static/baton/app/.tern-project
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"libs": [
|
||||
"browser",
|
||||
"ecma5",
|
||||
"ecma6"
|
||||
],
|
||||
"plugins": {
|
||||
"node": { },
|
||||
"modules": { },
|
||||
"complete_strings": {},
|
||||
"es_modules": {}
|
||||
}
|
||||
}
|
BIN
venv/Lib/site-packages/baton/static/baton/app/dist/07c3313b24f7b1ca85ee.ttf
vendored
Normal file
5034
venv/Lib/site-packages/baton/static/baton/app/dist/13de59f1a36b6cb4bca0.svg
vendored
Normal file
After Width: | Height: | Size: 898 KiB |
3
venv/Lib/site-packages/baton/static/baton/app/dist/1d5b13020cf1d7efde67.svg
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="15" height="15" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="#555555" d="M1216 832q0-185-131.5-316.5t-316.5-131.5-316.5 131.5-131.5 316.5 131.5 316.5 316.5 131.5 316.5-131.5 131.5-316.5zm512 832q0 52-38 90t-90 38q-54 0-90-38l-343-342q-179 124-399 124-143 0-273.5-55.5t-225-150-150-225-55.5-273.5 55.5-273.5 150-225 225-150 273.5-55.5 273.5 55.5 225 150 150 225 55.5 273.5q0 220-124 399l343 343q37 37 37 90z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 458 B |
3717
venv/Lib/site-packages/baton/static/baton/app/dist/216edb96b562c79adc09.svg
vendored
Normal file
After Width: | Height: | Size: 730 KiB |
BIN
venv/Lib/site-packages/baton/static/baton/app/dist/28b74339da09e9f659af.ttf
vendored
Normal file
BIN
venv/Lib/site-packages/baton/static/baton/app/dist/329a95a9172fdb2cccb4.woff
vendored
Normal file
34
venv/Lib/site-packages/baton/static/baton/app/dist/62397fb22f9cf321cfcd.svg
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<svg width="16" height="192" viewBox="0 0 1792 21504" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<g id="up">
|
||||
<path d="M1412 895q0-27-18-45l-362-362-91-91q-18-18-45-18t-45 18l-91 91-362 362q-18 18-18 45t18 45l91 91q18 18 45 18t45-18l189-189v502q0 26 19 45t45 19h128q26 0 45-19t19-45v-502l189 189q19 19 45 19t45-19l91-91q18-18 18-45zm252 1q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
|
||||
</g>
|
||||
<g id="down">
|
||||
<path d="M1412 897q0-27-18-45l-91-91q-18-18-45-18t-45 18l-189 189v-502q0-26-19-45t-45-19h-128q-26 0-45 19t-19 45v502l-189-189q-19-19-45-19t-45 19l-91 91q-18 18-18 45t18 45l362 362 91 91q18 18 45 18t45-18l91-91 362-362q18-18 18-45zm252-1q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
|
||||
</g>
|
||||
<g id="left">
|
||||
<path d="M1408 960v-128q0-26-19-45t-45-19h-502l189-189q19-19 19-45t-19-45l-91-91q-18-18-45-18t-45 18l-362 362-91 91q-18 18-18 45t18 45l91 91 362 362q18 18 45 18t45-18l91-91q18-18 18-45t-18-45l-189-189h502q26 0 45-19t19-45zm256-64q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
|
||||
</g>
|
||||
<g id="right">
|
||||
<path d="M1413 896q0-27-18-45l-91-91-362-362q-18-18-45-18t-45 18l-91 91q-18 18-18 45t18 45l189 189h-502q-26 0-45 19t-19 45v128q0 26 19 45t45 19h502l-189 189q-19 19-19 45t19 45l91 91q18 18 45 18t45-18l362-362 91-91q18-18 18-45zm251 0q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
|
||||
</g>
|
||||
<g id="clearall">
|
||||
<path transform="translate(336, 336) scale(0.75)" d="M1037 1395l102-102q19-19 19-45t-19-45l-307-307 307-307q19-19 19-45t-19-45l-102-102q-19-19-45-19t-45 19l-454 454q-19 19-19 45t19 45l454 454q19 19 45 19t45-19zm627-499q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
|
||||
</g>
|
||||
<g id="chooseall">
|
||||
<path transform="translate(336, 336) scale(0.75)" d="M845 1395l454-454q19-19 19-45t-19-45l-454-454q-19-19-45-19t-45 19l-102 102q-19 19-19 45t19 45l307 307-307 307q-19 19-19 45t19 45l102 102q19 19 45 19t45-19zm819-499q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
|
||||
</g>
|
||||
</defs>
|
||||
<use xlink:href="#up" x="0" y="0" fill="#666666" />
|
||||
<use xlink:href="#up" x="0" y="1792" fill="#447e9b" />
|
||||
<use xlink:href="#down" x="0" y="3584" fill="#666666" />
|
||||
<use xlink:href="#down" x="0" y="5376" fill="#447e9b" />
|
||||
<use xlink:href="#left" x="0" y="7168" fill="#666666" />
|
||||
<use xlink:href="#left" x="0" y="8960" fill="#447e9b" />
|
||||
<use xlink:href="#right" x="0" y="10752" fill="#666666" />
|
||||
<use xlink:href="#right" x="0" y="12544" fill="#447e9b" />
|
||||
<use xlink:href="#clearall" x="0" y="14336" fill="#666666" />
|
||||
<use xlink:href="#clearall" x="0" y="16128" fill="#447e9b" />
|
||||
<use xlink:href="#chooseall" x="0" y="17920" fill="#666666" />
|
||||
<use xlink:href="#chooseall" x="0" y="19712" fill="#447e9b" />
|
||||
</svg>
|
After Width: | Height: | Size: 3.2 KiB |
19
venv/Lib/site-packages/baton/static/baton/app/dist/7fd18804f2abd547c565.svg
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
<svg width="14" height="84" viewBox="0 0 1792 10752" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<g id="sort">
|
||||
<path d="M1408 1088q0 26-19 45l-448 448q-19 19-45 19t-45-19l-448-448q-19-19-19-45t19-45 45-19h896q26 0 45 19t19 45zm0-384q0 26-19 45t-45 19h-896q-26 0-45-19t-19-45 19-45l448-448q19-19 45-19t45 19l448 448q19 19 19 45z"/>
|
||||
</g>
|
||||
<g id="ascending">
|
||||
<path d="M1408 1216q0 26-19 45t-45 19h-896q-26 0-45-19t-19-45 19-45l448-448q19-19 45-19t45 19l448 448q19 19 19 45z"/>
|
||||
</g>
|
||||
<g id="descending">
|
||||
<path d="M1408 704q0 26-19 45l-448 448q-19 19-45 19t-45-19l-448-448q-19-19-19-45t19-45 45-19h896q26 0 45 19t19 45z"/>
|
||||
</g>
|
||||
</defs>
|
||||
<use xlink:href="#sort" x="0" y="0" fill="#999999" />
|
||||
<use xlink:href="#sort" x="0" y="1792" fill="#447e9b" />
|
||||
<use xlink:href="#ascending" x="0" y="3584" fill="#999999" />
|
||||
<use xlink:href="#ascending" x="0" y="5376" fill="#447e9b" />
|
||||
<use xlink:href="#descending" x="0" y="7168" fill="#999999" />
|
||||
<use xlink:href="#descending" x="0" y="8960" fill="#447e9b" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
14
venv/Lib/site-packages/baton/static/baton/app/dist/820a83e6dbb5ee491646.svg
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
<svg width="15" height="60" viewBox="0 0 1792 7168" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<g id="previous">
|
||||
<path d="M1037 1395l102-102q19-19 19-45t-19-45l-307-307 307-307q19-19 19-45t-19-45l-102-102q-19-19-45-19t-45 19l-454 454q-19 19-19 45t19 45l454 454q19 19 45 19t45-19zm627-499q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
|
||||
</g>
|
||||
<g id="next">
|
||||
<path d="M845 1395l454-454q19-19 19-45t-19-45l-454-454q-19-19-45-19t-45 19l-102 102q-19 19-19 45t19 45l307 307-307 307q-19 19-19 45t19 45l102 102q19 19 45 19t45-19zm819-499q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
|
||||
</g>
|
||||
</defs>
|
||||
<use xlink:href="#previous" x="0" y="0" fill="#333333" />
|
||||
<use xlink:href="#previous" x="0" y="1792" fill="#000000" />
|
||||
<use xlink:href="#next" x="0" y="3584" fill="#333333" />
|
||||
<use xlink:href="#next" x="0" y="5376" fill="#000000" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
BIN
venv/Lib/site-packages/baton/static/baton/app/dist/88591a33d733b344a8e3.ttf
vendored
Normal file
BIN
venv/Lib/site-packages/baton/static/baton/app/dist/89a52ae1d02b86d61439.eot
vendored
Normal file
BIN
venv/Lib/site-packages/baton/static/baton/app/dist/9e138496e8f1719c6ebf.ttf
vendored
Normal file
BIN
venv/Lib/site-packages/baton/static/baton/app/dist/ada6e6df937f7e5e8b79.woff2
vendored
Normal file
BIN
venv/Lib/site-packages/baton/static/baton/app/dist/b128f9e98de1bbea51b7.ttf
vendored
Normal file
2
venv/Lib/site-packages/baton/static/baton/app/dist/baton.min.js
vendored
Normal file
30
venv/Lib/site-packages/baton/static/baton/app/dist/baton.min.js.LICENSE.txt
vendored
Normal file
@@ -0,0 +1,30 @@
|
||||
/*!
|
||||
* Bootstrap v5.0.1 (https://getbootstrap.com/)
|
||||
* Copyright 2011-2021 The Bootstrap Authors (https://github.com/twbs/bootstrap/graphs/contributors)
|
||||
* Licensed under MIT (https://github.com/twbs/bootstrap/blob/main/LICENSE)
|
||||
*/
|
||||
|
||||
/*!
|
||||
* Sizzle CSS Selector Engine v2.3.6
|
||||
* https://sizzlejs.com/
|
||||
*
|
||||
* Copyright JS Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* https://js.foundation/
|
||||
*
|
||||
* Date: 2021-02-16
|
||||
*/
|
||||
|
||||
/*!
|
||||
* jQuery JavaScript Library v3.6.0
|
||||
* https://jquery.com/
|
||||
*
|
||||
* Includes Sizzle.js
|
||||
* https://sizzlejs.com/
|
||||
*
|
||||
* Copyright OpenJS Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* https://jquery.org/license
|
||||
*
|
||||
* Date: 2021-03-02T17:08Z
|
||||
*/
|
BIN
venv/Lib/site-packages/baton/static/baton/app/dist/c1210e5ebe4344da5083.woff2
vendored
Normal file
BIN
venv/Lib/site-packages/baton/static/baton/app/dist/c6ec080084769a6d8a34.woff
vendored
Normal file
3
venv/Lib/site-packages/baton/static/baton/app/dist/ce6c392454ee4567292d.svg
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
<svg width="13" height="13" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="#666666" d="M1024 1376v-192q0-14-9-23t-23-9h-192q-14 0-23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23-9t9-23zm256-672q0-88-55.5-163t-138.5-116-170-41q-243 0-371 213-15 24 8 42l132 100q7 6 19 6 16 0 25-12 53-68 86-92 34-24 86-24 48 0 85.5 26t37.5 59q0 38-20 61t-68 45q-63 28-115.5 86.5t-52.5 125.5v36q0 14 9 23t23 9h192q14 0 23-9t9-23q0-19 21.5-49.5t54.5-49.5q32-18 49-28.5t46-35 44.5-48 28-60.5 12.5-81zm384 192q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 655 B |
BIN
venv/Lib/site-packages/baton/static/baton/app/dist/efbd5d20e407bbf85f2b.eot
vendored
Normal file
8897
venv/Lib/site-packages/baton/static/baton/app/package-lock.json
generated
Normal file
54
venv/Lib/site-packages/baton/static/baton/app/package.json
Normal file
@@ -0,0 +1,54 @@
|
||||
{
|
||||
"name": "baton",
|
||||
"version": "2.2.3",
|
||||
"description": "Django Baton App",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"stats": "npx webpack --config ./webpack.prod.js --json > stats.json",
|
||||
"compile": "BATON_REVISION=$(git rev-parse HEAD) npx webpack --config ./webpack.prod.js",
|
||||
"watch": "npx webpack --watch --config ./webpack.dev.js",
|
||||
"dev": "BATON_REVISION=$(git rev-parse HEAD) webpack serve --host 0.0.0.0 --progress --config ./webpack.dev.js",
|
||||
"lint": "./node_modules/eslint/bin/eslint.js ."
|
||||
},
|
||||
"author": "abidibo",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.14.3",
|
||||
"@babel/preset-env": "^7.14.4",
|
||||
"@babel/register": "^7.13.16",
|
||||
"@fortawesome/fontawesome-free": "^5.15.3",
|
||||
"autoprefixer": "^10.2.6",
|
||||
"babel-cli": "^6.26.0",
|
||||
"babel-loader": "^8.2.2",
|
||||
"babel-register": "^6.26.0",
|
||||
"bootstrap": "^5.0.1",
|
||||
"css-loader": "^5.2.6",
|
||||
"file-loader": "^6.2.0",
|
||||
"ini": "^2.0.0",
|
||||
"jquery": "^3.6.0",
|
||||
"js-event-dispatcher": "^0.1.0",
|
||||
"loader": "^2.1.1",
|
||||
"lodash": "^4.17.21",
|
||||
"mini-svg-data-uri": "^1.3.3",
|
||||
"node-sass": "^6.0.0",
|
||||
"postcss-loader": "^5.3.0",
|
||||
"sass": "^1.34.0",
|
||||
"sass-loader": "^11.1.1",
|
||||
"style-loader": "^2.0.0",
|
||||
"url-loader": "^4.1.1",
|
||||
"webpack": "^5.38.1",
|
||||
"webpack-dev-server": "^3.11.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-eslint": "^10.1.0",
|
||||
"eslint": "^7.27.0",
|
||||
"eslint-config-standard": "^16.0.3",
|
||||
"eslint-plugin-babel": "^5.3.1",
|
||||
"eslint-plugin-flow-vars": "^0.5.0",
|
||||
"eslint-plugin-promise": "^5.1.0",
|
||||
"eslint-plugin-standard": "^5.0.0",
|
||||
"webpack-bundle-analyzer": "^4.4.2",
|
||||
"webpack-cli": "^4.7.0",
|
||||
"webpack-merge": "^5.7.3"
|
||||
}
|
||||
}
|
@@ -0,0 +1,5 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require('autoprefixer')
|
||||
]
|
||||
}
|
6
venv/Lib/site-packages/baton/static/baton/app/src/.vimrc
Normal file
@@ -0,0 +1,6 @@
|
||||
set smarttab
|
||||
set shiftwidth=2
|
||||
set softtabstop=2
|
||||
set tabstop=2
|
||||
set expandtab
|
||||
let syntastic_scss_checkers = ['scss_lint']
|
@@ -0,0 +1,14 @@
|
||||
import $ from 'jquery'
|
||||
|
||||
let ActionResult = {
|
||||
/**
|
||||
* Menu component
|
||||
*
|
||||
* Adds a sidebar menu to the document
|
||||
*/
|
||||
init: function () {
|
||||
$('body').addClass('actionresult')
|
||||
}
|
||||
}
|
||||
|
||||
export default ActionResult
|
@@ -0,0 +1,15 @@
|
||||
import $ from 'jquery'
|
||||
|
||||
let AdminDocs = {
|
||||
/**
|
||||
* Footer component
|
||||
*
|
||||
* Moves the footer inside the main external container
|
||||
*/
|
||||
init: function (opts) {
|
||||
let container = $('<div />', {'class': 'admindocs-body'})
|
||||
container.append($('#content > *:not(h1):not(.breadcrumbs)')).appendTo($('#content'))
|
||||
}
|
||||
}
|
||||
|
||||
export default AdminDocs
|
@@ -0,0 +1,214 @@
|
||||
import Translator from './i18n'
|
||||
|
||||
class Analytics {
|
||||
constructor (gapi, token, viewId, domIds) {
|
||||
this.gapi = gapi
|
||||
this.token = token
|
||||
this.domIds = domIds
|
||||
this.viewId = viewId
|
||||
this.t = new Translator($('html').attr('lang'))
|
||||
}
|
||||
|
||||
init (timedelta) {
|
||||
let self = this
|
||||
this.gapi.analytics.ready(function () { self.run(timedelta) })
|
||||
}
|
||||
|
||||
run (timedelta) {
|
||||
let self = this
|
||||
let gapi = this.gapi
|
||||
|
||||
let spinner = $('<div />').css({
|
||||
textAlign: 'center',
|
||||
padding: '3rem 0',
|
||||
color: '#aaa',
|
||||
}).append($('<i />', {'class': 'fa fa-spinner fa-spin fa-3x fa-fw'}))
|
||||
|
||||
for (let prop in this.domIds) {
|
||||
if (['traffic', 'popular', 'browsers', 'acquisition', 'audience', 'social'].indexOf(prop) !== -1) {
|
||||
$('#' + this.domIds[prop]).append(spinner.clone())
|
||||
}
|
||||
}
|
||||
|
||||
let errorCb = containerId => () => {
|
||||
$('#' + containerId).empty()
|
||||
|
||||
let message = $('<div />').css({
|
||||
textAlign: 'center',
|
||||
padding: '3rem 0',
|
||||
color: '#aaa',
|
||||
}).text(this.t.get('retrieveDataError'))
|
||||
|
||||
$('#' + containerId).append(message)
|
||||
}
|
||||
|
||||
gapi.analytics.ready(function () {
|
||||
/**
|
||||
* Authorize the user with an access token obtained server side.
|
||||
*/
|
||||
gapi.analytics.auth.authorize({
|
||||
'serverAuth': {
|
||||
'access_token': self.token
|
||||
}
|
||||
})
|
||||
/**
|
||||
* Create a new ViewSelector2 instance to be rendered inside of an
|
||||
* element with the id "view-selector-container".
|
||||
*/
|
||||
var viewSelector = new gapi.analytics.ViewSelector({
|
||||
container: self.domIds.viewSelector,
|
||||
})
|
||||
viewSelector.execute()
|
||||
|
||||
let baseQuery = {
|
||||
'ids': 'ga:' + self.viewId,
|
||||
'start-date': timedelta,
|
||||
'end-date': 'yesterday'
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new DataChart instance showing sessions over the past 15 days.
|
||||
*/
|
||||
let dataChart1 = new gapi.analytics.googleCharts.DataChart({
|
||||
query: {
|
||||
...baseQuery,
|
||||
'metrics': 'ga:sessions,ga:users',
|
||||
'dimensions': 'ga:date'
|
||||
},
|
||||
chart: {
|
||||
'container': self.domIds.traffic,
|
||||
'type': 'LINE',
|
||||
'options': {
|
||||
'width': '100%'
|
||||
}
|
||||
}
|
||||
})
|
||||
let trafficTimeout = setTimeout(errorCb(self.domIds.traffic), 20000)
|
||||
dataChart1.on('error', errorCb(self.domIds.traffic))
|
||||
dataChart1.on('success', () => clearTimeout(trafficTimeout))
|
||||
dataChart1.execute()
|
||||
/**
|
||||
* Creates a new DataChart instance showing top 5 most popular pages
|
||||
*/
|
||||
var dataChart2 = new gapi.analytics.googleCharts.DataChart({
|
||||
query: {
|
||||
...baseQuery,
|
||||
'metrics': 'ga:pageviews',
|
||||
'dimensions': 'ga:pagePath',
|
||||
'sort': '-ga:pageviews',
|
||||
'max-results': 7
|
||||
},
|
||||
chart: {
|
||||
'container': self.domIds.popular,
|
||||
'type': 'PIE',
|
||||
'options': {
|
||||
'width': '100%',
|
||||
'pieHole': 4 / 9,
|
||||
}
|
||||
}
|
||||
})
|
||||
let popularTimeout = setTimeout(errorCb(self.domIds.popular), 20000)
|
||||
dataChart2.on('error', errorCb(self.domIds.popular))
|
||||
dataChart2.on('success', () => clearTimeout(popularTimeout))
|
||||
dataChart2.execute()
|
||||
/**
|
||||
* Creates a new DataChart instance showing top borwsers
|
||||
*/
|
||||
var dataChart3 = new gapi.analytics.googleCharts.DataChart({
|
||||
query: {
|
||||
...baseQuery,
|
||||
'metrics': 'ga:sessions',
|
||||
'dimensions': 'ga:browser',
|
||||
'sort': '-ga:sessions',
|
||||
'max-results': 7
|
||||
},
|
||||
chart: {
|
||||
'container': self.domIds.browsers,
|
||||
'type': 'PIE',
|
||||
'options': {
|
||||
'width': '100%',
|
||||
'pieHole': 4 / 9,
|
||||
}
|
||||
}
|
||||
})
|
||||
let browsersTimeout = setTimeout(errorCb(self.domIds.browsers), 20000)
|
||||
dataChart3.on('error', errorCb(self.domIds.browsers))
|
||||
dataChart3.on('success', () => clearTimeout(browsersTimeout))
|
||||
dataChart3.execute()
|
||||
/**
|
||||
* Creates a new DataChart instance showing top referral
|
||||
*/
|
||||
var dataChart4 = new gapi.analytics.googleCharts.DataChart({
|
||||
query: {
|
||||
...baseQuery,
|
||||
'metrics': 'ga:sessions',
|
||||
'dimensions': 'ga:source',
|
||||
'sort': '-ga:sessions',
|
||||
'max-results': 7
|
||||
},
|
||||
chart: {
|
||||
'container': self.domIds.acquisition,
|
||||
'type': 'PIE',
|
||||
'options': {
|
||||
'width': '100%',
|
||||
'pieHole': 4 / 9,
|
||||
}
|
||||
}
|
||||
})
|
||||
let acquisitionTimeout = setTimeout(errorCb(self.domIds.acquisition), 20000)
|
||||
dataChart4.on('error', errorCb(self.domIds.acquisition))
|
||||
dataChart4.on('success', () => clearTimeout(acquisitionTimeout))
|
||||
dataChart4.execute()
|
||||
/**
|
||||
* Creates a new DataChart instance showing top visitors continents
|
||||
*/
|
||||
var dataChart5 = new gapi.analytics.googleCharts.DataChart({
|
||||
query: {
|
||||
...baseQuery,
|
||||
'metrics': 'ga:sessions',
|
||||
'dimensions': 'ga:country',
|
||||
'sort': '-ga:sessions',
|
||||
'max-results': 7
|
||||
},
|
||||
chart: {
|
||||
'container': self.domIds.audience,
|
||||
'type': 'PIE',
|
||||
'options': {
|
||||
'width': '100%',
|
||||
'pieHole': 4 / 9,
|
||||
}
|
||||
}
|
||||
})
|
||||
let audienceTimeout = setTimeout(errorCb(self.domIds.audience), 20000)
|
||||
dataChart5.on('error', errorCb(self.domIds.audience))
|
||||
dataChart5.on('success', () => clearTimeout(audienceTimeout))
|
||||
dataChart5.execute()
|
||||
/**
|
||||
* Creates a new DataChart instance showing social interactions over the past 15 days.
|
||||
*/
|
||||
var dataChart6 = new gapi.analytics.googleCharts.DataChart({
|
||||
query: {
|
||||
...baseQuery,
|
||||
'metrics': 'ga:socialInteractions',
|
||||
'dimensions': 'ga:socialInteractionNetwork',
|
||||
'sort': '-ga:socialInteractions',
|
||||
'max-results': 7
|
||||
},
|
||||
chart: {
|
||||
'container': self.domIds.social,
|
||||
'type': 'PIE',
|
||||
'options': {
|
||||
'width': '100%',
|
||||
'pieHole': 4 / 9,
|
||||
}
|
||||
}
|
||||
})
|
||||
let socialTimeout = setTimeout(errorCb(self.domIds.social), 20000)
|
||||
dataChart6.on('error', errorCb(self.domIds.social))
|
||||
dataChart6.on('success', () => clearTimeout(socialTimeout))
|
||||
dataChart6.execute()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default Analytics
|
@@ -0,0 +1,7 @@
|
||||
export default {
|
||||
sm: 576,
|
||||
md: 768,
|
||||
lg: 992,
|
||||
xl: 1200,
|
||||
xxl: 1400
|
||||
}
|
@@ -0,0 +1,193 @@
|
||||
import $ from 'jquery'
|
||||
import Translator from './i18n'
|
||||
|
||||
let ChangeForm = {
|
||||
/**
|
||||
* ChangeForm component
|
||||
*
|
||||
* Alert unsaved changes stuff
|
||||
* Display loading spinner if multipart
|
||||
*/
|
||||
init: function (opts) {
|
||||
var self = this
|
||||
this.form = $('#content-main form')
|
||||
if (opts.confirmUnsavedChanges) {
|
||||
this.formSubmitting = false
|
||||
this.t = new Translator($('html').attr('lang'))
|
||||
// wait for django SelectFilter to do its job
|
||||
setTimeout(function () {
|
||||
self.initData = self.serializeData()
|
||||
self.activate()
|
||||
}, 500)
|
||||
}
|
||||
if (opts.showMultipartUploading) {
|
||||
this.spinner()
|
||||
}
|
||||
self.fixNewlines()
|
||||
setTimeout(function () {
|
||||
self.fixNewlines() // js inserted ones
|
||||
}, 50)
|
||||
this.fixWrappedFields()
|
||||
if (opts.enableImagesPreview) {
|
||||
this.lazyLoadImages()
|
||||
}
|
||||
this.activateEntryCollapsing()
|
||||
this.changeFieldsetCollapseStyle()
|
||||
this.fixExpandFirstErrorCollapsing()
|
||||
this.initTemplates()
|
||||
},
|
||||
activate: function () {
|
||||
this.form.on('submit', () => (this.formSubmitting = true))
|
||||
$(window).on('beforeunload', this.alertDirty.bind(this))
|
||||
},
|
||||
serializeData: function () {
|
||||
// form serialize does not detect filter_horizontal controllers because
|
||||
// in that case options are not selected, just added to the list of options,
|
||||
// and jquery form serialize only serializes values which are set!
|
||||
let data = this.form.serialize()
|
||||
$('select.filtered[multiple][id$=_to]').each(function (k, select) {
|
||||
let optionsValues = []
|
||||
$(select).children('option').each(function (kk, option) {
|
||||
optionsValues.push($(option).attr('value'))
|
||||
})
|
||||
data += `&${jQuery(select).attr('name')}=${optionsValues.sort().join(',')}`
|
||||
})
|
||||
return data
|
||||
},
|
||||
isDirty: function () {
|
||||
return this.serializeData() !== this.initData
|
||||
},
|
||||
alertDirty: function (e) {
|
||||
if (this.formSubmitting || !this.isDirty()) {
|
||||
return undefined
|
||||
}
|
||||
let confirmationMessage = this.t.get('unsavedChangesAlert');
|
||||
(e || window.event).returnValue = confirmationMessage // Gecko + IE
|
||||
return confirmationMessage // Gecko + Webkit, Safari, Chrome etc.
|
||||
},
|
||||
spinner: function () {
|
||||
if (this.form.attr('enctype') === 'multipart/form-data') {
|
||||
this.form.on('submit', () => this.showSpinner())
|
||||
}
|
||||
},
|
||||
showSpinner: function () {
|
||||
let run = false
|
||||
let inputFiles = $('input[type=file]')
|
||||
inputFiles.each(function (index, input) {
|
||||
if (input.files.length !== 0) {
|
||||
run = true
|
||||
}
|
||||
})
|
||||
if (run) {
|
||||
let overlay = $('<div />', {'class': 'spinner-overlay'}).appendTo(document.body)
|
||||
let spinner = $('<i />', {'class': 'fa fa-spinner fa-spin fa-3x fa-fw'})
|
||||
$('<div />').append(
|
||||
$('<p />').text(this.t.get('uploading')),
|
||||
spinner
|
||||
).appendTo(overlay)
|
||||
}
|
||||
},
|
||||
fixWrappedFields: function () {
|
||||
this.form.find('.form-row').each(function (index, row) {
|
||||
var fieldBoxes = $(row).children('.fieldBox')
|
||||
fieldBoxes.each(function (index, fbox) {
|
||||
if ($(fbox).hasClass('errors')) {
|
||||
$(row).addClass('errors')
|
||||
}
|
||||
})
|
||||
fieldBoxes.wrapAll('<div class="wrapped-fields-container" />')
|
||||
if (fieldBoxes.length) {
|
||||
$(row).addClass('with-wrapped-fields')
|
||||
}
|
||||
})
|
||||
// this.form.find('.wrapped-fields-container > .fieldBox:first-child').children().unwrap()
|
||||
},
|
||||
fixNewlines: function () {
|
||||
$('.form-row br').replaceWith('<span class="newline"></span>')
|
||||
},
|
||||
lazyLoadImages: function () {
|
||||
$('.file-upload').each(function (index, p) {
|
||||
let cur = $(p).find('a')
|
||||
if (cur.length) {
|
||||
let url = cur.attr('href')
|
||||
let ext = url.split('?')[0].split('.').pop()
|
||||
if (['jpg', 'jpeg', 'png', 'bmp', 'svg', 'gif', 'tif', 'webp'].indexOf(ext) !== -1) {
|
||||
let spinner = $('<i />', {'class': 'fa fa-spinner fa-spin fa-2x fa-fw'}).css('color', '#aaa')
|
||||
let preview = $('<div />', {'class': 'py-2'}).append(spinner)
|
||||
$(p).prepend(preview)
|
||||
let image = new Image()
|
||||
image.onload = function () {
|
||||
spinner.replaceWith($(image).addClass('baton-image-preview'))
|
||||
}
|
||||
image.onerror = function () {
|
||||
preview.remove()
|
||||
}
|
||||
image.src = url
|
||||
}
|
||||
}
|
||||
})
|
||||
},
|
||||
activateEntryCollapsing: function () {
|
||||
$('.collapse-entry h3')
|
||||
.addClass('entry-collapsed entry-collapse-full-toggler')
|
||||
.append('<span />') // just to have the toggler right aligned
|
||||
.append('<span class="entry-collapse-toggler" />')
|
||||
$('.collapse-entry')
|
||||
.click(function (e) {
|
||||
let target = $(e.target)
|
||||
if (target.hasClass('entry-collapse-full-toggler')) {
|
||||
target.toggleClass('entry-collapsed')
|
||||
} else if (target.parent('.entry-collapse-full-toggler').length > 0) {
|
||||
target.parent('.entry-collapse-full-toggler').toggleClass('entry-collapsed')
|
||||
}
|
||||
})
|
||||
$('.form-row.errors').each(function (index, el) {
|
||||
if ($(el).parent('fieldset').prev('h3.entry-collapsed')) {
|
||||
$(el).parent('fieldset').prev('h3.entry-collapsed').removeClass('entry-collapsed')
|
||||
}
|
||||
})
|
||||
},
|
||||
fixExpandFirstErrorCollapsing: function () {
|
||||
$('.expand-first').each(function (index, el) {
|
||||
if ($(el).find('.inline-related[id$=0] .form-row.errors').length) {
|
||||
// inverse logic
|
||||
$(el).find('.inline-related[id$=0] .form-row.errors').parent('fieldset').prev('h3').addClass('entry-collapsed')
|
||||
}
|
||||
})
|
||||
},
|
||||
changeFieldsetCollapseStyle: function () {
|
||||
$(window).on('load', function () {
|
||||
$('fieldset.collapse > h2').each(function (index, title) {
|
||||
let text = $(title).text().replace(/\(.*\)/, '')
|
||||
setTimeout(function () {
|
||||
$(title).html(text).on('click', function () {
|
||||
$(this).parent('.collapse').toggleClass('collapsed')
|
||||
})
|
||||
}, 100)
|
||||
})
|
||||
})
|
||||
},
|
||||
initTemplates: function () {
|
||||
const positionMap = {
|
||||
above: 'before',
|
||||
below: 'after',
|
||||
top: 'prepend',
|
||||
bottom: 'append',
|
||||
right: 'after'
|
||||
}
|
||||
$('template').each(function (index, template) {
|
||||
let field = $(template).attr('id').replace('template-', '')
|
||||
let position = positionMap[$(template).attr('data-position')]
|
||||
if (position !== undefined) {
|
||||
let el = $(template).attr('data-position') === 'right'
|
||||
? $('.form-row.field-' + field + ' #id_' + field)
|
||||
: $('.form-row.field-' + field)
|
||||
el[position]($(template).html())
|
||||
} else {
|
||||
console.error('Baton: wrong form include position detected')
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default ChangeForm
|
@@ -0,0 +1,203 @@
|
||||
import $ from 'jquery'
|
||||
import Translator from './i18n'
|
||||
import Modal from './Modal'
|
||||
import breakpoints from './Breakpoints'
|
||||
|
||||
let ChangeList = {
|
||||
/**
|
||||
* ChangeList component
|
||||
*
|
||||
* Filtering stuff
|
||||
*/
|
||||
init: function (opts) {
|
||||
this._filtersDiv = $('#changelist-filter')
|
||||
this.t = new Translator($('html').attr('lang'))
|
||||
this.filtersForm = opts.changelistFiltersForm
|
||||
this.filtersInModal = opts.changelistFiltersInModal
|
||||
this.filtersAlwaysOpen = opts.changelistFiltersAlwaysOpen
|
||||
this.initTemplates()
|
||||
if (this._filtersDiv.length) {
|
||||
var self = this
|
||||
setTimeout(function () {
|
||||
self.activate()
|
||||
}, 200) // select2
|
||||
this.fixRangeFilter()
|
||||
}
|
||||
},
|
||||
activate: function () {
|
||||
if ($('.changelist-form-container').length) {
|
||||
// django >= 3.1
|
||||
$('#changelist-filter').appendTo($('.changelist-form-container'))
|
||||
}
|
||||
let isModal = false
|
||||
if (this.filtersAlwaysOpen) {
|
||||
$(document.body).addClass(
|
||||
'changelist-filter-active changelist-filter-always-open'
|
||||
)
|
||||
} else {
|
||||
// filters active?
|
||||
let _activeFilters = /__[^=]+=/.test(location.search)
|
||||
// actions ?
|
||||
let _activeActions = $('#changelist-form > .actions').length !== 0
|
||||
let _changelistForm = $('#changelist-form')
|
||||
let _filtersToggler = $('<a />', {
|
||||
class:
|
||||
'changelist-filter-toggler' +
|
||||
(_activeFilters ? ' active' : '') +
|
||||
(_activeActions ? ' with-actions' : '')
|
||||
}).html(
|
||||
'<i class="fa fa-filter"></i> <span>' + this.t.get('filter') + '</span>'
|
||||
)
|
||||
|
||||
if (this.filtersInModal || parseInt($(window).width()) < breakpoints.lg) {
|
||||
let self = this
|
||||
isModal = true
|
||||
// wait for filters used js to exec
|
||||
$('#changelist-filter').prop('id', 'changelist-filter-modal')
|
||||
let titleEl = $('#changelist-filter-modal > h2')
|
||||
let title = titleEl.html()
|
||||
titleEl.remove()
|
||||
let content = $('#changelist-filter-modal')
|
||||
// remove from dom
|
||||
this.modal = new Modal({
|
||||
title,
|
||||
content,
|
||||
size: 'md',
|
||||
hideFooter: !this.filtersForm,
|
||||
actionBtnLabel: this.t.get('filter'),
|
||||
actionBtnCb: function () { self.filter(content) }
|
||||
})
|
||||
_filtersToggler.click(() => {
|
||||
self.modal.toggle()
|
||||
})
|
||||
} else {
|
||||
_filtersToggler.click(() => {
|
||||
$(document.body).toggleClass('changelist-filter-active')
|
||||
if (parseInt(this._filtersDiv.css('max-width')) === 100) {
|
||||
// diff between mobile and lg
|
||||
$('html,body').animate({
|
||||
scrollTop: this._filtersDiv.offset().top
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
_changelistForm.prepend(_filtersToggler)
|
||||
}
|
||||
|
||||
if (!isModal && this.filtersForm) {
|
||||
// add filters button
|
||||
let btn = $('<a />', {'class': 'btn btn-primary'}).html(this.t.get('filter'))
|
||||
.on('click', () => this.filter($('#changelist-filter')))
|
||||
$('#changelist-filter').append($('<div />', {'class': 'text-center mb-3'}).append(btn))
|
||||
}
|
||||
|
||||
if (/_popup=1/.test(location.href)) {
|
||||
$('#changelist-form .results').css('padding-top', '78px')
|
||||
}
|
||||
},
|
||||
getDropdownValue: function (dropdown) {
|
||||
let items = $(dropdown).find('option').attr('value').substr(1).split('&')
|
||||
let values = $(dropdown).val().substr(1).split('&').filter(item => items.indexOf(item) === -1)
|
||||
return values.length ? values.join('&') : null
|
||||
},
|
||||
filter: function (wrapper) {
|
||||
var self = this
|
||||
let qs = []
|
||||
|
||||
let dropdowns = wrapper.find('select')
|
||||
let textInputs = wrapper.find('input').not('[type=hidden]')
|
||||
|
||||
dropdowns
|
||||
.toArray()
|
||||
.map(el => self.getDropdownValue(el))
|
||||
.filter(v => v !== null)
|
||||
.forEach(v => qs.push(v))
|
||||
|
||||
textInputs.each((idx, el) => el.value !== '' ? qs.push(`${el.name}=${el.value}`) : null)
|
||||
|
||||
// console.log(location.pathname + (qs.length ? '?' + qs.filter(q => q !== '').join('&') : ''), qs)
|
||||
location.href = location.pathname + (qs.length ? '?' + qs.filter(q => q !== '').join('&') : '')
|
||||
},
|
||||
initTemplates: function () {
|
||||
const positionMap = {
|
||||
above: 'before',
|
||||
below: 'after',
|
||||
top: 'prepend',
|
||||
bottom: 'append'
|
||||
}
|
||||
|
||||
$('template[data-type=include]').each(function (index, template) {
|
||||
let position = positionMap[$(template).attr('data-position')]
|
||||
if (position !== undefined) {
|
||||
let el = $('#changelist-form')
|
||||
el[position]($(template).html())
|
||||
} else {
|
||||
console.error('Baton: wrong changelist include position detected')
|
||||
}
|
||||
})
|
||||
|
||||
$('template[data-type=filters-include]').each(function (index, template) {
|
||||
let position = positionMap[$(template).attr('data-position')]
|
||||
if (
|
||||
position !== undefined &&
|
||||
position !== 'before' &&
|
||||
position !== 'after'
|
||||
) {
|
||||
if (position === 'prepend' && $('#changelist-filter-clear').length) {
|
||||
$('#changelist-filter-clear').after($(template).html())
|
||||
} else if (
|
||||
position === 'prepend' &&
|
||||
$('#changelist-filter > h2').length
|
||||
) {
|
||||
$('#changelist-filter > h2').after($(template).html())
|
||||
} else {
|
||||
let el = $('#changelist-filter')
|
||||
el[position]($(template).html())
|
||||
}
|
||||
} else {
|
||||
console.error(
|
||||
'Baton: wrong changelist filters include position detected'
|
||||
)
|
||||
}
|
||||
})
|
||||
|
||||
$('template[data-type=attributes]').each(function (index, template) {
|
||||
try {
|
||||
let data = JSON.parse($(template).html())
|
||||
|
||||
for (let key in data) {
|
||||
if (data.hasOwnProperty(key)) {
|
||||
let selector
|
||||
let getParent = 'tr'
|
||||
if (data[key]['selector']) {
|
||||
selector = data[key]['selector']
|
||||
delete data[key]['selector']
|
||||
} else {
|
||||
selector =
|
||||
'#result_list tr input[name=_selected_action][value=' +
|
||||
key +
|
||||
']'
|
||||
}
|
||||
if (data[key]['getParent'] !== undefined) {
|
||||
getParent = data[key]['getParent']
|
||||
delete data[key]['getParent']
|
||||
}
|
||||
|
||||
let el = getParent ? $(selector).parents(getParent) : $(selector)
|
||||
el.attr(data[key])
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e)
|
||||
}
|
||||
})
|
||||
},
|
||||
fixRangeFilter: function () {
|
||||
if (this.filtersForm) {
|
||||
$('.admindatefilter .controls').remove()
|
||||
$('.admindatefilter form').onSubmit = function () { return false }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default ChangeList
|
@@ -0,0 +1,30 @@
|
||||
import $ from 'jquery'
|
||||
import { copyTextToClipboard } from './Utils'
|
||||
|
||||
let Filer = {
|
||||
/**
|
||||
* ChangeList component
|
||||
*
|
||||
* Filtering stuff
|
||||
*/
|
||||
init: function (opts) {
|
||||
this.fixIcons()
|
||||
this.fixCopyToClipboard()
|
||||
},
|
||||
fixIcons: function () {
|
||||
$('.fa-pencil').addClass('fa-pencil-alt')
|
||||
},
|
||||
fixCopyToClipboard: function () {
|
||||
let copyBtns = $('.action-button .fa-link')
|
||||
copyBtns.on('click', function (evt) {
|
||||
evt.preventDefault()
|
||||
var link = $(this).parent('.action-button').attr('href')
|
||||
if (!link) {
|
||||
link = $(this).parent('.action-button').next('.action-button').attr('href')
|
||||
}
|
||||
copyTextToClipboard(link)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default Filer
|
@@ -0,0 +1,17 @@
|
||||
import $ from 'jquery'
|
||||
|
||||
let Footer = {
|
||||
/**
|
||||
* Footer component
|
||||
*
|
||||
* Moves the footer inside the main external container
|
||||
*/
|
||||
init: function (opts) {
|
||||
$('#footer').appendTo('#content')
|
||||
if (opts.remove) {
|
||||
$('#footer').remove()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Footer
|
@@ -0,0 +1,47 @@
|
||||
import $ from 'jquery'
|
||||
|
||||
const Login = {
|
||||
init: function (config) {
|
||||
// splash
|
||||
if (config.loginSplash) {
|
||||
$('body.login').css({
|
||||
background: `url(${config.loginSplash}) no-repeat center center`,
|
||||
backgroundSize: 'cover'
|
||||
})
|
||||
}
|
||||
// form
|
||||
let inputUsername = $('#id_username')
|
||||
let inputPassword = $('#id_password')
|
||||
|
||||
const usernameField = $('<div />', { class: 'input-group mb-2' })
|
||||
.append(
|
||||
$('<span />', { class: 'input-group-text' }).append(
|
||||
'<i class="fa fa-user"></i>'
|
||||
)
|
||||
)
|
||||
.append(inputUsername.clone())
|
||||
|
||||
inputUsername.replaceWith(usernameField)
|
||||
|
||||
// adds show/hide password functionality
|
||||
let passwordInputField = inputPassword.clone()
|
||||
let viewPasswordIcon = $('<i />', {'class': 'fa fa-eye pwd-visibility-toggle'}).on('click', function () {
|
||||
let visible = $(this).hasClass('fa-eye-slash')
|
||||
$(this)[visible ? 'removeClass' : 'addClass']('fa-eye-slash')
|
||||
passwordInputField.attr('type', visible ? 'password' : 'text')
|
||||
})
|
||||
|
||||
const passwordField = $('<div />', { class: 'input-group mb-2' })
|
||||
.append(
|
||||
$('<span />', { class: 'input-group-text' }).append(
|
||||
'<i class="fa fa-key"></i>'
|
||||
)
|
||||
)
|
||||
.append(passwordInputField)
|
||||
.append(viewPasswordIcon)
|
||||
|
||||
inputPassword.replaceWith(passwordField)
|
||||
}
|
||||
}
|
||||
|
||||
export default Login
|
375
venv/Lib/site-packages/baton/static/baton/app/src/core/Menu.js
Normal file
@@ -0,0 +1,375 @@
|
||||
import $ from 'jquery'
|
||||
import Translator from './i18n'
|
||||
|
||||
let Menu = {
|
||||
/**
|
||||
* Menu component
|
||||
*
|
||||
* Adds a sidebar menu to the document
|
||||
*/
|
||||
init: function (config, Dispatcher) {
|
||||
this.Dispatcher = Dispatcher
|
||||
this.t = new Translator($('html').attr('lang'))
|
||||
this.collapsableUserArea = config.collapsableUserArea
|
||||
this.menuTitle = config.menuTitle
|
||||
this.searchField = config.searchField
|
||||
this.appListUrl = config.api.app_list
|
||||
this.gravatarUrl = config.api.gravatar
|
||||
this.gravatarDefaultImg = config.gravatarDefaultImg
|
||||
this.alwaysCollapsed = $('#header').hasClass('menu-always-collapsed')
|
||||
this.fixNodes()
|
||||
this.brandingClone = $('#branding').clone()
|
||||
this.manageBrandingUserTools()
|
||||
this.manageSearchField()
|
||||
this.fetchData()
|
||||
this.setHeight()
|
||||
let self = this
|
||||
$(window).on('resize', function () {
|
||||
self.setHeight()
|
||||
self.manageBrandingUserTools()
|
||||
})
|
||||
},
|
||||
fixNodes: function () {
|
||||
let container = $('<div/>', { class: 'container-fluid' })
|
||||
$('#footer').before(container)
|
||||
let row = $('<div/>', { class: 'row' }).appendTo(container)
|
||||
this.menu = $('<nav/>', { class: 'col-lg-2 sidebar-menu' }).appendTo(row)
|
||||
$('#content')
|
||||
.addClass('col-lg-10')
|
||||
.prepend($('.breadcrumbs'))
|
||||
.appendTo(row)
|
||||
|
||||
$('#content > h1').after($('.messagelist'))
|
||||
|
||||
let title = $('<h1 />', { class: 'd-block d-lg-none' }).text(
|
||||
this.menuTitle ? this.menuTitle : 'Menu'
|
||||
)
|
||||
$('<i/>', { class: 'fa fa-times' })
|
||||
.click(() => {
|
||||
$(document.body).removeClass('menu-open')
|
||||
})
|
||||
.appendTo(title)
|
||||
this.menu.append(title)
|
||||
|
||||
if (this.alwaysCollapsed) {
|
||||
let close = $('<i />', { class: 'fa fa-times toggle-menu' })
|
||||
.appendTo(this.menu)
|
||||
.click(() => {
|
||||
$(document.body).removeClass('menu-open')
|
||||
})
|
||||
}
|
||||
},
|
||||
manageBrandingUserTools: function () {
|
||||
if (parseInt($(window).width()) >= 992) {
|
||||
// move user tools
|
||||
this.menu.prepend($('#user-tools'))
|
||||
if (this.alwaysCollapsed) {
|
||||
// copy branding
|
||||
this.menu.prepend(this.brandingClone)
|
||||
} else {
|
||||
// move branding
|
||||
this.menu.prepend($('#branding'))
|
||||
}
|
||||
if ($('#user-tools-sidebar').length === 0) {
|
||||
this.renderUserTools()
|
||||
}
|
||||
} else {
|
||||
$('#header').append($('#user-tools'))
|
||||
if (this.alwaysCollapsed) {
|
||||
this.menu.find('#branding').remove()
|
||||
} else {
|
||||
$('#header .navbar-toggler').after($('#branding'))
|
||||
}
|
||||
if ($('#user-tools-sidebar').length === 0) {
|
||||
this.removeUserTools()
|
||||
}
|
||||
}
|
||||
},
|
||||
manageSearchField () {
|
||||
// unset
|
||||
if (!this.searchField || !this.searchField.url) {
|
||||
return
|
||||
}
|
||||
|
||||
let container = $('<div />', { class: 'search-field-tool' })
|
||||
|
||||
let field = $('<input />', {
|
||||
class: 'form-control form-control-sm',
|
||||
type: 'text',
|
||||
list: 'admin-search-datalist',
|
||||
placeholder: this.searchField.label || this.t('search')
|
||||
})
|
||||
let dataList = $('<div />', { id: 'admin-search-datalist' }).on('mouseover', e => {
|
||||
if ($(e.target).hasClass('datalist-option') || $(e.target).parent('.datalist-option').length) {
|
||||
dataList.find('.datalist-option').removeClass('selected')
|
||||
let item = $(e.target).hasClass('datalist-option') ? $(e.target) : $(e.target).parent('.datalist-option')
|
||||
item.addClass('selected')
|
||||
}
|
||||
})
|
||||
|
||||
let navigateDataList = code => {
|
||||
let target
|
||||
let active = dataList.find('.datalist-option.selected').first()
|
||||
if (!active.length) {
|
||||
target = dataList.find('.datalist-option')[code === 40 ? 'first' : 'last']()
|
||||
} else {
|
||||
if (code === 40) {
|
||||
let next = active.next()
|
||||
target = next.length ? next : dataList.find('.datalist-option').first()
|
||||
} else {
|
||||
let prev = active.prev()
|
||||
target = prev.length ? prev : dataList.find('.datalist-option').last()
|
||||
}
|
||||
}
|
||||
if (target) {
|
||||
active.removeClass('selected')
|
||||
$(target).addClass('selected')
|
||||
target[0].scrollIntoView({
|
||||
behavior: 'smooth',
|
||||
block: 'end',
|
||||
inline: 'nearest'
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
field.on('blur', e => setTimeout(() => dataList.hide(), 150))
|
||||
field.on('focus', e => dataList.show())
|
||||
field.on('keyup', e => {
|
||||
var code = e.keyCode || e.which
|
||||
|
||||
if (code === 13) {
|
||||
// goto url if there is an active voice
|
||||
let active = dataList.find('.datalist-option.selected').first()
|
||||
if (active.length) {
|
||||
location.href = active.attr('data-url')
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
if ([40, 38].indexOf(code) !== -1) {
|
||||
// move
|
||||
navigateDataList(code)
|
||||
} else {
|
||||
// search
|
||||
if ($(field).val().length < 1) {
|
||||
dataList.empty()
|
||||
return
|
||||
}
|
||||
|
||||
container.addClass('loading')
|
||||
$.getJSON(this.searchField.url, { text: $(field).val() })
|
||||
.done(data => {
|
||||
container.removeClass('loading')
|
||||
dataList.empty()
|
||||
data.data.forEach((r, index) => dataList.append(`
|
||||
<div class="datalist-option${index === 0 ? ' selected' : ''}" onclick="location.href='${r.url}'" data-url="${r.url}"><a href="${r.url}">${r.label}</a>${r.icon ? `<i onclick="location.href='${r.url}'" class="${r.icon}"></i>` : ''}</div>`)
|
||||
)
|
||||
})
|
||||
.fail((jqxhr, textStatus, err) => {
|
||||
console.log(err)
|
||||
container.removeClass('loading')
|
||||
dataList.empty()
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
$('#user-tools-sidebar').after(container.append([field, dataList]))
|
||||
},
|
||||
renderUserTools: function () {
|
||||
let self = this
|
||||
let container = $('<div />', { id: 'user-tools-sidebar' })
|
||||
let expandUserArea = $('<i />', {'class': 'fa fa-angle-down user-area-toggler'}).on('click', function () {
|
||||
$(this).toggleClass('fa-angle-up')
|
||||
container.toggleClass('collapsed')
|
||||
})
|
||||
if (this.collapsableUserArea) {
|
||||
container.addClass('collapsed')
|
||||
}
|
||||
container.insertAfter('#user-tools')
|
||||
let userInfo = $('<div />', { class: 'user-info' })
|
||||
.html(
|
||||
'<div class="spinner-border text-primary" role="status"><span class="sr-only">Loading...</span></div><div>' +
|
||||
$('#user-tools .dropdown-toggle').text() +
|
||||
'</div>'
|
||||
)
|
||||
.appendTo(container)
|
||||
// gravatar
|
||||
$.getJSON(this.gravatarUrl, function (data) {
|
||||
let img = $('<img />', {
|
||||
class: 'gravatar-icon',
|
||||
src: 'https://www.gravatar.com/avatar/{hash}?s=50&d={default}'
|
||||
.replace('{hash}', data.hash)
|
||||
.replace('{default}', self.gravatarDefaultImg)
|
||||
})
|
||||
userInfo.find('.spinner-border').replaceWith(img)
|
||||
if (self.collapsableUserArea) {
|
||||
img.after(expandUserArea)
|
||||
}
|
||||
}).fail(function (err) {
|
||||
console.error(err.responseText)
|
||||
let img = $('<img />', {
|
||||
class: 'gravatar-icon',
|
||||
src: 'https://www.gravatar.com/avatar/{hash}?s=50&d={default}'
|
||||
.replace('{hash}', '')
|
||||
.replace('{default}', self.gravatarDefaultImg)
|
||||
})
|
||||
userInfo.find('.spinner-border').replaceWith(img)
|
||||
if (self.collapsableUserArea) {
|
||||
img.after(expandUserArea)
|
||||
}
|
||||
})
|
||||
let linksContainer = $('<div />', { class: 'user-links' }).appendTo(
|
||||
container
|
||||
)
|
||||
$('#user-tools .dropdown-menu a').each(function (index, el) {
|
||||
let cls = 'view-site'
|
||||
if (/password_change/.test($(el).attr('href'))) {
|
||||
cls = 'password'
|
||||
} else if (/logout/.test($(el).attr('href'))) {
|
||||
cls = 'logout'
|
||||
}
|
||||
let text = $(el).text()
|
||||
let clone = $(el)
|
||||
.clone()
|
||||
.html('')
|
||||
.attr('class', cls)
|
||||
.attr('title', text)
|
||||
if (cls === 'view-site') {
|
||||
clone.attr('target', '_blank')
|
||||
}
|
||||
linksContainer.append(clone)
|
||||
})
|
||||
},
|
||||
removeUserTools: function () {
|
||||
$('#user-tools-sidebar').remove()
|
||||
},
|
||||
fetchData: function () {
|
||||
let self = this
|
||||
$.getJSON(this.appListUrl, function (data) {
|
||||
self.render(data)
|
||||
self.Dispatcher.emit('onMenuReady')
|
||||
}).fail(function (err) {
|
||||
console.error(err.responseText)
|
||||
self.menu.remove()
|
||||
$('#content')
|
||||
.removeClass('col-md-9')
|
||||
.removeClass('col-lg-10')
|
||||
.css('flex-grow', 1)
|
||||
self.Dispatcher.emit('onMenuError')
|
||||
})
|
||||
},
|
||||
setHeight: function () {
|
||||
let height = $(window).height() - $('#header').height() - 19 // nav padding and border
|
||||
this.menu.css('min-height', height + 'px')
|
||||
$('#content').css('padding-bottom', $('#footer').height() + 20 + 'px')
|
||||
},
|
||||
render: function (data) {
|
||||
let self = this
|
||||
let mainUl = $('<ul/>', { class: 'depth-0' }).appendTo(self.menu)
|
||||
data.forEach((voice, index) => {
|
||||
let active = false
|
||||
if (voice.type === 'free') {
|
||||
if (voice.re) {
|
||||
let re = new RegExp(voice.re)
|
||||
active = re.test(location.pathname)
|
||||
} else {
|
||||
active = location.pathname === voice.url
|
||||
}
|
||||
} else {
|
||||
if (voice.url) {
|
||||
let pathRexp = new RegExp(voice.url)
|
||||
active = pathRexp.test(location.pathname)
|
||||
}
|
||||
}
|
||||
let li = $('<li />', {
|
||||
class:
|
||||
'top-level ' +
|
||||
voice.type +
|
||||
(voice.defaultOpen ? ' default-open' : '') +
|
||||
(active ? ' active' : '')
|
||||
})
|
||||
let a = $('<' + (voice.url ? 'a' : 'span') + ' />', {
|
||||
href: voice.url || '#'
|
||||
})
|
||||
.text(voice.label)
|
||||
.appendTo(li)
|
||||
// icon
|
||||
if (voice.icon) {
|
||||
$('<i />', { class: voice.icon }).prependTo(a)
|
||||
}
|
||||
let subUl
|
||||
if (voice.children && voice.children.length) {
|
||||
subUl = $('<ul />', { class: 'depth-1' }).appendTo(li)
|
||||
a.addClass('has-children')
|
||||
|
||||
voice.children.forEach((model, i) => {
|
||||
let active = false
|
||||
if (model.type === 'free') {
|
||||
if (model.re) {
|
||||
let re = new RegExp(model.re)
|
||||
active = re.test(location.pathname)
|
||||
} else {
|
||||
active = location.pathname === model.url
|
||||
}
|
||||
} else if (model.url) {
|
||||
let pathRexp = new RegExp(model.url)
|
||||
active = pathRexp.test(location.pathname)
|
||||
}
|
||||
let subLi = $('<li />')
|
||||
if (active) {
|
||||
subLi.addClass('active')
|
||||
li.addClass('with-active')
|
||||
}
|
||||
let a = $('<a />', {
|
||||
href: model.url
|
||||
})
|
||||
.text(model.label)
|
||||
.appendTo(subLi)
|
||||
// icon
|
||||
if (model.icon) {
|
||||
$('<i />', { class: model.icon }).prependTo(a)
|
||||
}
|
||||
subLi.appendTo(subUl)
|
||||
})
|
||||
}
|
||||
li.appendTo(mainUl)
|
||||
})
|
||||
|
||||
$('.has-children').on('click', function (evt) {
|
||||
evt.preventDefault()
|
||||
let self = this
|
||||
let p = $(this).parent()
|
||||
let depth0 = $('.depth-0')
|
||||
let depth1 = p.children('ul')
|
||||
if (
|
||||
p.hasClass('open') ||
|
||||
(p.hasClass('default-open') && !$('body').hasClass('menu-open'))
|
||||
) {
|
||||
p.removeClass('open default-open')
|
||||
depth1.children('.nav-back').remove()
|
||||
depth0.css('overflow', 'auto')
|
||||
} else {
|
||||
if (p.hasClass('top-level')) {
|
||||
$('.top-level').removeClass('open')
|
||||
$('.top-level')
|
||||
.find('.nav-back')
|
||||
.remove()
|
||||
}
|
||||
p.addClass('open')
|
||||
let back = $(
|
||||
'<li class="nav-item nav-back"><a href="#"><i class="fa fa-angle-double-left"></i> ' + // eslint-disable-line
|
||||
$(this).text() +
|
||||
'</a></li>'
|
||||
)
|
||||
back.on('click', function () {
|
||||
$(self).trigger('click')
|
||||
})
|
||||
depth1.prepend(back)
|
||||
depth0.css('overflow', 'hidden')
|
||||
depth0.scrollTop(0) // return to top
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default Menu
|
@@ -0,0 +1,72 @@
|
||||
import $ from 'jquery'
|
||||
import bootstrap from 'bootstrap/dist/js/bootstrap.bundle'
|
||||
|
||||
let Messages = {
|
||||
/**
|
||||
* Messages
|
||||
*
|
||||
* If toast are enabled, moves messages ul lis in toasts
|
||||
*/
|
||||
init: function (opts) {
|
||||
if (opts.messagesToasts) {
|
||||
let toasts = []
|
||||
let all = true
|
||||
$('.messagelist li').each((index, el) => {
|
||||
let lv = $(el).attr('class')
|
||||
if (opts.messagesToasts === true || opts.messagesToasts.indexOf(lv) !== -1) {
|
||||
toasts.push(this.createToast($(el).attr('class'), $(el).html()))
|
||||
$(el).remove()
|
||||
} else {
|
||||
all = false
|
||||
}
|
||||
})
|
||||
if (toasts.length) {
|
||||
$('<div />', {'class': 'toast-container position-absolute top-0 end-0 p-3'})
|
||||
.append(toasts).appendTo($(document.body))
|
||||
}
|
||||
if (all) {
|
||||
$('.messagelist').remove()
|
||||
}
|
||||
}
|
||||
const toastElList = [].slice.call(document.querySelectorAll('.toast'))
|
||||
toastElList.map(function (toastEl) {
|
||||
new bootstrap.Toast(toastEl, { autohide: false }).show()
|
||||
})
|
||||
},
|
||||
levelsMap: {
|
||||
info: {
|
||||
bg: 'info',
|
||||
icon: 'fa fa-info-circle',
|
||||
iconColor: '#fff'
|
||||
},
|
||||
success: {
|
||||
bg: 'success',
|
||||
icon: 'fa fa-check-circle',
|
||||
iconColor: '#fff'
|
||||
},
|
||||
warning: {
|
||||
bg: 'warning',
|
||||
icon: 'fa fa-exclamation-circle',
|
||||
iconColor: '#fff'
|
||||
},
|
||||
error: {
|
||||
bg: 'danger',
|
||||
icon: 'fa fa-exclamation-circle',
|
||||
iconColor: '#fff'
|
||||
}
|
||||
},
|
||||
createToast (level, content) {
|
||||
let toast = `
|
||||
<div class="toast d-flex align-items-center text-white bg-${this.levelsMap[level].bg} border-0" role="alert" aria-live="assertive" aria-atomic="true">
|
||||
<div class="toast-body">
|
||||
<i class="${this.levelsMap[level].icon}" style="color: ${this.levelsMap[level].iconColor}; margin-right: .5rem"></i>
|
||||
${content}
|
||||
</div>
|
||||
<button type="button" class="btn-close btn-close-white ms-auto me-2" data-bs-dismiss="toast" aria-label="Close"></button>
|
||||
</div>
|
||||
`
|
||||
return $(toast)
|
||||
}
|
||||
}
|
||||
|
||||
export default Messages
|
155
venv/Lib/site-packages/baton/static/baton/app/src/core/Modal.js
Normal file
@@ -0,0 +1,155 @@
|
||||
import $ from 'jquery'
|
||||
import Translator from './i18n'
|
||||
import bootstrap from 'bootstrap/dist/js/bootstrap.bundle'
|
||||
|
||||
class Modal {
|
||||
constructor (config) {
|
||||
this.t = new Translator($('html').attr('lang'))
|
||||
|
||||
this.opts = {
|
||||
subtitle: '',
|
||||
hideFooter: false,
|
||||
showBackBtn: false,
|
||||
backBtnCb: function () {},
|
||||
actionBtnLabel: this.t.get('save'),
|
||||
actionBtnCb: null,
|
||||
onUrlLoaded: function () {},
|
||||
size: 'lg',
|
||||
onClose: function () {}
|
||||
}
|
||||
|
||||
this.isOpen = false
|
||||
this.create() // adds modal, modalObj and events
|
||||
this.update(config)
|
||||
}
|
||||
|
||||
create () {
|
||||
this.modalObj = $('<div />', {'class': 'modal fade'}).appendTo(document.body)
|
||||
this.modalObj.html(`
|
||||
<div class="modal-dialog" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title"></h5>
|
||||
<div style="display: flex;">
|
||||
<button type="button" class="back me-1" aria-label="Back">
|
||||
<i class="fa fa-angle-left"></i>
|
||||
</button>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">${this.t.get('close')}</button>
|
||||
<button type="button" class="btn btn-primary btn-action"></button>
|
||||
</div>
|
||||
</div><!-- /.modal-content -->
|
||||
</div><!-- /.modal-dialog -->
|
||||
`)
|
||||
|
||||
var self = this
|
||||
this.modalObj.on('hidden.bs.modal', function () {
|
||||
self.close()
|
||||
})
|
||||
|
||||
this.modal = new bootstrap.Modal(this.modalObj[0])
|
||||
}
|
||||
|
||||
update (config) {
|
||||
this.options = $.extend({}, this.opts, config)
|
||||
this.setSize()
|
||||
this.setHeader()
|
||||
this.setTitle()
|
||||
this.setSubtitle()
|
||||
this.setContent()
|
||||
this.setButtons()
|
||||
}
|
||||
|
||||
setSize () {
|
||||
this.modalObj.find('.modal-dialog').addClass('modal-' + this.options.size)
|
||||
}
|
||||
|
||||
setHeader () {
|
||||
if (this.options.showBackBtn) {
|
||||
this.modalObj.find('.modal-header .back').show()
|
||||
this.modalObj
|
||||
.find('.modal-header .back')
|
||||
.on('click', this.options.backBtnCb)
|
||||
} else {
|
||||
this.modalObj.find('.modal-header .back').hide()
|
||||
}
|
||||
}
|
||||
|
||||
setTitle () {
|
||||
if (typeof this.options.title !== 'undefined') {
|
||||
this.modalObj.find('.modal-title').html(this.options.title)
|
||||
}
|
||||
}
|
||||
|
||||
setSubtitle () {
|
||||
if (this.options.subtitle) {
|
||||
this.modalObj
|
||||
.find('.modal-subtitle')
|
||||
.show()
|
||||
.html(this.options.subtitle)
|
||||
} else {
|
||||
this.modalObj
|
||||
.find('.modal-subtitle')
|
||||
.hide()
|
||||
.html('')
|
||||
}
|
||||
}
|
||||
|
||||
setContent () {
|
||||
var self = this
|
||||
if (typeof this.options.url !== 'undefined') {
|
||||
this.method = 'request'
|
||||
$.get(this.options.url, function (response) {
|
||||
self.modalObj.find('.modal-body').html(response)
|
||||
self.options.onUrlLoaded(self)
|
||||
})
|
||||
} else if (this.options.content instanceof jQuery) {
|
||||
self.modalObj.find('.modal-body').append(this.options.content)
|
||||
} else if (typeof this.options.content !== 'undefined') {
|
||||
self.modalObj.find('.modal-body').html(this.options.content)
|
||||
}
|
||||
};
|
||||
|
||||
setButtons () {
|
||||
if (this.options.hideFooter) {
|
||||
this.modalObj.find('.modal-footer').hide()
|
||||
} else {
|
||||
if (this.options.actionBtnCb) {
|
||||
this.modalObj.find('.btn-action').text(this.options.actionBtnLabel)
|
||||
this.modalObj.find('.btn-action').on('click', this.options.actionBtnCb)
|
||||
} else {
|
||||
this.modalObj.find('.btn-action').hide()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
open () {
|
||||
if (this.isOpen) {
|
||||
return
|
||||
}
|
||||
this.toggle()
|
||||
this.isOpen = true
|
||||
}
|
||||
|
||||
toggle () {
|
||||
this.modal[this.isOpen ? 'hide' : 'show']()
|
||||
this.isOpen = !this.isOpen
|
||||
}
|
||||
|
||||
close () {
|
||||
if (!this.isOpen) {
|
||||
return
|
||||
}
|
||||
|
||||
this.modal.hide()
|
||||
this.options.onClose()
|
||||
this.isOpen = false
|
||||
}
|
||||
}
|
||||
|
||||
export default Modal
|
@@ -0,0 +1,44 @@
|
||||
import $ from 'jquery'
|
||||
|
||||
let Navbar = {
|
||||
/**
|
||||
* Navbar component
|
||||
*
|
||||
* Adds a menu toggler for mobile and does some styling
|
||||
*/
|
||||
init: function (config) {
|
||||
this.menuAlwaysCollapsed = config.menuAlwaysCollapsed
|
||||
this.fixNodes()
|
||||
},
|
||||
fixNodes: function () {
|
||||
if (!this.menuAlwaysCollapsed) {
|
||||
$('#header').addClass('expand')
|
||||
} else {
|
||||
$('#header').addClass('menu-always-collapsed')
|
||||
}
|
||||
// insert burger
|
||||
$('#branding').before(
|
||||
$('<button/>', {
|
||||
'class': 'navbar-toggler navbar-toggler-right',
|
||||
'data-bs-toggle': 'collapse'
|
||||
}).html('<i class="fa fa-bars"></i>')
|
||||
.click(() => $(document.body).addClass('menu-open')))
|
||||
// remove only text
|
||||
$('#user-tools')
|
||||
.contents().filter(function () {
|
||||
return (this.nodeType === 3)
|
||||
}).remove()
|
||||
// dropdown
|
||||
let dropdown = $('<div/>', { 'class': 'dropdown' }).appendTo($('#user-tools'))
|
||||
let dropdownMenu = $('<div/>', { 'class': 'dropdown-menu dropdown-menu-right' }).appendTo(dropdown)
|
||||
$('#user-tools strong')
|
||||
.addClass('dropdown-toggle btn btn-default')
|
||||
.attr('data-bs-toggle', 'dropdown')
|
||||
.prependTo(dropdown)
|
||||
// @TODO find a way to mv view site from dropdown
|
||||
// password change view doesn't have it so breaks things
|
||||
$('#user-tools > a').addClass('dropdown-item').appendTo(dropdownMenu)
|
||||
}
|
||||
}
|
||||
|
||||
export default Navbar
|
@@ -0,0 +1,9 @@
|
||||
import $ from 'jquery'
|
||||
|
||||
let PasswordChange = {
|
||||
init: function () {
|
||||
$('body').addClass('passwordchange')
|
||||
}
|
||||
}
|
||||
|
||||
export default PasswordChange
|
163
venv/Lib/site-packages/baton/static/baton/app/src/core/Tabs.js
Normal file
@@ -0,0 +1,163 @@
|
||||
import $ from 'jquery'
|
||||
import bootstrap from 'bootstrap/dist/js/bootstrap.bundle'
|
||||
|
||||
let Tabs = {
|
||||
/**
|
||||
* Tabs component
|
||||
*/
|
||||
init: function (Dispatcher) {
|
||||
this.Dispatcher = Dispatcher
|
||||
if (this.shouldRun()) {
|
||||
console.info('Baton:', 'generating tabs')
|
||||
this.main.attr('data-baton-tab', 'main-tab')
|
||||
this.createNav()
|
||||
this.createPanes()
|
||||
this.checkHash()
|
||||
this.showErrors()
|
||||
this.Dispatcher.emit('onTabsReady')
|
||||
}
|
||||
},
|
||||
shouldRun: function () {
|
||||
this.main = $('#content-main form .baton-tabs-init')
|
||||
return this.main.length === 1
|
||||
},
|
||||
createNav: function () {
|
||||
this.mainOrder = 0
|
||||
this.tabsEl = []
|
||||
this.domTabsEl = []
|
||||
let classes = this.main.attr('class')
|
||||
classes.split(' ').forEach((cl) => {
|
||||
if (/baton-tab-/.test(cl)) {
|
||||
this.tabsEl.push(cl.substring(10))
|
||||
}
|
||||
if (/order-/.test(cl)) {
|
||||
this.mainOrder = parseInt(cl.replace('order-', ''))
|
||||
}
|
||||
})
|
||||
|
||||
let currentOrder = this.mainOrder ? 0 : this.mainOrder + 1
|
||||
|
||||
this.nav = $('<ul />', { 'class': 'nav nav-tabs' })
|
||||
$('<li />', { 'class': 'nav-item' })
|
||||
.css('order', this.mainOrder)
|
||||
.append($('<a />', {
|
||||
'class': 'nav-link' + (this.mainOrder === 0 ? ' active' : ''),
|
||||
'data-bs-toggle': 'tab',
|
||||
'data-bs-target': '#main-tab'
|
||||
// href: '#main-tab'
|
||||
}).text(this.main.children('h2').hide().text()))
|
||||
.appendTo(this.nav)
|
||||
|
||||
this.tabsEl.forEach((el) => {
|
||||
let domEl
|
||||
if (/^group-/.test(el)) {
|
||||
domEl = $('<div />').attr('data-baton-tab', el)
|
||||
let items = el.substr(6).split('--')
|
||||
items.forEach((item) => {
|
||||
let e
|
||||
if (/^inline-/.test(item)) {
|
||||
e = this.createInlineEl(item)
|
||||
} else {
|
||||
e = this.createFieldsetEl(item)
|
||||
}
|
||||
domEl.append(e)
|
||||
})
|
||||
} else if (/^inline-/.test(el)) {
|
||||
domEl = this.createInlineEl(el, true)
|
||||
} else {
|
||||
domEl = this.createFieldsetEl(el, true)
|
||||
}
|
||||
this.domTabsEl.push(domEl)
|
||||
$('<li />', { 'class': 'nav-item ' })
|
||||
.css('order', currentOrder)
|
||||
.append($('<a />', {
|
||||
'class': 'nav-link ' + (currentOrder === 0 ? ' active' : ''),
|
||||
'data-bs-toggle': 'tab',
|
||||
'data-bs-target': '#' + el
|
||||
// href: '#' + el
|
||||
}).text(domEl.find('h2:first-child').first().hide().text()))
|
||||
.appendTo(this.nav)
|
||||
currentOrder += 1
|
||||
if (currentOrder === this.mainOrder) {
|
||||
currentOrder += 1
|
||||
}
|
||||
})
|
||||
|
||||
this.main.before(this.nav)
|
||||
|
||||
$('a[data-bs-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||
// add hash to stay in same tab when save and continue
|
||||
const hash = $(e.target).attr('data-bs-target')
|
||||
window.location.replace(hash) // adding with replace won't add an history entry
|
||||
let tooltipTriggerList = [].slice.call($('[title]:not(iframe)'))
|
||||
tooltipTriggerList.map(function (tooltipTriggerEl) {
|
||||
return new bootstrap.Tooltip(tooltipTriggerEl)
|
||||
})
|
||||
})
|
||||
},
|
||||
createInlineEl: function (el, setDataTab = false) {
|
||||
let domEl
|
||||
if ($('#' + el.substring(7) + '_set-group').length) { // no related_name
|
||||
domEl = $('#' + el.substring(7) + '_set-group')
|
||||
} else {
|
||||
domEl = $('#' + el.substring(7) + '-group')
|
||||
}
|
||||
if (setDataTab) {
|
||||
domEl.attr('data-baton-tab', el)
|
||||
}
|
||||
return domEl
|
||||
},
|
||||
createFieldsetEl: function (el, setDataTab = false) {
|
||||
let domEl = $('.tab-' + el)
|
||||
if (setDataTab) {
|
||||
domEl.attr('data-baton-tab', el)
|
||||
}
|
||||
return domEl
|
||||
},
|
||||
createPanes: function () {
|
||||
let self = this
|
||||
this.tabContent = $('<div />', { 'class': 'tab-content' })
|
||||
this.tabMain = $('<div />', {
|
||||
'class': 'tab-pane fade' + (this.mainOrder === 0 ? ' active show' : ''),
|
||||
'id': 'main-tab'
|
||||
}).appendTo(this.tabContent)
|
||||
this.main.parent().children(':not(.nav-tabs):not(.submit-row):not(.errornote):not(.tab-fs-none)')
|
||||
.each((index, el) => {
|
||||
$(el).appendTo(self.tabMain)
|
||||
})
|
||||
this.nav.after(this.tabContent)
|
||||
|
||||
let currentOrder = this.mainOrder ? 0 : this.mainOrder + 1
|
||||
|
||||
this.domTabsEl.forEach((el, index) => {
|
||||
let tabPane = $('<div />', {
|
||||
'class': 'tab-pane' + (currentOrder === 0 ? ' active show' : ''),
|
||||
'id': self.tabsEl[index]
|
||||
}).appendTo(this.tabContent)
|
||||
el.appendTo(tabPane)
|
||||
currentOrder += 1
|
||||
if (currentOrder === this.mainOrder) {
|
||||
currentOrder += 1
|
||||
}
|
||||
})
|
||||
},
|
||||
showErrors: function () {
|
||||
let els = [this.main, ...this.domTabsEl]
|
||||
for (let i = 0, len = els.length; i < len; i++) {
|
||||
let el = els[i]
|
||||
if (el.find('.form-row.errors, .errorlist').length) {
|
||||
const tab = new bootstrap.Tab(this.nav.find('a[data-bs-target="#' + el.attr('data-baton-tab') + '"]')[0])
|
||||
tab.show()
|
||||
break
|
||||
}
|
||||
}
|
||||
},
|
||||
checkHash: function () {
|
||||
if (location.hash && this.nav.find('a[data-bs-target="' + location.hash + '"]').length) {
|
||||
const tab = new bootstrap.Tab(this.nav.find('a[data-bs-target="' + location.hash + '"]')[0])
|
||||
tab.show()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default Tabs
|
@@ -0,0 +1,600 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright (c) 2016 The Polymer Project Authors. All rights reserved.
|
||||
* This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
|
||||
* The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
|
||||
* The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
|
||||
* Code distributed by Google as part of the polymer project is also
|
||||
* subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
|
||||
*/
|
||||
|
||||
// minimal template polyfill
|
||||
(function() {
|
||||
'use strict';
|
||||
|
||||
var needsTemplate = (typeof HTMLTemplateElement === 'undefined');
|
||||
var brokenDocFragment = !(document.createDocumentFragment().cloneNode() instanceof DocumentFragment);
|
||||
var needsDocFrag = false;
|
||||
|
||||
// NOTE: Replace DocumentFragment to work around IE11 bug that
|
||||
// causes children of a document fragment modified while
|
||||
// there is a mutation observer to not have a parentNode, or
|
||||
// have a broken parentNode (!?!)
|
||||
if (/Trident/.test(navigator.userAgent)) {
|
||||
(function() {
|
||||
|
||||
needsDocFrag = true;
|
||||
|
||||
var origCloneNode = Node.prototype.cloneNode;
|
||||
Node.prototype.cloneNode = function cloneNode(deep) {
|
||||
var newDom = origCloneNode.call(this, deep);
|
||||
if (this instanceof DocumentFragment) {
|
||||
newDom.__proto__ = DocumentFragment.prototype;
|
||||
}
|
||||
return newDom;
|
||||
};
|
||||
|
||||
// IE's DocumentFragment querySelector code doesn't work when
|
||||
// called on an element instance
|
||||
DocumentFragment.prototype.querySelectorAll = HTMLElement.prototype.querySelectorAll;
|
||||
DocumentFragment.prototype.querySelector = HTMLElement.prototype.querySelector;
|
||||
|
||||
Object.defineProperties(DocumentFragment.prototype, {
|
||||
'nodeType': {
|
||||
get: function () {
|
||||
return Node.DOCUMENT_FRAGMENT_NODE;
|
||||
},
|
||||
configurable: true
|
||||
},
|
||||
|
||||
'localName': {
|
||||
get: function () {
|
||||
return undefined;
|
||||
},
|
||||
configurable: true
|
||||
},
|
||||
|
||||
'nodeName': {
|
||||
get: function () {
|
||||
return '#document-fragment';
|
||||
},
|
||||
configurable: true
|
||||
}
|
||||
});
|
||||
|
||||
var origInsertBefore = Node.prototype.insertBefore;
|
||||
function insertBefore(newNode, refNode) {
|
||||
if (newNode instanceof DocumentFragment) {
|
||||
var child;
|
||||
while ((child = newNode.firstChild)) {
|
||||
origInsertBefore.call(this, child, refNode);
|
||||
}
|
||||
} else {
|
||||
origInsertBefore.call(this, newNode, refNode);
|
||||
}
|
||||
return newNode;
|
||||
}
|
||||
Node.prototype.insertBefore = insertBefore;
|
||||
|
||||
var origAppendChild = Node.prototype.appendChild;
|
||||
Node.prototype.appendChild = function appendChild(child) {
|
||||
if (child instanceof DocumentFragment) {
|
||||
insertBefore.call(this, child, null);
|
||||
} else {
|
||||
origAppendChild.call(this, child);
|
||||
}
|
||||
return child;
|
||||
};
|
||||
|
||||
var origRemoveChild = Node.prototype.removeChild;
|
||||
var origReplaceChild = Node.prototype.replaceChild;
|
||||
Node.prototype.replaceChild = function replaceChild(newChild, oldChild) {
|
||||
if (newChild instanceof DocumentFragment) {
|
||||
insertBefore.call(this, newChild, oldChild);
|
||||
origRemoveChild.call(this, oldChild);
|
||||
} else {
|
||||
origReplaceChild.call(this, newChild, oldChild);
|
||||
}
|
||||
return oldChild;
|
||||
};
|
||||
|
||||
Document.prototype.createDocumentFragment = function createDocumentFragment() {
|
||||
var frag = this.createElement('df');
|
||||
frag.__proto__ = DocumentFragment.prototype;
|
||||
return frag;
|
||||
};
|
||||
|
||||
var origImportNode = Document.prototype.importNode;
|
||||
Document.prototype.importNode = function importNode(impNode, deep) {
|
||||
deep = deep || false;
|
||||
var newNode = origImportNode.call(this, impNode, deep);
|
||||
if (impNode instanceof DocumentFragment) {
|
||||
newNode.__proto__ = DocumentFragment.prototype;
|
||||
}
|
||||
return newNode;
|
||||
};
|
||||
})();
|
||||
}
|
||||
|
||||
// NOTE: we rely on this cloneNode not causing element upgrade.
|
||||
// This means this polyfill must load before the CE polyfill and
|
||||
// this would need to be re-worked if a browser supports native CE
|
||||
// but not <template>.
|
||||
var capturedCloneNode = Node.prototype.cloneNode;
|
||||
var capturedCreateElement = Document.prototype.createElement;
|
||||
var capturedImportNode = Document.prototype.importNode;
|
||||
var capturedRemoveChild = Node.prototype.removeChild;
|
||||
var capturedAppendChild = Node.prototype.appendChild;
|
||||
var capturedReplaceChild = Node.prototype.replaceChild;
|
||||
var capturedParseFromString = DOMParser.prototype.parseFromString;
|
||||
var capturedHTMLElementInnerHTML = Object.getOwnPropertyDescriptor(window.HTMLElement.prototype, 'innerHTML') || {
|
||||
/**
|
||||
* @this {!HTMLElement}
|
||||
* @return {string}
|
||||
*/
|
||||
get: function() {
|
||||
return this.innerHTML;
|
||||
},
|
||||
/**
|
||||
* @this {!HTMLElement}
|
||||
* @param {string}
|
||||
*/
|
||||
set: function(text) {
|
||||
this.innerHTML = text;
|
||||
}
|
||||
};
|
||||
var capturedChildNodes = Object.getOwnPropertyDescriptor(window.Node.prototype, 'childNodes') || {
|
||||
/**
|
||||
* @this {!Node}
|
||||
* @return {!NodeList}
|
||||
*/
|
||||
get: function() {
|
||||
return this.childNodes;
|
||||
}
|
||||
};
|
||||
|
||||
var elementQuerySelectorAll = Element.prototype.querySelectorAll;
|
||||
var docQuerySelectorAll = Document.prototype.querySelectorAll;
|
||||
var fragQuerySelectorAll = DocumentFragment.prototype.querySelectorAll;
|
||||
|
||||
var scriptSelector = 'script:not([type]),script[type="application/javascript"],script[type="text/javascript"]';
|
||||
|
||||
function QSA(node, selector) {
|
||||
// IE 11 throws a SyntaxError with `scriptSelector` if the node has no children due to the `:not([type])` syntax
|
||||
if (!node.childNodes.length) {
|
||||
return [];
|
||||
}
|
||||
switch (node.nodeType) {
|
||||
case Node.DOCUMENT_NODE:
|
||||
return docQuerySelectorAll.call(node, selector);
|
||||
case Node.DOCUMENT_FRAGMENT_NODE:
|
||||
return fragQuerySelectorAll.call(node, selector);
|
||||
default:
|
||||
return elementQuerySelectorAll.call(node, selector);
|
||||
}
|
||||
}
|
||||
|
||||
// returns true if nested templates cannot be cloned (they cannot be on
|
||||
// some impl's like Safari 8 and Edge)
|
||||
// OR if cloning a document fragment does not result in a document fragment
|
||||
var needsCloning = (function() {
|
||||
if (!needsTemplate) {
|
||||
var t = document.createElement('template');
|
||||
var t2 = document.createElement('template');
|
||||
t2.content.appendChild(document.createElement('div'));
|
||||
t.content.appendChild(t2);
|
||||
var clone = t.cloneNode(true);
|
||||
return (clone.content.childNodes.length === 0 || clone.content.firstChild.content.childNodes.length === 0
|
||||
|| brokenDocFragment);
|
||||
}
|
||||
})();
|
||||
|
||||
var TEMPLATE_TAG = 'template';
|
||||
var PolyfilledHTMLTemplateElement = function() {};
|
||||
|
||||
if (needsTemplate) {
|
||||
|
||||
var contentDoc = document.implementation.createHTMLDocument('template');
|
||||
var canDecorate = true;
|
||||
|
||||
var templateStyle = document.createElement('style');
|
||||
templateStyle.textContent = TEMPLATE_TAG + '{display:none;}';
|
||||
|
||||
var head = document.head;
|
||||
head.insertBefore(templateStyle, head.firstElementChild);
|
||||
|
||||
/**
|
||||
Provides a minimal shim for the <template> element.
|
||||
*/
|
||||
PolyfilledHTMLTemplateElement.prototype = Object.create(HTMLElement.prototype);
|
||||
|
||||
|
||||
// if elements do not have `innerHTML` on instances, then
|
||||
// templates can be patched by swizzling their prototypes.
|
||||
var canProtoPatch =
|
||||
!(document.createElement('div').hasOwnProperty('innerHTML'));
|
||||
|
||||
/**
|
||||
The `decorate` method moves element children to the template's `content`.
|
||||
NOTE: there is no support for dynamically adding elements to templates.
|
||||
*/
|
||||
PolyfilledHTMLTemplateElement.decorate = function(template) {
|
||||
// if the template is decorated or not in HTML namespace, return fast
|
||||
if (template.content ||
|
||||
template.namespaceURI !== document.documentElement.namespaceURI) {
|
||||
return;
|
||||
}
|
||||
template.content = contentDoc.createDocumentFragment();
|
||||
var child;
|
||||
while ((child = template.firstChild)) {
|
||||
capturedAppendChild.call(template.content, child);
|
||||
}
|
||||
// NOTE: prefer prototype patching for performance and
|
||||
// because on some browsers (IE11), re-defining `innerHTML`
|
||||
// can result in intermittent errors.
|
||||
if (canProtoPatch) {
|
||||
template.__proto__ = PolyfilledHTMLTemplateElement.prototype;
|
||||
} else {
|
||||
template.cloneNode = function(deep) {
|
||||
return PolyfilledHTMLTemplateElement._cloneNode(this, deep);
|
||||
};
|
||||
// add innerHTML to template, if possible
|
||||
// Note: this throws on Safari 7
|
||||
if (canDecorate) {
|
||||
try {
|
||||
defineInnerHTML(template);
|
||||
defineOuterHTML(template);
|
||||
} catch (err) {
|
||||
canDecorate = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// bootstrap recursively
|
||||
PolyfilledHTMLTemplateElement.bootstrap(template.content);
|
||||
};
|
||||
|
||||
// Taken from https://github.com/jquery/jquery/blob/73d7e6259c63ac45f42c6593da8c2796c6ce9281/src/manipulation/wrapMap.js
|
||||
var topLevelWrappingMap = {
|
||||
'option': ['select'],
|
||||
'thead': ['table'],
|
||||
'col': ['colgroup', 'table'],
|
||||
'tr': ['tbody', 'table'],
|
||||
'th': ['tr', 'tbody', 'table'],
|
||||
'td': ['tr', 'tbody', 'table']
|
||||
};
|
||||
|
||||
var getTagName = function(text) {
|
||||
// Taken from https://github.com/jquery/jquery/blob/73d7e6259c63ac45f42c6593da8c2796c6ce9281/src/manipulation/var/rtagName.js
|
||||
return ( /<([a-z][^/\0>\x20\t\r\n\f]+)/i.exec(text) || ['', ''])[1].toLowerCase();
|
||||
};
|
||||
|
||||
var defineInnerHTML = function defineInnerHTML(obj) {
|
||||
Object.defineProperty(obj, 'innerHTML', {
|
||||
get: function() {
|
||||
return getInnerHTML(this);
|
||||
},
|
||||
set: function(text) {
|
||||
// For IE11, wrap the text in the correct (table) context
|
||||
var wrap = topLevelWrappingMap[getTagName(text)];
|
||||
if (wrap) {
|
||||
for (var i = 0; i < wrap.length; i++) {
|
||||
text = '<' + wrap[i] + '>' + text + '</' + wrap[i] + '>';
|
||||
}
|
||||
}
|
||||
contentDoc.body.innerHTML = text;
|
||||
PolyfilledHTMLTemplateElement.bootstrap(contentDoc);
|
||||
while (this.content.firstChild) {
|
||||
capturedRemoveChild.call(this.content, this.content.firstChild);
|
||||
}
|
||||
var body = contentDoc.body;
|
||||
// If we had wrapped, get back to the original node
|
||||
if (wrap) {
|
||||
for (var j = 0; j < wrap.length; j++) {
|
||||
body = body.lastChild;
|
||||
}
|
||||
}
|
||||
while (body.firstChild) {
|
||||
capturedAppendChild.call(this.content, body.firstChild);
|
||||
}
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
};
|
||||
|
||||
var defineOuterHTML = function defineOuterHTML(obj) {
|
||||
Object.defineProperty(obj, 'outerHTML', {
|
||||
get: function() {
|
||||
return '<' + TEMPLATE_TAG + '>' + this.innerHTML + '</' + TEMPLATE_TAG + '>';
|
||||
},
|
||||
set: function(innerHTML) {
|
||||
if (this.parentNode) {
|
||||
contentDoc.body.innerHTML = innerHTML;
|
||||
var docFrag = this.ownerDocument.createDocumentFragment();
|
||||
while (contentDoc.body.firstChild) {
|
||||
capturedAppendChild.call(docFrag, contentDoc.body.firstChild);
|
||||
}
|
||||
capturedReplaceChild.call(this.parentNode, docFrag, this);
|
||||
} else {
|
||||
throw new Error("Failed to set the 'outerHTML' property on 'Element': This element has no parent node.");
|
||||
}
|
||||
},
|
||||
configurable: true
|
||||
});
|
||||
};
|
||||
|
||||
defineInnerHTML(PolyfilledHTMLTemplateElement.prototype);
|
||||
defineOuterHTML(PolyfilledHTMLTemplateElement.prototype);
|
||||
|
||||
/**
|
||||
The `bootstrap` method is called automatically and "fixes" all
|
||||
<template> elements in the document referenced by the `doc` argument.
|
||||
*/
|
||||
PolyfilledHTMLTemplateElement.bootstrap = function bootstrap(doc) {
|
||||
var templates = QSA(doc, TEMPLATE_TAG);
|
||||
for (var i=0, l=templates.length, t; (i<l) && (t=templates[i]); i++) {
|
||||
PolyfilledHTMLTemplateElement.decorate(t);
|
||||
}
|
||||
};
|
||||
|
||||
// auto-bootstrapping for main document
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
PolyfilledHTMLTemplateElement.bootstrap(document);
|
||||
});
|
||||
|
||||
// Patch document.createElement to ensure newly created templates have content
|
||||
Document.prototype.createElement = function createElement() {
|
||||
var el = capturedCreateElement.apply(this, arguments);
|
||||
if (el.localName === 'template') {
|
||||
PolyfilledHTMLTemplateElement.decorate(el);
|
||||
}
|
||||
return el;
|
||||
};
|
||||
|
||||
DOMParser.prototype.parseFromString = function() {
|
||||
var el = capturedParseFromString.apply(this, arguments);
|
||||
PolyfilledHTMLTemplateElement.bootstrap(el);
|
||||
return el;
|
||||
};
|
||||
|
||||
Object.defineProperty(HTMLElement.prototype, 'innerHTML', {
|
||||
get: function() {
|
||||
return getInnerHTML(this);
|
||||
},
|
||||
set: function(text) {
|
||||
capturedHTMLElementInnerHTML.set.call(this, text);
|
||||
PolyfilledHTMLTemplateElement.bootstrap(this);
|
||||
},
|
||||
configurable: true,
|
||||
enumerable: true
|
||||
});
|
||||
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#escapingString
|
||||
var escapeAttrRegExp = /[&\u00A0"]/g;
|
||||
var escapeDataRegExp = /[&\u00A0<>]/g;
|
||||
|
||||
var escapeReplace = function(c) {
|
||||
switch (c) {
|
||||
case '&':
|
||||
return '&';
|
||||
case '<':
|
||||
return '<';
|
||||
case '>':
|
||||
return '>';
|
||||
case '"':
|
||||
return '"';
|
||||
case '\u00A0':
|
||||
return ' ';
|
||||
}
|
||||
};
|
||||
|
||||
var escapeAttr = function(s) {
|
||||
return s.replace(escapeAttrRegExp, escapeReplace);
|
||||
};
|
||||
|
||||
var escapeData = function(s) {
|
||||
return s.replace(escapeDataRegExp, escapeReplace);
|
||||
};
|
||||
|
||||
var makeSet = function(arr) {
|
||||
var set = {};
|
||||
for (var i = 0; i < arr.length; i++) {
|
||||
set[arr[i]] = true;
|
||||
}
|
||||
return set;
|
||||
};
|
||||
|
||||
// http://www.whatwg.org/specs/web-apps/current-work/#void-elements
|
||||
var voidElements = makeSet([
|
||||
'area',
|
||||
'base',
|
||||
'br',
|
||||
'col',
|
||||
'command',
|
||||
'embed',
|
||||
'hr',
|
||||
'img',
|
||||
'input',
|
||||
'keygen',
|
||||
'link',
|
||||
'meta',
|
||||
'param',
|
||||
'source',
|
||||
'track',
|
||||
'wbr'
|
||||
]);
|
||||
|
||||
var plaintextParents = makeSet([
|
||||
'style',
|
||||
'script',
|
||||
'xmp',
|
||||
'iframe',
|
||||
'noembed',
|
||||
'noframes',
|
||||
'plaintext',
|
||||
'noscript'
|
||||
]);
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @param {Node} parentNode
|
||||
* @param {Function=} callback
|
||||
*/
|
||||
var getOuterHTML = function(node, parentNode, callback) {
|
||||
switch (node.nodeType) {
|
||||
case Node.ELEMENT_NODE: {
|
||||
var tagName = node.localName;
|
||||
var s = '<' + tagName;
|
||||
var attrs = node.attributes;
|
||||
for (var i = 0, attr; (attr = attrs[i]); i++) {
|
||||
s += ' ' + attr.name + '="' + escapeAttr(attr.value) + '"';
|
||||
}
|
||||
s += '>';
|
||||
if (voidElements[tagName]) {
|
||||
return s;
|
||||
}
|
||||
return s + getInnerHTML(node, callback) + '</' + tagName + '>';
|
||||
}
|
||||
case Node.TEXT_NODE: {
|
||||
var data = /** @type {Text} */ (node).data;
|
||||
if (parentNode && plaintextParents[parentNode.localName]) {
|
||||
return data;
|
||||
}
|
||||
return escapeData(data);
|
||||
}
|
||||
case Node.COMMENT_NODE: {
|
||||
return '<!--' + /** @type {Comment} */ (node).data + '-->';
|
||||
}
|
||||
default: {
|
||||
window.console.error(node);
|
||||
throw new Error('not implemented');
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {Node} node
|
||||
* @param {Function=} callback
|
||||
*/
|
||||
var getInnerHTML = function(node, callback) {
|
||||
if (node.localName === 'template') {
|
||||
node = /** @type {HTMLTemplateElement} */ (node).content;
|
||||
}
|
||||
var s = '';
|
||||
var c$ = callback ? callback(node) : capturedChildNodes.get.call(node);
|
||||
for (var i=0, l=c$.length, child; (i<l) && (child=c$[i]); i++) {
|
||||
s += getOuterHTML(child, node, callback);
|
||||
}
|
||||
return s;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// make cloning/importing work!
|
||||
if (needsTemplate || needsCloning) {
|
||||
|
||||
PolyfilledHTMLTemplateElement._cloneNode = function _cloneNode(template, deep) {
|
||||
var clone = capturedCloneNode.call(template, false);
|
||||
// NOTE: decorate doesn't auto-fix children because they are already
|
||||
// decorated so they need special clone fixup.
|
||||
if (this.decorate) {
|
||||
this.decorate(clone);
|
||||
}
|
||||
if (deep) {
|
||||
// NOTE: use native clone node to make sure CE's wrapped
|
||||
// cloneNode does not cause elements to upgrade.
|
||||
capturedAppendChild.call(clone.content, capturedCloneNode.call(template.content, true));
|
||||
// now ensure nested templates are cloned correctly.
|
||||
fixClonedDom(clone.content, template.content);
|
||||
}
|
||||
return clone;
|
||||
};
|
||||
|
||||
// Given a source and cloned subtree, find <template>'s in the cloned
|
||||
// subtree and replace them with cloned <template>'s from source.
|
||||
// We must do this because only the source templates have proper .content.
|
||||
var fixClonedDom = function fixClonedDom(clone, source) {
|
||||
// do nothing if cloned node is not an element
|
||||
if (!source.querySelectorAll) return;
|
||||
// these two lists should be coincident
|
||||
var s$ = QSA(source, TEMPLATE_TAG);
|
||||
if (s$.length === 0) {
|
||||
return;
|
||||
}
|
||||
var t$ = QSA(clone, TEMPLATE_TAG);
|
||||
for (var i=0, l=t$.length, t, s; i<l; i++) {
|
||||
s = s$[i];
|
||||
t = t$[i];
|
||||
if (PolyfilledHTMLTemplateElement && PolyfilledHTMLTemplateElement.decorate) {
|
||||
PolyfilledHTMLTemplateElement.decorate(s);
|
||||
}
|
||||
capturedReplaceChild.call(t.parentNode, cloneNode.call(s, true), t);
|
||||
}
|
||||
};
|
||||
|
||||
// make sure scripts inside of a cloned template are executable
|
||||
var fixClonedScripts = function fixClonedScripts(fragment) {
|
||||
var scripts = QSA(fragment, scriptSelector);
|
||||
for (var ns, s, i = 0; i < scripts.length; i++) {
|
||||
s = scripts[i];
|
||||
ns = capturedCreateElement.call(document, 'script');
|
||||
ns.textContent = s.textContent;
|
||||
var attrs = s.attributes;
|
||||
for (var ai = 0, a; ai < attrs.length; ai++) {
|
||||
a = attrs[ai];
|
||||
ns.setAttribute(a.name, a.value);
|
||||
}
|
||||
capturedReplaceChild.call(s.parentNode, ns, s);
|
||||
}
|
||||
};
|
||||
|
||||
// override all cloning to fix the cloned subtree to contain properly
|
||||
// cloned templates.
|
||||
var cloneNode = Node.prototype.cloneNode = function cloneNode(deep) {
|
||||
var dom;
|
||||
// workaround for Edge bug cloning documentFragments
|
||||
// https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/8619646/
|
||||
if (!needsDocFrag && brokenDocFragment && this instanceof DocumentFragment) {
|
||||
if (!deep) {
|
||||
return this.ownerDocument.createDocumentFragment();
|
||||
} else {
|
||||
dom = importNode.call(this.ownerDocument, this, true);
|
||||
}
|
||||
} else if (this.nodeType === Node.ELEMENT_NODE &&
|
||||
this.localName === TEMPLATE_TAG &&
|
||||
this.namespaceURI == document.documentElement.namespaceURI) {
|
||||
dom = PolyfilledHTMLTemplateElement._cloneNode(this, deep);
|
||||
} else {
|
||||
dom = capturedCloneNode.call(this, deep);
|
||||
}
|
||||
// template.content is cloned iff `deep`.
|
||||
if (deep) {
|
||||
fixClonedDom(dom, this);
|
||||
}
|
||||
return dom;
|
||||
};
|
||||
|
||||
// NOTE: we are cloning instead of importing <template>'s.
|
||||
// However, the ownerDocument of the cloned template will be correct!
|
||||
// This is because the native import node creates the right document owned
|
||||
// subtree and `fixClonedDom` inserts cloned templates into this subtree,
|
||||
// thus updating the owner doc.
|
||||
var importNode = Document.prototype.importNode = function importNode(element, deep) {
|
||||
deep = deep || false;
|
||||
if (element.localName === TEMPLATE_TAG) {
|
||||
return PolyfilledHTMLTemplateElement._cloneNode(element, deep);
|
||||
} else {
|
||||
var dom = capturedImportNode.call(this, element, deep);
|
||||
if (deep) {
|
||||
fixClonedDom(dom, element);
|
||||
fixClonedScripts(dom);
|
||||
}
|
||||
return dom;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (needsTemplate) {
|
||||
window.HTMLTemplateElement = PolyfilledHTMLTemplateElement;
|
||||
}
|
||||
|
||||
})();
|
@@ -0,0 +1,61 @@
|
||||
import Translator from './i18n'
|
||||
|
||||
export function copyTextToClipboard (text) {
|
||||
let t = new Translator($('html').attr('lang'))
|
||||
var textArea = document.createElement('textarea')
|
||||
|
||||
//
|
||||
// *** This styling is an extra step which is likely not required. ***
|
||||
//
|
||||
// Why is it here? To ensure:
|
||||
// 1. the element is able to have focus and selection.
|
||||
// 2. if element was to flash render it has minimal visual impact.
|
||||
// 3. less flakyness with selection and copying which **might** occur if
|
||||
// the textarea element is not visible.
|
||||
//
|
||||
// The likelihood is the element won't even render, not even a flash,
|
||||
// so some of these are just precautions. However in IE the element
|
||||
// is visible whilst the popup box asking the user for permission for
|
||||
// the web page to copy to the clipboard.
|
||||
//
|
||||
|
||||
// Place in top-left corner of screen regardless of scroll position.
|
||||
textArea.style.position = 'fixed'
|
||||
textArea.style.top = 0
|
||||
textArea.style.left = 0
|
||||
|
||||
// Ensure it has a small width and height. Setting to 1px / 1em
|
||||
// doesn't work as this gives a negative w/h on some browsers.
|
||||
textArea.style.width = '2em'
|
||||
textArea.style.height = '2em'
|
||||
|
||||
// We don't need padding, reducing the size if it does flash render.
|
||||
textArea.style.padding = 0
|
||||
|
||||
// Clean up any borders.
|
||||
textArea.style.border = 'none'
|
||||
textArea.style.outline = 'none'
|
||||
textArea.style.boxShadow = 'none'
|
||||
|
||||
// Avoid flash of white box if rendered for any reason.
|
||||
textArea.style.background = 'transparent'
|
||||
|
||||
textArea.value = text
|
||||
|
||||
document.body.appendChild(textArea)
|
||||
|
||||
textArea.select()
|
||||
|
||||
try {
|
||||
var successful = document.execCommand('copy')
|
||||
var msg = successful ? 'successful' : 'unsuccessful'
|
||||
console.log('Copying text command was ' + msg)
|
||||
} catch (err) {
|
||||
window.prompt(
|
||||
t.get('cannotCopyToClipboardMessage'),
|
||||
text
|
||||
)
|
||||
}
|
||||
|
||||
document.body.removeChild(textArea)
|
||||
}
|
@@ -0,0 +1,71 @@
|
||||
export const messages = {
|
||||
unsavedChangesAlert: {
|
||||
en: 'You have some unsaved changes.',
|
||||
it: 'Alcune modifiche non sono state salvate.'
|
||||
},
|
||||
uploading: {
|
||||
en: 'Uploading...',
|
||||
it: 'Uploading...'
|
||||
},
|
||||
filter: {
|
||||
en: 'Filter',
|
||||
it: 'Filtra'
|
||||
},
|
||||
close: {
|
||||
en: 'Close',
|
||||
it: 'Chiudi'
|
||||
},
|
||||
save: {
|
||||
en: 'Save',
|
||||
it: 'Salva'
|
||||
},
|
||||
search: {
|
||||
en: 'Search',
|
||||
it: 'Cerca'
|
||||
},
|
||||
cannotCopyToClipboardMessage: {
|
||||
en: 'Cannot copy to clipboard, please do it manually: Ctrl+C, Enter',
|
||||
it: 'Impossibile copiare negli appunti, copiare manualmente: Ctrl+C, Enter'
|
||||
},
|
||||
retrieveDataError: {
|
||||
en: 'There was an error retrieving the data',
|
||||
it: 'Si è verificato un errore nel reuperare i dati'
|
||||
}
|
||||
}
|
||||
|
||||
export default class Translator {
|
||||
constructor (lng) {
|
||||
this.lng = this.setLng(lng)
|
||||
}
|
||||
|
||||
setLng (lng) {
|
||||
if (lng === 'it' || /it-/.test(lng)) {
|
||||
return 'it'
|
||||
} else if (lng === 'en' || /en-/.test(lng)) {
|
||||
return 'en'
|
||||
}
|
||||
|
||||
return lng
|
||||
}
|
||||
|
||||
get (key) {
|
||||
// check custom translations first
|
||||
let b = window.Baton
|
||||
if (b.translations && b.translations[key] !== 'undefined') {
|
||||
return b.translations[key]
|
||||
}
|
||||
|
||||
// if key is not found, return empty string
|
||||
if (typeof messages[key] === 'undefined') {
|
||||
return ''
|
||||
}
|
||||
|
||||
// search localized message
|
||||
if (messages[key][this.lng] !== undefined) {
|
||||
return messages[key][this.lng]
|
||||
}
|
||||
|
||||
// default to english
|
||||
return messages[key]['en']
|
||||
}
|
||||
}
|
@@ -0,0 +1,14 @@
|
||||
<svg width="15" height="60" viewBox="0 0 1792 7168" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<g id="previous">
|
||||
<path d="M1037 1395l102-102q19-19 19-45t-19-45l-307-307 307-307q19-19 19-45t-19-45l-102-102q-19-19-45-19t-45 19l-454 454q-19 19-19 45t19 45l454 454q19 19 45 19t45-19zm627-499q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
|
||||
</g>
|
||||
<g id="next">
|
||||
<path d="M845 1395l454-454q19-19 19-45t-19-45l-454-454q-19-19-45-19t-45 19l-102 102q-19 19-19 45t19 45l307 307-307 307q-19 19-19 45t19 45l102 102q19 19 45 19t45-19zm819-499q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
|
||||
</g>
|
||||
</defs>
|
||||
<use xlink:href="#previous" x="0" y="0" fill="#333333" />
|
||||
<use xlink:href="#previous" x="0" y="1792" fill="#000000" />
|
||||
<use xlink:href="#next" x="0" y="3584" fill="#333333" />
|
||||
<use xlink:href="#next" x="0" y="5376" fill="#000000" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="13" height="13" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="#666666" d="M1024 1376v-192q0-14-9-23t-23-9h-192q-14 0-23 9t-9 23v192q0 14 9 23t23 9h192q14 0 23-9t9-23zm256-672q0-88-55.5-163t-138.5-116-170-41q-243 0-371 213-15 24 8 42l132 100q7 6 19 6 16 0 25-12 53-68 86-92 34-24 86-24 48 0 85.5 26t37.5 59q0 38-20 61t-68 45q-63 28-115.5 86.5t-52.5 125.5v36q0 14 9 23t23 9h192q14 0 23-9t9-23q0-19 21.5-49.5t54.5-49.5q32-18 49-28.5t46-35 44.5-48 28-60.5 12.5-81zm384 192q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 655 B |
@@ -0,0 +1,3 @@
|
||||
<svg width="15" height="15" viewBox="0 0 1792 1792" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill="#555555" d="M1216 832q0-185-131.5-316.5t-316.5-131.5-316.5 131.5-131.5 316.5 131.5 316.5 316.5 131.5 316.5-131.5 131.5-316.5zm512 832q0 52-38 90t-90 38q-54 0-90-38l-343-342q-179 124-399 124-143 0-273.5-55.5t-225-150-150-225-55.5-273.5 55.5-273.5 150-225 225-150 273.5-55.5 273.5 55.5 225 150 150 225 55.5 273.5q0 220-124 399l343 343q37 37 37 90z"/>
|
||||
</svg>
|
After Width: | Height: | Size: 458 B |
@@ -0,0 +1,34 @@
|
||||
<svg width="16" height="192" viewBox="0 0 1792 21504" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<g id="up">
|
||||
<path d="M1412 895q0-27-18-45l-362-362-91-91q-18-18-45-18t-45 18l-91 91-362 362q-18 18-18 45t18 45l91 91q18 18 45 18t45-18l189-189v502q0 26 19 45t45 19h128q26 0 45-19t19-45v-502l189 189q19 19 45 19t45-19l91-91q18-18 18-45zm252 1q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
|
||||
</g>
|
||||
<g id="down">
|
||||
<path d="M1412 897q0-27-18-45l-91-91q-18-18-45-18t-45 18l-189 189v-502q0-26-19-45t-45-19h-128q-26 0-45 19t-19 45v502l-189-189q-19-19-45-19t-45 19l-91 91q-18 18-18 45t18 45l362 362 91 91q18 18 45 18t45-18l91-91 362-362q18-18 18-45zm252-1q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
|
||||
</g>
|
||||
<g id="left">
|
||||
<path d="M1408 960v-128q0-26-19-45t-45-19h-502l189-189q19-19 19-45t-19-45l-91-91q-18-18-45-18t-45 18l-362 362-91 91q-18 18-18 45t18 45l91 91 362 362q18 18 45 18t45-18l91-91q18-18 18-45t-18-45l-189-189h502q26 0 45-19t19-45zm256-64q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
|
||||
</g>
|
||||
<g id="right">
|
||||
<path d="M1413 896q0-27-18-45l-91-91-362-362q-18-18-45-18t-45 18l-91 91q-18 18-18 45t18 45l189 189h-502q-26 0-45 19t-19 45v128q0 26 19 45t45 19h502l-189 189q-19 19-19 45t19 45l91 91q18 18 45 18t45-18l362-362 91-91q18-18 18-45zm251 0q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
|
||||
</g>
|
||||
<g id="clearall">
|
||||
<path transform="translate(336, 336) scale(0.75)" d="M1037 1395l102-102q19-19 19-45t-19-45l-307-307 307-307q19-19 19-45t-19-45l-102-102q-19-19-45-19t-45 19l-454 454q-19 19-19 45t19 45l454 454q19 19 45 19t45-19zm627-499q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
|
||||
</g>
|
||||
<g id="chooseall">
|
||||
<path transform="translate(336, 336) scale(0.75)" d="M845 1395l454-454q19-19 19-45t-19-45l-454-454q-19-19-45-19t-45 19l-102 102q-19 19-19 45t19 45l307 307-307 307q-19 19-19 45t19 45l102 102q19 19 45 19t45-19zm819-499q0 209-103 385.5t-279.5 279.5-385.5 103-385.5-103-279.5-279.5-103-385.5 103-385.5 279.5-279.5 385.5-103 385.5 103 279.5 279.5 103 385.5z"/>
|
||||
</g>
|
||||
</defs>
|
||||
<use xlink:href="#up" x="0" y="0" fill="#666666" />
|
||||
<use xlink:href="#up" x="0" y="1792" fill="#447e9b" />
|
||||
<use xlink:href="#down" x="0" y="3584" fill="#666666" />
|
||||
<use xlink:href="#down" x="0" y="5376" fill="#447e9b" />
|
||||
<use xlink:href="#left" x="0" y="7168" fill="#666666" />
|
||||
<use xlink:href="#left" x="0" y="8960" fill="#447e9b" />
|
||||
<use xlink:href="#right" x="0" y="10752" fill="#666666" />
|
||||
<use xlink:href="#right" x="0" y="12544" fill="#447e9b" />
|
||||
<use xlink:href="#clearall" x="0" y="14336" fill="#666666" />
|
||||
<use xlink:href="#clearall" x="0" y="16128" fill="#447e9b" />
|
||||
<use xlink:href="#chooseall" x="0" y="17920" fill="#666666" />
|
||||
<use xlink:href="#chooseall" x="0" y="19712" fill="#447e9b" />
|
||||
</svg>
|
After Width: | Height: | Size: 3.2 KiB |
@@ -0,0 +1,19 @@
|
||||
<svg width="14" height="84" viewBox="0 0 1792 10752" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<defs>
|
||||
<g id="sort">
|
||||
<path d="M1408 1088q0 26-19 45l-448 448q-19 19-45 19t-45-19l-448-448q-19-19-19-45t19-45 45-19h896q26 0 45 19t19 45zm0-384q0 26-19 45t-45 19h-896q-26 0-45-19t-19-45 19-45l448-448q19-19 45-19t45 19l448 448q19 19 19 45z"/>
|
||||
</g>
|
||||
<g id="ascending">
|
||||
<path d="M1408 1216q0 26-19 45t-45 19h-896q-26 0-45-19t-19-45 19-45l448-448q19-19 45-19t45 19l448 448q19 19 19 45z"/>
|
||||
</g>
|
||||
<g id="descending">
|
||||
<path d="M1408 704q0 26-19 45l-448 448q-19 19-45 19t-45-19l-448-448q-19-19-19-45t19-45 45-19h896q26 0 45 19t19 45z"/>
|
||||
</g>
|
||||
</defs>
|
||||
<use xlink:href="#sort" x="0" y="0" fill="#999999" />
|
||||
<use xlink:href="#sort" x="0" y="1792" fill="#447e9b" />
|
||||
<use xlink:href="#ascending" x="0" y="3584" fill="#999999" />
|
||||
<use xlink:href="#ascending" x="0" y="5376" fill="#447e9b" />
|
||||
<use xlink:href="#descending" x="0" y="7168" fill="#999999" />
|
||||
<use xlink:href="#descending" x="0" y="8960" fill="#447e9b" />
|
||||
</svg>
|
After Width: | Height: | Size: 1.1 KiB |
110
venv/Lib/site-packages/baton/static/baton/app/src/index.js
Normal file
@@ -0,0 +1,110 @@
|
||||
// jQuery is provided by webpack provider plugin
|
||||
import bootstrap from 'bootstrap/dist/js/bootstrap.bundle'
|
||||
import './styles/baton.scss'
|
||||
|
||||
import Dispatcher from 'js-event-dispatcher/dist/EventDispatcher'
|
||||
import Navbar from './core/Navbar'
|
||||
import Footer from './core/Footer'
|
||||
import Menu from './core/Menu'
|
||||
import ActionResult from './core/ActionResult'
|
||||
import PasswordChange from './core/PasswordChange'
|
||||
import Analytics from './core/Analytics'
|
||||
import Tabs from './core/Tabs'
|
||||
import ChangeList from './core/ChangeList'
|
||||
import ChangeForm from './core/ChangeForm'
|
||||
import Login from './core/Login'
|
||||
import AdminDocs from './core/AdminDocs'
|
||||
import Filer from './core/Filer'
|
||||
import Modal from './core/Modal'
|
||||
import Messages from './core/Messages'
|
||||
|
||||
window.Baton = {
|
||||
intialized: false,
|
||||
init: function (config) {
|
||||
console.info('Baton:', 'init')
|
||||
console.info('Baton:', `rev ${BATON_REVISION}`)
|
||||
this.initialized = true
|
||||
let page = this.detectPageHook ? this.detectPageHook(this.page) : this.page()
|
||||
$('body').addClass('page-' + page)
|
||||
|
||||
// toasts
|
||||
Messages.init(config)
|
||||
|
||||
Navbar.init(config)
|
||||
Dispatcher.emit('onNavbarReady')
|
||||
if (page !== 'login' && page !== 'logout' && !/_popup/.test(location.search)) {
|
||||
Menu.init(config, Dispatcher)
|
||||
}
|
||||
if (page === 'login') {
|
||||
Login.init(config)
|
||||
} else if (page === 'logout' || page === 'password_change_success') {
|
||||
ActionResult.init()
|
||||
} else if (page === 'password_change') {
|
||||
PasswordChange.init()
|
||||
} else if (page === 'changelist') {
|
||||
ChangeList.init(config)
|
||||
} else if (page === 'add_form' || page === 'change_form') {
|
||||
ChangeForm.init(config)
|
||||
} else if (page === 'admindocs') {
|
||||
AdminDocs.init()
|
||||
} else if (page === 'filer') {
|
||||
Filer.init()
|
||||
}
|
||||
Footer.init({
|
||||
remove: /_popup/.test(location.search)
|
||||
})
|
||||
|
||||
// tabs
|
||||
if (page === 'add_form' || page === 'change_form') {
|
||||
Tabs.init(Dispatcher)
|
||||
}
|
||||
|
||||
// tooltips
|
||||
setTimeout(this.loadTooltips, 1000) // wait a bit for tinymce
|
||||
|
||||
console.info('Baton:', 'ready')
|
||||
document.body.className += ' baton-ready'
|
||||
if (config.menuAlwaysCollapsed) {
|
||||
document.body.className += ' menu-mobile'
|
||||
}
|
||||
Dispatcher.emit('onReady')
|
||||
},
|
||||
loadTooltips: function () {
|
||||
let tooltipTriggerList = [].slice.call($('[title]:not(iframe)'))
|
||||
tooltipTriggerList.map(function (tooltipTriggerEl) {
|
||||
return new bootstrap.Tooltip(tooltipTriggerEl)
|
||||
})
|
||||
},
|
||||
page: function () {
|
||||
if (/^(\/[a-z]{2})?\/admin\/$/.test(location.pathname)) {
|
||||
return 'dashboard'
|
||||
} else if (/^(\/[a-z]{2})?\/admin\/doc\//.test(location.pathname)) {
|
||||
return 'admindocs'
|
||||
} else if (/^(\/[a-z]{2})?\/admin\/login\/$/.test(location.pathname)) {
|
||||
return 'login'
|
||||
} else if (/^(\/[a-z]{2})?\/admin\/logout\/$/.test(location.pathname)) {
|
||||
return 'logout'
|
||||
} else if (/^(\/[a-z]{2})?\/admin\/password_change\/$/.test(location.pathname)) {
|
||||
return 'password_change'
|
||||
} else if (/^(\/[a-z]{2})?\/admin\/password_change\/done\/$/.test(location.pathname)) {
|
||||
return 'password_change_success'
|
||||
} else if (/\/add\//.test(location.pathname)) {
|
||||
return 'add_form'
|
||||
} else if (/\/change\//.test(location.pathname)) {
|
||||
return 'change_form'
|
||||
} else if (document.getElementById('changelist')) {
|
||||
return 'changelist'
|
||||
} else if (document.getElementById('change-history') || /^(\/[a-z]{2})?\/admin\/[^/]+\/[^/]+\/[^/]+\/history/.test(location.pathname)) {
|
||||
return 'changehistory'
|
||||
} else if (/\/filer\//.test(location.pathname)) {
|
||||
return 'filer'
|
||||
} else {
|
||||
return 'default'
|
||||
}
|
||||
},
|
||||
Analytics: Analytics,
|
||||
Dispatcher: Dispatcher,
|
||||
Modal: Modal
|
||||
}
|
||||
|
||||
window.jQuery = jQuery
|
@@ -0,0 +1,19 @@
|
||||
// scss-lint:disable IdSelector PlaceholderInExtend SelectorDepth NestingDepth
|
||||
|
||||
.actionresult {
|
||||
#content {
|
||||
h1 + p {
|
||||
@extend .pt-3;
|
||||
}
|
||||
|
||||
> p {
|
||||
@extend .ps-3;
|
||||
@extend .pe-3;
|
||||
|
||||
a {
|
||||
@extend .btn;
|
||||
@extend .btn-secondary;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,115 @@
|
||||
.page-admindocs {
|
||||
.admindocs-body {
|
||||
padding: 0 1rem;
|
||||
|
||||
#content-main {
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: 1.5rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
.subhead {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.help {
|
||||
@extend .alert;
|
||||
@extend .alert-info;
|
||||
|
||||
&::before {
|
||||
content: '\f05a';
|
||||
display: inline-block;
|
||||
font-family: 'Font Awesome\ 5 Free';
|
||||
margin-right: .5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.simple {
|
||||
background: $admindocs-simple-bg;
|
||||
padding-bottom: .5rem;
|
||||
padding-top: 1rem;
|
||||
}
|
||||
|
||||
pre {
|
||||
background: $admindocs-pre-bg;
|
||||
color: $admindocs-pre-color;
|
||||
font-size: .8rem;
|
||||
padding: 1rem;
|
||||
}
|
||||
|
||||
table {
|
||||
@extend .table;
|
||||
border: $admindocs-table-border-color !important;
|
||||
}
|
||||
|
||||
.module {
|
||||
background: $admindocs-module-bg;
|
||||
margin-bottom: 1rem;
|
||||
max-width: 100%;
|
||||
overflow: auto;
|
||||
|
||||
h2 {
|
||||
background: $admindocs-module-header-bg;
|
||||
border: 1px solid $admindocs-module-header-border-color;
|
||||
font-size: 1.4rem;
|
||||
padding: .5rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
color: $base;
|
||||
font-size: 1.4rem;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-size: 1.2rem;
|
||||
}
|
||||
|
||||
table {
|
||||
@extend .table;
|
||||
|
||||
thead {
|
||||
@extend .table-dark;
|
||||
}
|
||||
}
|
||||
|
||||
> h3, > p, > h4, > dl {
|
||||
padding-left: .5rem;
|
||||
padding-right: .5rem;
|
||||
}
|
||||
}
|
||||
|
||||
.small a {
|
||||
@extend .btn;
|
||||
@extend .btn-sm;
|
||||
@extend .btn-secondary;
|
||||
}
|
||||
}
|
||||
|
||||
.colSM .admindocs-body {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
#content-main {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
#content-related {
|
||||
order: 1;
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
margin-right: 1rem;
|
||||
padding-top: 1rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,19 @@
|
||||
$white: #fff;
|
||||
|
||||
.container-analytics {
|
||||
width: 100%;
|
||||
|
||||
h1 {
|
||||
font-size: $h1-size;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: $h2-size;
|
||||
}
|
||||
|
||||
.chart-container {
|
||||
background: $chart-bg;
|
||||
border: 1px solid $chart-border-color;
|
||||
padding: 15px;
|
||||
}
|
||||
}
|
@@ -0,0 +1,18 @@
|
||||
// scss-lint:disable IdSelector PlaceholderInExtend NestingDepth
|
||||
.breadcrumbs {
|
||||
@extend .p-3;
|
||||
background: $breadcrumbs-bg;
|
||||
// border-bottom: 1px solid $breadcrumbs-border-color;
|
||||
line-height: 1.9;
|
||||
word-spacing: 5px;
|
||||
|
||||
a {
|
||||
&:first-child {
|
||||
&::before {
|
||||
@extend %font-awesome;
|
||||
@extend .me-1;
|
||||
content: '\f015';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,195 @@
|
||||
// scss-lint:disable all
|
||||
/* CALENDARS & CLOCKS */
|
||||
|
||||
.calendarbox,
|
||||
.clockbox {
|
||||
margin: 5px auto;
|
||||
font-size: 12px;
|
||||
width: 19em;
|
||||
text-align: center;
|
||||
background: white;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.15);
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.clockbox {
|
||||
width: auto;
|
||||
|
||||
h2 {
|
||||
background: $clockbox-title-bg;
|
||||
border-bottom: 1px solid $clockbox-title-border-color;
|
||||
font-size: 1rem;
|
||||
padding: 0.5rem 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.calendar {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.calendar table {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
border-collapse: collapse;
|
||||
background: white;
|
||||
width: 100%;
|
||||
|
||||
caption {
|
||||
caption-side: top;
|
||||
}
|
||||
}
|
||||
|
||||
.calendar caption,
|
||||
.calendarbox h2 {
|
||||
margin: 0;
|
||||
text-align: center;
|
||||
border-top: none;
|
||||
background: #f5dd5d;
|
||||
font-weight: 700;
|
||||
font-size: 12px;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.calendar th {
|
||||
padding: 8px 5px;
|
||||
background: #f8f8f8;
|
||||
border-bottom: 1px solid #ddd;
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
color: #666;
|
||||
}
|
||||
|
||||
.calendar td {
|
||||
font-weight: 400;
|
||||
font-size: 12px;
|
||||
text-align: center;
|
||||
padding: 0;
|
||||
border-top: 1px solid #eee;
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.calendar td.selected a {
|
||||
background: #79aec8;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.calendar td.nonday {
|
||||
background: #f8f8f8;
|
||||
}
|
||||
|
||||
.calendar td.today a {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.calendar td a,
|
||||
.timelist a {
|
||||
display: block;
|
||||
font-weight: 400;
|
||||
padding: 6px;
|
||||
text-decoration: none;
|
||||
color: #444;
|
||||
}
|
||||
|
||||
.calendar td a:focus,
|
||||
.timelist a:focus,
|
||||
.calendar td a:hover,
|
||||
.timelist a:hover {
|
||||
background: #79aec8;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.calendar td a:active,
|
||||
.timelist a:active {
|
||||
background: #417690;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.calendarnav {
|
||||
font-size: 10px;
|
||||
text-align: center;
|
||||
color: #ccc;
|
||||
margin: 0;
|
||||
padding: 1px 3px;
|
||||
}
|
||||
|
||||
.calendarnav a:link,
|
||||
#calendarnav a:visited,
|
||||
#calendarnav a:focus,
|
||||
#calendarnav a:hover {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.calendar-shortcuts {
|
||||
background: white;
|
||||
border-top: 1px solid #eee;
|
||||
font-size: 11px;
|
||||
line-height: 11px;
|
||||
padding: 8px 0;
|
||||
color: #ccc;
|
||||
}
|
||||
|
||||
.calendarbox .calendarnav-previous,
|
||||
.calendarbox .calendarnav-next {
|
||||
display: block;
|
||||
height: 15px;
|
||||
padding: 0;
|
||||
position: absolute;
|
||||
text-indent: -9999px;
|
||||
top: 14px;
|
||||
width: 15px;
|
||||
}
|
||||
|
||||
.calendarnav-previous {
|
||||
background: url(../img/calendar-icons.svg) 0 0 no-repeat;
|
||||
left: 10px;
|
||||
}
|
||||
|
||||
.calendarbox .calendarnav-previous:focus,
|
||||
.calendarbox .calendarnav-previous:hover {
|
||||
background-position: 0 -15px;
|
||||
}
|
||||
|
||||
.calendarnav-next {
|
||||
right: 10px;
|
||||
background: url(../img/calendar-icons.svg) 0 -30px no-repeat;
|
||||
}
|
||||
|
||||
.calendarbox .calendarnav-next:focus,
|
||||
.calendarbox .calendarnav-next:hover {
|
||||
background-position: 0 -45px;
|
||||
}
|
||||
|
||||
.calendar-cancel {
|
||||
margin: 0;
|
||||
padding: 4px 0;
|
||||
font-size: 12px;
|
||||
background: #eee;
|
||||
border-top: 1px solid #ddd;
|
||||
color: #333;
|
||||
}
|
||||
|
||||
.calendar-cancel:focus,
|
||||
.calendar-cancel:hover {
|
||||
background: #ddd;
|
||||
}
|
||||
|
||||
.calendar-cancel a {
|
||||
color: black;
|
||||
display: block;
|
||||
}
|
||||
|
||||
ul.timelist,
|
||||
.timelist li {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.timelist a {
|
||||
padding: 2px;
|
||||
}
|
@@ -0,0 +1,165 @@
|
||||
// scss-lint:disable IdSelector PlaceholderInExtend NestingDepth QualifyingElement SelectorDepth ImportantRule
|
||||
.change-form {
|
||||
#content {
|
||||
form {
|
||||
@extend %admin-form;
|
||||
}
|
||||
}
|
||||
|
||||
#content-main {
|
||||
@extend .container-fluid;
|
||||
}
|
||||
|
||||
.object-tools {
|
||||
@extend .ps-0;
|
||||
@extend .m-2;
|
||||
float: right;
|
||||
list-style-type: none;
|
||||
|
||||
.historylink {
|
||||
&::before {
|
||||
content: '\f017';
|
||||
}
|
||||
}
|
||||
|
||||
.viewsitelink {
|
||||
&::before {
|
||||
content: '\f26c';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.baton-image-preview {
|
||||
height: 100px;
|
||||
|
||||
&:hover {
|
||||
animation: bounce 0.1s;
|
||||
animation-direction: alternate;
|
||||
animation-iteration-count: 4;
|
||||
}
|
||||
}
|
||||
|
||||
.collapse-entry {
|
||||
h3 {
|
||||
cursor: pointer;
|
||||
|
||||
.entry-collapse-toggler {
|
||||
margin-left: 1rem !important;
|
||||
order: 1;
|
||||
|
||||
&::before {
|
||||
color: $collapse-entry-icon-color;
|
||||
content: '\f070';
|
||||
cursor: pointer;
|
||||
font-family: 'Font Awesome\ 5 Free';
|
||||
}
|
||||
|
||||
& + span {
|
||||
margin-left: auto;
|
||||
}
|
||||
}
|
||||
|
||||
&.entry-collapsed {
|
||||
+ fieldset {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.entry-collapse-toggler {
|
||||
&::before {
|
||||
content: '\f06e';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.collapse-entry .last-related, // do not collapse the newly added row
|
||||
.expand-first .inline-related[id$="-0"] {
|
||||
h3 {
|
||||
.entry-collapse-toggler {
|
||||
&::before {
|
||||
content: '\f06e';
|
||||
}
|
||||
}
|
||||
|
||||
+ fieldset {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
&.entry-collapsed {
|
||||
.entry-collapse-toggler {
|
||||
&::before {
|
||||
content: '\f070';
|
||||
}
|
||||
}
|
||||
|
||||
+ fieldset {
|
||||
display: block !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.spinner-overlay {
|
||||
align-items: center;
|
||||
background: $spinner-overlay-bg;
|
||||
bottom: 0;
|
||||
color: $spinner-overlay-fg;
|
||||
display: flex;
|
||||
height: 100%;
|
||||
justify-content: center;
|
||||
left: 0;
|
||||
position: fixed;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 100;
|
||||
|
||||
p {
|
||||
font-size: 3rem;
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
|
||||
// tabs
|
||||
.nav-tabs {
|
||||
.nav-link {
|
||||
background: #fafafa;
|
||||
border: 1px solid #dee2e6;
|
||||
color: #999;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: $gray-700;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&.active {
|
||||
font-weight: bold;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.submit-row + .nav-tabs {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
// padding-top: 1rem;
|
||||
}
|
||||
|
||||
.baton-form-include {
|
||||
display: block;
|
||||
min-width: 100%;
|
||||
}
|
||||
|
||||
.baton-form-include-right {
|
||||
display: inline !important;
|
||||
min-width: auto !important;
|
||||
}
|
||||
|
||||
.change-form #content-main>form .form-row>div.baton-form-include {
|
||||
display: block;
|
||||
}
|
@@ -0,0 +1,33 @@
|
||||
// scss-lint:disable IdSelector PlaceholderInExtend NestingDepth QualifyingElement SelectorDepth ImportantRule
|
||||
body.page-changehistory #content-main {
|
||||
@extend .container-fluid;
|
||||
|
||||
> .module {
|
||||
@extend .p-3;
|
||||
@extend .table-responsive;
|
||||
background: $changehistory-bg;
|
||||
border: 1px solid $changehistory-border-color;
|
||||
margin-top: 15px;
|
||||
|
||||
#change-history {
|
||||
@extend .table;
|
||||
@extend .table-bordered;
|
||||
margin-bottom: 0;
|
||||
|
||||
thead > tr {
|
||||
background: $rl-head-bg;
|
||||
color: $rl-head-color;
|
||||
}
|
||||
|
||||
tbody tr:nth-child(2n + 1) {
|
||||
background: $rl-tr-odd-bg;
|
||||
color: $rl-tr-odd-color;
|
||||
}
|
||||
|
||||
td,
|
||||
th {
|
||||
padding: .3rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,484 @@
|
||||
// scss-lint:disable IdSelector PlaceholderInExtend NestingDepth QualifyingElement SelectorDepth ImportantRule
|
||||
.change-list {
|
||||
#content-main {
|
||||
@extend .container-fluid;
|
||||
}
|
||||
|
||||
.object-tools {
|
||||
.addlink {
|
||||
&::before {
|
||||
content: '\f067';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.select2-container {
|
||||
z-index: 1070;
|
||||
}
|
||||
|
||||
#changelist {
|
||||
border: 1px solid $changelist-border-color;
|
||||
clear: both;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
overflow: hidden;
|
||||
|
||||
.changelist-form-container { // django 3.1.1
|
||||
display: flex;
|
||||
flex: 0 0 100%;
|
||||
flex-wrap: wrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
// no object tools
|
||||
&:first-child {
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
.toplinks {
|
||||
margin-bottom: 0;
|
||||
padding-left: 0;
|
||||
|
||||
li {
|
||||
background: rgba(0, 0, 0, .1);
|
||||
display: inline-block;
|
||||
padding: .2rem 1rem;
|
||||
|
||||
&.date-back {
|
||||
background: $base;
|
||||
a {
|
||||
color: $white;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+ br {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.xfull {
|
||||
overflow: auto;
|
||||
width: 100%;
|
||||
|
||||
.toplinks {
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.date-icon {
|
||||
&::before {
|
||||
@extend %font-awesome;
|
||||
content: '\f073';
|
||||
}
|
||||
}
|
||||
|
||||
.clock-icon {
|
||||
&::before {
|
||||
@extend %font-awesome;
|
||||
content: '\f017';
|
||||
}
|
||||
}
|
||||
|
||||
#result_list {
|
||||
input[type=text],
|
||||
input[type=number],
|
||||
input[type=email],
|
||||
input[type=date] {
|
||||
@extend .form-control;
|
||||
display: inline;
|
||||
height: 28px;
|
||||
margin: 2px 0;
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#toolbar {
|
||||
@extend .mb-0;
|
||||
@extend .p-3;
|
||||
@include make-col(12);
|
||||
background: $toolbar-bg;
|
||||
order: 1;
|
||||
}
|
||||
|
||||
#changelist-search {
|
||||
label,
|
||||
input {
|
||||
display: inline-block !important;
|
||||
}
|
||||
|
||||
label {
|
||||
@extend .pe-2;
|
||||
position: relative;
|
||||
top: -2px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
input[type=text] {
|
||||
@extend .form-control;
|
||||
@extend .form-control-sm;
|
||||
max-width: 160px;
|
||||
}
|
||||
|
||||
input[type=submit] {
|
||||
@extend .btn;
|
||||
@extend .btn-sm;
|
||||
@extend .ms-2;
|
||||
background: $toolbar-btn-bg;
|
||||
margin-top: -3px;
|
||||
max-width: 100px;
|
||||
|
||||
&:hover {
|
||||
background: $toolbar-btn-hover-bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.action-counter {
|
||||
display: block;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
.changelist-filter-toggler {
|
||||
@extend .btn;
|
||||
@extend .btn-info;
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
display: inline;
|
||||
float: right;
|
||||
font-size: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
min-height: 39px;
|
||||
|
||||
&.active {
|
||||
background: $accent;
|
||||
border-color: $accent !important;
|
||||
}
|
||||
|
||||
&.with-actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
float: none;
|
||||
margin-bottom: 0;
|
||||
position: absolute;
|
||||
right: 16px;
|
||||
top: 32px;
|
||||
}
|
||||
|
||||
> span {
|
||||
display: none;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
display: inline-block;
|
||||
margin-left: .5rem;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#changelist-filter {
|
||||
@include make-col(12);
|
||||
background: $filters-bg;
|
||||
max-width: 100%;
|
||||
order: 3;
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
@include make-col(0);
|
||||
max-height: 200px;
|
||||
max-width: 99%;
|
||||
display: none;
|
||||
}
|
||||
|
||||
h2 {
|
||||
background: $filters-title-bg;
|
||||
color: $filters-title-color;
|
||||
font-size: $h2-size;
|
||||
margin-bottom: 0;
|
||||
padding: .5rem 1rem;
|
||||
}
|
||||
|
||||
#changelist-filter-clear {
|
||||
background: $filters-clear-bg;
|
||||
font-size: .9rem;
|
||||
margin-bottom: 0;
|
||||
margin-top: 0;
|
||||
padding: .5rem 1rem;
|
||||
|
||||
a {
|
||||
color: $filters-title-color;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
h3 {
|
||||
font-size: $h3-size;
|
||||
margin-top: 1rem;
|
||||
padding: 0 1rem;
|
||||
|
||||
&:first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
padding-left: 15px;
|
||||
padding-right: 15px;
|
||||
|
||||
.selected {
|
||||
border-left: 5px solid $filter-selected-border-color;
|
||||
margin-left: -15px;
|
||||
padding-left: 10px;
|
||||
}
|
||||
|
||||
.select2-container {
|
||||
outline: 0 !important;
|
||||
min-width: auto !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
|
||||
.select2-selection {
|
||||
max-width: 100% !important;
|
||||
width: 226px !important;
|
||||
}
|
||||
.select2-container--focus,
|
||||
.select2-selection--single:focus {
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 0 0 0.25rem rgba(127, 27, 39, .25) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.changelist-filter-always-open {
|
||||
#changelist-filter,
|
||||
#changelist-form {
|
||||
transition: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
// show filters
|
||||
&.changelist-filter-active {
|
||||
#changelist-filter {
|
||||
@include media-breakpoint-up(lg) {
|
||||
@include make-col(2);
|
||||
max-height: 100%;
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
#changelist-form {
|
||||
@include media-breakpoint-up(lg) {
|
||||
@include make-col(10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#changelist-filter-modal {
|
||||
@extend .modal-body;
|
||||
@extend #changelist-filter;
|
||||
display: block;
|
||||
max-width: 100% !important;
|
||||
max-height: 100% !important;
|
||||
order: 0 !important;
|
||||
padding: .5rem 0 !important;
|
||||
width: auto !important;
|
||||
|
||||
select {
|
||||
margin-left: 0 !important;
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
> div,
|
||||
> p {
|
||||
display: block;
|
||||
}
|
||||
|
||||
ul {
|
||||
li {
|
||||
.select2-container {
|
||||
width: 100% !important;
|
||||
}
|
||||
.select2-selection {
|
||||
border: 1px solid #ced4da;
|
||||
outline: 0 !important;
|
||||
width: 100% !important;
|
||||
max-width: 100% !important;
|
||||
}
|
||||
.select2-container--focus,
|
||||
.select2-selection--single:focus {
|
||||
border-radius: 2px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#changelist-form {
|
||||
@include make-col(12);
|
||||
background: $changelist-bg;
|
||||
order: 2;
|
||||
padding: 1rem !important;
|
||||
position: relative; // filter icon
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
@include make-col(12);
|
||||
}
|
||||
|
||||
.actions {
|
||||
@extend .mb-4;
|
||||
|
||||
label {
|
||||
@extend .pe-2;
|
||||
}
|
||||
|
||||
button {
|
||||
@extend .btn;
|
||||
@extend .btn-sm;
|
||||
@extend .btn-light;
|
||||
@extend .ms-2;
|
||||
@extend .me-2;
|
||||
}
|
||||
|
||||
.all,
|
||||
.question,
|
||||
.clear {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
@extend .form-select;
|
||||
@extend .form-select-sm;
|
||||
-moz-appearance: none;
|
||||
text-indent: .01px;
|
||||
text-overflow: clip;
|
||||
}
|
||||
}
|
||||
|
||||
.results {
|
||||
@extend .mt-2;
|
||||
@extend .table-responsive;
|
||||
background: $changelist-bg;
|
||||
clear: both;
|
||||
|
||||
table {
|
||||
@extend .table;
|
||||
@extend .table-bordered;
|
||||
|
||||
thead > tr {
|
||||
background: $rl-head-bg;
|
||||
color: $rl-head-color;
|
||||
}
|
||||
|
||||
tbody tr:nth-child(2n + 1) {
|
||||
background: $rl-tr-odd-bg;
|
||||
color: $rl-tr-odd-color;
|
||||
}
|
||||
|
||||
tbody tr.selected, tbody tr.selected td, tbody tr.selected th {
|
||||
background: $rl-tr-selected-bg !important;
|
||||
color: $rl-tr-selected-color;
|
||||
}
|
||||
|
||||
.action-checkbox-column {
|
||||
width: 20px;
|
||||
|
||||
.text {
|
||||
padding-right: 0;
|
||||
}
|
||||
}
|
||||
|
||||
th,
|
||||
td {
|
||||
padding: .3rem;
|
||||
}
|
||||
}
|
||||
|
||||
.sortoptions {
|
||||
float: right;
|
||||
}
|
||||
|
||||
th .text {
|
||||
padding-right: 44px;
|
||||
}
|
||||
|
||||
.sorted .sortoptions a {
|
||||
background: url('../img/sorting-icons.svg') 0 0 no-repeat;
|
||||
background-size: 14px auto;
|
||||
display: inline-block;
|
||||
height: 14px;
|
||||
position: relative;
|
||||
width: 14px;
|
||||
|
||||
&.sortremove::after {
|
||||
color: $sort-icon-color;
|
||||
content: '\\';
|
||||
font-size: 18px;
|
||||
font-weight: 200;
|
||||
left: 3px;
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
}
|
||||
|
||||
&.descending {
|
||||
background-position: 0 -56px;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
&.ascending {
|
||||
background-position: 0 -42px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.baton-cl-include-top {
|
||||
padding-right: 50px;
|
||||
|
||||
@include media-breakpoint-up(sm) {
|
||||
padding-right: 100px;
|
||||
}
|
||||
}
|
||||
|
||||
.baton-cl-include-above,
|
||||
.baton-cl-include-below {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.baton-cl-include-below {
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.admindatefilter {
|
||||
border-bottom: 0 !important;
|
||||
margin-right: 15px;
|
||||
padding-bottom: 0;
|
||||
position: relative;
|
||||
|
||||
form > p {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
}
|
||||
|
||||
.datetimeshortcuts {
|
||||
right: 2rem;
|
||||
}
|
||||
|
||||
input[type='text'] {
|
||||
@extend .form-control;
|
||||
@extend .form-control-sm;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
input[type='submit'],
|
||||
input[type='reset'] {
|
||||
@extend .btn-sm;
|
||||
}
|
||||
|
||||
input[type='reset'] {
|
||||
@extend .btn-secondary;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,134 @@
|
||||
// scss-lint:disable IdSelector PlaceholderInExtend NestingDepth
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
.menu-mobile {
|
||||
#content {
|
||||
flex: 0 0 100% !important;
|
||||
max-width: 100% !important;
|
||||
width: 100% !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#content {
|
||||
background: $content-bg;
|
||||
margin-right: 0 !important;
|
||||
padding-left: 0 !important;
|
||||
padding-right: 0 !important;
|
||||
padding-top: 0 !important;
|
||||
position: relative;
|
||||
|
||||
@include media-breakpoint-down(md) {
|
||||
flex: 0 0 100% !important;
|
||||
max-width: 100% !important;
|
||||
}
|
||||
|
||||
> h1 {
|
||||
@extend .mb-0;
|
||||
@extend .p-3;
|
||||
background: $dashboard-title-bg;
|
||||
font-size: 1.6rem;
|
||||
font-weight: 700;
|
||||
|
||||
+ h2 {
|
||||
@extend .mb-0;
|
||||
@extend .px-3;
|
||||
background: $dashboard-title-bg;
|
||||
font-size: 1.2rem;
|
||||
padding-bottom: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
.object-tools {
|
||||
@extend .ps-0;
|
||||
@extend .m-2;
|
||||
float: right;
|
||||
list-style-type: none;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
a {
|
||||
@extend .btn;
|
||||
@extend .btn-secondary;
|
||||
|
||||
&::before {
|
||||
@extend %font-awesome;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.messagelist {
|
||||
list-style-type: none;
|
||||
padding: 0;
|
||||
|
||||
.success {
|
||||
@extend .alert;
|
||||
@extend .alert-success;
|
||||
@extend .ps-3;
|
||||
|
||||
&::before {
|
||||
@extend %font-awesome;
|
||||
content: "\f00c";
|
||||
}
|
||||
}
|
||||
|
||||
.info {
|
||||
@extend .alert;
|
||||
@extend .alert-info;
|
||||
@extend .ps-3;
|
||||
|
||||
&::before {
|
||||
@extend %font-awesome;
|
||||
content: "\f05a";
|
||||
}
|
||||
}
|
||||
|
||||
.warning {
|
||||
@extend .alert;
|
||||
@extend .alert-warning;
|
||||
@extend .ps-3;
|
||||
|
||||
&::before {
|
||||
@extend %font-awesome;
|
||||
content: "\f12a";
|
||||
}
|
||||
}
|
||||
|
||||
.error {
|
||||
@extend .alert;
|
||||
@extend .alert-danger;
|
||||
@extend .ps-3;
|
||||
|
||||
&::before {
|
||||
@extend %font-awesome;
|
||||
content: "\f071";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// modal
|
||||
.modal-header {
|
||||
align-items: center !important;
|
||||
}
|
||||
|
||||
.modal-dialog button.back {
|
||||
align-items: center;
|
||||
background: $modal-back-btn-bg;
|
||||
border: none;
|
||||
border-radius: 50%;
|
||||
color: $modal-back-btn-fg;
|
||||
display: flex;
|
||||
height: 24px;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
top: -4px;
|
||||
width: 24px;
|
||||
|
||||
&:focus {
|
||||
border: none;
|
||||
outline: none;
|
||||
}
|
||||
}
|
@@ -0,0 +1,193 @@
|
||||
// scss-lint:disable PlaceholderInExtend IdSelector SelectorDepth NestingDepth ImportantRule
|
||||
.dashboard {
|
||||
|
||||
#content {
|
||||
background: $dashboard-bg;
|
||||
}
|
||||
|
||||
#content-main {
|
||||
@include make-row();
|
||||
float: left;
|
||||
margin-left: 0 !important;
|
||||
padding: 16px 0;
|
||||
width: 100%;
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
margin-left: -15px;
|
||||
width: 75%;
|
||||
}
|
||||
|
||||
> p {
|
||||
@extend .ps-3;
|
||||
@extend .pe-3;
|
||||
}
|
||||
|
||||
> .module {
|
||||
@include make-col-ready();
|
||||
@include make-col(12);
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
@include make-col(6);
|
||||
}
|
||||
|
||||
@media(min-width: 1600px) {
|
||||
@include make-col(4);
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
@extend .table;
|
||||
background: $dashboard-module-bg;
|
||||
border: 1px solid $dashboard-module-border-color;
|
||||
|
||||
tbody {
|
||||
font-size: .9rem;
|
||||
}
|
||||
|
||||
th {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
td {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#content-related {
|
||||
float: right;
|
||||
margin-bottom: 2rem;
|
||||
margin-right: 0 !important;
|
||||
padding: 0 15px;
|
||||
width: 100%;
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
margin-right: 25px;
|
||||
width: 23%;
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-size: $h2-size;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: $h3-size;
|
||||
}
|
||||
|
||||
> div {
|
||||
@extend .p-3;
|
||||
@extend .mt-3;
|
||||
|
||||
background: $dashboard-module-bg;
|
||||
border: 1px solid $dashboard-module-border-color;
|
||||
}
|
||||
|
||||
.actionlist {
|
||||
font-size: .9rem;
|
||||
}
|
||||
}
|
||||
|
||||
caption {
|
||||
@extend .ps-2;
|
||||
@extend .pe-2;
|
||||
background: $dashboard-caption-bg;
|
||||
border: 1px solid $dashboard-module-border-color;
|
||||
caption-side: top;
|
||||
|
||||
a {
|
||||
color: $dashboard-caption-color;
|
||||
}
|
||||
}
|
||||
|
||||
.actionlist {
|
||||
border-left: 5px solid #e7e7e7;
|
||||
list-style-type: none;
|
||||
margin-left: .5rem;
|
||||
margin-top: 1.5rem;
|
||||
padding-left: 0;
|
||||
position: relative;
|
||||
|
||||
|
||||
&::after {
|
||||
background-image: linear-gradient(#e7e7e7 50%, rgba(255, 255, 255, 0) 0%);
|
||||
background-position: center;
|
||||
background-repeat: repeat-y;
|
||||
background-size: 5px 13px;
|
||||
bottom: -25px;
|
||||
content: '';
|
||||
height: 25px;
|
||||
left: -5px;
|
||||
position: absolute;
|
||||
width: 5px;
|
||||
}
|
||||
|
||||
li {
|
||||
padding: 1.5rem;
|
||||
padding-top: 0;
|
||||
position: relative;
|
||||
|
||||
&::before {
|
||||
background: $dashboard-icon-color;
|
||||
border-radius: 50%;
|
||||
color: $white !important;
|
||||
display: inline-block;
|
||||
height: 30px;
|
||||
left: -18px;
|
||||
line-height: 30px;
|
||||
position: absolute;
|
||||
text-align: center;
|
||||
width: 30px;
|
||||
}
|
||||
|
||||
&.addlink::before {
|
||||
background: $dashboard-add-bg;
|
||||
}
|
||||
|
||||
&.changelink::before {
|
||||
background: $dashboard-change-bg;
|
||||
}
|
||||
|
||||
&.deletelink::before {
|
||||
background: $dashboard-delete-bg;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.addlink,
|
||||
.viewlink,
|
||||
.deletelink,
|
||||
.changelink {
|
||||
&::before {
|
||||
@extend %font-awesome;
|
||||
@extend .me-1;
|
||||
color: $dashboard-icon-color;
|
||||
white-space: nowrap;
|
||||
}
|
||||
}
|
||||
|
||||
.addlink {
|
||||
&::before {
|
||||
content: '\f067';
|
||||
}
|
||||
}
|
||||
|
||||
.changelink {
|
||||
&::before {
|
||||
content: '\f304';
|
||||
}
|
||||
}
|
||||
|
||||
.deletelink {
|
||||
&::before {
|
||||
content: '\f1f8';
|
||||
}
|
||||
}
|
||||
|
||||
.viewlink {
|
||||
&::before {
|
||||
content: '\f26c';
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,24 @@
|
||||
// scss-lint:disable IdSelector PlaceholderInExtend NestingDepth QualifyingElement SelectorDepth ImportantRule
|
||||
.delete-confirmation-content {
|
||||
@extend .m-3;
|
||||
@extend .p-3;
|
||||
background: $delete-confirmation-bg;
|
||||
border: 1px solid $delete-confirmation-border-color;
|
||||
|
||||
form {
|
||||
input[type=submit] {
|
||||
@extend .btn;
|
||||
@extend.btn-danger;
|
||||
}
|
||||
|
||||
.cancel-link {
|
||||
@extend .btn;
|
||||
@extend.btn-success;
|
||||
|
||||
&::before {
|
||||
@extend %font-awesome;
|
||||
content: '\f0e2';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,45 @@
|
||||
.filter-files-field.js-filter-files {
|
||||
width: 170px;
|
||||
}
|
||||
|
||||
.filter-files-container .filter-search-wrapper {
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
.filebrowser {
|
||||
.paginator {
|
||||
span {
|
||||
border: 0 !important;
|
||||
width: auto !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-is-focused .filter-files-container {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
form .form-row .filer-dropzone.filer-dropzone-mobile .filerFile {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.js-filer-dropzone .insertlinkButton {
|
||||
padding-top: 0 !important;
|
||||
}
|
||||
|
||||
.form-row .filer-dropzone .filerFile .related-lookup.related-lookup-change {
|
||||
min-width: 36px;
|
||||
|
||||
&::before {
|
||||
content: '' !important;
|
||||
}
|
||||
|
||||
.edit-file {
|
||||
margin-top: -10px;
|
||||
}
|
||||
}
|
||||
|
||||
form .form-row .filer-dropzone {
|
||||
min-width: 100% !important;
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
@font-face {
|
||||
font-family: 'Dosis';
|
||||
font-style: normal;
|
||||
font-weight: 300;
|
||||
src: url('../fonts/Dosis-Light.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Dosis';
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
src: url('../fonts/Dosis-Regular.ttf') format('truetype');
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: 'Dosis';
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
src: url('../fonts/Dosis-Bold.ttf') format('truetype');
|
||||
}
|
@@ -0,0 +1,34 @@
|
||||
// scss-lint:disable PlaceholderInExtend IdSelector
|
||||
.site-footer {
|
||||
@extend .p-3;
|
||||
background: $footer-bg;
|
||||
border-top: 1px solid $footer-border-color;
|
||||
bottom: 0;
|
||||
color: $footer-color;
|
||||
font-size: .9rem;
|
||||
left: 0;
|
||||
margin-top: 20px;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
|
||||
p {
|
||||
margin-bottom: 5px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $footer-link-color;
|
||||
|
||||
&:hover {
|
||||
color: $footer-link-color-hover;
|
||||
}
|
||||
}
|
||||
|
||||
.btn-light {
|
||||
color: $footer-support-fg;
|
||||
}
|
||||
}
|
||||
|
||||
.login #footer {
|
||||
display: none;
|
||||
}
|
@@ -0,0 +1,85 @@
|
||||
// scss-lint:disable ImportantRule IdSelector SelectorDepth NestingDepth PlaceholderInExtend
|
||||
body.login {
|
||||
align-items: center;
|
||||
background: $login-bg;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
padding: 1px 1rem 0;
|
||||
|
||||
#header #branding {
|
||||
margin: auto !important;
|
||||
}
|
||||
}
|
||||
|
||||
.login {
|
||||
#content {
|
||||
padding-top: 1px !important;
|
||||
}
|
||||
|
||||
#content-main + br.clear {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#container {
|
||||
border: 0 !important;
|
||||
border-radius: 0;
|
||||
max-width: 100%;
|
||||
min-width: auto;
|
||||
width: 24em;
|
||||
|
||||
.navbar-toggler {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.submit-row {
|
||||
padding: 10px 0;
|
||||
text-align: center;
|
||||
|
||||
input {
|
||||
@extend .btn;
|
||||
@extend .btn-secondary;
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
form {
|
||||
padding: 1rem;
|
||||
|
||||
.input-group-text {
|
||||
justify-content: center;
|
||||
width: 42px;
|
||||
}
|
||||
}
|
||||
|
||||
input[type='text'],
|
||||
input[type='password'] {
|
||||
@extend .form-control;
|
||||
background: #fff !important;
|
||||
border-top-left-radius: 0 !important;
|
||||
border-bottom-left-radius: 0 !important;
|
||||
}
|
||||
|
||||
.pwd-visibility-toggle {
|
||||
color: $password-visibility-toggler-icon-fg;
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 8px;
|
||||
top: 11px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
margin-left: 0 !important;
|
||||
margin-right: 0 !important;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.errornote {
|
||||
@extend .alert;
|
||||
@extend .alert-warning;
|
||||
margin: 1rem 1rem 0;
|
||||
padding: .5rem;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,9 @@
|
||||
.page-logout {
|
||||
#header {
|
||||
padding-left: 1rem;
|
||||
}
|
||||
|
||||
.site-footer {
|
||||
position: static;
|
||||
}
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
html {
|
||||
background: $navbar-bg;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
font-weight: 300;
|
||||
min-height: 100%;
|
||||
opacity: 0;
|
||||
transition: opacity .2s linear;
|
||||
|
||||
&.baton-ready {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
&.btn {
|
||||
&:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
button,
|
||||
input,
|
||||
optgroup,
|
||||
select,
|
||||
textarea {
|
||||
font-family: $font-family-sans-serif;
|
||||
}
|
||||
|
||||
input[type=checkbox] {
|
||||
@extend .form-check-input;
|
||||
}
|
||||
|
||||
.clear {
|
||||
clear: both;
|
||||
}
|
||||
|
||||
// remove django 3.1 sidebar
|
||||
#toggle-nav-sidebar,
|
||||
#nav-sidebar {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
@keyframes bounce {
|
||||
0% { transform: translateY(0) rotate(0deg); }
|
||||
100% { transform: translateY(-5px) rotate(5deg); }
|
||||
}
|
@@ -0,0 +1,438 @@
|
||||
//scss-lint:disable PlaceholderInExtend NestingDepth ImportantRule SelectorDepth
|
||||
|
||||
.menu-open .sidebar-menu {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
body:not(.menu-mobile) {
|
||||
@include media-breakpoint-up(lg) {
|
||||
.sidebar-menu {
|
||||
height: auto;
|
||||
left: 0;
|
||||
position: static;
|
||||
|
||||
h1 {
|
||||
i {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.sidebar-menu {
|
||||
background: $menu-bg;
|
||||
color: $menu-color;
|
||||
height: 100%;
|
||||
left: -100%;
|
||||
padding: 0;
|
||||
position: fixed;
|
||||
top: 0;
|
||||
z-index: 100;
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
#branding {
|
||||
background: $menu-branding-bg;
|
||||
border-bottom: 1px solid $menu-branding-bg;
|
||||
padding-top: 0;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
|
||||
> h1 {
|
||||
background: $menu-branding-bg;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $menu-branding-color !important;
|
||||
}
|
||||
}
|
||||
|
||||
.toggle-menu {
|
||||
cursor: pointer;
|
||||
position: absolute;
|
||||
right: 1rem;
|
||||
top: 1.6rem;
|
||||
}
|
||||
|
||||
#user-tools {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#user-tools-sidebar {
|
||||
padding: 1rem;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
|
||||
.user-links {
|
||||
height: 38px;
|
||||
transition: height .2s linear;
|
||||
}
|
||||
|
||||
.user-area-toggler {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
&.collapsed {
|
||||
.user-links,
|
||||
.user-info div {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.gravatar-icon {
|
||||
border: 2px solid $gravatar-border-color;
|
||||
border-radius: 50%;
|
||||
}
|
||||
|
||||
.user-info {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 1.2rem;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.user-links {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: center;
|
||||
margin-top: .5rem;
|
||||
}
|
||||
|
||||
a {
|
||||
color: $menu-link-color !important;
|
||||
|
||||
&.view-site {
|
||||
&::after {
|
||||
content: '\f108';
|
||||
font-family: 'Font Awesome\ 5 Free';
|
||||
}
|
||||
|
||||
&[href*=doc] {
|
||||
&::after {
|
||||
content: '\f02d' !important;
|
||||
font-family: 'Font Awesome\ 5 Free';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&.password {
|
||||
&::after {
|
||||
content: '\f084';
|
||||
font-family: 'Font Awesome\ 5 Free';
|
||||
}
|
||||
}
|
||||
|
||||
&.logout {
|
||||
&::after {
|
||||
content: '\f2f5';
|
||||
font-family: 'Font Awesome\ 5 Free';
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
}
|
||||
|
||||
&::after {
|
||||
color: $user-links-fg;
|
||||
font-size: 1.3rem;
|
||||
display: inline-block;
|
||||
margin: 0 .6rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.search-field-tool {
|
||||
margin: .5rem 1rem;
|
||||
position: relative;
|
||||
|
||||
input {
|
||||
background: $search-field-input-bg;
|
||||
border-color: $search-field-input-border-color;
|
||||
color: $search-field-color;
|
||||
padding-right: 30px;
|
||||
|
||||
&:focus {
|
||||
box-shadow: 0 0 0 transparent;
|
||||
outline: 0 none;
|
||||
}
|
||||
}
|
||||
|
||||
&::after {
|
||||
color: $secondary;
|
||||
content: '\f002';
|
||||
font-family: 'Font Awesome\ 5 Free';
|
||||
position: absolute;
|
||||
right: .5rem;
|
||||
top: .2rem;
|
||||
}
|
||||
|
||||
&.loading {
|
||||
&::after {
|
||||
animation: fa-spin 2s linear infinite;
|
||||
content: '\f1ce';
|
||||
}
|
||||
}
|
||||
|
||||
#admin-search-datalist {
|
||||
background: $search-field-datalist-bg;
|
||||
max-height: 50vh;
|
||||
overflow: auto;
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
|
||||
div {
|
||||
align-items: center;
|
||||
border-bottom: 1px solid darken($search-field-datalist-bg, 2%);
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
font-size: .9rem;
|
||||
justify-content: space-between;
|
||||
max-height: 50vh;
|
||||
overflow: auto;
|
||||
padding: .5rem;
|
||||
|
||||
&.selected {
|
||||
background: $search-field-selected-bg;
|
||||
color: $search-field-selected-color;
|
||||
|
||||
a {
|
||||
color: $search-field-selected-color;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
a {
|
||||
color: $search-field-link-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
i {
|
||||
color: $search-field-icon-color;
|
||||
font-size: .9rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
h1 {
|
||||
@extend .clearfix;
|
||||
background: $menu-mobile-title-bg;
|
||||
// border-bottom: 2px solid $menu-mobile-title-border-color;
|
||||
color: $menu-mobile-title-color;
|
||||
font-size: 1.6rem;
|
||||
margin-bottom: 0;
|
||||
padding: 1rem 16px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 12;
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
background: $menu-title-bg;
|
||||
position: static;
|
||||
}
|
||||
|
||||
i {
|
||||
cursor: pointer;
|
||||
float: right;
|
||||
font-weight: normal;
|
||||
margin-right: 10px;
|
||||
margin-top: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.depth-0,
|
||||
.depth-1 {
|
||||
background: $menu-bg;
|
||||
height: 100%;
|
||||
left: 0;
|
||||
list-style-type: none;
|
||||
overflow: auto;
|
||||
padding: 0;
|
||||
padding-top: 66px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
z-index: 10;
|
||||
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
height: auto;
|
||||
padding-top: 0;
|
||||
position: static;
|
||||
}
|
||||
|
||||
li {
|
||||
// border-bottom: 1px solid $menu-li-border-color;
|
||||
padding: 0;
|
||||
|
||||
a,
|
||||
span {
|
||||
padding: 10px 20px;
|
||||
}
|
||||
}
|
||||
|
||||
a,
|
||||
span {
|
||||
color: $menu-link-color;
|
||||
display: block;
|
||||
outline: 0;
|
||||
|
||||
&:hover {
|
||||
color: $menu-link-hover-color;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&.has-children {
|
||||
@extend .clearfix;
|
||||
|
||||
&::after {
|
||||
@extend %font-awesome;
|
||||
content: '\f105';
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
|
||||
i {
|
||||
display: inline-block;
|
||||
margin-right: 8px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.depth-0 {
|
||||
> li:not(.title) {
|
||||
&:hover {
|
||||
background: $menu-li-hover-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.title {
|
||||
background: $menu-voice-title-bg !important;
|
||||
|
||||
> span {
|
||||
color: $menu-voice-title-color !important;
|
||||
font-weight: bold;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.depth-1 {
|
||||
display: block;
|
||||
margin-left: -100%;
|
||||
transition: margin-left .0s linear;
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
display: none;
|
||||
margin-left: 0;
|
||||
|
||||
li {
|
||||
padding-left: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.title > .depth-1 li {
|
||||
@include media-breakpoint-up(lg) {
|
||||
padding-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.open {
|
||||
@include media-breakpoint-up(lg) {
|
||||
.has-children {
|
||||
&::after {
|
||||
content: '\f107' !important;
|
||||
}
|
||||
}
|
||||
|
||||
ul,
|
||||
li {
|
||||
background: $menu-selected-sub-bg !important;
|
||||
}
|
||||
}
|
||||
|
||||
> .depth-1 {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.depth-1 {
|
||||
margin-left: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
|
||||
.default-open {
|
||||
@include media-breakpoint-up(lg) {
|
||||
.has-children {
|
||||
&::after {
|
||||
content: '\f107' !important;
|
||||
}
|
||||
}
|
||||
|
||||
ul,
|
||||
li {
|
||||
background: $menu-selected-sub-bg !important;
|
||||
}
|
||||
|
||||
> .depth-1 {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.depth-1 {
|
||||
margin-left: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.nav-back {
|
||||
background: $menu-mobile-back-bg;
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.with-active {
|
||||
@include media-breakpoint-up(lg) {
|
||||
.has-children {
|
||||
&::after {
|
||||
content: '\f107' !important;
|
||||
}
|
||||
}
|
||||
|
||||
ul,
|
||||
li {
|
||||
background: $menu-selected-sub-bg;
|
||||
}
|
||||
|
||||
> .depth-1 {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.depth-1 {
|
||||
margin-left: 0;
|
||||
z-index: 10;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.active:not(.with-active) {
|
||||
@include media-breakpoint-up(lg) {
|
||||
background: $menu-active-voice-bg !important;
|
||||
border-left: 5px solid $menu-active-voice-border-color;
|
||||
position: relative;
|
||||
|
||||
a {
|
||||
margin-left: -5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,106 @@
|
||||
// scss-lint:disable IdSelector NestingDepth PlaceholderInExtend
|
||||
body:not(.login):not(.page-logout) #header {
|
||||
&.expand {
|
||||
@extend .d-flex;
|
||||
@extend .d-lg-none;
|
||||
@extend .navbar-expand-lg;
|
||||
}
|
||||
}
|
||||
|
||||
body.page-logout #header {
|
||||
.navbar-toggler {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
#header {
|
||||
@extend .navbar;
|
||||
@extend .navbar-dark;
|
||||
@extend .bg-dark;
|
||||
|
||||
align-items: center;
|
||||
background: $navbar-bg !important;
|
||||
color: $navbar-color;
|
||||
flex-direction: row !important;
|
||||
padding: .6rem 0;
|
||||
|
||||
strong {
|
||||
color: $navbar-color;
|
||||
padding-left: 0;
|
||||
|
||||
&::before {
|
||||
content: '\f007';
|
||||
display: inline-block;
|
||||
font-family: 'Font Awesome\ 5 Free';
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
color: $navbar-link-color;
|
||||
|
||||
&:hover {
|
||||
color: $navbar-link-color-hover;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
&.dropdown-item {
|
||||
color: $navbar-dropdown-link-color;
|
||||
}
|
||||
}
|
||||
|
||||
#user-tools {
|
||||
@extend .d-inline-flex;
|
||||
|
||||
> a {
|
||||
@extend .navbar-text;
|
||||
order: 2;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
@include media-breakpoint-up(md) {
|
||||
left: auto;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.navbar-toggler {
|
||||
border-width: 0 !important;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.nav-menu.is-active {
|
||||
background: $navbar-mobile-pane-bg;
|
||||
}
|
||||
}
|
||||
|
||||
#branding {
|
||||
// @extend .nav-left;
|
||||
@extend .navbar-brand;
|
||||
@extend .me-auto;
|
||||
display: inline-block;
|
||||
padding-bottom: 0;
|
||||
|
||||
h1 {
|
||||
font-size: 1.6rem;
|
||||
}
|
||||
}
|
||||
|
||||
#site-name {
|
||||
// @extend .nav-item;
|
||||
}
|
||||
|
||||
#user-tools {
|
||||
// @extend .nav-right;
|
||||
// @extend .nav-menu;
|
||||
|
||||
a {
|
||||
// @extend .nav-item;
|
||||
}
|
||||
|
||||
strong {
|
||||
// @extend .button;
|
||||
// @extend .is-primary;
|
||||
}
|
||||
}
|
@@ -0,0 +1,56 @@
|
||||
// scss-lint:disable PlaceholderInExtend
|
||||
.paginator {
|
||||
@extend .clearfix;
|
||||
overflow: auto;
|
||||
padding-top: .5rem;
|
||||
white-space: nowrap;
|
||||
|
||||
span,
|
||||
a:not(.showall) {
|
||||
background: $pag-bg;
|
||||
border: 1px solid $pag-border-color;
|
||||
color: $pag-color;
|
||||
display: inline-block;
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
padding: 0 !important;
|
||||
text-align: center;
|
||||
width: 40px;
|
||||
|
||||
&:hover {
|
||||
background: $pag-hover-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.end {
|
||||
@extend .me-3;
|
||||
}
|
||||
|
||||
.this-page {
|
||||
background: $pag-selected-bg;
|
||||
color: $pag-selected-color;
|
||||
|
||||
&:hover {
|
||||
background: $pag-selected-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.showall {
|
||||
@extend .btn;
|
||||
@extend .btn-sm;
|
||||
@extend .btn-outline-primary;
|
||||
@extend .ms-2;
|
||||
margin-top: -5px;
|
||||
}
|
||||
|
||||
input {
|
||||
@extend .btn;
|
||||
@extend .btn-success;
|
||||
margin-top: -4px;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
float: right;
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,20 @@
|
||||
// scss-lint:disable IdSelector PlaceholderInExtend NestingDepth QualifyingElement SelectorDepth ImportantRule
|
||||
.passwordchange,
|
||||
.auth-user.change-form {
|
||||
|
||||
#content-main {
|
||||
@extend .container-fluid;
|
||||
|
||||
> form {
|
||||
@extend %admin-form;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
align-items: flex-start;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,867 @@
|
||||
// scss-lint:disable IdSelector PlaceholderInExtend NestingDepth QualifyingElement SelectorDepth ImportantRule SelectorFormat
|
||||
%font-awesome {
|
||||
display: inline-block;
|
||||
font-family: 'Font Awesome\ 5 Free';
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
%admin-form {
|
||||
@extend .p-2;
|
||||
@extend .mt-3;
|
||||
background: $changeform-bg;
|
||||
border: 1px solid $changeform-border-color;
|
||||
clear: both;
|
||||
overflow: auto;
|
||||
|
||||
h3 {
|
||||
font-size: $h3-size;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
// @extend .form-group; // @TODO check
|
||||
background: $field-bg;
|
||||
margin-bottom: .5rem;
|
||||
padding: 1rem .5rem;
|
||||
|
||||
&.with-wrapped-fields {
|
||||
background: transparent;
|
||||
}
|
||||
|
||||
&.errors {
|
||||
background: $field-row-error-bg;
|
||||
|
||||
.errorlist {
|
||||
@extend .pt-2;
|
||||
padding-left: 0;
|
||||
width: 100%;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
padding-left: 1.2rem;
|
||||
}
|
||||
|
||||
li {
|
||||
color: $danger-fg !important;
|
||||
list-style-type: none;
|
||||
font-weight: bold;
|
||||
text-decoration: underline;
|
||||
|
||||
&::before {
|
||||
@extend %font-awesome;
|
||||
content: '\f12a';
|
||||
display: inline-block;
|
||||
margin-right: .5rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wrapped-fields-container {
|
||||
.errorlist {
|
||||
padding-left: 0 !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.newline {
|
||||
display: block;
|
||||
height: .5rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
> div {
|
||||
align-items: flex-start;
|
||||
display: flex;
|
||||
flex: 1;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
|
||||
&.checkbox-row {
|
||||
input {
|
||||
margin-top: 5px;
|
||||
order: 2;
|
||||
}
|
||||
|
||||
label {
|
||||
order: 1;
|
||||
}
|
||||
|
||||
.help {
|
||||
order: 3;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.date-icon {
|
||||
&::before {
|
||||
@extend %font-awesome;
|
||||
content: '\f073';
|
||||
}
|
||||
}
|
||||
|
||||
.clock-icon {
|
||||
&::before {
|
||||
@extend %font-awesome;
|
||||
content: '\f017';
|
||||
}
|
||||
}
|
||||
|
||||
.datetime {
|
||||
align-items: flex-start;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
margin: 0;
|
||||
|
||||
input {
|
||||
margin: 0 10px;
|
||||
}
|
||||
|
||||
a + a {
|
||||
@extend .me-3;
|
||||
}
|
||||
|
||||
.datetimeshortcuts {
|
||||
align-self: center;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.timezonewarning {
|
||||
margin-left: 0 !important;
|
||||
white-space: nowrap;
|
||||
width: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.datetimeshortcuts {
|
||||
align-self: center;
|
||||
|
||||
+ .newline,
|
||||
+ br {
|
||||
content: '';
|
||||
display: block;
|
||||
height: .5rem;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.timezonewarning {
|
||||
@extend .py-0;
|
||||
|
||||
align-self: center;
|
||||
color: $warning-fg;
|
||||
display: block;
|
||||
margin: .2rem 0;
|
||||
padding-left: 1px;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
margin-left: 20%;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
margin-left: 10%;
|
||||
}
|
||||
}
|
||||
|
||||
.related-widget-wrapper {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-grow: 1;
|
||||
|
||||
+ p /* django 1.11 */ {
|
||||
flex-basis: 100%;
|
||||
margin-left: 0 !important;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
margin-left: 20% !important;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
margin-left: 10% !important;
|
||||
}
|
||||
}
|
||||
|
||||
.add-related {
|
||||
margin-left: 15px;
|
||||
margin-right: 15px;
|
||||
order: 2;
|
||||
}
|
||||
|
||||
select {
|
||||
display: inline-block !important;
|
||||
}
|
||||
}
|
||||
|
||||
// selector
|
||||
.selector {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: nowrap;
|
||||
|
||||
&.stacked {
|
||||
flex-direction: column;
|
||||
|
||||
.selector-chooser {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin: 15px 0;
|
||||
width: auto;
|
||||
|
||||
.selector-add {
|
||||
background: url('../img/selector-icons.svg') 0 -32px no-repeat; // 46
|
||||
|
||||
&.active {
|
||||
background: url('../img/selector-icons.svg') 0 -48px no-repeat; // 46
|
||||
}
|
||||
}
|
||||
|
||||
.selector-remove {
|
||||
background: url('../img/selector-icons.svg') 0 0 no-repeat; // 46
|
||||
|
||||
&.active {
|
||||
background: url('../img/selector-icons.svg') 0 -16px no-repeat; // 46
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.help-icon {
|
||||
background: url('../img/icon-unknown.svg') 0 0 no-repeat;
|
||||
cursor: help;
|
||||
display: inline-block;
|
||||
height: 13px;
|
||||
margin: -2px 0 0 2px;
|
||||
vertical-align: middle;
|
||||
width: 13px;
|
||||
}
|
||||
}
|
||||
|
||||
.selector-filter {
|
||||
align-items: center;
|
||||
border-left: 1px solid $selector-item-border-color;
|
||||
border-right: 1px solid $selector-item-border-color;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
margin-bottom: 0;
|
||||
padding: 5px;
|
||||
|
||||
label {
|
||||
margin-bottom: 0;
|
||||
padding-right: 2px !important;
|
||||
}
|
||||
|
||||
.search-label-icon {
|
||||
background: url('../img/search.svg') 0 0 no-repeat;
|
||||
cursor: help;
|
||||
display: inline-block;
|
||||
height: 18px;
|
||||
margin-top: 5px;
|
||||
width: 18px;
|
||||
}
|
||||
|
||||
input {
|
||||
padding: 5px;
|
||||
}
|
||||
}
|
||||
|
||||
.selector-available,
|
||||
.selector-chosen {
|
||||
text-align: center;
|
||||
width: 330px;
|
||||
|
||||
h2 {
|
||||
@extend .p-2;
|
||||
background: $selector-available-title-bg;
|
||||
border-left: 1px solid $selector-item-border-color;
|
||||
border-right: 1px solid $selector-item-border-color;
|
||||
border-top: 1px solid $selector-item-border-color;
|
||||
font-size: 1rem;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
select {
|
||||
border-radius: 0;
|
||||
min-height: 200px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.selector-chosen {
|
||||
h2 {
|
||||
background: $selector-chosen-title-bg;
|
||||
}
|
||||
}
|
||||
|
||||
.selector-chooseall,
|
||||
.selector-clearall {
|
||||
@extend .btn;
|
||||
@extend .btn-light;
|
||||
display: inline-block;
|
||||
margin: 5px auto;
|
||||
|
||||
&:not(.active) {
|
||||
@extend .text-muted;
|
||||
}
|
||||
}
|
||||
|
||||
.selector-chooser {
|
||||
align-self: center;
|
||||
background-color: $selector-chooser-bg;
|
||||
border-radius: 10px;
|
||||
display: inline-block;
|
||||
float: left;
|
||||
margin: 0 15px;
|
||||
padding: 0;
|
||||
width: 22px;
|
||||
|
||||
li {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 3px;
|
||||
}
|
||||
|
||||
.selector-add {
|
||||
background: url('../img/selector-icons.svg') 0 -112px no-repeat;
|
||||
}
|
||||
|
||||
.selector-remove {
|
||||
background: url('../img/selector-icons.svg') 0 -80px no-repeat;
|
||||
}
|
||||
|
||||
.selector-add,
|
||||
.selector-remove {
|
||||
cursor: default;
|
||||
display: block;
|
||||
height: 16px;
|
||||
opacity: .3;
|
||||
overflow: hidden;
|
||||
text-indent: -3000px;
|
||||
width: 16px;
|
||||
|
||||
&.active {
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-related,
|
||||
.change-related {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.change-related {
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
.related-lookup {
|
||||
&::before {
|
||||
@extend %font-awesome;
|
||||
content: '\f002';
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
label {
|
||||
@extend .pe-3;
|
||||
flex-basis: 100%;
|
||||
text-align: left;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
flex-basis: 20%;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
flex-basis: 10%;
|
||||
text-align: right;
|
||||
}
|
||||
}
|
||||
|
||||
.required {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
input[type=text],
|
||||
input[type=password],
|
||||
input[type=url],
|
||||
input[type=number],
|
||||
input[type=email],
|
||||
input[type=date],
|
||||
input[type=file],
|
||||
select[multiple] {
|
||||
@extend .form-control;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
input[type=url] {
|
||||
display: inline-block !important;
|
||||
}
|
||||
|
||||
input[type=text][size] {
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
input[type=text]:not([size]) {
|
||||
@include media-breakpoint-up(md) {
|
||||
min-width: 240px;
|
||||
}
|
||||
}
|
||||
|
||||
textarea {
|
||||
@extend .form-control;
|
||||
resize: both;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
.tabular.inline-related {
|
||||
input[type=text],
|
||||
input[type=number],
|
||||
input[type=email],
|
||||
input[type=date],
|
||||
textarea,
|
||||
select {
|
||||
min-width: auto !important;
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.inline-deletelink {
|
||||
float: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
select[multiple] {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
select:not([multiple]):not(.admin-autocomplete) {
|
||||
@extend .form-select;
|
||||
text-indent: .01px;
|
||||
text-overflow: clip;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
width: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// automcomplete
|
||||
.select2-container--admin-autocomplete {
|
||||
min-width: 320px; // m2m
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--single .select2-selection__arrow {
|
||||
height: 34px;
|
||||
}
|
||||
|
||||
.select2-container--admin-autocomplete .select2-selection--single .select2-selection__rendered {
|
||||
line-height: 36px;
|
||||
}
|
||||
|
||||
.select2-container .select2-selection--single {
|
||||
height: 36px;
|
||||
}
|
||||
|
||||
.radiolist {
|
||||
list-style-type: none;
|
||||
padding-left: 0;
|
||||
|
||||
&.inline {
|
||||
li {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.help {
|
||||
@extend .form-text;
|
||||
@extend .text-muted;
|
||||
@extend .ms-3;
|
||||
flex-basis: 100% !important;
|
||||
margin-left: 0 !important;
|
||||
margin-top: .5rem;
|
||||
padding-left: 1px;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
margin-left: 20% !important;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
margin-left: 10% !important;
|
||||
}
|
||||
|
||||
> ul {
|
||||
padding-left: 1.2rem;
|
||||
}
|
||||
}
|
||||
|
||||
div.help {
|
||||
color: $help-text-color !important;
|
||||
}
|
||||
|
||||
img.help {
|
||||
display: inline-block;
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
.collapse {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.collapsed * {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.collapsed h2 {
|
||||
display: block;
|
||||
|
||||
a {
|
||||
display: inline;
|
||||
}
|
||||
}
|
||||
|
||||
.submit-row {
|
||||
align-items: center;
|
||||
display: flex;
|
||||
flex-basis: baseline;
|
||||
flex-direction: column;
|
||||
margin-top: 15px;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
flex-direction: row-reverse;
|
||||
}
|
||||
|
||||
input[type=submit] {
|
||||
@extend .btn;
|
||||
@extend .btn-success;
|
||||
@extend .ms-1;
|
||||
margin-bottom: 15px;
|
||||
margin-left: auto;
|
||||
order: 1;
|
||||
width: 200px;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
> a {
|
||||
margin-bottom: 15px;
|
||||
margin-left: .25rem;
|
||||
order: 1;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.deletelink-box {
|
||||
margin-bottom: 0;
|
||||
margin-left: auto;
|
||||
margin-right: auto;
|
||||
order: 2;
|
||||
text-align: center;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.deletelink {
|
||||
@extend .btn;
|
||||
@extend .btn-danger;
|
||||
width: 200px;
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
&::before {
|
||||
@extend %font-awesome;
|
||||
content: '\f1f8';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.errornote {
|
||||
@extend .alert;
|
||||
@extend .alert-danger;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
||||
// fieldsets
|
||||
|
||||
fieldset .description {
|
||||
@extend .pb-3;
|
||||
@extend .pt-3;
|
||||
}
|
||||
|
||||
fieldset.collapse {
|
||||
display: block;
|
||||
|
||||
h2 {
|
||||
align-items: center;
|
||||
cursor: pointer;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
|
||||
&::after {
|
||||
color: $collapse-entry-icon-color;
|
||||
content: '\f070';
|
||||
display: inline-block;
|
||||
font-family: 'Font Awesome\ 5 Free';
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
}
|
||||
|
||||
&.collapsed {
|
||||
h2 {
|
||||
&::after {
|
||||
content: '\f06e';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// inline
|
||||
fieldset .form-row {
|
||||
margin-left: 0;
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
fieldset > h2 {
|
||||
background: $fieldset-title-bg;
|
||||
font-size: $h2-size;
|
||||
margin-bottom: 0;
|
||||
padding: 5px 10px;
|
||||
|
||||
+ .form-row {
|
||||
margin-top: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.inline-related {
|
||||
overflow-x: auto;
|
||||
|
||||
&.empty-form, // stacked inline
|
||||
.empty-form { // tabular
|
||||
display: none !important; // inline extra param
|
||||
}
|
||||
|
||||
textarea {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
h3 {
|
||||
@extend .clearfix;
|
||||
@extend .mt-2;
|
||||
align-items: center;
|
||||
background: $inline-related-title-bg;
|
||||
border-bottom: 1px solid $inline-related-title-border-color;
|
||||
border-top: 5px solid $inline-related-title-border-top-color;
|
||||
display: flex;
|
||||
font-size: 1.1rem;
|
||||
padding: 8px 10px;
|
||||
|
||||
.inline_label {
|
||||
margin-left: .5rem;
|
||||
margin-right: auto;
|
||||
}
|
||||
|
||||
/* replaced by prev rules, keeping here for reference for a while
|
||||
> .delete,
|
||||
> .inline_label + span {
|
||||
margin-left: auto;
|
||||
}
|
||||
*/
|
||||
|
||||
> .delete {
|
||||
label {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// datetime fields should not be blocks because are followed by the calendar icon
|
||||
.vDateField {
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
.errorlist {
|
||||
background: $field-row-error-bg;
|
||||
}
|
||||
|
||||
> .module {
|
||||
// @extend .table-responsive;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
table {
|
||||
@extend .table;
|
||||
@extend .table-bordered;
|
||||
|
||||
th {
|
||||
background: $inline-related-title-bg;
|
||||
font-weight: normal !important;
|
||||
|
||||
&.required {
|
||||
font-weight: bold !important;
|
||||
}
|
||||
|
||||
.help-tooltip {
|
||||
height: 15px;
|
||||
margin-top: -3px;
|
||||
width: 15px;
|
||||
}
|
||||
}
|
||||
|
||||
.form-row {
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
.original {
|
||||
border-right: 0px;
|
||||
padding: 0;
|
||||
position: relative;
|
||||
width: 0;
|
||||
|
||||
p {
|
||||
align-items: center;
|
||||
background: $inline-tabular-original-bg;
|
||||
border-bottom: 1px solid $inline-tabular-original-border-color;
|
||||
display: flex;
|
||||
font-size: .9rem;
|
||||
flex-direction: row;
|
||||
left: 14px;
|
||||
padding: 0 4px;
|
||||
position: absolute;
|
||||
top: 8px;
|
||||
white-space: nowrap;
|
||||
|
||||
.inlinechangelink {
|
||||
position: relative;
|
||||
right: -4px;
|
||||
}
|
||||
}
|
||||
|
||||
& + td,
|
||||
& + th {
|
||||
border-left: 0px;
|
||||
}
|
||||
}
|
||||
|
||||
.has_original td {
|
||||
padding-top: 44px;
|
||||
}
|
||||
}
|
||||
|
||||
.inlinechangelink {
|
||||
background: $inline-changelink-bg;
|
||||
font-size: .9rem;
|
||||
margin-left: 8px;
|
||||
padding: 2px 4px;
|
||||
|
||||
&::before {
|
||||
content: '\f304';
|
||||
font-family: 'Font Awesome\ 5 Free';
|
||||
margin-right: 4px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: darken($inline-changelink-bg, 10%);
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.add-row {
|
||||
@extend .mt-2;
|
||||
@extend .mb-2;
|
||||
|
||||
a {
|
||||
@extend .btn;
|
||||
@extend .btn-secondary;
|
||||
|
||||
&::before {
|
||||
@extend %font-awesome;
|
||||
content: '\f067';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.inline-deletelink {
|
||||
@extend .btn;
|
||||
@extend .btn-warning;
|
||||
float: right;
|
||||
margin-right: 15px;
|
||||
white-space: nowrap;
|
||||
|
||||
&::before {
|
||||
@extend %font-awesome;
|
||||
content: '\f00d';
|
||||
}
|
||||
}
|
||||
|
||||
.wrapped-fields-container {
|
||||
flex-direction: column !important;
|
||||
|
||||
.datetimeshortcuts {
|
||||
align-self: top;
|
||||
}
|
||||
|
||||
label {
|
||||
flex-basis: auto !important;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
flex-direction: row !important;
|
||||
|
||||
label {
|
||||
flex-basis: 20% !important;
|
||||
vertical-align: top;
|
||||
}
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(lg) {
|
||||
label {
|
||||
flex-basis: 10% !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.wrapped-fields-container > * {
|
||||
flex-grow: 0 !important;
|
||||
}
|
||||
|
||||
.wrapped-fields-container .fieldBox {
|
||||
margin-top: 1rem;
|
||||
width: 100%;
|
||||
|
||||
label {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.help {
|
||||
margin-left: 0 !important;
|
||||
}
|
||||
|
||||
@include media-breakpoint-up(md) {
|
||||
margin-left: 1rem;
|
||||
margin-top: 0;
|
||||
width: auto;
|
||||
|
||||
label {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
label + *:not(.datetime) {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -0,0 +1,172 @@
|
||||
// bootstrap
|
||||
$base: #d32d41;
|
||||
$primary: darken($base, 20%);
|
||||
$secondary: #b3c100;
|
||||
$accent: #b3c100;
|
||||
$font-family-sans-serif: 'Dosis', sans-serif !default;
|
||||
|
||||
// fonts
|
||||
$h1-size: 1.6rem;
|
||||
$h2-size: 1.4rem;
|
||||
$h3-size: 1.2rem;
|
||||
|
||||
// utils
|
||||
$transparent: transparent;
|
||||
$warning-fg: darken(#ffc107, 10%);
|
||||
$danger-fg: #dc3545;
|
||||
|
||||
// login
|
||||
$login-bg: #fff;
|
||||
$password-visibility-toggler-icon-fg: #999;
|
||||
|
||||
// navbar
|
||||
$navbar-bg: #1c2429;
|
||||
$navbar-link-color: #fff;
|
||||
$navbar-dropdown-link-color: #000;
|
||||
$navbar-link-color-hover: #d32d41;
|
||||
$navbar-color: #fff;
|
||||
$navbar-mobile-pane-bg: #263238;
|
||||
|
||||
// footer
|
||||
$footer-bg: #1c2429;
|
||||
$footer-link-color: $accent;
|
||||
$footer-link-color-hover: darken($accent, 10%);
|
||||
$footer-color: #fff;
|
||||
$footer-border-color: #fff;
|
||||
$footer-support-fg: #1c2429;
|
||||
|
||||
// menu
|
||||
$menu-bg: #263238;
|
||||
$menu-color: #fff;
|
||||
$menu-branding-color: #fff;
|
||||
$gravatar-border-color: #fff;
|
||||
$user-links-fg: $accent;
|
||||
$menu-link-color: #ccc;
|
||||
$menu-link-hover-color: #fff;
|
||||
$menu-li-hover-bg: darken($menu-bg, 2%);
|
||||
$menu-li-border-color: #444;
|
||||
$menu-active-voice-bg: darken($primary, 10%);
|
||||
$menu-active-voice-border-color: #f5f5f5;
|
||||
$menu-mobile-title-bg: #37474f;
|
||||
$menu-mobile-title-color: #fff;
|
||||
$menu-mobile-title-border-color: rgba(255, 255, 255, .2);
|
||||
$menu-mobile-back-bg: darken($menu-bg, 5%);
|
||||
$menu-selected-sub-bg: lighten($menu-bg, 5%);
|
||||
$menu-title-bg: darken($menu-mobile-title-bg, 5%);
|
||||
$menu-voice-title-color: $base;
|
||||
$menu-voice-title-bg: darken($menu-bg, 5%);
|
||||
$menu-active-bg: #f5f5f5;
|
||||
$menu-branding-bg: darken($menu-bg, 5%);
|
||||
|
||||
// search field
|
||||
$search-field-input-bg: lighten($menu-bg, 10%);
|
||||
$search-field-input-border-color: $menu-bg;
|
||||
$search-field-color: $menu-color;
|
||||
$search-field-datalist-bg: darken($menu-bg, 5%);
|
||||
$search-field-icon-color: lighten(#007eed, 25%);
|
||||
$search-field-link-color: #fff;
|
||||
$search-field-selected-bg: lighten($menu-bg, 20%);
|
||||
$search-field-selected-color: #fff;
|
||||
|
||||
// dashboard
|
||||
$dashboard-bg: #f5f5f5;
|
||||
$dashboard-title-bg: #fafafa;
|
||||
$dashboard-module-bg: #fff;
|
||||
$dashboard-module-border-color: #fff;
|
||||
$dashboard-caption-bg: #f6f6f6;
|
||||
$dashboard-caption-color: #000;
|
||||
$dashboard-icon-color: #f90;
|
||||
$dashboard-delete-bg: #dc3545;
|
||||
$dashboard-add-bg: #28a745;
|
||||
$dashboard-change-bg: #007eed;
|
||||
|
||||
// breadcrumbs
|
||||
$breadcrumbs-bg: #f0f0f0;
|
||||
$breadcrumbs-border-color: #bbb;
|
||||
|
||||
// content
|
||||
$content-bg: #f5f5f5;
|
||||
|
||||
// changelist
|
||||
$changelist-bg: #fff;
|
||||
$changelist-border-color: #fff;
|
||||
$toolbar-bg: lighten($navbar-mobile-pane-bg, 75%);
|
||||
$toolbar-btn-bg: #fff;
|
||||
$toolbar-btn-hover-bg: #fafafa;
|
||||
$sort-icon-color: #999;
|
||||
$filter-toggler-color: #fff;
|
||||
$filter-toggler-bg: #17a2b8;
|
||||
$filters-bg: #fafafa;
|
||||
$filters-title-bg: #263238;
|
||||
$filters-title-color: #fff;
|
||||
$filter-selected-border-color: $base;
|
||||
$filters-clear-bg: #17a2b8;
|
||||
$rl-head-bg: #f0f0f0;
|
||||
$rl-head-color: inherit;
|
||||
$rl-tr-odd-bg: #fafafa;
|
||||
$rl-tr-odd-color: inherit;
|
||||
$rl-tr-selected-bg-color: #cfc4a8;
|
||||
$rl-tr-selected-bg: lighten($rl-tr-selected-bg-color, 10%);
|
||||
$rl-tr-selected-color: inherit;
|
||||
|
||||
// changeform
|
||||
$changeform-bg: #fff;
|
||||
$changeform-border-color: #fff;
|
||||
$collapse-entry-icon-color: #666;
|
||||
$state-danger-bg: #f2dede;
|
||||
$field-bg: #f9f9f9;
|
||||
$field-row-error-bg: $state-danger-bg;
|
||||
$fieldset-title-bg: lighten($base, 35%);
|
||||
$inline-related-title-bg: #fafafa;
|
||||
$inline-related-title-border-color: #eee;
|
||||
$inline-related-title-border-top-color: #eee;
|
||||
$inline-changelink-bg: #ffe4dc;
|
||||
$inline-tabular-original-bg: #fafafa;
|
||||
$inline-tabular-original-border-color: #eee;
|
||||
$help-text-color: #007eed;
|
||||
$clockbox-title-bg: #eee;
|
||||
$clockbox-title-border-color: #ddd;
|
||||
|
||||
// changeform spinner
|
||||
$spinner-overlay-bg: rgba(255, 255, 255, .8);
|
||||
$spinner-overlay-fg: #000;
|
||||
|
||||
// form components
|
||||
$selector-item-border-color: #ccc;
|
||||
$selector-available-title-bg: #fafafa;
|
||||
$selector-chosen-title-bg: lighten($base, 35%);
|
||||
$selector-chooser-bg: #eee;
|
||||
|
||||
// changehistory
|
||||
$changehistory-bg: #fff;
|
||||
$changehistory-border-color: #fff;
|
||||
|
||||
// pagination
|
||||
$pag-bg: #fff;
|
||||
$pag-hover-bg: #eee;
|
||||
$pag-border-color: #eee;
|
||||
$pag-color: #000;
|
||||
$pag-selected-bg: #455a64;
|
||||
$pag-selected-color: #fff;
|
||||
$pag-selected-border-color: #455a64;
|
||||
|
||||
// delete confirmation
|
||||
$delete-confirmation-bg: #fff;
|
||||
$delete-confirmation-border-color: #fff;
|
||||
|
||||
// analytics
|
||||
$chart-bg: #fff;
|
||||
$chart-border-color: #fff;
|
||||
|
||||
// modal
|
||||
$modal-back-btn-bg: #007eed;
|
||||
$modal-back-btn-fg: #fff;
|
||||
|
||||
// admindocs
|
||||
$admindocs-module-bg: #fff;
|
||||
$admindocs-module-header-bg: #f6f6f6;
|
||||
$admindocs-module-header-border-color: #fff;
|
||||
$admindocs-simple-bg: #ddd;
|
||||
$admindocs-pre-bg: #333;
|
||||
$admindocs-pre-color: #fff;
|
||||
$admindocs-table-border-color: #e0e0e0;
|
@@ -0,0 +1,28 @@
|
||||
@import 'variables';
|
||||
@import 'bootstrap/scss/bootstrap';
|
||||
$fa-font-path: '../../node_modules/@fortawesome/fontawesome-free/webfonts';
|
||||
@import '../../node_modules/@fortawesome/fontawesome-free/scss/fontawesome';
|
||||
@import '../../node_modules/@fortawesome/fontawesome-free/scss/solid';
|
||||
@import '../../node_modules/@fortawesome/fontawesome-free/scss/brands';
|
||||
@import 'fonts';
|
||||
@import 'placeholders';
|
||||
@import 'main';
|
||||
@import 'login';
|
||||
@import 'logout';
|
||||
@import 'navbar';
|
||||
@import 'footer';
|
||||
@import 'menu';
|
||||
@import 'dashboard';
|
||||
@import 'breadcrumbs';
|
||||
@import 'content';
|
||||
@import 'changelist';
|
||||
@import 'changeform';
|
||||
@import 'changehistory';
|
||||
@import 'pagination';
|
||||
@import 'delete_confirmation';
|
||||
@import 'passwordchange';
|
||||
@import 'actionresult';
|
||||
@import 'calendarclock';
|
||||
@import 'analytics';
|
||||
@import 'admindocs';
|
||||
@import 'filer';
|
1
venv/Lib/site-packages/baton/static/baton/app/stats.json
Normal file
@@ -0,0 +1,51 @@
|
||||
const webpack = require("webpack");
|
||||
const path = require("path");
|
||||
|
||||
module.exports = {
|
||||
resolve: {
|
||||
// always import from root (src and node_modules)
|
||||
modules: [path.join(__dirname, "src"), "node_modules"],
|
||||
extensions: [".js"],
|
||||
},
|
||||
// library entry point
|
||||
entry: "./src/index.js",
|
||||
output: {
|
||||
path: path.join(__dirname, "dist"),
|
||||
publicPath: "/static/baton/app/dist/",
|
||||
filename: "baton.min.js",
|
||||
clean: true,
|
||||
},
|
||||
plugins: [
|
||||
new webpack.ProvidePlugin({
|
||||
jQuery: "jquery",
|
||||
$: "jquery",
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
BATON_REVISION: JSON.stringify(process.env.BATON_REVISION),
|
||||
}),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.(js)$/,
|
||||
exclude: /node_modules/,
|
||||
loader: "babel-loader",
|
||||
options: {
|
||||
presets: ["@babel/preset-env"],
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.scss/,
|
||||
use: ["style-loader", "css-loader", "postcss-loader", "sass-loader"],
|
||||
},
|
||||
{
|
||||
test: /\.sass/,
|
||||
use: ["style-loader", "css-loader", "postcss-loader", "sass-loader"],
|
||||
},
|
||||
{
|
||||
test: /\.(svg|eot|woff|woff2|ttf|png|jpe?g|gif)(\?\S*)?$/,
|
||||
type: "asset/resource",
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
20
venv/Lib/site-packages/baton/static/baton/app/webpack.dev.js
Normal file
@@ -0,0 +1,20 @@
|
||||
const { merge } = require("webpack-merge");
|
||||
const common = require("./webpack.common.js");
|
||||
const BundleAnalyzerPlugin = require("webpack-bundle-analyzer")
|
||||
.BundleAnalyzerPlugin;
|
||||
|
||||
module.exports = merge(common, {
|
||||
mode: "development",
|
||||
output: {
|
||||
...common.output,
|
||||
publicPath: "http://localhost:8080/static/baton/app/dist/",
|
||||
},
|
||||
plugins: [...common.plugins, new BundleAnalyzerPlugin()],
|
||||
// this for creating source maps
|
||||
devtool: "eval-source-map",
|
||||
devServer: {
|
||||
headers: {
|
||||
"Access-Control-Allow-Origin": "*", // allow CORS on fonts
|
||||
},
|
||||
},
|
||||
});
|
@@ -0,0 +1,7 @@
|
||||
const { merge } = require('webpack-merge')
|
||||
const common = require('./webpack.common.js')
|
||||
|
||||
module.exports = merge(common, {
|
||||
mode: 'production',
|
||||
devtool: false,
|
||||
})
|
BIN
venv/Lib/site-packages/baton/static/baton/img/logo.png
Normal file
After Width: | Height: | Size: 6.1 KiB |