This commit is contained in:
raman 2025-10-27 17:54:12 +05:30
parent 69b7c01cb2
commit 07818afb3e
123 changed files with 112074 additions and 0 deletions

View File

@ -0,0 +1,5 @@
# -*- coding: utf-8 -*-
# Part of Softhealer Technologies.
from . import controllers
from . import models

View File

@ -0,0 +1,37 @@
# -*- coding: utf-8 -*-
{
"name": "Backend Theme",
"author": "Softhealer Technologies",
"category": "Extra Tools",
"summary": "Material Backend Theme Responsive Backend",
"description": """Backend Base""",
"depends": ['base_setup',],
"data": [
"security/ir.model.access.csv",
"views/sh_user_push_notification_views.xml",
"views/res_config_setting.xml",
],
'assets': {
'web.assets_backend': [
# pyeval domain
# "backend_base/static/src/lib/pyeval.js",
#Notification
'backend_base/static/src/xml/notification_menu.xml',
'backend_base/static/src/scss/notification.scss',
'backend_base/static/src/js/systray_activity_menu.js',
'backend_base/static/src/scss/light_icon/style.css',
'backend_base/static/src/scss/regular_icon/style.css',
'backend_base/static/src/scss/thin_icon/style.css',
# Push Notification
'https://www.gstatic.com/firebasejs/8.4.3/firebase-app.js',
'https://www.gstatic.com/firebasejs/8.4.3/firebase-messaging.js',
'backend_base/static/src/js/firebase.js',
],
},
"images": ["static/description/background.png", ],
"installable": True,
"auto_install": False,
"application": True,
}

View File

@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import firebase_main

View File

@ -0,0 +1,114 @@
import json
from odoo import http
from odoo.http import request
from datetime import datetime
from odoo.tools.safe_eval import safe_eval
class Main(http.Controller):
@http.route('/firebase-messaging-sw.js', type='http', auth="public")
def sw_http(self):
if request.env.company and request.env.company.enable_web_push_notification:
config_obj = request.env.company.config_details
js = """
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(function(registration) {
console.log('Registration successful, scope is:', registration.scope);
}).catch(function(err) {
console.log('Service worker registration failed, error:', err);
});
}
importScripts('https://www.gstatic.com/firebasejs/8.4.2/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/8.4.2/firebase-messaging.js');
var firebaseConfig =
"""+ config_obj +""" ;
firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
messaging.setBackgroundMessageHandler(function(payload) {
const notificationTitle = "Background Message Title";
const notificationOptions = {
body: payload.notification.body,
icon:'https://i.pinimg.com/originals/3f/77/56/3f7756330cd418e46e642254a900a507.jpg',
};
return self.registration.showNotification(
notificationTitle,
notificationOptions,
);
});
"""
return http.request.make_response(js, [('Content-Type', 'text/javascript')])
else:
js = """
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register('/sw.js')
.then(function(registration) {
console.log('Registration successful, scope is:', registration.scope);
}).catch(function(err) {
console.log('Service worker registration failed, error:', err);
});
}
"""
return http.request.make_response(js, [('Content-Type', 'text/javascript')])
@http.route('/web/push_token', type='http', auth="public", csrf=False)
def getToken(self,**post):
device_search = request.env['sh.push.notification'].sudo().search(
[('register_id', '=', post.get('name'))], limit=1)
if device_search and not request.env.user._is_public() and device_search.user_id != request.env.user.id:
if request.env.user.has_group('base.group_portal'):
device_search.write({'user_id':request.env.user.id,'user_type':'portal'})
elif request.env.user:
device_search.write({'user_id':request.env.user.id,'user_type':'internal'})
if not device_search:
vals = {
'register_id' : post.get('name'),
'datetime' : datetime.now()
}
if request.env.user._is_public():
public_users = request.env['res.users'].sudo()
public_groups = request.env.ref("base.group_public", raise_if_not_found=False)
if public_groups:
public_users = public_groups.sudo().with_context(active_test=False).mapped("users")
if public_users:
vals.update({'user_id':public_users[0].id,'user_type':'public'})
elif request.env.user.has_group('base.group_portal'):
vals.update({'user_id':request.env.user.id,'user_type':'portal'})
elif request.env.user:
vals.update({'user_id':request.env.user.id,'user_type':'internal'})
request.env['sh.push.notification'].sudo().create(vals)
@http.route('/web/_config', type='json', auth="public")
def sendConfig(self):
config_vals = {}
if request.env.company and request.env.company.enable_web_push_notification:
config_obj = request.env.company.config_details.replace(" ","")
config_obj = request.env.company.config_details.replace("\n","").replace("\t","").replace(" ","").replace("\"","'").replace('apiKey','\'apiKey\'').replace('authDomain','\'authDomain\'').replace('projectId','\'projectId\'').replace('storageBucket','\'storageBucket\'').replace('messagingSenderId','\'messagingSenderId\'').replace('appId','\'appId\'').replace('measurementId','\'measurementId\'')
config_vals['apiKey'] = safe_eval(config_obj)['apiKey']
config_vals['authDomain'] = safe_eval(config_obj)['authDomain']
config_vals['projectId'] = safe_eval(config_obj)['projectId']
config_vals['storageBucket'] = safe_eval(config_obj)['storageBucket']
config_vals['messagingSenderId'] = safe_eval(config_obj)['messagingSenderId']
config_vals['appId'] = safe_eval(config_obj)['appId']
config_vals['measurementId'] = safe_eval(config_obj)['measurementId']
vals = {
'vapid' : request.env.company.vapid,
'config': config_vals
}
json_vals = json.dumps(vals)
return json_vals

View File

@ -0,0 +1,7 @@
# -*- coding: utf-8 -*-
from . import res_config_settings
from . import res_company
from . import res_users
from . import sh_push_notification
from . import sh_user_push_notification

View File

@ -0,0 +1,14 @@
# -*- coding: utf-8 -*-
from odoo import fields, models
class ResCompany(models.Model):
_inherit = 'res.company'
enable_web_push_notification = fields.Boolean("Enable Firebase Push Notification")
enable_bell_notification = fields.Boolean("Enable Bell Notification")
api_key = fields.Char("Api Key")
vapid = fields.Char("Vapid",readonly=False)
config_details = fields.Text("Config Details")

View File

@ -0,0 +1,15 @@
# -*- coding: utf-8 -*-
# Copyright (C) Softhealer Technologies.
from odoo import api, fields, models
import base64
class ResConfigSettings(models.TransientModel):
_inherit = 'res.config.settings'
enable_web_push_notification = fields.Boolean(related='company_id.enable_web_push_notification',readonly=False)
enable_bell_notification = fields.Boolean(related='company_id.enable_bell_notification',readonly=False)
api_key = fields.Char(related='company_id.api_key',readonly=False)
vapid = fields.Char(related='company_id.vapid',readonly=False)
config_details = fields.Text(related='company_id.config_details',readonly=False)

View File

@ -0,0 +1,45 @@
# -*- coding: utf-8 -*-
from odoo import models, api
class res_users(models.Model):
_inherit = "res.users"
@api.model
def systray_get_firebase_notifications(self):
notifications = self.env['sh.user.push.notification'].sudo().search([('user_id','=',self.env.uid)],limit=25, order='msg_read,id desc')
unread_notifications = self.env['sh.user.push.notification'].sudo().search([('user_id','=',self.env.uid),('msg_read','=',False)])
data_notifications = []
for notification in notifications:
data_notifications.append({
'id':notification.id,
'desc':notification.description,
'name':notification.name,
'user_id':notification.user_id,
'datetime':notification.datetime,
'uid':notification.user_id.id,
'res_model':notification.res_model,
'res_id':notification.res_id,
'msg_read':notification.msg_read ,
})
return list(data_notifications), len(unread_notifications)
@api.model
def systray_get_firebase_all_notifications(self):
notifications = self.env['sh.user.push.notification'].search([('user_id','=',self.env.uid)],order='msg_read,id desc')
unread_notifications = self.env['sh.user.push.notification'].search([('user_id','=',self.env.uid),('msg_read','=',False)])
data_notifications = []
for notification in notifications:
data_notifications.append({
'id':notification.id,
'desc':notification.description,
'name':notification.name,
'user_id':notification.user_id,
'datetime':notification.datetime,
'uid':notification.user_id.id,
'res_model':notification.res_model,
'res_id':notification.res_id,
'msg_read':notification.msg_read,
})
return list(data_notifications), len(unread_notifications)

View File

@ -0,0 +1,12 @@
# -*- coding: utf-8 -*-
from odoo import fields, models
class WebPushNotification(models.Model):
_name = 'sh.push.notification'
_description = 'Web Push Notification'
user_id = fields.Many2one("res.users",string="User")
user_type=fields.Selection([('public','Public'),('portal','Portal'),('internal','Internal')],string="User Type")
datetime = fields.Datetime("Registration Time")
register_id = fields.Char("Registration Id")

View File

@ -0,0 +1,66 @@
# -*- coding: utf-8 -*-
from odoo import fields, models, api, _
from pyfcm import FCMNotification
class UserPushNotification(models.Model):
_name = 'sh.user.push.notification'
_description = "User Notification"
_order = 'msg_read,id desc'
user_id = fields.Many2one("res.users",string="User")
name = fields.Char("Title")
description = fields.Text("Description")
datetime = fields.Datetime("Time")
res_model = fields.Char("Res Model")
res_id = fields.Integer("Res ID")
msg_read = fields.Boolean("Read ?")
@api.model
def has_bell_notification_enabled(self):
has_bell_notification_enabled = False
if self.env.company.enable_bell_notification:
has_bell_notification_enabled = True
result = {
'has_bell_notification_enabled':has_bell_notification_enabled,
}
return result
def open_record(self):
self.write({'msg_read':True})
if self.res_model:
return {
'name':self.name,
'type': 'ir.actions.act_window',
'view_type': 'form',
'view_mode': 'form',
'res_model': self.res_model,
'res_id':self.res_id,
'target': 'current',
}
def create_user_notification(self,user='',name='',description='',res_model='',res_id=''):
if self.env.company.enable_bell_notification:
self.env['bus.bus']._sendone(user.partner_id,
'sh.user.push.notifications', {})
self.env['sh.user.push.notification'].sudo().create({
'user_id': user.id,
'name':name,
'description':description,
'datetime':fields.Datetime.now(),
'res_model':res_model,
'res_id':res_id,
'msg_read':False,
})
if self.env.company.enable_web_push_notification:
domain = ([])
api_key = self.env.company.api_key
push_service = FCMNotification(api_key=api_key)
registration_tokens = []
domain = [('user_id','=',user.id)]
reg_ids = self.env['sh.push.notification'].search(domain)
for ids in reg_ids:
registration_tokens.append(ids.register_id)
message_title = name
message_body = description
push_service.notify_multiple_devices(registration_ids=registration_tokens,message_title=message_title, message_body=message_body)

View File

@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
backend_base.access_sh_user_push_notification,access_sh_user_push_notification,backend_base.model_sh_user_push_notification,base.group_user,1,1,1,1
backend_base.access_sh_push_notification,access_sh_push_notification,backend_base.model_sh_push_notification,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 backend_base.access_sh_user_push_notification access_sh_user_push_notification backend_base.model_sh_user_push_notification base.group_user 1 1 1 1
3 backend_base.access_sh_push_notification access_sh_push_notification backend_base.model_sh_push_notification base.group_user 1 1 1 1

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6d1a8d77b6ef765feac2dfde4611cb7533cbfb54e5d42368d1e1c10c162d4d83
size 32810

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:a3b0409d9e2fcee2d00a4c0b4f98756d131f75d0dc3ed44feff636423dc2a565
size 2167096

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4787fe7d558850226bdf221a3924323879bbc487e97839e544046821315873bd
size 2166932

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:bc24710ffd23fd85c74d4c286e60910e0a90b89214ae091bfb69f987d804f18b
size 2167008

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e4f073de73be01d8686fa92588c8d281f952866bbffae642dceba5add5c6d309
size 1003848

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7e88f115b84e17b47bcf09a82b02116c16566e0c831c4af27648aa33df6f389e
size 1972196

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:751e56ff2c429fd06b8abbd25f988d96b274e9f8877562e85c2e38564d4cb8dc
size 1972032

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:51803c63042c7cae70cc6121edb95ac422fa06b95ff501d6f2371d8382e60589
size 1972108

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:d8df0c389fef55d27b0fa19d3a3033af186edd4c9b4c3a60f65de92eda38958e
size 921976

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:4dff44855f6722278ef33cc3ac727e8fc16c726b95b5a44e485e540bf143eeea
size 2257312

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8b4e230263ec8b1bd6e11d0709279ca71244a7570c5b2ec763cb09862c8b23e9
size 2257148

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e64c1d22db9dd5ecfe857984d50c4114e910c7d2f289bfdb9be94a4b4f6dad18
size 2257224

View File

@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:9b1eae825eae1133932a52ed2cf1e24c811cc67ad01a19265a2b1bbca115fcd7
size 1065520

View File

@ -0,0 +1,55 @@
/** @odoo-module **/
/**
* Executes an action of type 'ir.actions.server'.
*
* @private
* @param {ServerAction} action
* @param {ActionOptions} options
* @returns {Promise<void>}
*/
// import ajax from "@web/legacy/js/core/ajax";
import { rpc } from "@web/core/network/rpc";
var vapid = ''
var firebaseConfig = {};
// ajax.jsonRpc("/web/_config", 'call', {}).then(function (data) {
rpc("/web/_config").then(function (data) {
console.log("\n\n\n\n\n\n\n Dataa", data);
if(data){
var json = JSON.parse(data)
vapid = json.vapid
firebaseConfig = json.config
firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
messaging.onMessage((payload) => {
const notificationOptions = {
body: payload.notification.body,
};
let notification = payload.notification;
navigator.serviceWorker.getRegistrations().then((registration) => {
registration[0].showNotification(notification.title, notificationOptions);
});
});
messaging.requestPermission()
.then(function () {
messaging.getToken({ vapidKey: vapid }).then((currentToken) => {
if (currentToken) {
$.post("/web/push_token",
{
name: currentToken
})
} else {
console.log('No registration token available. Request permission to generate one.');
}
}).catch((err) => {
console.log('An error occurred while retrieving token. ', err);
});
})
}
});

View File

@ -0,0 +1,199 @@
/** @odoo-module **/
import { registry } from "@web/core/registry";
import { _t } from "@web/core/l10n/translation";
import { session } from "@web/session";
import { onWillStart } from "@odoo/owl";
import { useService } from "@web/core/utils/hooks";
const { Component } = owl;
import { rpc } from "@web/core/network/rpc";
export class UserNotificationMenu extends Component {
setup() {
this.busService = this.env.services.bus_service;
this.notifications = this._getActivityData();
this.action = useService("action");
onWillStart(this.onWillStart);
this._updateCounter();
}
async onWillStart() {
this.busService.addEventListener("notification", ({ detail: notifications }) => {
for (const notif of notifications) {
if (notif.type === "sh.user.push.notifications") {
this._getActivityData();
this._updateCounter();
const searchInput = document.querySelector(".o_searchview_input");
if (searchInput) searchInput.click();
document.body.click();
}
}
});
const result = await rpc(
"/web/dataset/call_kw/sh.user.push.notification/has_bell_notification_enabled",
{
model: "sh.user.push.notification",
method: "has_bell_notification_enabled",
args: [],
kwargs: {},
}
);
const bellElements = document.querySelectorAll(".js_bell_notification");
bellElements.forEach((el) => {
if (result.has_bell_notification_enabled) {
el.classList.remove("d-none");
} else {
el.classList.add("d-none");
}
});
}
async _onPushNotificationClick(notification) {
const data = notification;
await rpc("/web/dataset/call_kw/sh.user.push.notification/write", {
model: "sh.user.push.notification",
method: "write",
args: [data.id, { msg_read: true }],
kwargs: {},
});
await this._getActivityData();
this._updateCounter();
if (data.res_model) {
await this.action.doAction({
type: "ir.actions.act_window",
name: data.res_model,
res_model: data.res_model,
views: [
[false, "form"],
[false, "tree"],
],
domain: [["id", "=", data.res_id]],
res_id: data.res_id,
context: {},
});
}
}
async _onClickReadAllNotification() {
const data = await rpc(
"/web/dataset/call_kw/res.users/systray_get_firebase_all_notifications",
{
model: "res.users",
method: "systray_get_firebase_all_notifications",
args: [],
kwargs: { context: session.user_context },
}
);
this._notifications = data[0] || [];
for (const each_data of this._notifications) {
await rpc("/web/dataset/call_kw/sh.user.push.notification/write", {
model: "sh.user.push.notification",
method: "write",
args: [each_data.id, { msg_read: true }],
kwargs: {},
});
}
await this._getActivityData();
this._updateCounter();
}
_onClickAllNotification() {
this.action.doAction({
type: "ir.actions.act_window",
name: "Notifications",
res_model: "sh.user.push.notification",
views: [[false, "list"]],
target: "current",
domain: [["user_id", "=", session.uid]],
});
}
_updateCounter() {
const counter = this._counter || 0;
const counterEl = document.querySelector(".o_notification_counter");
if (counterEl) {
counterEl.textContent = counter > 0 ? counter : "";
}
}
async _getActivityData() {
const data = await rpc(
"/web/dataset/call_kw/res.users/systray_get_firebase_notifications",
{
model: "res.users",
method: "systray_get_firebase_notifications",
args: [],
kwargs: { context: session.user_context },
}
);
this._notifications = data[0] || [];
this._counter = data[1] || 0;
for (const each_data of this._notifications) {
each_data.datetime = this.formatRelativeTime(each_data.datetime);
}
this._updateCounter();
return data;
}
async _updateActivityPreview() {
this.notifications = this._notifications || [];
document
.querySelector(".o_notification_systray_dropdown_items")
?.classList.remove("d-none");
}
async _onActivityMenuShow() {
const dropdown = document.querySelector(".o_notification_systray_dropdown");
if (dropdown) {
dropdown.style.display =
dropdown.style.display === "none" || !dropdown.style.display
? "block"
: "none";
}
await this._updateActivityPreview();
this.render(true);
}
formatRelativeTime(dateTime) {
const now = new Date();
const dt = new Date(dateTime);
const diffInSeconds = Math.floor((now - dt) / 1000);
if (diffInSeconds < 60) return _t("less than a minute ago");
if (diffInSeconds < 120) return _t("about a minute ago");
if (diffInSeconds < 3600)
return _t(`${Math.floor(diffInSeconds / 60)} minutes ago`);
if (diffInSeconds < 7200) return _t("about an hour ago");
if (diffInSeconds < 86400)
return _t(`${Math.floor(diffInSeconds / 3600)} hours ago`);
if (diffInSeconds < 172800) return _t("a day ago");
if (diffInSeconds < 2592000)
return _t(`${Math.floor(diffInSeconds / 86400)} days ago`);
if (diffInSeconds < 5184000) return _t("about a month ago");
if (diffInSeconds < 31536000)
return _t(`${Math.floor(diffInSeconds / 2592000)} months ago`);
if (diffInSeconds < 63072000) return _t("about a year ago");
return _t(`${Math.floor(diffInSeconds / 31536000)} years ago`);
}
}
UserNotificationMenu.template = "mail.systray.UserNotificationMenu";
export const systrayItem = {
Component: UserNotificationMenu,
};
registry.category("systray").add("UserNotificationMenu", systrayItem);

View File

@ -0,0 +1,988 @@
odoo.define('sh_domain_field', function (require) {
"use strict";
var core = require('web.core');
var utils = require('web.utils');
var py_utils = require('web.py_utils');
var _t = core._t;
var py = window.py; // to silence linters
/* Methods copied from pyeval from odoo11 */
var obj = function () {};
obj.prototype = py.object;
var asJS = function (arg) {
if (arg instanceof obj) {
return arg.toJSON();
}
return arg;
};
var datetime = py.PY_call(py.object);
var zero = py.float.fromJSON(0);
// Port from pypy/lib_pypy/datetime.py
var DAYS_IN_MONTH = [null, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
var DAYS_BEFORE_MONTH = [null];
var dbm = 0;
for (var i=1; i<DAYS_IN_MONTH.length; ++i) {
DAYS_BEFORE_MONTH.push(dbm);
dbm += DAYS_IN_MONTH[i];
}
function is_leap(year) {
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
}
function days_before_year(year) {
var y = year - 1;
return y*365 + Math.floor(y/4) - Math.floor(y/100) + Math.floor(y/400);
}
function days_in_month(year, month) {
if (month === 2 && is_leap(year)) {
return 29;
}
return DAYS_IN_MONTH[month];
}
function days_before_month(year, month) {
var post_leap_feb = month > 2 && is_leap(year);
return DAYS_BEFORE_MONTH[month] + (post_leap_feb ? 1 : 0);
}
function ymd2ord(year, month, day) {
var dim = days_in_month(year, month);
if (!(1 <= day && day <= dim)) {
throw new Error("ValueError: day must be in 1.." + dim);
}
return days_before_year(year) +
days_before_month(year, month) +
day;
}
var DI400Y = days_before_year(401);
var DI100Y = days_before_year(101);
var DI4Y = days_before_year(5);
function ord2ymd(n) {
--n;
var n400, n100, n4, n1, n0;
utils.divmod(n, DI400Y, function (_n400, n) {
n400 = _n400;
utils.divmod(n, DI100Y, function (_n100, n) {
n100 = _n100;
utils.divmod(n, DI4Y, function (_n4, n) {
n4 = _n4;
utils.divmod(n, 365, function (_n1, n) {
n1 = _n1;
n0 = n;
});
});
});
});
n = n0;
var year = n400 * 400 + 1 + n100 * 100 + n4 * 4 + n1;
if (n1 == 4 || n100 == 100) {
utils.assert(n0 === 0);
return {
year: year - 1,
month: 12,
day: 31
};
}
var leapyear = n1 === 3 && (n4 !== 24 || n100 == 3);
utils.assert(leapyear == is_leap(year));
var month = (n + 50) >> 5;
var preceding = DAYS_BEFORE_MONTH[month] + ((month > 2 && leapyear) ? 1 : 0);
if (preceding > n) {
--month;
preceding -= DAYS_IN_MONTH[month] + ((month === 2 && leapyear) ? 1 : 0);
}
n -= preceding;
return {
year: year,
month: month,
day: n+1
};
}
/**
* Converts the stuff passed in into a valid date, applying overflows as needed
*/
function tmxxx(year, month, day, hour, minute, second, microsecond) {
hour = hour || 0; minute = minute || 0; second = second || 0;
microsecond = microsecond || 0;
if (microsecond < 0 || microsecond > 999999) {
utils.divmod(microsecond, 1000000, function (carry, ms) {
microsecond = ms;
second += carry;
});
}
if (second < 0 || second > 59) {
utils.divmod(second, 60, function (carry, s) {
second = s;
minute += carry;
});
}
if (minute < 0 || minute > 59) {
utils.divmod(minute, 60, function (carry, m) {
minute = m;
hour += carry;
});
}
if (hour < 0 || hour > 23) {
utils.divmod(hour, 24, function (carry, h) {
hour = h;
day += carry;
});
}
// That was easy. Now it gets muddy: the proper range for day
// can't be determined without knowing the correct month and year,
// but if day is, e.g., plus or minus a million, the current month
// and year values make no sense (and may also be out of bounds
// themselves).
// Saying 12 months == 1 year should be non-controversial.
if (month < 1 || month > 12) {
utils.divmod(month-1, 12, function (carry, m) {
month = m + 1;
year += carry;
});
}
// Now only day can be out of bounds (year may also be out of bounds
// for a datetime object, but we don't care about that here).
// If day is out of bounds, what to do is arguable, but at least the
// method here is principled and explainable.
var dim = days_in_month(year, month);
if (day < 1 || day > dim) {
// Move day-1 days from the first of the month. First try to
// get off cheap if we're only one day out of range (adjustments
// for timezone alone can't be worse than that).
if (day === 0) {
--month;
if (month > 0) {
day = days_in_month(year, month);
} else {
--year; month=12; day=31;
}
} else if (day == dim + 1) {
++month;
day = 1;
if (month > 12) {
month = 1;
++year;
}
} else {
var r = ord2ymd(ymd2ord(year, month, 1) + (day - 1));
year = r.year;
month = r.month;
day = r.day;
}
}
return {
year: year,
month: month,
day: day,
hour: hour,
minute: minute,
second: second,
microsecond: microsecond
};
}
datetime.timedelta = py.type('timedelta', null, {
__init__: function () {
var args = py.PY_parseArgs(arguments, [
['days', zero], ['seconds', zero], ['microseconds', zero],
['milliseconds', zero], ['minutes', zero], ['hours', zero],
['weeks', zero]
]);
var d = 0, s = 0, m = 0;
var days = args.days.toJSON() + args.weeks.toJSON() * 7;
var seconds = args.seconds.toJSON()
+ args.minutes.toJSON() * 60
+ args.hours.toJSON() * 3600;
var microseconds = args.microseconds.toJSON()
+ args.milliseconds.toJSON() * 1000;
// Get rid of all fractions, and normalize s and us.
// Take a deep breath <wink>.
var daysecondsfrac = utils.modf(days, function (dayfrac, days) {
d = days;
if (dayfrac) {
return utils.modf(dayfrac * 24 * 3600, function (dsf, dsw) {
s = dsw;
return dsf;
});
}
return 0;
});
var secondsfrac = utils.modf(seconds, function (sf, s) {
seconds = s;
return sf + daysecondsfrac;
});
utils.divmod(seconds, 24*3600, function (days, seconds) {
d += days;
s += seconds;
});
// seconds isn't referenced again before redefinition
microseconds += secondsfrac * 1e6;
utils.divmod(microseconds, 1000000, function (seconds, microseconds) {
utils.divmod(seconds, 24*3600, function (days, seconds) {
d += days;
s += seconds;
m += Math.round(microseconds);
});
});
// Carrying still possible here?
this.days = d;
this.seconds = s;
this.microseconds = m;
},
__str__: function () {
var hh, mm, ss;
utils.divmod(this.seconds, 60, function (m, s) {
utils.divmod(m, 60, function (h, m) {
hh = h;
mm = m;
ss = s;
});
});
var s = _.str.sprintf("%d:%02d:%02d", hh, mm, ss);
if (this.days) {
s = _.str.sprintf("%d day%s, %s",
this.days,
(this.days != 1 && this.days != -1) ? 's' : '',
s);
}
if (this.microseconds) {
s = _.str.sprintf("%s.%06d", s, this.microseconds);
}
return py.str.fromJSON(s);
},
__eq__: function (other) {
if (!py.PY_isInstance(other, datetime.timedelta)) {
return py.False;
}
return (this.days === other.days
&& this.seconds === other.seconds
&& this.microseconds === other.microseconds)
? py.True : py.False;
},
__add__: function (other) {
if (!py.PY_isInstance(other, datetime.timedelta)) {
return py.NotImplemented;
}
return py.PY_call(datetime.timedelta, [
py.float.fromJSON(this.days + other.days),
py.float.fromJSON(this.seconds + other.seconds),
py.float.fromJSON(this.microseconds + other.microseconds)
]);
},
__radd__: function (other) { return this.__add__(other); },
__sub__: function (other) {
if (!py.PY_isInstance(other, datetime.timedelta)) {
return py.NotImplemented;
}
return py.PY_call(datetime.timedelta, [
py.float.fromJSON(this.days - other.days),
py.float.fromJSON(this.seconds - other.seconds),
py.float.fromJSON(this.microseconds - other.microseconds)
]);
},
__rsub__: function (other) {
if (!py.PY_isInstance(other, datetime.timedelta)) {
return py.NotImplemented;
}
return this.__neg__().__add__(other);
},
__neg__: function () {
return py.PY_call(datetime.timedelta, [
py.float.fromJSON(-this.days),
py.float.fromJSON(-this.seconds),
py.float.fromJSON(-this.microseconds)
]);
},
__pos__: function () { return this; },
__mul__: function (other) {
if (!py.PY_isInstance(other, py.float)) {
return py.NotImplemented;
}
var n = other.toJSON();
return py.PY_call(datetime.timedelta, [
py.float.fromJSON(this.days * n),
py.float.fromJSON(this.seconds * n),
py.float.fromJSON(this.microseconds * n)
]);
},
__rmul__: function (other) { return this.__mul__(other); },
__div__: function (other) {
if (!py.PY_isInstance(other, py.float)) {
return py.NotImplemented;
}
var usec = ((this.days * 24 * 3600) + this.seconds) * 1000000
+ this.microseconds;
return py.PY_call(
datetime.timedelta, [
zero, zero, py.float.fromJSON(usec / other.toJSON())]);
},
__floordiv__: function (other) { return this.__div__(other); },
total_seconds: function () {
return py.float.fromJSON(
this.days * 86400
+ this.seconds
+ this.microseconds / 1000000);
},
__nonzero__: function () {
return (!!this.days || !!this.seconds || !!this.microseconds)
? py.True
: py.False;
}
});
datetime.datetime = py.type('datetime', null, {
__init__: function () {
var zero = py.float.fromJSON(0);
var args = py.PY_parseArgs(arguments, [
'year', 'month', 'day',
['hour', zero], ['minute', zero], ['second', zero],
['microsecond', zero], ['tzinfo', py.None]
]);
for(var key in args) {
if (!args.hasOwnProperty(key)) { continue; }
this[key] = asJS(args[key]);
}
},
replace: function () {
var args = py.PY_parseArgs(arguments, [
['year', py.None], ['month', py.None], ['day', py.None],
['hour', py.None], ['minute', py.None], ['second', py.None],
['microsecond', py.None] // FIXME: tzinfo, can't use None as valid input
]);
var params = {};
for(var key in args) {
if (!args.hasOwnProperty(key)) { continue; }
var arg = args[key];
params[key] = (arg === py.None ? this[key] : asJS(arg));
}
return py.PY_call(datetime.datetime, params);
},
strftime: function () {
var self = this;
var args = py.PY_parseArgs(arguments, 'format');
return py.str.fromJSON(args.format.toJSON()
.replace(/%([A-Za-z])/g, function (m, c) {
switch (c) {
case 'Y': return _.str.sprintf('%04d', self.year);
case 'm': return _.str.sprintf('%02d', self.month);
case 'd': return _.str.sprintf('%02d', self.day);
case 'H': return _.str.sprintf('%02d', self.hour);
case 'M': return _.str.sprintf('%02d', self.minute);
case 'S': return _.str.sprintf('%02d', self.second);
}
throw new Error('ValueError: No known conversion for ' + m);
}));
},
now: py.classmethod.fromJSON(function () {
var d = new Date();
return py.PY_call(datetime.datetime, [
d.getFullYear(), d.getMonth() + 1, d.getDate(),
d.getHours(), d.getMinutes(), d.getSeconds(),
d.getMilliseconds() * 1000]);
}),
today: py.classmethod.fromJSON(function () {
var dt_class = py.PY_getAttr(datetime, 'datetime');
return py.PY_call(py.PY_getAttr(dt_class, 'now'));
}),
utcnow: py.classmethod.fromJSON(function () {
var d = new Date();
return py.PY_call(datetime.datetime,
[d.getUTCFullYear(), d.getUTCMonth() + 1, d.getUTCDate(),
d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(),
d.getUTCMilliseconds() * 1000]);
}),
combine: py.classmethod.fromJSON(function () {
var args = py.PY_parseArgs(arguments, 'date time');
return py.PY_call(datetime.datetime, [
py.PY_getAttr(args.date, 'year'),
py.PY_getAttr(args.date, 'month'),
py.PY_getAttr(args.date, 'day'),
py.PY_getAttr(args.time, 'hour'),
py.PY_getAttr(args.time, 'minute'),
py.PY_getAttr(args.time, 'second')
]);
}),
toJSON: function () {
return new Date(
this.year,
this.month - 1,
this.day,
this.hour,
this.minute,
this.second,
this.microsecond / 1000);
},
__add__: function (other) {
if (!py.PY_isInstance(other, datetime.timedelta)) {
return py.NotImplemented;
}
var s = tmxxx(this.year, this.month, this.day + other.days, this.hour, this.minute, this.second + other.seconds);
return datetime.datetime.fromJSON(s.year, s.month, s.day, s.hour, s.minute, s.second);
},
__sub__: function (other) {
if (py.PY_isInstance(other, datetime.timedelta)) {
return py.PY_add(this, py.PY_negative(other));
}
return py.NotImplemented;
},
fromJSON: function (year, month, day, hour, minute, second) {
return py.PY_call(datetime.datetime, [year, month, day, hour, minute, second]);
},
});
datetime.date = py.type('date', null, {
__init__: function () {
var args = py.PY_parseArgs(arguments, 'year month day');
this.year = asJS(args.year);
this.month = asJS(args.month);
this.day = asJS(args.day);
},
strftime: function () {
var self = this;
var args = py.PY_parseArgs(arguments, 'format');
return py.str.fromJSON(args.format.toJSON()
.replace(/%([A-Za-z])/g, function (m, c) {
switch (c) {
case 'Y': return self.year;
case 'm': return _.str.sprintf('%02d', self.month);
case 'd': return _.str.sprintf('%02d', self.day);
}
throw new Error('ValueError: No known conversion for ' + m);
}));
},
__eq__: function (other) {
return (this.year === other.year
&& this.month === other.month
&& this.day === other.day)
? py.True : py.False;
},
replace: function () {
var args = py.PY_parseArgs(arguments, [
['year', py.None], ['month', py.None], ['day', py.None]
]);
var params = {};
for(var key in args) {
if (!args.hasOwnProperty(key)) { continue; }
var arg = args[key];
params[key] = (arg === py.None ? this[key] : asJS(arg));
}
return py.PY_call(datetime.date, params);
},
__add__: function (other) {
if (!py.PY_isInstance(other, datetime.timedelta)) {
return py.NotImplemented;
}
var s = tmxxx(this.year, this.month, this.day + other.days);
return datetime.date.fromJSON(s.year, s.month, s.day);
},
__radd__: function (other) { return this.__add__(other); },
__sub__: function (other) {
if (py.PY_isInstance(other, datetime.timedelta)) {
return py.PY_add(this, py.PY_negative(other));
}
if (py.PY_isInstance(other, datetime.date)) {
// FIXME: getattr and sub API methods
return py.PY_call(datetime.timedelta, [
py.PY_subtract(
py.PY_call(py.PY_getAttr(this, 'toordinal')),
py.PY_call(py.PY_getAttr(other, 'toordinal')))
]);
}
return py.NotImplemented;
},
toordinal: function () {
return py.float.fromJSON(ymd2ord(this.year, this.month, this.day));
},
weekday: function () {
return py.float.fromJSON((this.toordinal().toJSON()+6)%7);
},
fromJSON: function (year, month, day) {
return py.PY_call(datetime.date, [year, month, day]);
},
today: py.classmethod.fromJSON(function () {
var d = new Date ();
return py.PY_call(datetime.date, [
d.getFullYear(), d.getMonth() + 1, d.getDate()]);
}),
});
/**
* Returns the current local date, which means the date on the client (which can be different
* compared to the date of the server).
*
* @return {datetime.date}
*/
function context_today() {
var d = new Date();
return py.PY_call(
datetime.date, [d.getFullYear(), d.getMonth() + 1, d.getDate()]);
}
datetime.time = py.type('time', null, {
__init__: function () {
var zero = py.float.fromJSON(0);
var args = py.PY_parseArgs(arguments, [
['hour', zero], ['minute', zero], ['second', zero], ['microsecond', zero],
['tzinfo', py.None]
]);
for(var k in args) {
if (!args.hasOwnProperty(k)) { continue; }
this[k] = asJS(args[k]);
}
}
});
var time = py.PY_call(py.object);
time.strftime = py.PY_def.fromJSON(function () {
var args = py.PY_parseArgs(arguments, 'format');
var dt_class = py.PY_getAttr(datetime, 'datetime');
var d = py.PY_call(py.PY_getAttr(dt_class, 'utcnow'));
return py.PY_call(py.PY_getAttr(d, 'strftime'), [args.format]);
});
var args = _.map(('year month day '
+ 'years months weeks days '
+ 'weekday leapdays yearday nlyearday').split(' '), function (arg) {
switch (arg) {
case 'years':case 'months':case 'days':case 'leapdays':case 'weeks':
return [arg, zero];
case 'year':case 'month':case 'day':case 'weekday':
case 'yearday':case 'nlyearday':
return [arg, null];
default:
throw new Error("Unknown relativedelta argument " + arg);
}
});
args.unshift('*');
var _utils = {
monthrange: function (year, month) {
if (month < 1 || month > 12) {
throw new Error("Illegal month " + month);
}
var day1 = this.weekday(year, month, 1);
var ndays = this.mdays[month] + (month == this.February && this.isleap(year));
return [day1, ndays];
},
weekday: function (year, month, day) {
var date = py.PY_call(datetime.date, [year, month, day]);
return py.PY_call(py.PY_getAttr(date, 'weekday'));
},
isleap: function (year) {
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);
},
mdays: [0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
January: 1,
February: 2
};
var relativedelta = py.type('relativedelta', null, {
__init__: function () {
this.ops = py.PY_parseArgs(arguments, args);
this.ops.days = py.float.fromJSON(
asJS(this.ops.days) + asJS(this.ops.weeks) * 7
);
var yday = zero;
if (this.ops.nlyearday) {
yday = this.ops.nlyearday;
} else if (this.ops.yearday) {
yday = this.ops.yearday;
if (asJS(this.ops.yearday) > 59) {
this.ops.leapdays = py.float.fromJS(-1);
}
}
if (py.PY_isTrue(yday)) {
var ydayidx = [31, 59, 90, 120, 151, 181, 212,
243, 273, 304, 334, 366];
for(var idx=0; idx<ydayidx.length; ++idx) {
var ydays = ydayidx[idx];
if (asJS(yday) <= ydays) {
this.ops.month = py.float.fromJSON(idx+1);
if (!idx) {
this.ops.day = yday;
} else {
this.ops.day = py.PY_subtract(
yday,
py.float.fromJSON(ydayidx[idx-1])
);
}
break;
}
}
if (idx === ydayidx.length) {
throw new Error("Invalid year day (" + asJS(yday) + ")");
}
}
this._fix();
},
_fix: function () {
var self = this;
var months = asJS(this.ops.months);
if (Math.abs(months) > 11) {
var s = months > 0 ? 1 : -1;
utils.divmod(months * s, 12, function (years, months) {
self.ops.months = py.float.fromJSON(months*s);
self.ops.years = py.float.fromJSON(
asJS(self.ops.years) + years*s);
});
}
this._has_time = 0;
},
__add__: function (other) {
if (!py.PY_isInstance(other, datetime.date)) {
return py.NotImplemented;
}
// TODO: test this whole mess
var year = (asJS(this.ops.year) || asJS(other.year)) + asJS(this.ops.years);
var month = asJS(this.ops.month) || asJS(other.month);
var months;
if (months = asJS(this.ops.months)) {
if (Math.abs(months) < 1 || Math.abs(months) > 12) {
throw new Error("Can only use relative months between -12 and +12");
}
month += months;
if (month > 12) {
year += 1;
month -= 12;
}
if (month < 1) {
year -= 1;
month += 12;
}
}
var day = Math.min(_utils.monthrange(year, month)[1],
asJS(this.ops.day) || asJS(other.day));
var repl = {
year: py.float.fromJSON(year),
month: py.float.fromJSON(month),
day: py.float.fromJSON(day)
};
var days = asJS(this.ops.days);
if (py.PY_isTrue(this.ops.leapdays) && month > 2 && _utils.isleap(year)) {
days += asJS(this.ops.leapdays);
}
var ret = py.PY_add(
py.PY_call(py.PY_getAttr(other, 'replace'), repl),
py.PY_call(datetime.timedelta, {
days: py.float.fromJSON(days)
})
);
if (this.ops.weekday) {
// FIXME: only handles numeric weekdays, not decorated
var weekday = asJS(this.ops.weekday), nth = 1;
var jumpdays = (Math.abs(nth) - 1) * 7;
var ret_weekday = asJS(py.PY_call(py.PY_getAttr(ret, 'weekday')));
if (nth > 0) {
jumpdays += (7-ret_weekday+weekday) % 7;
} else {
jumpdays += (ret_weekday - weekday) % 7;
jumpdays *= -1;
}
ret = py.PY_add(
ret,
py.PY_call(datetime.timedelta, {
days: py.float.fromJSON(jumpdays)
})
);
}
return ret;
},
__radd__: function (other) {
return this.__add__(other);
},
__rsub__: function (other) {
return this.__neg__().__radd__(other);
},
__neg__: function () {
return py.PY_call(relativedelta, {
years: py.PY_negative(this.ops.years),
months: py.PY_negative(this.ops.months),
days: py.PY_negative(this.ops.days),
leapdays: this.ops.leapdays,
year: this.ops.year,
month: this.ops.month,
day: this.ops.day,
weekday: this.ops.weekday
});
}
});
// recursively wraps JS objects passed into the context to attributedicts
// which jsonify back to JS objects
function wrap(value) {
if (value === null) { return py.None; }
switch (typeof value) {
case 'undefined': throw new Error("No conversion for undefined");
case 'boolean': return py.bool.fromJSON(value);
case 'number': return py.float.fromJSON(value);
case 'string': return py.str.fromJSON(value);
}
switch(value.constructor) {
case Object: return wrapping_dict.fromJSON(value);
case Array: return wrapping_list.fromJSON(value);
}
throw new Error("ValueError: unable to wrap " + value);
}
var wrapping_dict = py.type('wrapping_dict', null, {
__init__: function () {
this._store = {};
},
__getitem__: function (key) {
var k = key.toJSON();
if (!(k in this._store)) {
throw new Error("KeyError: '" + k + "'");
}
return wrap(this._store[k]);
},
__getattr__: function (key) {
return this.__getitem__(py.str.fromJSON(key));
},
__len__: function () {
return Object.keys(this._store).length;
},
__nonzero__: function () {
return py.PY_size(this) > 0 ? py.True : py.False;
},
get: function () {
var args = py.PY_parseArgs(arguments, ['k', ['d', py.None]]);
if (!(args.k.toJSON() in this._store)) { return args.d; }
return this.__getitem__(args.k);
},
fromJSON: function (d) {
var instance = py.PY_call(wrapping_dict);
instance._store = d;
return instance;
},
toJSON: function () {
return this._store;
},
});
var wrapping_list = py.type('wrapping_list', null, {
__init__: function () {
this._store = [];
},
__getitem__: function (index) {
return wrap(this._store[index.toJSON()]);
},
__len__: function () {
return this._store.length;
},
__nonzero__: function () {
return py.PY_size(this) > 0 ? py.True : py.False;
},
fromJSON: function (ar) {
var instance = py.PY_call(wrapping_list);
instance._store = ar;
return instance;
},
toJSON: function () {
return this._store;
},
});
function wrap_context(context) {
for (var k in context) {
if (!context.hasOwnProperty(k)) { continue; }
var val = context[k];
if (val === null) { continue; }
if (val.constructor === Array) {
context[k] = wrapping_list.fromJSON(val);
} else if (val.constructor === Object
&& !py.PY_isInstance(val, py.object)) {
context[k] = wrapping_dict.fromJSON(val);
}
}
return context;
}
function eval_domains(domains, evaluation_context) {
evaluation_context = _.extend(pycontext(), evaluation_context || {});
var result_domain = [];
// Normalize only if the first domain is the array ["|"] or ["!"]
var need_normalization = (
domains &&
domains.length > 0 &&
domains[0].length === 1 &&
(domains[0][0] === "|" || domains[0][0] === "!")
);
_(domains).each(function (domain) {
if (_.isString(domain)) {
// wrap raw strings in domain
if (domain in evaluation_context) {
result_domain.push.apply(
result_domain, $.parseJSON(evaluation_context[domain]));
return;
}
domain = { __ref: 'domain', __debug: domain };
}
var domain_array_to_combine;
switch(domain.__ref) {
case 'domain':
evaluation_context.context = evaluation_context;
domain_array_to_combine = py.eval(domain.__debug, wrap_context(evaluation_context));
break;
default:
domain_array_to_combine = domain;
}
if (need_normalization) {
domain_array_to_combine = get_normalized_domain(domain_array_to_combine);
}
result_domain.push.apply(result_domain, domain_array_to_combine);
});
return result_domain;
}
function pycontext() {
return {
datetime: datetime,
context_today: context_today,
time: time,
relativedelta: relativedelta,
current_date: py.PY_call(
time.strftime, [py.str.fromJSON('%Y-%m-%d')]),
};
}
function eval_contexts(contexts, evaluation_context) {
evaluation_context = _.extend(pycontext(), evaluation_context || {});
return _(contexts).reduce(function (result_context, ctx) {
// __eval_context evaluations can lead to some of `contexts`'s
// values being null, skip them as well as empty contexts
if (_.isEmpty(ctx)) { return result_context; }
if (_.isString(ctx)) {
// wrap raw strings in context
ctx = { __ref: 'context', __debug: ctx };
}
var evaluated = ctx;
switch(ctx.__ref) {
case 'context':
evaluation_context.context = evaluation_context;
evaluated = py.eval(ctx.__debug, wrap_context(evaluation_context));
break;
case 'compound_context':
var eval_context = eval_contexts([ctx.__eval_context]);
evaluated = eval_contexts(
ctx.__contexts, _.extend({}, evaluation_context, eval_context));
break;
}
// add newly evaluated context to evaluation context for following
// siblings
_.extend(evaluation_context, evaluated);
return _.extend(result_context, evaluated);
}, {});
}
function eval_groupbys(contexts, evaluation_context) {
evaluation_context = _.extend(pycontext(), evaluation_context || {});
var result_group = [];
_(contexts).each(function (ctx) {
if (_.isString(ctx)) {
// wrap raw strings in context
ctx = { __ref: 'context', __debug: ctx };
}
var group;
var evaluated = ctx;
switch(ctx.__ref) {
case 'context':
evaluation_context.context = evaluation_context;
evaluated = py.eval(ctx.__debug, wrap_context(evaluation_context));
break;
case 'compound_context':
var eval_context = eval_contexts([ctx.__eval_context]);
evaluated = eval_contexts(
ctx.__contexts, _.extend({}, evaluation_context, eval_context));
break;
}
group = evaluated.group_by;
if (!group) { return; }
if (typeof group === 'string') {
result_group.push(group);
} else if (group instanceof Array) {
result_group.push.apply(result_group, group);
} else {
throw new Error('Got invalid groupby {{'
+ JSON.stringify(group) + '}}');
}
_.extend(evaluation_context, evaluated);
});
return result_group;
}
function pyeval(type, object, context, options) {
context = _.extend(pycontext(), context || {});
//noinspection FallthroughInSwitchStatementJS
switch(type) {
case 'context':
case 'contexts':
if (type === 'context') {
object = [object];
}
return eval_contexts(object, context);
case 'domain':
case 'domains':
if (type === 'domain')
object = [object];
return eval_domains(object, context);
case 'groupbys':
return eval_groupbys(object, context);
}
throw new Error("Unknow evaluation type " + type);
}
py_utils.eval = pyeval;
function eval_domains_and_contexts(source) {
// see Session.eval_context in Python
return {
context: pyeval('contexts', source.contexts || [], source.eval_context),
domain: pyeval('domains', source.domains, source.eval_context),
group_by: pyeval('groupbys', source.group_by_seq || [], source.eval_context),
};
}
py_utils.eval_domains_and_contexts = eval_domains_and_contexts;
});

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,33 @@
//.o_main_navbar .o_menu_systray .o_notification_systray_item .o_notification_counter.badge{background: $primary_hover;font-size: 10px !important;margin-top: -0.8rem;margin-right: 0px;margin-left: -0.6rem;color: white;vertical-align: super;}
.o_menu_systray .o_notification_systray_item a.sh_view_all_btn .sh_view_all_notification{color: #fff;}
.o_menu_systray .o_notification_systray_item .view_all_btn_right a.sh_view_all_btn,
.o_menu_systray .o_notification_systray_item .rd_all_btn_left a.sh_view_read_all_btn{padding: 6px 10px;background: darken($o-brand-primary, 10%);text-align: right;cursor: pointer;text-decoration:none;color: #fff;display: block;}
.o_menu_systray .o_notification_systray_item .o_mail_preview .o_preview_info{padding: 10px;}
.o_menu_systray .o_notification_systray_item .o_notification_systray_dropdown.dropdown-menu {flex: 0 1 auto;width: 350px;min-height: 50px;max-height: 562px;z-index: 1100; left: auto; right:0;}
.o_menu_systray .o_notification_systray_item .o_mail_preview:hover{background: #ededed;}
.o_menu_systray .o_notification_systray_item .o_mail_preview .o_preview_info.sh_unread .o_preview_title{color: darken($o-brand-primary, 10%);}
.o_menu_systray .o_notification_systray_item .o_mail_preview .o_preview_info.sh_unread{background: #ededed;}
.o_menu_systray .o_notification_systray_item .o_mail_preview .o_preview_info p.para_text{margin-bottom: 0px;}
.o_menu_systray .o_notification_systray_item .o_mail_preview .o_preview_info h6{margin-bottom: 0px;}
.o_menu_systray .o_notification_systray_item .o_mail_preview .o_preview_info p.para_text{width: 100%;max-height: 20px;color: #9d9d9d;max-width: 100%;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;vertical-align: top;}
.o_menu_systray .o_notification_systray_item .o_mail_preview .o_preview_info .d-flex{display: flex;justify-content: space-between;align-items: center;width: 100%;}
.o_menu_systray .o_notification_systray_item .o_mail_preview .o_preview_info b {width: 75%;max-height: 20px;max-width: 75%;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;}
.o_menu_systray .o_notification_systray_item .o_mail_preview .o_preview_info .o_preview_name{width: 100%;}
.o_menu_systray .o_notification_systray_item .js_bell_notification{display: flex;align-items: center;width: auto;height: var(--o-navbar-height, 40px);user-select: none;background: transparent;font-size: 1.08333333rem;color: rgba(255, 255, 255, 0.9); margin-right: 10px;}
@media only screen and (max-width: 992px) and (min-width: 768px){
.o_menu_systray .o_notification_systray_item{position: unset;}
}
@media only screen and (max-width: 767.98px){
.o_menu_systray .o_notification_systray_item .o_mail_preview .o_preview_info{margin-left: 0px;}
.o_menu_systray .o_notification_systray_item .o_mail_preview{padding: 0px;}
.o_menu_systray .o_notification_systray_item .o_notification_systray_dropdown.dropdown-menu{margin-top: 0px;}
.o_menu_systray .o_notification_systray_item .o_notification_systray_dropdown.dropdown-menu{box-shadow: none;-webkit-box-orient: vertical;-webkit-box-direction: normal;flex-direction: column;height: calc(100vh - 46px);max-height: calc(100vh - 46px);position: fixed;width: 100vw;z-index: 500;top: 52px;transform: none;}
}
.o_notification_systray_item .dropdown-item-text.text-center.o_no_activity{padding: 0.45rem 1.5rem;}
.o_menu_systray .o_notification_systray_item .tile_header{display: flex;background: darken($o-brand-primary, 10%);justify-content: space-between;}
// 24-2-23 //
.o_menu_systray .o_notification_systray_item .js_bell_notification .o_notification_counter{position: relative;transform: translate(-5px, -5px);margin-right: -10px;background: #222;border: 1px solid #222;}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,51 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates>
<t t-name="mail.systray.UserNotificationMenu">
<div class="o_notification_systray_item">
<a class="openDropdown js_bell_notification" data-toggle="dropdown" aria-expanded="false" title="Notificatons" href="#" t-on-click="_onActivityMenuShow">
<i class="fa fa-bell" role="img" aria-label="Activities"/> <span class="o_notification_counter badge badge-pill"/>
</a>
<div class="o_notification_systray_dropdown dropdown-menu dropdown-menu-right" role="menu">
<div class="o_notification_systray_dropdown_items d-none">
<div class="tile_header">
<div class="rd_all_btn_left">
<a class="sh_view_read_all_btn" t-on-click="_onClickReadAllNotification">
<span class="sh_view_read_all_notification">Read All</span>
</a>
</div>
<div class="view_all_btn_right">
<a class="sh_view_all_btn" t-on-click="_onClickAllNotification">
<span class="sh_view_all_notification">View All</span>
</a>
</div>
</div>
<t t-esc="console.log('>>>>>>>>>>', notifications)"></t>
<t t-if="notifications.length === 0">
<t t-esc="notifications"/>
<div class="dropdown-item-text text-center o_no_activity">
<span>You have No Notification !</span>
</div>
</t>
<!-- <t t-foreach="notifications" t-as="notification"> -->
<t t-foreach='notifications' t-as="notification" t-key="notification_index">
<div class="o_mail_preview" t-on-click.stop.prevent="() => this._onPushNotificationClick(notification)" t-att-data-id="notification.id" t-att-data-res_model="notification.res_model" t-att-data-model_name="notification.res_model" t-att-data-res_id="notification.res_id" >
<div t-attf-class="o_preview_info #{notification.msg_read ? 'sh_read' : 'sh_unread'}">
<div class="o_preview_title">
<span class="o_preview_name">
<div class="d-flex">
<b><t t-esc="notification.name"/></b>
<h6><t t-esc="notification.datetime"/></h6>
</div>
<p class="para_text"><t t-esc="notification.desc"/></p>
</span>
</div>
</div>
</div>
</t>
</div>
</div>
</div>
</t>
</templates>

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="sh_push_noti_config_form" model="ir.ui.view">
<field name="name">sh.push.noti.config.form</field>
<field name="model">res.config.settings</field>
<field name="inherit_id" ref="base_setup.res_config_settings_view_form" />
<field name="arch" type="xml">
<xpath expr="//div[@id='contacts_settings']" position="after">
<div id="web_push_notification">
<h2>Notifications</h2>
<div class="row mt16 o_settings_container">
<div id="firebase_setting" class="col-xs-12 col-md-12 o_setting_box">
<div class="o_setting_left_pane">
<field name="enable_web_push_notification" />
</div>
<div class="o_setting_right_pane">
<label for="enable_web_push_notification"/>
</div>
</div>
<!-- <div id="firebase_other_setting" class="col-xs-12 col-md-12 o_setting_box" attrs="{'invisible':[('enable_web_push_notification','=',False)]}"> -->
<div id="firebase_other_setting" class="col-xs-12 col-md-12 o_setting_box" invisible="not enable_web_push_notification">
<div class="o_setting_left_pane">
</div>
<div class="o_setting_right_pane">
<label for="api_key" class="col-2 col-lg-2 o_light_label" />
<field name="api_key" required="enable_web_push_notification"/>
</div>
<div class="o_setting_left_pane">
</div>
<div class="o_setting_right_pane">
<label for="vapid" class="col-2 col-lg-2 o_light_label"/>
<field name="vapid" required="enable_web_push_notification"/>
</div>
<div class="o_setting_left_pane">
</div>
<div class="o_setting_right_pane">
<label for="config_details" class="col-2 col-lg-2 o_light_label"/>
<field name="config_details" required="enable_web_push_notification"/>
</div>
</div>
<div id="firebase_setting" class="col-xs-12 col-md-12 o_setting_box">
<div class="o_setting_left_pane">
<field name="enable_bell_notification" />
</div>
<div class="o_setting_right_pane">
<label for="enable_bell_notification"/>
</div>
</div>
</div>
</div>
</xpath>
</field>
</record>
</odoo>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="backend_base_tree_view" model="ir.ui.view">
<field name="name">sh.user.push.notification.tree</field>
<field name="model">sh.user.push.notification</field>
<field name="arch" type="xml">
<list string="Notifications" create="0" edit="0">
<field name="user_id"/>
<field name="name"/>
<field name="description"/>
<field name="datetime"/>
<button name="open_record" type="object" class="btn btn-primary" string="View"/>
</list>
</field>
</record>
<record id="backend_base_action" model="ir.actions.act_window">
<field name="name">Notifications</field>
<field name="res_model">sh.user.push.notification</field>
<field name="type">ir.actions.act_window</field>
<field name='view_mode'>tree,form</field>
</record>
</odoo>

View File

@ -0,0 +1,4 @@
# -*- coding: utf-8 -*-
from . import models

View File

@ -0,0 +1,19 @@
# -*- coding: utf-8 -*-
{
'name': 'BOM Costing',
'category': 'Manufacturing',
'summary': 'Apps for process costing on bom',
'description': """ BOM Cost """,
'author': 'Raman Marikanti',
'category': 'Manufacturing',
'depends': ['sale_management', 'mrp','stock'],
'data': [
"views/bom_view.xml",
"report/mrp_costing_report.xml",
"report/mrp_bom_report_view.xml"
],
'installable': True,
'auto_install': False,
'license': 'LGPL-3',
}

View File

@ -0,0 +1,2 @@
from . import mrp
from . import sale_order_line

View File

@ -0,0 +1,106 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from ast import literal_eval
from collections import defaultdict
from odoo import fields, models, _, api
from odoo.tools import float_round
from odoo.exceptions import ValidationError
class MrpProduction(models.Model):
_inherit = 'mrp.production'
def _get_moves_raw_values(self):
moves = []
for production in self:
if not production.bom_id:
continue
factor = production.product_uom_id._compute_quantity(production.product_qty, production.bom_id.product_uom_id) / production.bom_id.product_qty
_boms, lines = production.bom_id.explode(production.product_id, factor, picking_type=production.bom_id.picking_type_id, never_attribute_values=production.never_product_template_attribute_value_ids)
for bom_line, line_data in lines:
# if bom_line.child_bom_id and bom_line.child_bom_id.type == 'phantom' or\
# bom_line.product_id.type != 'consu':
if bom_line.child_bom_id and bom_line.child_bom_id.type == 'phantom':
continue
operation = bom_line.operation_id.id or line_data['parent_line'] and line_data['parent_line'].operation_id.id
moves.append(production._get_move_raw_values(
bom_line.product_id,
line_data['qty'],
bom_line.product_uom_id,
operation,
bom_line
))
return moves
class MrpBomLine(models.Model):
_inherit = 'mrp.bom.line'
unit_cost = fields.Float(compute='_compute_product_price', digits=(16, 2), string="Unit Cost")
total_price = fields.Float(compute='_compute_total_price', string="Total Cost")
is_service_product = fields.Float(compute='_compute_is_service_product', default=False)
@api.depends('product_id')
def _compute_product_price(self):
for rec in self:
if rec.product_id:
# Get product cost in the company context
standard_price = rec.product_id.with_company(rec.env.company).standard_price
# Convert cost from product's UoM to BoM line UoM
unit_cost = rec.product_id.uom_id._compute_price(
standard_price, rec.product_uom_id
)
rec.unit_cost = unit_cost
else:
rec.unit_cost = 0.0
@api.depends('unit_cost', 'product_qty')
def _compute_total_price(self):
for rec in self:
if rec.product_id:
# Get product cost in the company context
standard_price = rec.product_id.with_company(rec.env.company).standard_price
# Convert cost from product's UoM to BoM line UoM
unit_cost = rec.product_id.uom_id._compute_price(
standard_price, rec.product_uom_id
)
else:
unit_cost = 0.0
rec.total_price = unit_cost * rec.product_qty
@api.depends('product_id')
def _compute_is_service_product(self):
for rec in self:
rec.is_service_product = True if rec.product_id.type == 'service' else False
@api.constrains('product_id', 'bom_id')
@api.onchange('product_id', 'bom_id')
def _check_unique_product_in_bom(self):
for line in self:
# Find all lines in the same BoM with the same product
duplicate_lines = line.bom_id.bom_line_ids.filtered(
lambda l: l.product_id == line.product_id
)
if len(duplicate_lines) > 1:
raise ValidationError(
f"The product '{line.product_id.display_name}' is already used in this BoM."
)
class StockMove(models.Model):
_inherit = 'stock.move'
is_service_product = fields.Float(compute='_compute_is_service_product', default=False)
@api.depends('product_id')
def _compute_is_service_product(self):
for rec in self:
rec.is_service_product = True if rec.product_id.type == 'service' else False

View File

@ -0,0 +1,16 @@
from odoo import fields, models, _, api
from odoo.tools import float_round
from odoo.exceptions import ValidationError
class SaleOrderLine(models.Model):
_inherit = 'sale.order.line'
unit_prod_cost = fields.Float('Unit Prodcut Cost',digits="Product Unit of Measure")
@api.depends('product_id')
def _compute_unit_prod_cost(self):
for line in self:
line.unit_prod_cost = line.product_id.standard_price

View File

@ -0,0 +1,125 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<template id="mrp_bom_cost_report_custom">
<t t-call="web.external_layout">
<div class="page">
<t t-foreach="docs" t-as="o">
<!-- Report Title -->
<div class="text-center">
<h2 style="margin-bottom: 0;font-weight: bold;">Bill of Materials</h2>
<small style="color: #888;">Detailed Cost Breakdown</small>
<hr/>
</div>
<!-- BOM Information Table -->
<table class="table table-sm table-bordered" style="margin-top: 15px;">
<tbody>
<tr>
<th style="width: 20%;font-size: 13px;font-weight: bold;">Product:</th>
<td style="width: 30%;font-size: 13px;">
[<span t-field="o.product_tmpl_id.default_code"/>]
<span t-field="o.product_tmpl_id.name"/>
</td>
<th style="width: 20%;font-size: 13px;font-weight: bold;">Reference:</th>
<td style="width: 30%;font-size: 13px">
<span t-field="o.code"/>
</td>
</tr>
<tr>
<th style="font-size: 13px;font-weight: bold;">BOM Type:</th>
<td style="font-size: 13px">
<span t-field="o.type"/>
</td>
<th style="font-size: 13px;font-weight: bold;">Quantity:</th>
<td style="font-size: 13px">
<span t-field="o.product_qty"/>
<span t-field="o.product_uom_id" style="margin-left: 5px;"/>
</td>
</tr>
</tbody>
</table>
<!-- Components Section -->
<div style="margin-top: 25px;">
<h4 style="border-bottom: 1px solid #ccc; padding-bottom: 5px;font-weight: bold;">Component Details</h4>
</div>
<table class="table table-sm table-striped table-bordered" style="font-size: 12px; margin-top: 10px;">
<thead style="background-color: #f5f5f5;">
<tr>
<th style="width: 30%;font-weight: bold;">Product</th>
<th style="width: 15%; text-align: right;font-weight: bold;">Quantity</th>
<th style="width: 15%;font-weight: bold;">UOM</th>
<th style="width: 20%; text-align: right;font-weight: bold;">Unit Price</th>
<th style="width: 20%; text-align: right;font-weight: bold;">Total</th>
</tr>
</thead>
<tbody>
<t t-set="total_cost" t-value="0.0"/>
<t t-foreach="o.bom_line_ids" t-as="bom_line">
<t t-set="line_total" t-value="bom_line.unit_cost * bom_line.product_qty"/>
<t t-set="total_cost" t-value="total_cost + line_total"/>
<tr>
<td>
<span t-field="bom_line.product_id.name"/>
</td>
<td style="text-align: right;">
<t t-if="bom_line.product_id.type == 'consu'">
<span t-field="bom_line.product_qty"/>
</t>
<t t-else="">
<span>-</span>
</t>
</td>
<td>
<t t-if="bom_line.product_id.type == 'consu'">
<span t-field="bom_line.product_uom_id.name"/>
</t>
<t t-else="">
<span>-</span>
</t>
</td>
<td style="text-align: right;">
<span t-field="bom_line.unit_cost"
t-options='{"widget": "monetary", "display_currency": o.env.company.currency_id}'/>
</td>
<td style="text-align: right;">
<span t-esc="line_total"
t-options='{"widget": "monetary", "display_currency": o.env.company.currency_id}'/>
</td>
</tr>
</t>
<!-- Grand Total Row -->
<tr>
<td colspan="4" style="text-align: right;"><strong>Total BOM Cost:</strong></td>
<td style="text-align: right;">
<span t-esc="total_cost"
t-options='{"widget": "monetary", "display_currency": o.env.company.currency_id}'/>
</td>
</tr>
</tbody>
</table>
</t>
</div>
</t>
</template>
<template id="mrp_bom_cost_report">
<t t-call="web.html_container">
<t t-foreach="docs" t-as="o">
<t t-call="costing_mrp_bom.mrp_bom_cost_report_custom" />
</t>
</t>
</template>
</data>
</odoo>

View File

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record id="action_report_bom_cost_report" model="ir.actions.report">
<field name="name">BOM Cost Report</field>
<field name="model">mrp.bom</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">costing_mrp_bom.mrp_bom_cost_report</field>
<field name="report_file">costing_mrp_bom.mrp_bom_cost_report</field>
<field name="binding_model_id" ref="mrp.model_mrp_bom"/>
<field name="print_report_name">'BOM - %s' % (object.product_id.name or object.product_tmpl_id.name or '').replace('/','')
</field>
<field name="binding_type">report</field>
</record>
<!-- <record id="action_report_order_cost" model="ir.actions.report">-->
<!-- <field name="name">Production Order Cost</field>-->
<!-- <field name="model">mrp.production</field>-->
<!-- <field name="report_type">qweb-pdf</field>-->
<!-- <field name="report_name">process_costing_mrp.mrp_production_order_report</field>-->
<!-- <field name="report_file">process_costing_mrp.mrp_production_order_report</field>-->
<!-- <field name="binding_model_id" ref="model_mrp_production"/>-->
<!-- <field name="print_report_name">'Production Order Cost - %s' % (object.name or '').replace('/','')-->
<!-- </field>-->
<!-- <field name="binding_type">report</field>-->
<!-- </record>-->
</data>
</odoo>

View File

@ -0,0 +1,226 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<template id="mrp_production_order_report_custom">
<t t-call="web.external_layout">
<div class="page">
<t t-foreach="docs" t-as="o">
<div class="row">
<h2>Manufacturing Orders - <span t-field="o.name"/></h2><br/>
</div>
<table style="border-collapse: collapse;width: 100%;" class="table table-condensed">
<tr style="padding: 8px;text-align: left;border-top: 1px solid #ddd;height:50%;">
<td><strong >Product : </strong> </td>
<td>[<span t-field="o.product_id.default_code"/>] <span style="margin-left:10px;" t-field="o.product_id.name" /></td>
<td><strong >Deadline Start : </strong> </td>
<td><span t-field="o.date_planned_start" /></td>
</tr>
<tr style="padding: 8px;text-align: left;border-top: 1px solid #ddd;">
<td><strong >Quantity To Produce : </strong> </td>
<td><span t-field="o.product_qty" /></td>
<td><strong >Responsible : </strong> </td>
<td><span t-field="o.user_id.name" /></td>
</tr>
<tr style="padding: 8px;text-align: left;border-top: 1px solid #ddd;">
<td><strong >Source : </strong> </td>
<td><span t-field="o.origin" /></td>
<td><strong >Bill of Material : </strong> </td>
<td><span t-field="o.bom_id.product_tmpl_id.name" /></td>
</tr>
</table>
<h2>Consumed Materials</h2><br/>
<table style="border-collapse: collapse;width: 100%;" class="table table-condensed">
<thead>
<tr>
<th>Product</th>
<th>Unit of Measure</th>
<th>To Consume</th>
<th>Consumed</th>
</tr>
</thead>
<tbody class="consumed_tbody">
<t t-foreach="o.move_raw_ids" t-as="move">
<tr>
<td>
<span t-field="move.product_id.name" />
</td>
<td>
<span t-field="move.product_uom.name" />
</td>
<td>
<span t-field="move.product_uom_qty" />
</td>
<td>
<span t-field="move.quantity_done" />
</td>
</tr>
</t>
</tbody>
</table>
<h2>Finished Products</h2><br/>
<table style="border-collapse: collapse;width: 100%;" class="table table-condensed">
<thead>
<tr>
<th>Product</th>
<th>Unit of Measure</th>
<th>Produced</th>
</tr>
</thead>
<tbody class="Finished_tbody">
<t t-foreach="o.finished_move_line_ids" t-as="finish_move">
<tr>
<td>
<span t-field="finish_move.product_id.name" />
</td>
<td>
<span t-field="finish_move.product_uom_id.name" />
</td>
<td>
<span t-field="finish_move.qty_done" />
</td>
</tr>
</t>
</tbody>
</table>
<h2>Direct Material Cost</h2><br/>
<table style="border-collapse: collapse;width: 100%;" class="table table-condensed">
<thead>
<tr>
<th>Operation</th>
<th>Product</th>
<th>Planned Qty</th>
<th>Actual Qty</th>
<th>UOM</th>
<th>Cost/Unit</th>
<th>Total Cost</th>
<th>Total Actual Cost</th>
</tr>
</thead>
<tbody class="material_tbody">
<t t-set="material_total" t-value="0.0" />
<t t-set="actual_material_total" t-value="0.0" />
<t t-foreach="o.pro_material_cost_ids" t-as="bom_material">
<tr>
<td>
<span t-field="bom_material.operation_id.name" />
</td>
<td>
<span t-field="bom_material.product_id.name" />
</td>
<td>
<span t-field="bom_material.planned_qty" />
</td>
<td>
<span t-field="bom_material.actual_qty" />
</td>
<td>
<span t-field="bom_material.uom_id.name" />
</td>
<td>
<span t-field="bom_material.cost" />
</td>
<td>
<span t-field="bom_material.total_cost" />
</td>
<td>
<span t-field="bom_material.total_actual_cost" />
</td>
<t t-set="material_total" t-value="material_total +int (bom_material.total_cost) " />
<t t-set="actual_material_total" t-value="actual_material_total +int (bom_material.total_actual_cost) " />
</tr>
</t>
<tr>
<td></td>
<td></td>
<td></td>
<td></td>
<td></td>
<td style="text-align: right;font-weight: bold;">Total Cost :</td>
<td style="text-align: center; vertical-align: right;font-weight: bold;">
<span t-esc="material_total" />
</td>
<td style="text-align: center; vertical-align: right;font-weight: bold;">
<span t-esc="actual_material_total" />
</td>
</tr>
</tbody>
</table>
<h2>Direct Labour Cost</h2><br/>
<table style="border-collapse: collapse;width: 100%;" class="table table-condensed">
<thead>
<tr>
<th>Operation</th>
<th>Planned Hour</th>
<th>Actual Hour</th>
<th>Cost/Hour</th>
<th>Total Cost</th>
<th>Total Actual Cost</th>
</tr>
</thead>
<tbody class="labour_tbody">
<t t-set="labour_total" t-value="0.0" />
<t t-set="actual_labour_total" t-value="0.0" />
<t t-foreach="o.pro_labour_cost_ids" t-as="bom_labour">
<tr>
<td>
<span t-field="bom_labour.operation_id.name" />
</td>
<td>
<span t-field="bom_labour.planned_qty" />
</td>
<td>
<span t-field="bom_labour.actual_qty" />
</td>
<td>
<span t-field="bom_labour.cost" />
</td>
<td>
<span t-field="bom_labour.total_cost" />
</td>
<td>
<span t-field="bom_labour.total_actual_cost" />
</td>
<t t-set="labour_total" t-value="labour_total +int (bom_labour.total_cost) " />
<t t-set="actual_labour_total" t-value="actual_labour_total +int (bom_labour.total_actual_cost) " />
</tr>
</t>
</tbody>
</table>
</t>
</div>
</t>
</template>
<template id="mrp_production_order_report">
<t t-call="web.html_container">
<t t-foreach="doc_ids" t-as="o">
<t t-call="process_costing_mrp.mrp_production_order_report_custom" />
</t>
</t>
</template>
</data>
</odoo>

View File

@ -0,0 +1,48 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="mrp_bom_form_view_cost" model="ir.ui.view">
<field name="name">mrp.bom.form.cost.view</field>
<field name="model">mrp.bom</field>
<field name="inherit_id" ref="mrp.mrp_bom_form_view" />
<field name="arch" type="xml">
<xpath expr="//page//field[@name='product_uom_id']" position="after">
<field name="unit_cost"/>
<field name="total_price" sum="Total"/>
</xpath>
<xpath expr="//list" position="attributes">
<attribute name="decoration-info">is_service_product</attribute>
</xpath>
</field>
</record>
<record id="mrp_production_form_view_decoration" model="ir.ui.view">
<field name="name">mrp.production.inherited.form.decoration</field>
<field name="model">mrp.production</field>
<field name="priority">64</field>
<field name="inherit_id" ref="mrp.mrp_production_form_view"/>
<field name="arch" type="xml">
<xpath expr="//page//list" position="attributes">
<attribute name="decoration-info">is_service_product</attribute>
</xpath>
</field>
</record>
<record id="stock_move_line_action_consumption" model="ir.actions.act_window">
<field name="name">Stock Consumption History</field>
<field name="res_model">stock.move.line</field>
<field name="view_mode">list,form</field>
<field name="view_id" ref="stock.view_move_line_tree"/>
<field name="domain">[('state','=','done'),('location_dest_id.usage','=','production')]</field>
<field name="context">{'search_default_groupby_product_id': 1, 'create': 0}</field>
</record>
<menuitem id="menu_mrp_stock_consumption"
action="stock_move_line_action_consumption"
parent="mrp.menu_mrp_root"
name="Consumption"
sequence="13"/>
<menuitem id="menu_mrp_bom_form_1"
action="mrp.mrp_bom_form_action"
parent="mrp.menu_mrp_root"
sequence="11"/>
</odoo>

View File

@ -0,0 +1 @@
from . import models

View File

@ -0,0 +1,25 @@
{
'name': 'Samashti Dashboard (OWL)',
'version': '1.0',
'category': 'View',
'summary': 'Samashti Dashboard (OWL + pqGrid)',
'author': 'Raman Marikanti',
'depends': ['stock', 'web_grid','costing_mrp_bom'],
'data': [
'security/ir.model.access.csv',
'security/security_group.xml',
'views/pqgrid_dashboard.xml',
],
'assets': {
'web.assets_backend': [
('include', 'web_grid._assets_pqgrid'),
# Internal module JS and XML files (ensure correct paths within 'static/src')
'dashboard/static/src/components/pqgrid_dashboard/pqgrid_stock_dashboard.js',
'dashboard/static/src/components/pqgrid_dashboard/pqgrid_stock_dashboard.xml',
],
},
'installable': True,
}

View File

@ -0,0 +1 @@
from . import stock_dashboard

View File

@ -0,0 +1,154 @@
from odoo import models, fields, api, _
from odoo.exceptions import UserError, ValidationError
from collections import defaultdict
from functools import reduce
from datetime import datetime, time
class SamashtiDashboard(models.AbstractModel):
_name = 'samashti.board'
_description = "Samashti Dashboard"
@api.model
def get_stock_moves_data(self, from_date,to_date):
fromDate = "'"+str(from_date)+" 00:00:00'"
toDate = "'"+str(to_date)+" 23:59:59'"
sql = f"""
SELECT
pp.default_code AS product_code,
pt.name AS product_name,
pc.name AS category,
uom.name AS uom,
-- Opening Stock
COALESCE(SUM(CASE
WHEN sm.date < {fromDate} AND sl_dest.usage = 'internal' THEN sm.product_uom_qty
WHEN sm.date < {fromDate} AND sl_src.usage = 'internal' THEN -sm.product_uom_qty
ELSE 0
END), 0) AS opening_stock,
-- Receipts (to internal from supplier/purchase)
COALESCE(SUM(CASE
WHEN sm.date BETWEEN {fromDate} AND {toDate}
AND sl_dest.usage = 'internal'
AND sl_src.usage = 'supplier' THEN sm.product_uom_qty
ELSE 0
END), 0) AS receipts,
-- Production (to internal from Production)
COALESCE(SUM(CASE
WHEN sm.date BETWEEN {fromDate} AND {toDate}
AND sl_dest.usage = 'internal'
AND sl_src.usage = 'production' THEN sm.product_uom_qty
ELSE 0
END), 0) AS production,
-- Consumption (to production only)
COALESCE(SUM(CASE
WHEN sm.date BETWEEN {fromDate} AND {toDate}
AND sl_src.usage = 'internal'
AND sl_dest.usage = 'production' THEN sm.product_uom_qty
ELSE 0
END), 0) AS consumption,
-- Dispatch (to customer only)
COALESCE(SUM(CASE
WHEN sm.date BETWEEN {fromDate} AND {toDate}
AND sl_src.usage = 'internal'
AND sl_dest.usage = 'customer' THEN sm.product_uom_qty
ELSE 0
END), 0) AS dispatch,
-- Closing Stock = Opening + Receipts + Production - Consumption - Dispatch
(
COALESCE(SUM(CASE
WHEN sm.date < {fromDate} AND sl_dest.usage = 'internal' THEN sm.product_uom_qty
WHEN sm.date < {fromDate} AND sl_src.usage = 'internal' THEN -sm.product_uom_qty
WHEN sm.date BETWEEN {fromDate} AND {toDate} AND sl_dest.usage = 'internal' AND sl_src.usage IN ('supplier', 'production') THEN sm.product_uom_qty
WHEN sm.date BETWEEN {fromDate} AND {toDate} AND sl_src.usage = 'internal' AND sl_dest.usage = 'production' THEN -sm.product_uom_qty
WHEN sm.date BETWEEN {fromDate} AND {toDate} AND sl_src.usage = 'internal' AND sl_dest.usage = 'customer' THEN -sm.product_uom_qty
ELSE 0
END), 0)
) AS closing_stock
FROM
stock_move sm
JOIN
product_product pp ON sm.product_id = pp.id
JOIN
product_template pt ON pp.product_tmpl_id = pt.id
JOIN
product_category pc ON pt.categ_id = pc.id
JOIN
uom_uom uom ON pt.uom_id = uom.id
JOIN
stock_location sl_src ON sm.location_id = sl_src.id
JOIN
stock_location sl_dest ON sm.location_dest_id = sl_dest.id
WHERE
sl_src.usage IN ('internal', 'supplier', 'production', 'customer') AND
sl_dest.usage IN ('internal', 'supplier', 'production', 'customer') AND
sm.state = 'done' AND pt.type = 'consu' AND sm.date BETWEEN {fromDate} AND {toDate}
GROUP BY
pp.default_code, pt.name, pc.name, uom.name
ORDER BY
pt.name;
"""
self.env.cr.execute(sql)
data = self.env.cr.dictfetchall()
if data:
for row in data:
row['product_name'] = '['+row['product_code']+'] '+ list(row['product_name'].values())[0] if row['product_name'] else ''
row['uom'] = list(row['uom'].values())[0] if row['uom'] else '-'
return data
else:
return []
@api.model
def get_sale_margin_data(self,from_date,to_date):
fromDate = "'"+str(from_date)+" 00:00:00'"
toDate = "'"+str(to_date)+" 23:59:59'"
where_caluse = f" AND so.date_order BETWEEN {fromDate} AND {toDate}"
sql = """
SELECT
so.name AS sale_order,
COALESCE(pp.default_code, '') AS product_code,
'[' || (COALESCE(pp.default_code, '') || '] ' || jsonb_extract_path_text(pt.name, rp.lang)) AS product_name,
pc.complete_name AS category,
sl.product_uom_qty AS quantity,
COALESCE(sl.unit_prod_cost, 1) AS unit_cost,
COALESCE(sl.price_unit, 1) AS unit_sale_price,
ABS(COALESCE(sl.unit_prod_cost, 1) - COALESCE(sl.price_unit, 1)) AS margin,
sl.product_uom_qty * COALESCE(sl.unit_prod_cost, 1) AS total_cost,
sl.product_uom_qty * COALESCE(sl.price_unit, 1) AS total_sale_price,
ABS((sl.product_uom_qty * COALESCE(sl.unit_prod_cost, 1))
- (sl.product_uom_qty * COALESCE(sl.price_unit, 1))) AS total_margin
FROM sale_order_line sl
JOIN sale_order so
ON so.id = sl.order_id
JOIN product_product pp
ON pp.id = sl.product_id
JOIN product_template pt
ON pt.id = pp.product_tmpl_id
LEFT JOIN product_category pc
ON pc.id = pt.categ_id
JOIN res_company rc
ON rc.id = sl.company_id
JOIN res_partner rp
ON rp.id = rc.partner_id
WHERE sl.state = 'sale'
"""
if where_caluse:
sql += where_caluse
self.env.cr.execute(sql)
data = self.env.cr.dictfetchall()
if data:
return data
else:
return []

View File

@ -0,0 +1,2 @@
id,name,model_id:id,group_id,perm_read,perm_write,perm_create,perm_unlink
user.samashti.board,user.samashti.board,model_samashti_board,,1,1,1,1
1 id name model_id:id group_id perm_read perm_write perm_create perm_unlink
2 user.samashti.board user.samashti.board model_samashti_board 1 1 1 1

View File

@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="0">
<record id="group_proforma_sales" model="res.groups">
<field name="name">Samashti Dashboard </field>
<field name="category_id" ref="base.module_category_hidden"/>
</record>
</data>
</odoo>

View File

@ -0,0 +1,463 @@
/** @odoo-module **/
//import { standardWidgetProps } from "@web/views/widgets/standard_widget_props";
import { Component, onMounted, useRef, useState, onWillStart } from "@odoo/owl";
import { registry } from "@web/core/registry";
import { useService } from "@web/core/utils/hooks";
import { loadJS, loadCSS,loadBundle } from "@web/core/assets";
export class SamashtiDashboard extends Component {
// static props = {
// ...standardWidgetProps,
// };
static template = "SamashtiDashboard";
setup() {
this.orm = useService("orm");
this.gridRef = useRef("gridContainer");
this.gridSaleContainer = useRef("gridSaleContainer");
this.notification = useService("notification");
this.action = useService("action");
// Reactive state
this.state = useState({
activeTab: 'stock',
rows: [],
sale_rows: [],
fromDate: "",
toDate: "",
saleFromDate: "",
saleToDate:""
});
onWillStart(async () => {
await this.loadDependencies();
this.initializeDates();
await this.loadGridData();
await this.loadSaleData();
});
onMounted(() => {
this.initDatePickers();
if (this.gridRef.el) {
this.renderGrid();
} else {
console.error("Grid element not found");
};
if (this.gridSaleContainer.el) {
this.renderSaleGrid();
} else {
console.error("Grid element not found");
}
});
}
setActiveTab(tab) {
this.state.activeTab = tab;
}
// --- Load external JS/CSS dependencies
async loadDependencies() {
try {
// await loadJS("https://code.jquery.com/ui/1.13.2/jquery-ui.min.js");
// await loadCSS("https://code.jquery.com/ui/1.13.2/themes/smoothness/jquery-ui.css");
window.$ = window.jQuery = window.$ || window.jQuery;
if (!window.pq) throw new Error("pqGrid failed to load");
} catch (error) {
console.error("Failed to load dependencies:", error);
this.notification.add("Failed to load required components", { type: "danger" });
throw error;
}
}
// --- Initialize default From/To dates
initializeDates() {
const today = new Date();
const firstDay = new Date(today.getFullYear(), today.getMonth(), 1);
// Function to format a Date object to YYYY-MM-DD in local time
const formatLocalDate = (date) => {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0'); // months are 0-indexed
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
};
this.state.fromDate = formatLocalDate(firstDay);
this.state.saleFromDate = formatLocalDate(firstDay);
this.state.toDate = formatLocalDate(today);
this.state.saleToDate = formatLocalDate(today);
}
// --- Initialize jQuery UI datepickers
initDatePickers() {
const self = this;
$("#fromDate").datepicker({
dateFormat: "yy-mm-dd",
defaultDate: this.state.fromDate,
onSelect(dateText) {
self.state.fromDate = dateText;
},
}).datepicker("setDate", this.state.fromDate);
$("#saleFromDate").datepicker({
dateFormat: "yy-mm-dd",
defaultDate: this.state.saleFromDate,
onSelect(dateText) {
self.state.saleFromDate = dateText;
},
}).datepicker("setDate", this.state.saleFromDate);
$("#toDate").datepicker({
dateFormat: "yy-mm-dd",
defaultDate: this.state.toDate,
onSelect(dateText) {
self.state.toDate = dateText;
},
}).datepicker("setDate", this.state.toDate);
$("#saleToDate").datepicker({
dateFormat: "yy-mm-dd",
defaultDate: this.state.saleToDate,
onSelect(dateText) {
self.state.saleToDate = dateText;
},
}).datepicker("setDate", this.state.saleToDate);
}
// --- Fetch grid data from backend
async loadGridData() {
try {
const records = await this.orm.call("samashti.board", "get_stock_moves_data", [
this.state.fromDate,
this.state.toDate,
]);
this.state.rows = records || [];
this.renderGrid();
} catch (error) {
console.error("Error loading data:", error);
}
}
async loadSaleData(){
debugger;
try {
const data = await this.orm.call("samashti.board", "get_sale_margin_data",[
this.state.saleFromDate,
this.state.saleToDate
]);
this.state.sale_rows = data || []
this.renderSaleGrid();
} catch (error) {
console.error("Error loading data:", error);
}
}
// --- Define grid columns
async getColumns() {
return [
{ title: "Product Code", dataIndx: "product_code", width: 100,filter: { type: 'textbox', condition: 'contain', listeners: ['keyup'] } },
{ title: "Product Name", dataIndx: "product_name", width: 280,filter: { type: 'textbox', condition: 'contain', listeners: ['keyup'] } },
{ title: "Category", dataIndx: "category", width: 150 },
{ title: "Opening Stock", dataIndx: "opening_stock", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
{ title: "Receipts", dataIndx: "receipts", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
{ title: "Production", dataIndx: "production", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
{ title: "Consumption", dataIndx: "consumption", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
{ title: "Dispatch", dataIndx: "dispatch", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
{ title: "Closing Stock", dataIndx: "closing_stock", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
{ title: "Uom", dataIndx: "uom", width: 90, dataType:"text" },
];
}
async getSaleColumns(){
return[
{ title: "Sale Order", dataIndx: "sale_order", width: 100,filter: { type: 'textbox', condition: 'contain', listeners: ['keyup'] } },
{ title: "Product Code", dataIndx: "product_code", width: 100,filter: { type: 'textbox', condition: 'contain', listeners: ['keyup'] } },
{ title: "Product Name", dataIndx: "product_name", width: 280,filter: { type: 'textbox', condition: 'contain', listeners: ['keyup'] } },
{ title: "Category", dataIndx: "category", width: 150 },
{ title: "Quantity", dataIndx: "quantity", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
{ title: "Unit Cost", dataIndx: "unit_cost", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
{ title: "Unit Sale Price", dataIndx: "unit_sale_price", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
{ title: "Unit Margin", dataIndx: "margin", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
{ title: "Total Cost", dataIndx: "total_cost", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
{ title: "Total Sale Price", dataIndx: "total_sale_price", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
{ title: "Total Margin", dataIndx: "total_margin", width: 120, dataType: "float", format: "#,###.00",summary: { type: "sum" },align: "right" },
]
}
async renderGrid() {
const columns = await this.getColumns();
const agg = pq.aggregate; // ensure pq is loaded globally
const gridOptions = {
selectionModel: { type: "row" },
width: "100%",
height: "100%",
editable: false,
stripeRows: true,
filterModel: { on: true, mode: "AND", header: true, autoSearch: true, type: 'local', minLength: 1 },
dataModel: { data: this.state.rows, location: "local", sorting: "local", paging: "local" },
colModel: columns,
toolbar: {
items: [
{
type: 'select',
label: '<span style="color: #555; font-size: 13px;">Format:</span>',
attr: 'id="export_format" style="margin-left: 10px; margin-right: 20px; padding: 5px 10px; border: 1px solid #ddd; border-radius: 4px; background: #fafafa; color: #333; font-size: 13px; min-width: 110px;"',
options: [{ xlsx: '📊 Excel', csv: '📝 CSV', htm: '🌐 HTML', json: '🔤 JSON'}]
},
{ type: "button", label: "Export", icon: "ui-icon-arrowthickstop-1-s",
attr: 'style="padding: 8px 16px; border: 1px solid #3498db; border-radius: 6px; background: linear-gradient(135deg, #3498db, #2980b9); color: white; font-weight: 600; font-size: 13px; cursor: pointer; transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(52, 152, 219, 0.3);"',
listener: () => this.exportGrid() },
{
type: 'button',
icon: 'ui-icon-print',
label: 'Print',
attr: 'style="padding: 8px 16px; border: 1px solid #3498db; border-radius: 6px; background: linear-gradient(135deg, #3498db, #2980b9); color: white; font-weight: 600; font-size: 13px; cursor: pointer; transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(52, 152, 219, 0.3);"',
listener: function() {
var exportHtml = this.exportData({
title: 'jQuery grid',
format: 'htm',
render: true
}),
newWin = window.open('', '', 'width=1200, height=700'),
doc = newWin.document.open();
doc.write(exportHtml);
doc.close();
newWin.print();
}
},
],
},
detailModel: {
cache: false,
}
};
// Initialize PQGrid without groupModel
var grid = $(this.gridRef.el).pqGrid()
if (grid.length){
grid.pqGrid("destroy");
}
$(this.gridRef.el)
.css({ height: '600px', width: '100%' })
.pqGrid(gridOptions);
// Then set groupModel using groupOption
const groupModel = {
on: true,
checkbox: true,
checkboxHead: true,
header:true,
cascade: true,
titleInFirstCol: true,
fixCols: true,
showSummary: [true, true],
grandSummary: true,
title: [
"{0} ({1})",
"{0} - {1}"
]
};
$(this.gridRef.el).pqGrid("groupOption", groupModel);
// Refresh grid to apply grouping
$(this.gridRef.el).pqGrid("refreshDataAndView");
}
async renderSaleGrid(){
const columns = await this.getSaleColumns()
const agg = pq.aggregate;
const gridOptions = {
selectionModel: { type: "row" },
width: "100%",
height: "100%",
editable: false,
stripeRows: true,
filterModel: { on: true, mode: "AND", header: true, autoSearch: true, type: 'local', minLength: 1 },
dataModel: { data: this.state.sale_rows, location: "local", sorting: "local", paging: "local" },
colModel: columns,
toolbar: {
items: [
{
type: 'select',
label: '<span style="color: #555; font-size: 13px;">Format:</span>',
attr: 'id="export_format" style="margin-left: 10px; margin-right: 20px; padding: 5px 10px; border: 1px solid #ddd; border-radius: 4px; background: #fafafa; color: #333; font-size: 13px; min-width: 110px;"',
options: [{ xlsx: '📊 Excel', csv: '📝 CSV', htm: '🌐 HTML', json: '🔤 JSON'}]
},
{ type: "button", label: "Export", icon: "ui-icon-arrowthickstop-1-s",
attr: 'style="padding: 8px 16px; border: 1px solid #3498db; border-radius: 6px; background: linear-gradient(135deg, #3498db, #2980b9); color: white; font-weight: 600; font-size: 13px; cursor: pointer; transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(52, 152, 219, 0.3);"',
listener: () => this.exportSaleGrid() },
{
type: 'button',
icon: 'ui-icon-print',
label: 'Print',
attr: 'style="padding: 8px 16px; border: 1px solid #3498db; border-radius: 6px; background: linear-gradient(135deg, #3498db, #2980b9); color: white; font-weight: 600; font-size: 13px; cursor: pointer; transition: all 0.2s ease; box-shadow: 0 2px 4px rgba(52, 152, 219, 0.3);"',
listener: function() {
var exportHtml = this.exportData({
title: 'jQuery grid',
format: 'htm',
render: true
}),
newWin = window.open('', '', 'width=1200, height=700'),
doc = newWin.document.open();
doc.write(exportHtml);
doc.close();
newWin.print();
}
},
],
},
detailModel: {
cache: false,
}
};
$(this.gridSaleContainer.el)
.css({ height: '600px', width: '100%' })
.pqGrid(gridOptions);
// Then set groupModel using groupOption
const groupModel = {
on: true,
checkbox: true,
checkboxHead: true,
header:true,
cascade: true,
titleInFirstCol: true,
fixCols: true,
showSummary: [true, true],
grandSummary: true,
title: [
"{0} ({1})",
"{0} - {1}"
]
};
$(this.gridSaleContainer.el).pqGrid("groupOption", groupModel);
// Refresh grid to apply grouping
$(this.gridSaleContainer.el).pqGrid("refreshDataAndView");
}
exportGrid() {
const format_ex = $("#export_format").val();
const grid = $(this.gridRef.el);
console.log("Starting export with format:", format_ex);
// Different handling for different formats
switch(format_ex) {
case 'xlsx':
const blobXlsx = grid.pqGrid("exportData", {
format: 'xlsx',
render: true
});
saveAs(blobXlsx, "StockData.xlsx");
break;
case 'csv':
const blobCsv = grid.pqGrid("exportData", {
format: 'csv',
render: true
});
// CSV often returns as string
if (typeof blobCsv === 'string') {
saveAs(new Blob([blobCsv], { type: 'text/csv' }), "StockData.csv");
} else {
saveAs(blobCsv, "StockData.csv");
}
break;
case 'htm':
case 'html':
const blobHtml = grid.pqGrid("exportData", {
format: 'htm',
render: true
});
if (typeof blobHtml === 'string') {
saveAs(new Blob([blobHtml], { type: 'text/html' }), "StockData.html");
} else {
saveAs(blobHtml, "StockData.html");
}
break;
case 'json':
const blobJson = grid.pqGrid("exportData", {
format: 'json',
render: true
});
if (typeof blobJson === 'string') {
saveAs(new Blob([blobJson], { type: 'application/json' }), "StockData.json");
} else {
saveAs(blobJson, "StockData.json");
}
break;
default:
alert('Unsupported format: ' + format_ex);
}
}
exportSaleGrid() {
const format_ex = $("#export_format").val();
const grid = $(this.gridSaleContainer.el);
console.log("Starting export with format:", format_ex);
// Different handling for different formats
switch(format_ex) {
case 'xlsx':
const blobXlsx = grid.pqGrid("exportData", {
format: 'xlsx',
render: true
});
saveAs(blobXlsx, "SaleMarginData.xlsx");
break;
case 'csv':
const blobCsv = grid.pqGrid("exportData", {
format: 'csv',
render: true
});
// CSV often returns as string
if (typeof blobCsv === 'string') {
saveAs(new Blob([blobCsv], { type: 'text/csv' }), "StockData.csv");
} else {
saveAs(blobCsv, "SaleMarginData.csv");
}
break;
case 'htm':
case 'html':
const blobHtml = grid.pqGrid("exportData", {
format: 'htm',
render: true
});
if (typeof blobHtml === 'string') {
saveAs(new Blob([blobHtml], { type: 'text/html' }), "StockData.html");
} else {
saveAs(blobHtml, "SaleMarginData.html");
}
break;
case 'json':
const blobJson = grid.pqGrid("exportData", {
format: 'json',
render: true
});
if (typeof blobJson === 'string') {
saveAs(new Blob([blobJson], { type: 'application/json' }), "StockData.json");
} else {
saveAs(blobJson, "SaleMargin.json");
}
break;
default:
alert('Unsupported format: ' + format_ex);
}
}
}
registry.category("actions").add("SamashtiDashboard", SamashtiDashboard);

View File

@ -0,0 +1,134 @@
<?xml version="1.0" encoding="utf-8"?>
<templates xml:space="preserve">
<t t-name="SamashtiDashboard" owl="1">
<div class="p-4" style="height: 100%; overflow-y: auto;">
<!-- 🔹 Dashboard Selection Tabs -->
<div class="card shadow-sm mb-4">
<div class="card-body text-center">
<div class="btn-group" role="group">
<button type="button"
class="btn"
t-att-class="state.activeTab === 'stock' ? 'btn-primary' : 'btn-outline-primary'"
t-on-click="() => this.setActiveTab('stock')">
Stock Dashboard
</button>
<button type="button"
class="btn"
t-att-class="state.activeTab === 'sale' ? 'btn-success' : 'btn-outline-success'"
t-on-click="() => this.setActiveTab('sale')">
Sale Margin Dashboard
</button>
</div>
</div>
</div>
<!-- 🔹 Cards Side by Side -->
<div class="row mb-4">
<!-- Stock Dashboard Card -->
<div class="col-md-6">
<div class="card shadow-sm">
<div class="card-body">
<h4 class="text-center text-primary fw-bold mb-3">
Samashti Stock Dashboard
</h4>
<p class="text-center text-muted mb-3">
<span t-esc="state.fromDate || 'Start Date'"/> to <span t-esc="state.toDate || 'End Date'"/>
</p>
<div class="row g-3 align-items-end">
<!-- From Date -->
<div class="col-lg-5 col-md-6 col-12">
<label class="form-label fw-semibold">From Date</label>
<input type="text" id="fromDate" t-model="state.fromDate" class="form-control"/>
</div>
<!-- To Date -->
<div class="col-lg-5 col-md-6 col-12">
<label class="form-label fw-semibold">To Date</label>
<input type="text" id="toDate" t-model="state.toDate" class="form-control"/>
</div>
<!-- Load Button -->
<div class="col-lg-2 col-md-12 col-12">
<button type="button" class="btn btn-primary w-100" t-on-click="loadGridData">
<i class="fa fa-sync me-1"></i> Load
</button>
</div>
</div>
</div>
</div>
</div>
<!-- Sale Dashboard Card -->
<div class="col-md-6">
<div class="card shadow-sm h-100">
<div class="card-body">
<h4 class="text-center text-success fw-bold mb-3">
Samashti Sale Margin Dashboard
</h4>
<p class="text-center text-muted mb-3">
<span t-esc="state.saleFromDate || 'Start Date'"/> to <span t-esc="state.saleToDate || 'End Date'"/>
</p>
<div class="row g-3 align-items-end">
<!-- From Date -->
<div class="col-lg-5 col-md-6 col-12">
<label class="form-label fw-semibold">From Date</label>
<input type="text" id="saleFromDate" t-model="state.saleFromDate" class="form-control"/>
</div>
<!-- To Date -->
<div class="col-lg-5 col-md-6 col-12">
<label class="form-label fw-semibold">To Date</label>
<input type="text" id="saleToDate" t-model="state.saleToDate" class="form-control "/>
</div>
<!-- Load Button -->
<div class="col-lg-2 col-md-12 col-12">
<button type="button" class="btn btn-success w-100" t-on-click="loadSaleData">
<i class="fa fa-sync me-1"></i> Load
</button>
</div>
</div>
</div>
</div>
</div>
</div>
<!-- 🔹 Grid Sections (Conditional Display) -->
<!-- Stock Grid -->
<t t-if="state.activeTab === 'stock'">
<div class="card shadow-sm">
<div class="card-header bg-primary text-white">
<h5 class="mb-0">
<i class="fa fa-cubes me-2"></i>Stock Data Grid
<small class="float-end" t-esc="'Showing data from ' + (state.fromDate || 'start') + ' to ' + (state.toDate || 'end')"/>
</h5>
</div>
<div class="card-body" style="padding: 0;">
<div t-ref="gridContainer" style="width: 100%; height: 600px;"></div>
</div>
</div>
</t>
<!-- Sale Grid -->
<t t-if="state.activeTab === 'sale'">
<div class="card shadow-sm">
<div class="card-header bg-success text-white">
<h5 class="mb-0">
<i class="fa fa-chart-line me-2"></i>Sale Margin Data Grid
<small class="float-end" t-esc="'Showing data from ' + (state.saleFromDate || 'start') + ' to ' + (state.saleToDate || 'end')"/>
</h5>
</div>
<div class="card-body" style="padding: 0;">
<div t-ref="gridSaleContainer" style="width: 100%; height: 600px;"></div>
</div>
</div>
</t>
</div>
</t>
</templates>

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8" ?>
<odoo>
<!-- Client action record for Dashboard -->
<record id="samashti_action_dashboards" model="ir.actions.client">
<field name="name">Dashboard</field>
<field name="tag">SamashtiDashboard</field>
<field name="context">{'user_id':uid}</field>
</record>
<!-- Menu record for dashboard -->
<menuitem id="samashti_dashboard_root"
name="Overview"
action="samashti_action_dashboards"
sequence="-100" groups="base.group_user"/>
</odoo>

View File

@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import models

View File

@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-
{
'name': 'GRN',
'version': '1.0',
'summary': 'Goods Recepts Note',
'description': '''
Stock Goods Recepts Note Stock Update
''',
'category': 'Inventory',
'author': 'Raman Marikanti',
'depends': ['base', 'mail','stock_account','product'],
'data': [
'data/ir_sequence.xml',
'security/ir.model.access.csv',
'views/grn_views.xml',
'report/grn_report_action.xml',
'report/report_grn_template.xml'
],
'license': 'LGPL-3',
'installable': True,
'application': False,
'auto_install': False,
}

View File

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data noupdate="1">
<record id="seq_grn" model="ir.sequence">
<field name="name">GRN</field>
<field name="code">grn</field>
<field name="prefix">GRN/%(year)s/</field>
<field name="padding">5</field>
<field name="company_id" eval="False" />
</record>
</data>
</odoo>

View File

@ -0,0 +1,3 @@
# -*- coding: utf-8 -*-
from . import grn

View File

@ -0,0 +1,219 @@
# -*- coding: utf-8 -*-
from email.policy import default
from odoo import _, api, fields, models
from odoo.exceptions import ValidationError, UserError
class Grn(models.Model):
_name = 'grn'
_description = 'Goods Receipt Note'
_inherit = ['mail.thread', 'mail.activity.mixin', 'product.catalog.mixin']
name = fields.Char(
string='Name',
copy=False,
readonly=True,
default=lambda self: _('New')
)
vendor_id = fields.Many2one('res.partner', string='Vendor', readonly=True, )
note = fields.Text(string='Source Document / Note')
date = fields.Date(string='Date', default=fields.Date.context_today, copy=False)
picking_id = fields.Many2one("stock.picking", string="Stock Transfer", copy=False)
state = fields.Selection(
[('draft', 'Draft'), ('confirmed', 'Confirmed'), ('done', 'Done'), ('cancel', 'Cancelled')],
string='State',
default='draft',
tracking=True
)
grn_line_ids = fields.One2many('grn.lines', 'grn_id', string="GRN Lines")
received_by = fields.Many2one('res.users', string='Received By')
location_id = fields.Many2one(
'stock.location',
string='To',
domain="[('usage', '=', 'internal')]",
required=True
)
total_amount = fields.Float(string='Amount', compute='_compute_total_amount')
company_id = fields.Many2one(
'res.company',
string='Company',
required=True,
readonly=True,
default=lambda self: self.env.company,
)
def _get_product_catalog_order_data(self, products, **kwargs):
res = super()._get_product_catalog_order_data(products, **kwargs)
return res
@api.depends('grn_line_ids')
def _compute_total_amount(self):
"""Compute the value of the field computed_field."""
for record in self:
amount = 0
for line in record.grn_line_ids:
amount += (line.quantity * line.price)
record.total_amount = amount
def button_action_confirm(self):
"""Confirm the GRN and assign sequence and received user"""
if not self.grn_line_ids:
raise UserError(_(
"Cannot confirm the GRN '%s' because no products have been added in the lines. "
"Please add at least one product before confirming."
) % self.name)
if not self.name or self.name == _('New'):
self.name = self.env['ir.sequence'].next_by_code('grn') or _('New')
self.state = 'confirmed'
self.received_by = self.env.user
for line in self.grn_line_ids:
if line.price:
continue
else:
line.price = line.product_id.standard_price
def button_action_done(self):
"""Set GRN state to done if picking is completed"""
if not self.picking_id or self.picking_id.state != 'done':
raise ValidationError(_(
"Cannot mark the GRN '%s' as done because the associated stock transfer is not yet completed. "
"Please complete the transfer before proceeding."
) % (self.name,))
if self.state == 'confirmed':
self.state = 'done'
def button_action_cancel(self):
"""Cancel GRN if stock transfer is not done"""
if self.picking_id and self.picking_id.state == 'done':
raise ValidationError(_(
"Cannot cancel the GRN '%s' because the stock transfer '%s' has already been completed. "
) % (self.name, self.picking_id.name))
if self.picking_id:
self.picking_id.action_cancel()
self.picking_id.unlink()
self.state = 'cancel'
def button_action_reset_to_draft(self):
self.state = 'draft'
def button_create_transfer(self):
"""Create stock picking for confirmed GRN"""
if self.picking_id:
return
if self.state != 'confirmed':
raise UserError(_(
"The GRN '%s' cannot be transferred because it is not confirmed yet. "
"Please confirm the GRN first."
) % self.name)
picking_type = self.env['stock.picking.type'].search([('code', '=', 'incoming')], limit=1)
if not picking_type:
raise UserError(_(
"No Incoming Picking Type is configured in the system. "
"Please create an Incoming Picking Type before transferring GRN '%s'."
) % self.name)
picking = self.env['stock.picking'].create({
'origin': self.name,
'location_dest_id': self.location_id.id,
'location_id': picking_type.default_location_src_id.id,
'picking_type_id': picking_type.id,
'partner_id':self.vendor_id.id
})
moves = []
for line in self.grn_line_ids:
moves.append((0, 0, {
'name': line.product_id.name,
'product_id': line.product_id.id,
'product_uom': line.product_uom_id.id,
'product_uom_qty': line.quantity,
'location_id': picking_type.default_location_src_id.id,
'location_dest_id': self.location_id.id,
'price_unit': line.price if line.price > 1 else line.product_id.standard_price,
}))
picking.write({'move_ids_without_package': moves})
picking.action_confirm()
for move in picking:
move.location_dest_id = self.location_id
picking.location_dest_id = self.location_id
self.picking_id = picking
def action_view_transfer(self):
"""Return action to view related stock picking"""
self.ensure_one()
return {
'type': 'ir.actions.act_window',
'name': _('Receipts'),
'res_model': 'stock.picking',
'view_mode': 'form',
'target': 'current',
'res_id': self.picking_id.id,
}
@api.model_create_multi
def create(self, vals_list):
return super().create(vals_list)
def write(self, vals):
return super().write(vals)
def unlink(self):
if any(rec.state not in ['cancel', 'draft'] for rec in self):
raise UserError(_(
"Unable to delete the GRN '%s' because it has already been confirmed or processed. "
) % self.name)
return super().unlink()
def action_add_from_catalog(self):
res = super().action_add_from_catalog()
return res
class GrnLines(models.Model):
_name = 'grn.lines'
_description = 'GRN Lines'
grn_id = fields.Many2one('grn', string="GRN", required=True, ondelete='cascade')
product_id = fields.Many2one(
'product.product',
string='Product',
ondelete="cascade",
domain=[('type', '!=', 'service'),('purchase_ok','=',True)],
index=True
)
product_uom_id = fields.Many2one(related='product_id.uom_id', string='Unit of Measure')
quantity = fields.Float('Quantity', digits='Product Unit of Measure')
price = fields.Float("Unit Price")
total_price = fields.Float("Total Price", compute='_compute_product_total_price', store=True)
@api.depends('quantity', 'price')
def _compute_product_total_price(self):
for rec in self:
rec.total_price = rec.quantity * rec.price if rec.quantity and rec.price else 0
@api.constrains('product_id')
def _check_unique_product_grn(self):
for rec in self:
duplicate_lines = rec.grn_id.grn_line_ids.filtered(lambda l: l.product_id == rec.product_id)
if len(duplicate_lines) > 1:
raise UserError(_('The product %s already exists in the GRN.') % rec.product_id.display_name)
def action_add_from_catalog(self):
order = self.env['grn'].browse(self.env.context.get('order_id'))
return order.with_context(child_field='grn_line_ids').action_add_from_catalog()
def unlink(self):
if any(rec.grn_id.state not in ['cancel', 'draft'] for rec in self):
raise UserError(_(
"Unable to delete the GRN '%s' because it has already been confirmed or processed. "
) % self.name)
return super().unlink()

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<record id="action_report_grn" model="ir.actions.report">
<field name="name">Goods Receipt Note</field>
<field name="model">grn</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">grn.report_grn_document_template</field>
<field name="report_file">grn.report_grn_document_template</field>
<field name="print_report_name">'GRN - %s' % (object.name.replace("/",""))</field>
</record>
</odoo>

View File

@ -0,0 +1,112 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<template id="report_grn_document_template">
<t t-set="company" t-value="docs.env.company"/>
<t t-call="web.external_layout">
<t t-set="doc_font" t-value="'font-family: Helvetica, Arial, sans-serif; font-size: 12px; color: #333;'" />
<t t-foreach="docs" t-as="doc">
<main class="page" t-att-style="doc_font">
<!-- ======= HEADER ======= -->
<div style="text-align: center; border-bottom: 2px solid #444; padding-bottom: 5px; margin-bottom: 15px;">
<h2 style="margin: 0; font-weight: bold; color: #000;">GOODS RECEIVED NOTE</h2>
<p style="margin: 0; font-size: 11px;">(Official Record of Goods Received)</p>
</div>
<!-- ======= INFO BLOCKS ======= -->
<table style="width: 100%; margin-bottom: 10px;">
<tr>
<td style="width: 50%; vertical-align: top;">
<div style="border: 1px solid #ccc; border-radius: 6px; padding: 8px;height:120px;">
<strong>GRN DETAILS</strong><br/>
<span><strong>GRN Number:</strong> <t t-esc="doc.name" /></span><br/>
<span><strong>Date:</strong> <t t-esc="doc.date.strftime('%d/%m/%Y') if doc.date else ''" /></span>
</div>
</td>
<td style="width: 50%; vertical-align: top;">
<div style="border: 1px solid #ccc; border-radius: 6px; padding: 8px;height:120px">
<strong>SUPPLIER DETAILS</strong><br/>
<span><strong>Name:</strong> <t t-esc="doc.vendor_id.name or ''" /></span><br/>
<span><strong>Address:</strong><br/>
<!-- <t t-esc="doc.vendor_id. or ''" />-->
<span t-esc="doc.vendor_id.street"/><br/>
<span t-esc="doc.vendor_id.street2"/><br/>
<span t-esc="doc.vendor_id.zip"/>
<span t-esc="doc.vendor_id.city"/>
</span><br/>
</div>
</td>
</tr>
</table>
<!-- ======= RECEIVER INFO ======= -->
<div style="border: 1px solid #ccc; border-radius: 6px; padding: 8px; margin-bottom: 15px;">
<strong>RECEIVER DETAILS</strong><br/>
<span><strong>Received By:</strong> <t t-esc="doc.received_by.name or ''" /></span><br/>
</div>
<!-- ======= RECEIVED ITEMS TABLE ======= -->
<t t-if="doc.grn_line_ids">
<h4 style="margin-top: 20px; font-weight: bold; border-bottom: 1px solid #ccc;">Received Items</h4>
<table class="table table-bordered table-sm" style="width: 100%; border-collapse: collapse; margin-top: 10px;">
<thead style="background-color: #f5f5f5;">
<tr>
<th style="padding: 6px; border: 1px solid #ccc;font-weight: bold;">Item</th>
<th style="padding: 6px; border: 1px solid #ccc; text-align: right;font-weight: bold;">Quantity</th>
<th style="padding: 6px; border: 1px solid #ccc;font-weight: bold;">UoM</th>
<th style="padding: 6px; border: 1px solid #ccc; text-align: right;font-weight: bold;">Unit Price</th>
<th style="padding: 6px; border: 1px solid #ccc; text-align: right;font-weight: bold;">Total Price</th>
</tr>
</thead>
<tbody>
<t t-foreach="doc.grn_line_ids" t-as="line">
<tr t-att-style="'background-color: #ffffff;'">
<td style="padding: 5px; border: 1px solid #ccc;"><t t-esc="line.product_id.name or ''" /></td>
<td style="padding: 5px; border: 1px solid #ccc; text-align: right;"><t t-esc="'%.2f' % line.quantity" /></td>
<td style="padding: 5px; border: 1px solid #ccc;"><t t-esc="line.product_uom_id.name if line.product_uom_id else ''" /></td>
<td style="padding: 5px; border: 1px solid #ccc; text-align: right;"><t t-esc="'%.2f' % line.price" /></td>
<td style="padding: 5px; border: 1px solid #ccc; text-align: right;"><t t-esc="'%.2f' % (line.quantity * line.price) if line.quantity else 0" /></td>
</tr>
</t>
</tbody>
</table>
<!-- ======= SUMMARY ======= -->
<table style="width: 40%; margin-top: 15px; margin-left: 60%; border: 1px solid #ccc; border-radius: 6px;">
<tr style="background-color: #f9f9f9;">
<td style="padding: 6px; border-bottom: 1px solid #ccc;"><strong>Total Quantity:</strong></td>
<td style="padding: 6px; border-bottom: 1px solid #ccc; text-align: right;">
<t t-esc="'%.2f' % sum(doc.grn_line_ids.mapped('quantity'))" />
</td>
</tr>
<tr>
<td style="padding: 6px;"><strong>Total Amount:</strong></td>
<td style="padding: 6px; text-align: right;">
<t t-esc="'%.2f' % sum([l.quantity * l.price for l in doc.grn_line_ids])" />
</td>
</tr>
</table>
</t>
<!-- ======= COMMENTS ======= -->
<div style="margin-top: 25px;">
<strong>Comments / Remarks:</strong><br/>
<p style="border: 1px solid #ccc; border-radius: 6px; padding: 8px; min-height: 40px;">
<t t-esc="doc.note or '—'" />
</p>
</div>
<!-- ======= SIGNATURE ======= -->
<div style="margin-top: 50px; text-align: right;">
<p style="margin-right: 40px;">
___________________________<br/>
<strong>Receiver Signature</strong>
</p>
</div>
</main>
</t>
</t>
</template>
</odoo>

View File

@ -0,0 +1,3 @@
id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
access_grn_user,access.grn.user,model_grn,base.group_user,1,1,1,1
access_grn_lines_user,access.grn.lines.user,model_grn_lines,base.group_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
2 access_grn_user access.grn.user model_grn base.group_user 1 1 1 1
3 access_grn_lines_user access.grn.lines.user model_grn_lines base.group_user 1 1 1 1

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 MiB

View File

@ -0,0 +1,179 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<!-- Sample form view -->
<record id="grn_view_form" model="ir.ui.view">
<field name="name">grn.view.form</field>
<field name="model">grn</field>
<field name="arch" type="xml">
<form string="GRN">
<header>
<button name="button_action_confirm" string="Confirm" type="object" class="btn-primary" invisible="state != 'draft'"/>
<button name="button_create_transfer" string="Create Transfer" type="object" class="btn-info" invisible="state != 'confirmed' or picking_id != False"/>
<button name="button_action_done" string="Done" type="object" class="btn-primary" invisible="state != 'confirmed'"/>
<button name="button_action_cancel" string="Cancel" type="object" class="btn-secondary" invisible="state not in ['done','confirmed']"/>
<button name="button_action_reset_to_draft" string="Reset To Draft" type="object" class="btn-secondary" invisible="state != 'cancel'"/>
<field name="state" widget="statusbar" statusbar_visible="draft,confirmed,done" readonly="1"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
<button icon="fa-truck" type="object" name="action_view_transfer" invisible="not picking_id">
Receipts
</button>
</div>
<div class="oe_title">
<label for="name"/>
<h1>
<field name="name" placeholder="e.g Marc Demo"/>
</h1>
</div>
<group>
<group>
<field name="vendor_id" readonly="state != 'draft'"/>
<field name="location_id" readonly="state != 'draft'"/>
</group>
<group>
<field name="date" readonly="state != 'draft'"/>
<field name="note" readonly="state != 'draft'"/>
</group>
</group>
<notebook>
<page string="GRN Details">
<field name="grn_line_ids" readonly="state != 'draft'">
<list editable="bottom">
<control>
<create string="Add a line"/>
<button name="action_add_from_catalog" string="Catalog" type="object" class="px-4 btn-link" context="{'order_id': parent.id}"/>
</control>
<field name="product_id" readonly="parent.state != 'draft'"/>
<field name="quantity" readonly="parent.state != 'draft'"/>
<field name="product_uom_id" readonly="1" string="UoM"/>
<field name="price" readonly="parent.state != 'draft'"/>
<field name="total_price" sum="Total" readonly="1" force_save="1"/>
</list>
</field>
</page>
</notebook>
</sheet>
<chatter/>
</form>
</field>
</record>
<!-- Sample list view -->
<record id="grn_view_list" model="ir.ui.view">
<field name="name">grn.view.list</field>
<field name="model">grn</field>
<field name="arch" type="xml">
<list string="GRN">
<field name="name"/>
<field name="date"/>
<field name="vendor_id"/>
<field name="state"/>
<field name="total_amount" readonly="1" string="Amount" sum="Total"/>
</list>
</field>
</record>
<record id="grn_stock_quant_view_list" model="ir.ui.view">
<field name="name">stock.quant.grn.list</field>
<field name="model">stock.quant</field>
<field name="arch" type="xml">
<list string="Product Value">
<field name="product_id" column_invisible="context.get('single_product', False)"/>
<field name="location_id" column_invisible="context.get('hide_location', False)"/>
<field name="lot_id" groups="stock.group_production_lot" column_invisible="context.get('hide_lot', False)"/>
<field name="lot_properties"/>
<field name="quantity" string="On Hand"/>
<field name="product_uom_id" groups="uom.group_uom" string="Unit"/>
<field name="available_quantity" string="Available"/>
<field name="product_uom_id" groups="uom.group_uom" string="Unit"/>
<field name="company_id" groups="base.group_multi_company" optional="hidden"/>
<field name="currency_id" column_invisible="True"/>
<field name="cost_method" column_invisible="True"/>
<field name="value" sum="Total Value"/>
</list>
</field>
</record>
<!-- Kanban View -->
<record id="grn_view_kanban" model="ir.ui.view">
<field name="name">grn.view.kanban</field>
<field name="model">grn</field>
<field name="arch" type="xml">
<kanban>
<field name="state"/>
<templates>
<t t-name="kanban-box">
<div class="oe_kanban_global_click">
<field name="name"/><br/>
<field name="date"/><br/>
<field name="state"/>
</div>
</t>
</templates>
</kanban>
</field>
</record>
<!-- Search View -->
<record id="grn_view_search" model="ir.ui.view">
<field name="name">grn.view.search</field>
<field name="model">grn</field>
<field name="arch" type="xml">
<search>
<field name="name"/>
<filter string="Draft" name="filter_draft" domain="[('state','=','draft')]"/>
<filter string="Confirmed" name="filter_confirmed" domain="[('state','=','confirmed')]"/>
<filter string="Done" name="filter_done" domain="[('state','=','done')]"/>
</search>
</field>
</record>
<!-- Action -->
<record id="grn_action" model="ir.actions.act_window">
<field name="name">GRN</field>
<field name="res_model">grn</field>
<field name="view_mode">list,form,kanban</field>
</record>
<record id="action_picking_list_incoming" model="ir.actions.act_window">
<field name="name">GRN Receipts</field>
<field name="res_model">stock.picking</field>
<field name="path">grnreceipts</field>
<field name="view_mode">list,kanban,form,calendar,activity</field>
<field name="domain">[('picking_type_id.code', '=', 'incoming')]</field>
<field name="context">{}</field>
</record>
<record model="ir.actions.act_window" id="location_open_quants_grn"> <!-- Used in location -->
<field name="context">{'search_default_productgroup': 1}</field>
<field name="domain">[('quantity','&gt;',0),('location_id.usage', '=', 'internal')]</field>
<field name="name">Current Stock</field>
<field name="res_model">stock.quant</field>
<field name="view_id" ref="grn_stock_quant_view_list"/>
</record>
<!-- Menus -->
<menuitem name="GRN"
groups="stock.group_stock_manager,stock.group_stock_user"
web_icon="grn,static/description/icon.png"
id="grn_menu_root"/>
<menuitem name="GRN"
id="grn_menu"
parent="grn_menu_root"
sequence="1"
action="grn_action"/>
<menuitem id="grn_receipts"
name="Receipts"
parent="grn_menu_root"
action="action_picking_list_incoming"
sequence="2"
/>
<menuitem id="grn_raw_value"
name="Valuation"
parent="grn_menu_root"
action="location_open_quants_grn"
sequence="2"
/>
</odoo>

View File

@ -0,0 +1 @@
# from . import models

View File

@ -0,0 +1,13 @@
{
"name" : "Web extended",
"author": "Shankar Ankepaka",
"license" : "LGPL-3",
"data":[
],
'assets': {
'web.assets_backend': [
'/web_extended/static/src/xml/form_status_indicator_inherit.xml'
],
}
}

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<templates xml:space="preserve">
<t t-inherit="web.FormStatusIndicator" t-inherit-mode="extension">
<xpath expr="//button[@t-ref='save']" position="replace">
<button style="font-size:10px; background-color:#dcc4f5; color:black;border-radius:4px"
type="button"
class="o_form_button_save btn btn-light border-0 px-3 py-1 lh-sm"
data-hotkey="s"
t-on-click.stop="save"
data-tooltip="Save manually"
aria-label="Save manually"
t-ref="save">
Save
<i class="fa fa-check" aria-hidden="true"/>
</button>
</xpath>
<xpath expr="//button[@data-hotkey='j']" position="replace">
<button style="font-size:10px; background-color:#c4d9f5; color:black; border-radius:6px"
type="button"
class="o_form_button_cancel btn btn-light border-0 px-3 py-1 lh-sm"
data-hotkey="j"
t-on-click.stop="discard"
data-tooltip="Discard all changes"
aria-label="Discard all changes">
Discard
<i class="fa fa-times fa-fw" />
</button>
</xpath>
</t>
</templates>

View File

@ -0,0 +1,2 @@
# -*- coding: utf-8 -*-

View File

@ -0,0 +1,40 @@
# -*- coding: utf-8 -*-
{
'name': 'Web Grid',
'version': '1.0',
'summary': 'Paramquery Grid',
'description': '''
Paramquery Grid views
''',
'category': 'Other Tools',
'author': 'Raman Marikanti',
'depends': ['web'],
'data': [],
'assets': {
'web_grid._assets_pqgrid': [
('include', 'web._assets_jquery'),
'web_grid/static/lib/jquery-ui/jquery-ui.min.js',
'web_grid/static/lib/jquery-ui/jquery-ui.min.css',
'web_grid/static/lib/jquery-ui/jquery-ui.structure.css',
'web_grid/static/lib/pq_grid/pqgrid.min.js',
'web_grid/static/lib/pq_grid/jszip.min.js',
'web_grid/static/lib/pq_grid/FileSaver.min.js',
# 'web_grid/static/lib/pq_grid/pqgrid.ui.dev.css',
'web_grid/static/lib/pq_grid/pqgrid.min.css',
'web_grid/static/lib/pq_grid/pqgrid.ui.min.css',
'web_grid/static/lib/pq_grid/themes/Office/pqgrid.css',
# 'web_grid/static/lib/pq_grid/themes/**/*',
# 'web_grid/static/lib/pq_grid/pqgrid.dev.css',
# 'web_grid/static/lib/pq_grid/pqgrid.dev.js',
'web_grid/static/lib/pq_grid/pq-localize-en.js',
]
},
'license': 'LGPL-3',
'installable': True,
'application': False,
'auto_install': False,
}

View File

@ -0,0 +1,381 @@
Authors ordered by first contribution
A list of current team members is available at https://jqueryui.com/about
Paul Bakaus <paul.bakaus@gmail.com>
Richard Worth <rdworth@gmail.com>
Yehuda Katz <wycats@gmail.com>
Sean Catchpole <sean@sunsean.com>
John Resig <jeresig@gmail.com>
Tane Piper <piper.tane@gmail.com>
Dmitri Gaskin <dmitrig01@gmail.com>
Klaus Hartl <klaus.hartl@gmail.com>
Stefan Petre <stefan.petre@gmail.com>
Gilles van den Hoven <gilles@webunity.nl>
Micheil Bryan Smith <micheil@brandedcode.com>
Jörn Zaefferer <joern.zaefferer@gmail.com>
Marc Grabanski <m@marcgrabanski.com>
Keith Wood <kbwood@iinet.com.au>
Brandon Aaron <brandon.aaron@gmail.com>
Scott González <scott.gonzalez@gmail.com>
Eduardo Lundgren <eduardolundgren@gmail.com>
Aaron Eisenberger <aaronchi@gmail.com>
Joan Piedra <theneojp@gmail.com>
Bruno Basto <b.basto@gmail.com>
Remy Sharp <remy@leftlogic.com>
Bohdan Ganicky <bohdan.ganicky@gmail.com>
David Bolter <david.bolter@gmail.com>
Chi Cheng <cloudream@gmail.com>
Ca-Phun Ung <pazu2k@gmail.com>
Ariel Flesler <aflesler@gmail.com>
Maggie Wachs <maggie@filamentgroup.com>
Scott Jehl <scottjehl@gmail.com>
Todd Parker <todd@filamentgroup.com>
Andrew Powell <andrew@shellscape.org>
Brant Burnett <btburnett3@gmail.com>
Douglas Neiner <doug@dougneiner.com>
Paul Irish <paul.irish@gmail.com>
Ralph Whitbeck <ralph.whitbeck@gmail.com>
Thibault Duplessis <thibault.duplessis@gmail.com>
Dominique Vincent <dominique.vincent@toitl.com>
Jack Hsu <jack.hsu@gmail.com>
Adam Sontag <ajpiano@ajpiano.com>
Carl Fürstenberg <carl@excito.com>
Kevin Dalman <development@allpro.net>
Alberto Fernández Capel <afcapel@gmail.com>
Jacek Jędrzejewski (https://jacek.jedrzejewski.name)
Ting Kuei <ting@kuei.com>
Samuel Cormier-Iijima <sam@chide.it>
Jon Palmer <jonspalmer@gmail.com>
Ben Hollis <bhollis@amazon.com>
Justin MacCarthy <Justin@Rubystars.biz>
Eyal Kobrigo <kobrigo@hotmail.com>
Tiago Freire <tiago.freire@gmail.com>
Diego Tres <diegotres@gmail.com>
Holger Rüprich <holger@rueprich.de>
Ziling Zhao <zilingzhao@gmail.com>
Mike Alsup <malsup@gmail.com>
Robson Braga Araujo <robsonbraga@gmail.com>
Pierre-Henri Ausseil <ph.ausseil@gmail.com>
Christopher McCulloh <cmcculloh@gmail.com>
Andrew Newcomb <ext.github@preceptsoftware.co.uk>
Lim Chee Aun <cheeaun@gmail.com>
Jorge Barreiro <yortx.barry@gmail.com>
Daniel Steigerwald <daniel@steigerwald.cz>
John Firebaugh <john_firebaugh@bigfix.com>
John Enters <github@darkdark.net>
Andrey Kapitcyn <ru.m157y@gmail.com>
Dmitry Petrov <dpetroff@gmail.com>
Eric Hynds <eric@hynds.net>
Chairat Sunthornwiphat <pipo@sixhead.com>
Josh Varner <josh.varner@gmail.com>
Stéphane Raimbault <stephane.raimbault@gmail.com>
Jay Merrifield <fracmak@gmail.com>
J. Ryan Stinnett <jryans@gmail.com>
Peter Heiberg <peter@heiberg.se>
Alex Dovenmuehle <adovenmuehle@gmail.com>
Jamie Gegerson <git@jamiegegerson.com>
Raymond Schwartz <skeetergraphics@gmail.com>
Phillip Barnes <philbar@gmail.com>
Kyle Wilkinson <kai@wikyd.org>
Khaled AlHourani <me@khaledalhourani.com>
Marian Rudzynski <mr@impaled.org>
Jean-Francois Remy <jeff@melix.org>
Doug Blood <dougblood@gmail.com>
Filippo Cavallarin <filippo.cavallarin@codseq.it>
Heiko Henning <heiko@thehennings.ch>
Aliaksandr Rahalevich <saksmlz@gmail.com>
Mario Visic <mario@mariovisic.com>
Xavi Ramirez <xavi.rmz@gmail.com>
Max Schnur <max.schnur@gmail.com>
Saji Nediyanchath <saji89@gmail.com>
Corey Frang <gnarf37@gmail.com>
Aaron Peterson <aaronp123@yahoo.com>
Ivan Peters <ivan@ivanpeters.com>
Mohamed Cherif Bouchelaghem <cherifbouchelaghem@yahoo.fr>
Marcos Sousa <falecomigo@marcossousa.com>
Michael DellaNoce <mdellanoce@mailtrust.com>
George Marshall <echosx@gmail.com>
Tobias Brunner <tobias@strongswan.org>
Martin Solli <msolli@gmail.com>
David Petersen <public@petersendidit.com>
Dan Heberden <danheberden@gmail.com>
William Kevin Manire <williamkmanire@gmail.com>
Gilmore Davidson <gilmoreorless@gmail.com>
Michael Wu <michaelmwu@gmail.com>
Adam Parod <mystic414@gmail.com>
Guillaume Gautreau <guillaume+github@ghusse.com>
Marcel Toele <EleotleCram@gmail.com>
Dan Streetman <ddstreet@ieee.org>
Matt Hoskins <matt@nipltd.com>
Giovanni Giacobbi <giovanni@giacobbi.net>
Kyle Florence <kyle.florence@gmail.com>
Pavol Hluchý <lopo@losys.sk>
Hans Hillen <hans.hillen@gmail.com>
Mark Johnson <virgofx@live.com>
Trey Hunner <treyhunner@gmail.com>
Shane Whittet <whittet@gmail.com>
Edward A Faulkner <ef@alum.mit.edu>
Adam Baratz <adam@adambaratz.com>
Kato Kazuyoshi <kato.kazuyoshi@gmail.com>
Eike Send <eike.send@gmail.com>
Kris Borchers <kris.borchers@gmail.com>
Eddie Monge <eddie@eddiemonge.com>
Israel Tsadok <itsadok@gmail.com>
Carson McDonald <carson@ioncannon.net>
Jason Davies <jason@jasondavies.com>
Garrison Locke <gplocke@gmail.com>
David Murdoch <david@davidmurdoch.com>
Benjamin Scott Boyle <benjamins.boyle@gmail.com>
Jesse Baird <jebaird@gmail.com>
Jonathan Vingiano <jvingiano@gmail.com>
Dylan Just <dev@ephox.com>
Hiroshi Tomita <tomykaira@gmail.com>
Glenn Goodrich <glenn.goodrich@gmail.com>
Tarafder Ashek-E-Elahi <mail.ashek@gmail.com>
Ryan Neufeld <ryan@neufeldmail.com>
Marc Neuwirth <marc.neuwirth@gmail.com>
Philip Graham <philip.robert.graham@gmail.com>
Benjamin Sterling <benjamin.sterling@kenzomedia.com>
Wesley Walser <waw325@gmail.com>
Kouhei Sutou <kou@clear-code.com>
Karl Kirch <karlkrch@gmail.com>
Chris Kelly <ckdake@ckdake.com>
Jason Oster <jay@kodewerx.org>
Felix Nagel <info@felixnagel.com>
Alexander Polomoshnov <alex.polomoshnov@gmail.com>
David Leal <dgleal@gmail.com>
Igor Milla <igor.fsp.milla@gmail.com>
Dave Methvin <dave.methvin@gmail.com>
Florian Gutmann <f.gutmann@chronimo.com>
Marwan Al Jubeh <marwan.aljubeh@gmail.com>
Milan Broum <midlis@googlemail.com>
Sebastian Sauer <info@dynpages.de>
Gaëtan Muller <m.gaetan89@gmail.com>
Michel Weimerskirch <michel@weimerskirch.net>
William Griffiths <william@ycymro.com>
Stojce Slavkovski <stojce@gmail.com>
David Soms <david.soms@gmail.com>
David De Sloovere <david.desloovere@outlook.com>
Michael P. Jung <michael.jung@terreon.de>
Shannon Pekary <spekary@gmail.com>
Dan Wellman <danwellman@hotmail.com>
Matthew Edward Hutton <meh@corefiling.co.uk>
James Khoury <james@jameskhoury.com>
Rob Loach <robloach@gmail.com>
Alberto Monteiro <betimbrasil@gmail.com>
Alex Rhea <alex.rhea@gmail.com>
Krzysztof Rosiński <rozwell69@gmail.com>
Ryan Olton <oltonr@gmail.com>
Genie <386@mail.com>
Rick Waldron <waldron.rick@gmail.com>
Ian Simpson <spoonlikesham@gmail.com>
Lev Kitsis <spam4lev@gmail.com>
TJ VanToll <tj.vantoll@gmail.com>
Justin Domnitz <jdomnitz@gmail.com>
Douglas Cerna <douglascerna@yahoo.com>
Bert ter Heide <bertjh@hotmail.com>
Jasvir Nagra <jasvir@gmail.com>
Yuriy Khabarov <13real008@gmail.com>
Harri Kilpiö <harri.kilpio@gmail.com>
Lado Lomidze <lado.lomidze@gmail.com>
Amir E. Aharoni <amir.aharoni@mail.huji.ac.il>
Simon Sattes <simon.sattes@gmail.com>
Jo Liss <joliss42@gmail.com>
Guntupalli Karunakar <karunakarg@yahoo.com>
Shahyar Ghobadpour <shahyar@gmail.com>
Lukasz Lipinski <uzza17@gmail.com>
Timo Tijhof <krinklemail@gmail.com>
Jason Moon <jmoon@socialcast.com>
Martin Frost <martinf55@hotmail.com>
Eneko Illarramendi <eneko@illarra.com>
EungJun Yi <semtlenori@gmail.com>
Courtland Allen <courtlandallen@gmail.com>
Viktar Varvanovich <non4eg@gmail.com>
Danny Trunk <dtrunk90@gmail.com>
Pavel Stetina <pavel.stetina@nangu.tv>
Michael Stay <metaweta@gmail.com>
Steven Roussey <sroussey@gmail.com>
Michael Hollis <hollis21@gmail.com>
Lee Rowlands <lee.rowlands@previousnext.com.au>
Timmy Willison <timmywillisn@gmail.com>
Karl Swedberg <kswedberg@gmail.com>
Baoju Yuan <the_guy_1987@hotmail.com>
Maciej Mroziński <maciej.k.mrozinski@gmail.com>
Luis Dalmolin <luis.nh@gmail.com>
Mark Aaron Shirley <maspwr@gmail.com>
Martin Hoch <martin@fidion.de>
Jiayi Yang <tr870829@gmail.com>
Philipp Benjamin Köppchen <xgxtpbk@gws.ms>
Sindre Sorhus <sindresorhus@gmail.com>
Bernhard Sirlinger <bernhard.sirlinger@tele2.de>
Jared A. Scheel <jared@jaredscheel.com>
Rafael Xavier de Souza <rxaviers@gmail.com>
John Chen <zhang.z.chen@intel.com>
Robert Beuligmann <robertbeuligmann@gmail.com>
Dale Kocian <dale.kocian@gmail.com>
Mike Sherov <mike.sherov@gmail.com>
Andrew Couch <andy@couchand.com>
Marc-Andre Lafortune <github@marc-andre.ca>
Nate Eagle <nate.eagle@teamaol.com>
David Souther <davidsouther@gmail.com>
Mathias Stenbom <mathias@stenbom.com>
Sergey Kartashov <ebishkek@yandex.ru>
Avinash R <nashpapa@gmail.com>
Ethan Romba <ethanromba@gmail.com>
Cory Gackenheimer <cory.gack@gmail.com>
Juan Pablo Kaniefsky <jpkaniefsky@gmail.com>
Roman Salnikov <bardt.dz@gmail.com>
Anika Henke <anika@selfthinker.org>
Samuel Bovée <samycookie2000@yahoo.fr>
Fabrício Matté <ult_combo@hotmail.com>
Viktor Kojouharov <vkojouharov@gmail.com>
Pawel Maruszczyk (http://hrabstwo.net)
Pavel Selitskas <p.selitskas@gmail.com>
Bjørn Johansen <post@bjornjohansen.no>
Matthieu Penant <thieum22@hotmail.com>
Dominic Barnes <dominic@dbarnes.info>
David Sullivan <david.sullivan@gmail.com>
Thomas Jaggi <thomas@responsive.ch>
Vahid Sohrabloo <vahid4134@gmail.com>
Travis Carden <travis.carden@gmail.com>
Bruno M. Custódio <bruno@brunomcustodio.com>
Nathanael Silverman <nathanael.silverman@gmail.com>
Christian Wenz <christian@wenz.org>
Steve Urmston <steve@urm.st>
Zaven Muradyan <megalivoithos@gmail.com>
Woody Gilk <shadowhand@deviantart.com>
Zbigniew Motyka <zbigniew.motyka@gmail.com>
Suhail Alkowaileet <xsoh.k7@gmail.com>
Toshi MARUYAMA <marutosijp2@yahoo.co.jp>
David Hansen <hansede@gmail.com>
Brian Grinstead <briangrinstead@gmail.com>
Christian Klammer <christian314159@gmail.com>
Steven Luscher <jquerycla@steveluscher.com>
Gan Eng Chin <engchin.gan@gmail.com>
Gabriel Schulhof <gabriel.schulhof@intel.com>
Alexander Schmitz <arschmitz@gmail.com>
Vilhjálmur Skúlason <vis@dmm.is>
Siebrand Mazeland <siebrand@kitano.nl>
Mohsen Ekhtiari <mohsenekhtiari@yahoo.com>
Pere Orga <gotrunks@gmail.com>
Jasper de Groot <mail@ugomobi.com>
Stephane Deschamps <stephane.deschamps@gmail.com>
Jyoti Deka <dekajp@gmail.com>
Andrei Picus <office.nightcrawler@gmail.com>
Ondrej Novy <novy@ondrej.org>
Jacob McCutcheon <jacob.mccutcheon@gmail.com>
Monika Piotrowicz <monika.piotrowicz@gmail.com>
Imants Horsts <imants.horsts@inbox.lv>
Eric Dahl <eric.c.dahl@gmail.com>
Dave Stein <dave@behance.com>
Dylan Barrell <dylan@barrell.com>
Daniel DeGroff <djdegroff@gmail.com>
Michael Wiencek <mwtuea@gmail.com>
Thomas Meyer <meyertee@gmail.com>
Ruslan Yakhyaev <ruslan@ruslan.io>
Brian J. Dowling <bjd-dev@simplicity.net>
Ben Higgins <ben@extrahop.com>
Yermo Lamers <yml@yml.com>
Patrick Stapleton <github@gdi2290.com>
Trisha Crowley <trisha.crowley@gmail.com>
Usman Akeju <akeju00+github@gmail.com>
Rodrigo Menezes <rod333@gmail.com>
Jacques Perrault <jacques_perrault@us.ibm.com>
Frederik Elvhage <frederik.elvhage@googlemail.com>
Will Holley <willholley@gmail.com>
Uri Gilad <antishok@gmail.com>
Richard Gibson <richard.gibson@gmail.com>
Simen Bekkhus <sbekkhus91@gmail.com>
Chen Eshchar <eshcharc@gmail.com>
Bruno Pérel <brunoperel@gmail.com>
Mohammed Alshehri <m@dralshehri.com>
Lisa Seacat DeLuca <ldeluca@us.ibm.com>
Anne-Gaelle Colom <coloma@westminster.ac.uk>
Adam Foster <slimfoster@gmail.com>
Luke Page <luke.a.page@gmail.com>
Daniel Owens <daniel@matchstickmixup.com>
Michael Orchard <morchard@scottlogic.co.uk>
Marcus Warren <marcus@envoke.com>
Nils Heuermann <nils@world-of-scripts.de>
Marco Ziech <marco@ziech.net>
Patricia Juarez <patrixd@gmail.com>
Ben Mosher <me@benmosher.com>
Ablay Keldibek <atomio.ak@gmail.com>
Thomas Applencourt <thomas.applencourt@irsamc.ups-tlse.fr>
Jiabao Wu <jiabao.foss@gmail.com>
Eric Lee Carraway <github@ericcarraway.com>
Victor Homyakov <vkhomyackov@gmail.com>
Myeongjin Lee <aranet100@gmail.com>
Liran Sharir <lsharir@gmail.com>
Weston Ruter <weston@xwp.co>
Mani Mishra <manimishra902@gmail.com>
Hannah Methvin <hannahmethvin@gmail.com>
Leonardo Balter <leonardo.balter@gmail.com>
Benjamin Albert <benjamin_a5@yahoo.com>
Michał Gołębiowski-Owczarek <m.goleb@gmail.com>
Alyosha Pushak <alyosha.pushak@gmail.com>
Fahad Ahmad <fahadahmad41@hotmail.com>
Matt Brundage <github@mattbrundage.com>
Francesc Baeta <francesc.baeta@gmail.com>
Piotr Baran <piotros@wp.pl>
Mukul Hase <mukulhase@gmail.com>
Konstantin Dinev <kdinev@mail.bw.edu>
Rand Scullard <rand@randscullard.com>
Dan Strohl <dan@wjcg.net>
Maksim Ryzhikov <rv.maksim@gmail.com>
Amine HADDAD <haddad@allegorie.tv>
Amanpreet Singh <apsdehal@gmail.com>
Alexey Balchunas <bleshik@gmail.com>
Peter Kehl <peter.kehl@gmail.com>
Peter Dave Hello <hsu@peterdavehello.org>
Johannes Schäfer <johnschaefer@gmx.de>
Ville Skyttä <ville.skytta@iki.fi>
Ryan Oriecuia <ryan.oriecuia@visioncritical.com>
Sergei Ratnikov <sergeir82@gmail.com>
milk54 <milk851@gmail.com>
Evelyn Masso <evoutofambit@gmail.com>
Robin <mail@robin-fowler.com>
Simon Asika <asika32764@gmail.com>
Kevin Cupp <kevin.cupp@gmail.com>
Jeremy Mickelson <Jeremy.Mickelson@gmail.com>
Kyle Rosenberg <kyle.rosenberg@gmail.com>
Petri Partio <petri.partio@gmail.com>
pallxk <github@pallxk.com>
Luke Brookhart <luke@onjax.com>
claudi <hirt-claudia@gmx.de>
Eirik Sletteberg <eiriksletteberg@gmail.com>
Albert Johansson <albert@intervaro.se>
A. Wells <borgboyone@users.noreply.github.com>
Robert Brignull <robertbrignull@gmail.com>
Horus68 <pauloizidoro@gmail.com>
Maksymenkov Eugene <foatei@gmail.com>
OskarNS <soerensen.oskar@gmail.com>
Gez Quinn <holla@gezquinn.design>
jigar gala <jigar.gala140291@gmail.com>
Florian Wegscheider <flo.wegscheider@gmail.com>
Fatér Zsolt <fater.zsolt@gmail.com>
Szabolcs Szabolcsi-Toth <nec@shell8.net>
Jérémy Munsch <github@jeremydev.ovh>
Hrvoje Novosel <hrvoje.novosel@gmail.com>
Paul Capron <PaulCapron@users.noreply.github.com>
Micah Miller <mikhey@runbox.com>
sakshi87 <53863764+sakshi87@users.noreply.github.com>
Mikolaj Wolicki <wolicki.mikolaj@gmail.com>
Patrick McKay <patrick.mckay@vumc.org>
c-lambert <58025159+c-lambert@users.noreply.github.com>
Josep Sanz <josepsanzcamp@gmail.com>
Ben Mullins <benm@umich.edu>
Christian Oliff <christianoliff@pm.me>
dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Adam Lidén Hällgren <adamlh92@gmail.com>
James Hinderks <hinderks@gmail.com>
Denny Septian Panggabean <97607754+ddevsr@users.noreply.github.com>
Matías Cánepa <matias.canepa@gmail.com>
Ashish Kurmi <100655670+boahc077@users.noreply.github.com>
DeerBear <andrea.raimondi@gmail.com>
Дилян Палаузов <dpa-github@aegee.org>
Kenneth DeBacker <kcdebacker@gmail.com>
Timo Tijhof <krinkle@fastmail.com>
Timmy Willison <timmywil@users.noreply.github.com>
divdeploy <166095818+divdeploy@users.noreply.github.com>
mark van tilburg <markvantilburg@gmail.com>

View File

@ -0,0 +1,43 @@
Copyright OpenJS Foundation and other contributors, https://openjsf.org/
This software consists of voluntary contributions made by many
individuals. For exact contribution history, see the revision history
available at https://github.com/jquery/jquery-ui
The following license applies to all parts of this software except as
documented below:
====
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:
The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
====
Copyright and related rights for sample code are waived via CC0. Sample
code is defined as all source code contained within the demos directory.
CC0: http://creativecommons.org/publicdomain/zero/1.0/
====
All files located in the node_modules and external directories are
externally maintained libraries used by this software which have their
own licenses; we recommend you read them, as their terms may differ from
the terms above.

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -0,0 +1,503 @@
<!doctype html>
<html lang="us">
<head>
<meta charset="utf-8">
<title>jQuery UI Example Page</title>
<link href="jquery-ui.css" rel="stylesheet">
<style>
body{
font-family: "Trebuchet MS", sans-serif;
margin: 50px;
}
.demoHeaders {
margin-top: 2em;
}
#dialog-link {
padding: .4em 1em .4em 20px;
text-decoration: none;
position: relative;
}
#dialog-link span.ui-icon {
margin: 0 5px 0 0;
position: absolute;
left: .2em;
top: 50%;
margin-top: -8px;
}
#icons {
margin: 0;
padding: 0;
}
#icons li {
margin: 2px;
position: relative;
padding: 4px 0;
cursor: pointer;
float: left;
list-style: none;
}
#icons span.ui-icon {
float: left;
margin: 0 4px;
}
.fakewindowcontain .ui-widget-overlay {
position: absolute;
}
select {
width: 200px;
}
</style>
</head>
<body>
<h1>Welcome to jQuery UI!</h1>
<div class="ui-widget">
<p>This page demonstrates the widgets and theme you selected in Download Builder. Please make sure you are using them with a compatible jQuery version.</p>
</div>
<h1>YOUR COMPONENTS:</h1>
<!-- Accordion -->
<h2 class="demoHeaders">Accordion</h2>
<div id="accordion">
<h3>First</h3>
<div>Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet.</div>
<h3>Second</h3>
<div>Phasellus mattis tincidunt nibh.</div>
<h3>Third</h3>
<div>Nam dui erat, auctor a, dignissim quis.</div>
</div>
<!-- Autocomplete -->
<h2 class="demoHeaders">Autocomplete</h2>
<div>
<input id="autocomplete" title="type &quot;a&quot;">
</div>
<!-- Button -->
<h2 class="demoHeaders">Button</h2>
<button id="button">A button element</button>
<button id="button-icon">An icon-only button</button>
<!-- Checkboxradio -->
<h2 class="demoHeaders">Checkboxradio</h2>
<form style="margin-top: 1em;">
<div id="radioset">
<input type="radio" id="radio1" name="radio"><label for="radio1">Choice 1</label>
<input type="radio" id="radio2" name="radio" checked="checked"><label for="radio2">Choice 2</label>
<input type="radio" id="radio3" name="radio"><label for="radio3">Choice 3</label>
</div>
</form>
<!-- Controlgroup -->
<h2 class="demoHeaders">Controlgroup</h2>
<fieldset>
<legend>Rental Car</legend>
<div id="controlgroup">
<select id="car-type">
<option>Compact car</option>
<option>Midsize car</option>
<option>Full size car</option>
<option>SUV</option>
<option>Luxury</option>
<option>Truck</option>
<option>Van</option>
</select>
<label for="transmission-standard">Standard</label>
<input type="radio" name="transmission" id="transmission-standard">
<label for="transmission-automatic">Automatic</label>
<input type="radio" name="transmission" id="transmission-automatic">
<label for="insurance">Insurance</label>
<input type="checkbox" name="insurance" id="insurance">
<label for="horizontal-spinner" class="ui-controlgroup-label"># of cars</label>
<input id="horizontal-spinner" class="ui-spinner-input">
<button>Book Now!</button>
</div>
</fieldset>
<!-- Tabs -->
<h2 class="demoHeaders">Tabs</h2>
<div id="tabs">
<ul>
<li><a href="#tabs-1">First</a></li>
<li><a href="#tabs-2">Second</a></li>
<li><a href="#tabs-3">Third</a></li>
</ul>
<div id="tabs-1">Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</div>
<div id="tabs-2">Phasellus mattis tincidunt nibh. Cras orci urna, blandit id, pretium vel, aliquet ornare, felis. Maecenas scelerisque sem non nisl. Fusce sed lorem in enim dictum bibendum.</div>
<div id="tabs-3">Nam dui erat, auctor a, dignissim quis, sollicitudin eu, felis. Pellentesque nisi urna, interdum eget, sagittis et, consequat vestibulum, lacus. Mauris porttitor ullamcorper augue.</div>
</div>
<h2 class="demoHeaders">Dialog</h2>
<p>
<button id="dialog-link" class="ui-button ui-corner-all ui-widget">
<span class="ui-icon ui-icon-newwin"></span>Open Dialog
</button>
</p>
<h2 class="demoHeaders">Overlay and Shadow Classes</h2>
<div style="position: relative; width: 96%; height: 200px; padding:1% 2%; overflow:hidden;" class="fakewindowcontain">
<p>Lorem ipsum dolor sit amet, Nulla nec tortor. Donec id elit quis purus consectetur consequat. </p><p>Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id, sem. Morbi in orci. </p><p>Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur consequat. </p><p>Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id, sem. Morbi in orci. Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. </p><p>Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. Aliquam ante. </p><p>Suspendisse scelerisque dui nec velit. Duis augue augue, gravida euismod, vulputate ac, facilisis id, sem. Morbi in orci. Nulla purus lacus, pulvinar vel, malesuada ac, mattis nec, quam. Nam molestie scelerisque quam. Nullam feugiat cursus lacus.orem ipsum dolor sit amet, consectetur adipiscing elit. Donec libero risus, commodo vitae, pharetra mollis, posuere eu, pede. Nulla nec tortor. Donec id elit quis purus consectetur consequat. Nam congue semper tellus. Sed erat dolor, dapibus sit amet, venenatis ornare, ultrices ut, nisi. </p>
<!-- ui-dialog -->
<div class="ui-widget-overlay ui-front"></div>
<div style="position: absolute; width: 320px; left: 50px; top: 30px; padding: 1.2em" class="ui-widget ui-front ui-widget-content ui-corner-all ui-widget-shadow">
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
</div>
</div>
<!-- ui-dialog -->
<div id="dialog" title="Dialog Title">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.</p>
</div>
<h2 class="demoHeaders">Framework Icons (content color preview)</h2>
<ul id="icons" class="ui-widget ui-helper-clearfix">
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-1-n"><span class="ui-icon ui-icon-caret-1-n"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-1-ne"><span class="ui-icon ui-icon-caret-1-ne"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-1-e"><span class="ui-icon ui-icon-caret-1-e"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-1-se"><span class="ui-icon ui-icon-caret-1-se"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-1-s"><span class="ui-icon ui-icon-caret-1-s"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-1-sw"><span class="ui-icon ui-icon-caret-1-sw"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-1-w"><span class="ui-icon ui-icon-caret-1-w"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-1-nw"><span class="ui-icon ui-icon-caret-1-nw"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-2-n-s"><span class="ui-icon ui-icon-caret-2-n-s"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-caret-2-e-w"><span class="ui-icon ui-icon-caret-2-e-w"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-n"><span class="ui-icon ui-icon-triangle-1-n"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-ne"><span class="ui-icon ui-icon-triangle-1-ne"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-e"><span class="ui-icon ui-icon-triangle-1-e"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-se"><span class="ui-icon ui-icon-triangle-1-se"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-s"><span class="ui-icon ui-icon-triangle-1-s"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-sw"><span class="ui-icon ui-icon-triangle-1-sw"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-w"><span class="ui-icon ui-icon-triangle-1-w"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-1-nw"><span class="ui-icon ui-icon-triangle-1-nw"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-2-n-s"><span class="ui-icon ui-icon-triangle-2-n-s"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-triangle-2-e-w"><span class="ui-icon ui-icon-triangle-2-e-w"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-n"><span class="ui-icon ui-icon-arrow-1-n"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-ne"><span class="ui-icon ui-icon-arrow-1-ne"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-e"><span class="ui-icon ui-icon-arrow-1-e"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-se"><span class="ui-icon ui-icon-arrow-1-se"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-s"><span class="ui-icon ui-icon-arrow-1-s"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-sw"><span class="ui-icon ui-icon-arrow-1-sw"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-w"><span class="ui-icon ui-icon-arrow-1-w"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-1-nw"><span class="ui-icon ui-icon-arrow-1-nw"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-2-n-s"><span class="ui-icon ui-icon-arrow-2-n-s"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-2-ne-sw"><span class="ui-icon ui-icon-arrow-2-ne-sw"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-2-e-w"><span class="ui-icon ui-icon-arrow-2-e-w"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-2-se-nw"><span class="ui-icon ui-icon-arrow-2-se-nw"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowstop-1-n"><span class="ui-icon ui-icon-arrowstop-1-n"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowstop-1-e"><span class="ui-icon ui-icon-arrowstop-1-e"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowstop-1-s"><span class="ui-icon ui-icon-arrowstop-1-s"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowstop-1-w"><span class="ui-icon ui-icon-arrowstop-1-w"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-n"><span class="ui-icon ui-icon-arrowthick-1-n"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-ne"><span class="ui-icon ui-icon-arrowthick-1-ne"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-e"><span class="ui-icon ui-icon-arrowthick-1-e"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-se"><span class="ui-icon ui-icon-arrowthick-1-se"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-s"><span class="ui-icon ui-icon-arrowthick-1-s"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-sw"><span class="ui-icon ui-icon-arrowthick-1-sw"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-w"><span class="ui-icon ui-icon-arrowthick-1-w"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-1-nw"><span class="ui-icon ui-icon-arrowthick-1-nw"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-2-n-s"><span class="ui-icon ui-icon-arrowthick-2-n-s"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-2-ne-sw"><span class="ui-icon ui-icon-arrowthick-2-ne-sw"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-2-e-w"><span class="ui-icon ui-icon-arrowthick-2-e-w"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthick-2-se-nw"><span class="ui-icon ui-icon-arrowthick-2-se-nw"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthickstop-1-n"><span class="ui-icon ui-icon-arrowthickstop-1-n"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthickstop-1-e"><span class="ui-icon ui-icon-arrowthickstop-1-e"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthickstop-1-s"><span class="ui-icon ui-icon-arrowthickstop-1-s"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowthickstop-1-w"><span class="ui-icon ui-icon-arrowthickstop-1-w"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturnthick-1-w"><span class="ui-icon ui-icon-arrowreturnthick-1-w"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturnthick-1-n"><span class="ui-icon ui-icon-arrowreturnthick-1-n"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturnthick-1-e"><span class="ui-icon ui-icon-arrowreturnthick-1-e"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturnthick-1-s"><span class="ui-icon ui-icon-arrowreturnthick-1-s"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturn-1-w"><span class="ui-icon ui-icon-arrowreturn-1-w"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturn-1-n"><span class="ui-icon ui-icon-arrowreturn-1-n"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturn-1-e"><span class="ui-icon ui-icon-arrowreturn-1-e"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowreturn-1-s"><span class="ui-icon ui-icon-arrowreturn-1-s"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowrefresh-1-w"><span class="ui-icon ui-icon-arrowrefresh-1-w"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowrefresh-1-n"><span class="ui-icon ui-icon-arrowrefresh-1-n"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowrefresh-1-e"><span class="ui-icon ui-icon-arrowrefresh-1-e"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrowrefresh-1-s"><span class="ui-icon ui-icon-arrowrefresh-1-s"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-4"><span class="ui-icon ui-icon-arrow-4"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-arrow-4-diag"><span class="ui-icon ui-icon-arrow-4-diag"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-extlink"><span class="ui-icon ui-icon-extlink"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-newwin"><span class="ui-icon ui-icon-newwin"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-refresh"><span class="ui-icon ui-icon-refresh"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-shuffle"><span class="ui-icon ui-icon-shuffle"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-transfer-e-w"><span class="ui-icon ui-icon-transfer-e-w"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-transferthick-e-w"><span class="ui-icon ui-icon-transferthick-e-w"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-folder-collapsed"><span class="ui-icon ui-icon-folder-collapsed"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-folder-open"><span class="ui-icon ui-icon-folder-open"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-document"><span class="ui-icon ui-icon-document"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-document-b"><span class="ui-icon ui-icon-document-b"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-note"><span class="ui-icon ui-icon-note"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-mail-closed"><span class="ui-icon ui-icon-mail-closed"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-mail-open"><span class="ui-icon ui-icon-mail-open"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-suitcase"><span class="ui-icon ui-icon-suitcase"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-comment"><span class="ui-icon ui-icon-comment"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-person"><span class="ui-icon ui-icon-person"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-print"><span class="ui-icon ui-icon-print"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-trash"><span class="ui-icon ui-icon-trash"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-locked"><span class="ui-icon ui-icon-locked"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-unlocked"><span class="ui-icon ui-icon-unlocked"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-bookmark"><span class="ui-icon ui-icon-bookmark"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-tag"><span class="ui-icon ui-icon-tag"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-home"><span class="ui-icon ui-icon-home"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-flag"><span class="ui-icon ui-icon-flag"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-calculator"><span class="ui-icon ui-icon-calculator"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-cart"><span class="ui-icon ui-icon-cart"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-pencil"><span class="ui-icon ui-icon-pencil"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-clock"><span class="ui-icon ui-icon-clock"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-disk"><span class="ui-icon ui-icon-disk"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-calendar"><span class="ui-icon ui-icon-calendar"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-zoomin"><span class="ui-icon ui-icon-zoomin"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-zoomout"><span class="ui-icon ui-icon-zoomout"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-search"><span class="ui-icon ui-icon-search"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-wrench"><span class="ui-icon ui-icon-wrench"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-gear"><span class="ui-icon ui-icon-gear"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-heart"><span class="ui-icon ui-icon-heart"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-star"><span class="ui-icon ui-icon-star"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-link"><span class="ui-icon ui-icon-link"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-cancel"><span class="ui-icon ui-icon-cancel"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-plus"><span class="ui-icon ui-icon-plus"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-plusthick"><span class="ui-icon ui-icon-plusthick"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-minus"><span class="ui-icon ui-icon-minus"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-minusthick"><span class="ui-icon ui-icon-minusthick"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-close"><span class="ui-icon ui-icon-close"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-closethick"><span class="ui-icon ui-icon-closethick"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-key"><span class="ui-icon ui-icon-key"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-lightbulb"><span class="ui-icon ui-icon-lightbulb"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-scissors"><span class="ui-icon ui-icon-scissors"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-clipboard"><span class="ui-icon ui-icon-clipboard"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-copy"><span class="ui-icon ui-icon-copy"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-contact"><span class="ui-icon ui-icon-contact"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-image"><span class="ui-icon ui-icon-image"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-video"><span class="ui-icon ui-icon-video"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-script"><span class="ui-icon ui-icon-script"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-alert"><span class="ui-icon ui-icon-alert"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-info"><span class="ui-icon ui-icon-info"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-notice"><span class="ui-icon ui-icon-notice"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-help"><span class="ui-icon ui-icon-help"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-check"><span class="ui-icon ui-icon-check"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-bullet"><span class="ui-icon ui-icon-bullet"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-radio-off"><span class="ui-icon ui-icon-radio-off"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-radio-on"><span class="ui-icon ui-icon-radio-on"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-pin-w"><span class="ui-icon ui-icon-pin-w"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-pin-s"><span class="ui-icon ui-icon-pin-s"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-play"><span class="ui-icon ui-icon-play"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-pause"><span class="ui-icon ui-icon-pause"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-seek-next"><span class="ui-icon ui-icon-seek-next"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-seek-prev"><span class="ui-icon ui-icon-seek-prev"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-seek-end"><span class="ui-icon ui-icon-seek-end"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-seek-first"><span class="ui-icon ui-icon-seek-first"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-stop"><span class="ui-icon ui-icon-stop"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-eject"><span class="ui-icon ui-icon-eject"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-volume-off"><span class="ui-icon ui-icon-volume-off"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-volume-on"><span class="ui-icon ui-icon-volume-on"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-power"><span class="ui-icon ui-icon-power"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-signal-diag"><span class="ui-icon ui-icon-signal-diag"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-signal"><span class="ui-icon ui-icon-signal"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-battery-0"><span class="ui-icon ui-icon-battery-0"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-battery-1"><span class="ui-icon ui-icon-battery-1"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-battery-2"><span class="ui-icon ui-icon-battery-2"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-battery-3"><span class="ui-icon ui-icon-battery-3"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-plus"><span class="ui-icon ui-icon-circle-plus"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-minus"><span class="ui-icon ui-icon-circle-minus"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-close"><span class="ui-icon ui-icon-circle-close"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-triangle-e"><span class="ui-icon ui-icon-circle-triangle-e"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-triangle-s"><span class="ui-icon ui-icon-circle-triangle-s"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-triangle-w"><span class="ui-icon ui-icon-circle-triangle-w"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-triangle-n"><span class="ui-icon ui-icon-circle-triangle-n"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-arrow-e"><span class="ui-icon ui-icon-circle-arrow-e"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-arrow-s"><span class="ui-icon ui-icon-circle-arrow-s"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-arrow-w"><span class="ui-icon ui-icon-circle-arrow-w"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-arrow-n"><span class="ui-icon ui-icon-circle-arrow-n"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-zoomin"><span class="ui-icon ui-icon-circle-zoomin"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-zoomout"><span class="ui-icon ui-icon-circle-zoomout"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-circle-check"><span class="ui-icon ui-icon-circle-check"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-circlesmall-plus"><span class="ui-icon ui-icon-circlesmall-plus"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-circlesmall-minus"><span class="ui-icon ui-icon-circlesmall-minus"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-circlesmall-close"><span class="ui-icon ui-icon-circlesmall-close"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-squaresmall-plus"><span class="ui-icon ui-icon-squaresmall-plus"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-squaresmall-minus"><span class="ui-icon ui-icon-squaresmall-minus"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-squaresmall-close"><span class="ui-icon ui-icon-squaresmall-close"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-grip-dotted-vertical"><span class="ui-icon ui-icon-grip-dotted-vertical"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-grip-dotted-horizontal"><span class="ui-icon ui-icon-grip-dotted-horizontal"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-grip-solid-vertical"><span class="ui-icon ui-icon-grip-solid-vertical"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-grip-solid-horizontal"><span class="ui-icon ui-icon-grip-solid-horizontal"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-gripsmall-diagonal-se"><span class="ui-icon ui-icon-gripsmall-diagonal-se"></span></li>
<li class="ui-state-default ui-corner-all" title=".ui-icon-grip-diagonal-se"><span class="ui-icon ui-icon-grip-diagonal-se"></span></li>
</ul>
<!-- Slider -->
<h2 class="demoHeaders">Slider</h2>
<div id="slider"></div>
<!-- Datepicker -->
<h2 class="demoHeaders">Datepicker</h2>
<div id="datepicker"></div>
<!-- Progressbar -->
<h2 class="demoHeaders">Progressbar</h2>
<div id="progressbar"></div>
<!-- Progressbar -->
<h2 class="demoHeaders">Selectmenu</h2>
<select id="selectmenu">
<option>Slower</option>
<option>Slow</option>
<option selected="selected">Medium</option>
<option>Fast</option>
<option>Faster</option>
</select>
<!-- Spinner -->
<h2 class="demoHeaders">Spinner</h2>
<input id="spinner">
<!-- Menu -->
<h2 class="demoHeaders">Menu</h2>
<ul style="width:100px;" id="menu">
<li><div>Item 1</div></li>
<li><div>Item 2</div></li>
<li><div>Item 3</div>
<ul>
<li><div>Item 3-1</div></li>
<li><div>Item 3-2</div></li>
<li><div>Item 3-3</div></li>
<li><div>Item 3-4</div></li>
<li><div>Item 3-5</div></li>
</ul>
</li>
<li><div>Item 4</div></li>
<li><div>Item 5</div></li>
</ul>
<!-- Tooltip -->
<h2 class="demoHeaders">Tooltip</h2>
<p id="tooltip">
<a href="#" title="That&apos;s what this widget is">Tooltips</a> can be attached to any element. When you hover
the element with your mouse, the title attribute is displayed in a little box next to the element, just like a native tooltip.
</p>
<!-- Highlight / Error -->
<h2 class="demoHeaders">Highlight / Error</h2>
<div class="ui-widget">
<div class="ui-state-highlight ui-corner-all" style="margin-top: 20px; padding: 0 .7em;">
<p><span class="ui-icon ui-icon-info" style="float: left; margin-right: .3em;"></span>
<strong>Hey!</strong> Sample ui-state-highlight style.</p>
</div>
</div>
<br>
<div class="ui-widget">
<div class="ui-state-error ui-corner-all" style="padding: 0 .7em;">
<p><span class="ui-icon ui-icon-alert" style="float: left; margin-right: .3em;"></span>
<strong>Alert:</strong> Sample ui-state-error style.</p>
</div>
</div>
<script src="external/jquery/jquery.js"></script>
<script src="jquery-ui.js"></script>
<script>
$( "#accordion" ).accordion();
var availableTags = [
"ActionScript",
"AppleScript",
"Asp",
"BASIC",
"C",
"C++",
"Clojure",
"COBOL",
"ColdFusion",
"Erlang",
"Fortran",
"Groovy",
"Haskell",
"Java",
"JavaScript",
"Lisp",
"Perl",
"PHP",
"Python",
"Ruby",
"Scala",
"Scheme"
];
$( "#autocomplete" ).autocomplete({
source: availableTags
});
$( "#button" ).button();
$( "#button-icon" ).button({
icon: "ui-icon-gear",
showLabel: false
});
$( "#radioset" ).controlgroup();
$( "#controlgroup" ).controlgroup();
$( "#tabs" ).tabs();
$( "#dialog" ).dialog({
autoOpen: false,
width: 400,
buttons: [
{
text: "Ok",
click: function() {
$( this ).dialog( "close" );
}
},
{
text: "Cancel",
click: function() {
$( this ).dialog( "close" );
}
}
]
});
// Link to open the dialog
$( "#dialog-link" ).click(function( event ) {
$( "#dialog" ).dialog( "open" );
event.preventDefault();
});
$( "#datepicker" ).datepicker({
inline: true
});
$( "#slider" ).slider({
range: true,
values: [ 17, 67 ]
});
$( "#progressbar" ).progressbar({
value: 20
});
$( "#spinner" ).spinner();
$( "#menu" ).menu();
$( "#tooltip" ).tooltip();
$( "#selectmenu" ).selectmenu();
// Hover states on the static widgets
$( "#dialog-link, #icons li" ).hover(
function() {
$( this ).addClass( "ui-state-hover" );
},
function() {
$( this ).removeClass( "ui-state-hover" );
}
);
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,886 @@
/*!
* jQuery UI CSS Framework 1.13.3
* https://jqueryui.com
*
* Copyright OpenJS Foundation and other contributors
* Released under the MIT license.
* https://jquery.org/license
*
* https://api.jqueryui.com/category/theming/
*/
.ui-draggable-handle {
-ms-touch-action: none;
touch-action: none;
}
/* Layout helpers
----------------------------------*/
.ui-helper-hidden {
display: none;
}
.ui-helper-hidden-accessible {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.ui-helper-reset {
margin: 0;
padding: 0;
border: 0;
outline: 0;
line-height: 1.3;
text-decoration: none;
font-size: 100%;
list-style: none;
}
.ui-helper-clearfix:before,
.ui-helper-clearfix:after {
content: "";
display: table;
border-collapse: collapse;
}
.ui-helper-clearfix:after {
clear: both;
}
.ui-helper-zfix {
width: 100%;
height: 100%;
top: 0;
left: 0;
position: absolute;
opacity: 0;
-ms-filter: "alpha(opacity=0)"; /* support: IE8 */
}
.ui-front {
z-index: 100;
}
/* Interaction Cues
----------------------------------*/
.ui-state-disabled {
cursor: default !important;
pointer-events: none;
}
/* Icons
----------------------------------*/
.ui-icon {
display: inline-block;
vertical-align: middle;
margin-top: -.25em;
position: relative;
text-indent: -99999px;
overflow: hidden;
background-repeat: no-repeat;
}
.ui-widget-icon-block {
left: 50%;
margin-left: -8px;
display: block;
}
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.ui-resizable {
position: relative;
}
.ui-resizable-handle {
position: absolute;
font-size: 0.1px;
display: block;
-ms-touch-action: none;
touch-action: none;
}
.ui-resizable-disabled .ui-resizable-handle,
.ui-resizable-autohide .ui-resizable-handle {
display: none;
}
.ui-resizable-n {
cursor: n-resize;
height: 7px;
width: 100%;
top: -5px;
left: 0;
}
.ui-resizable-s {
cursor: s-resize;
height: 7px;
width: 100%;
bottom: -5px;
left: 0;
}
.ui-resizable-e {
cursor: e-resize;
width: 7px;
right: -5px;
top: 0;
height: 100%;
}
.ui-resizable-w {
cursor: w-resize;
width: 7px;
left: -5px;
top: 0;
height: 100%;
}
.ui-resizable-se {
cursor: se-resize;
width: 12px;
height: 12px;
right: 1px;
bottom: 1px;
}
.ui-resizable-sw {
cursor: sw-resize;
width: 9px;
height: 9px;
left: -5px;
bottom: -5px;
}
.ui-resizable-nw {
cursor: nw-resize;
width: 9px;
height: 9px;
left: -5px;
top: -5px;
}
.ui-resizable-ne {
cursor: ne-resize;
width: 9px;
height: 9px;
right: -5px;
top: -5px;
}
.ui-selectable {
-ms-touch-action: none;
touch-action: none;
}
.ui-selectable-helper {
position: absolute;
z-index: 100;
border: 1px dotted black;
}
.ui-sortable-handle {
-ms-touch-action: none;
touch-action: none;
}
.ui-accordion .ui-accordion-header {
display: block;
cursor: pointer;
position: relative;
margin: 2px 0 0 0;
padding: .5em .5em .5em .7em;
font-size: 100%;
}
.ui-accordion .ui-accordion-content {
padding: 1em 2.2em;
border-top: 0;
overflow: auto;
}
.ui-autocomplete {
position: absolute;
top: 0;
left: 0;
cursor: default;
}
.ui-menu {
list-style: none;
padding: 0;
margin: 0;
display: block;
outline: 0;
}
.ui-menu .ui-menu {
position: absolute;
}
.ui-menu .ui-menu-item {
margin: 0;
cursor: pointer;
/* support: IE10, see #8844 */
list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
}
.ui-menu .ui-menu-item-wrapper {
position: relative;
padding: 3px 1em 3px .4em;
}
.ui-menu .ui-menu-divider {
margin: 5px 0;
height: 0;
font-size: 0;
line-height: 0;
border-width: 1px 0 0 0;
}
.ui-menu .ui-state-focus,
.ui-menu .ui-state-active {
margin: -1px;
}
/* icon support */
.ui-menu-icons {
position: relative;
}
.ui-menu-icons .ui-menu-item-wrapper {
padding-left: 2em;
}
/* left-aligned */
.ui-menu .ui-icon {
position: absolute;
top: 0;
bottom: 0;
left: .2em;
margin: auto 0;
}
/* right-aligned */
.ui-menu .ui-menu-icon {
left: auto;
right: 0;
}
.ui-button {
padding: .4em 1em;
display: inline-block;
position: relative;
line-height: normal;
margin-right: .1em;
cursor: pointer;
vertical-align: middle;
text-align: center;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
/* Support: IE <= 11 */
overflow: visible;
}
.ui-button,
.ui-button:link,
.ui-button:visited,
.ui-button:hover,
.ui-button:active {
text-decoration: none;
}
/* to make room for the icon, a width needs to be set here */
.ui-button-icon-only {
width: 2em;
box-sizing: border-box;
text-indent: -9999px;
white-space: nowrap;
}
/* no icon support for input elements */
input.ui-button.ui-button-icon-only {
text-indent: 0;
}
/* button icon element(s) */
.ui-button-icon-only .ui-icon {
position: absolute;
top: 50%;
left: 50%;
margin-top: -8px;
margin-left: -8px;
}
.ui-button.ui-icon-notext .ui-icon {
padding: 0;
width: 2.1em;
height: 2.1em;
text-indent: -9999px;
white-space: nowrap;
}
input.ui-button.ui-icon-notext .ui-icon {
width: auto;
height: auto;
text-indent: 0;
white-space: normal;
padding: .4em 1em;
}
/* workarounds */
/* Support: Firefox 5 - 40 */
input.ui-button::-moz-focus-inner,
button.ui-button::-moz-focus-inner {
border: 0;
padding: 0;
}
.ui-controlgroup {
vertical-align: middle;
display: inline-block;
}
.ui-controlgroup > .ui-controlgroup-item {
float: left;
margin-left: 0;
margin-right: 0;
}
.ui-controlgroup > .ui-controlgroup-item:focus,
.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus {
z-index: 9999;
}
.ui-controlgroup-vertical > .ui-controlgroup-item {
display: block;
float: none;
width: 100%;
margin-top: 0;
margin-bottom: 0;
text-align: left;
}
.ui-controlgroup-vertical .ui-controlgroup-item {
box-sizing: border-box;
}
.ui-controlgroup .ui-controlgroup-label {
padding: .4em 1em;
}
.ui-controlgroup .ui-controlgroup-label span {
font-size: 80%;
}
.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item {
border-left: none;
}
.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item {
border-top: none;
}
.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content {
border-right: none;
}
.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content {
border-bottom: none;
}
/* Spinner specific style fixes */
.ui-controlgroup-vertical .ui-spinner-input {
/* Support: IE8 only, Android < 4.4 only */
width: 75%;
width: calc( 100% - 2.4em );
}
.ui-controlgroup-vertical .ui-spinner .ui-spinner-up {
border-top-style: solid;
}
.ui-checkboxradio-label .ui-icon-background {
box-shadow: inset 1px 1px 1px #ccc;
border-radius: .12em;
border: none;
}
.ui-checkboxradio-radio-label .ui-icon-background {
width: 16px;
height: 16px;
border-radius: 1em;
overflow: visible;
border: none;
}
.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,
.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon {
background-image: none;
width: 8px;
height: 8px;
border-width: 4px;
border-style: solid;
}
.ui-checkboxradio-disabled {
pointer-events: none;
}
.ui-datepicker {
width: 17em;
padding: .2em .2em 0;
display: none;
}
.ui-datepicker .ui-datepicker-header {
position: relative;
padding: .2em 0;
}
.ui-datepicker .ui-datepicker-prev,
.ui-datepicker .ui-datepicker-next {
position: absolute;
top: 2px;
width: 1.8em;
height: 1.8em;
}
.ui-datepicker .ui-datepicker-prev-hover,
.ui-datepicker .ui-datepicker-next-hover {
top: 1px;
}
.ui-datepicker .ui-datepicker-prev {
left: 2px;
}
.ui-datepicker .ui-datepicker-next {
right: 2px;
}
.ui-datepicker .ui-datepicker-prev-hover {
left: 1px;
}
.ui-datepicker .ui-datepicker-next-hover {
right: 1px;
}
.ui-datepicker .ui-datepicker-prev span,
.ui-datepicker .ui-datepicker-next span {
display: block;
position: absolute;
left: 50%;
margin-left: -8px;
top: 50%;
margin-top: -8px;
}
.ui-datepicker .ui-datepicker-title {
margin: 0 2.3em;
line-height: 1.8em;
text-align: center;
}
.ui-datepicker .ui-datepicker-title select {
font-size: 1em;
margin: 1px 0;
}
.ui-datepicker select.ui-datepicker-month,
.ui-datepicker select.ui-datepicker-year {
width: 45%;
}
.ui-datepicker table {
width: 100%;
font-size: .9em;
border-collapse: collapse;
margin: 0 0 .4em;
}
.ui-datepicker th {
padding: .7em .3em;
text-align: center;
font-weight: bold;
border: 0;
}
.ui-datepicker td {
border: 0;
padding: 1px;
}
.ui-datepicker td span,
.ui-datepicker td a {
display: block;
padding: .2em;
text-align: right;
text-decoration: none;
}
.ui-datepicker .ui-datepicker-buttonpane {
background-image: none;
margin: .7em 0 0 0;
padding: 0 .2em;
border-left: 0;
border-right: 0;
border-bottom: 0;
}
.ui-datepicker .ui-datepicker-buttonpane button {
float: right;
margin: .5em .2em .4em;
cursor: pointer;
padding: .2em .6em .3em .6em;
width: auto;
overflow: visible;
}
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
float: left;
}
/* with multiple calendars */
.ui-datepicker.ui-datepicker-multi {
width: auto;
}
.ui-datepicker-multi .ui-datepicker-group {
float: left;
}
.ui-datepicker-multi .ui-datepicker-group table {
width: 95%;
margin: 0 auto .4em;
}
.ui-datepicker-multi-2 .ui-datepicker-group {
width: 50%;
}
.ui-datepicker-multi-3 .ui-datepicker-group {
width: 33.3%;
}
.ui-datepicker-multi-4 .ui-datepicker-group {
width: 25%;
}
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
border-left-width: 0;
}
.ui-datepicker-multi .ui-datepicker-buttonpane {
clear: left;
}
.ui-datepicker-row-break {
clear: both;
width: 100%;
font-size: 0;
}
/* RTL support */
.ui-datepicker-rtl {
direction: rtl;
}
.ui-datepicker-rtl .ui-datepicker-prev {
right: 2px;
left: auto;
}
.ui-datepicker-rtl .ui-datepicker-next {
left: 2px;
right: auto;
}
.ui-datepicker-rtl .ui-datepicker-prev:hover {
right: 1px;
left: auto;
}
.ui-datepicker-rtl .ui-datepicker-next:hover {
left: 1px;
right: auto;
}
.ui-datepicker-rtl .ui-datepicker-buttonpane {
clear: right;
}
.ui-datepicker-rtl .ui-datepicker-buttonpane button {
float: left;
}
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
.ui-datepicker-rtl .ui-datepicker-group {
float: right;
}
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
border-right-width: 0;
border-left-width: 1px;
}
/* Icons */
.ui-datepicker .ui-icon {
display: block;
text-indent: -99999px;
overflow: hidden;
background-repeat: no-repeat;
left: .5em;
top: .3em;
}
.ui-dialog {
position: absolute;
top: 0;
left: 0;
padding: .2em;
outline: 0;
}
.ui-dialog .ui-dialog-titlebar {
padding: .4em 1em;
position: relative;
}
.ui-dialog .ui-dialog-title {
float: left;
margin: .1em 0;
white-space: nowrap;
width: 90%;
overflow: hidden;
text-overflow: ellipsis;
}
.ui-dialog .ui-dialog-titlebar-close {
position: absolute;
right: .3em;
top: 50%;
width: 20px;
margin: -10px 0 0 0;
padding: 1px;
height: 20px;
}
.ui-dialog .ui-dialog-content {
position: relative;
border: 0;
padding: .5em 1em;
background: none;
overflow: auto;
}
.ui-dialog .ui-dialog-buttonpane {
text-align: left;
border-width: 1px 0 0 0;
background-image: none;
margin-top: .5em;
padding: .3em 1em .5em .4em;
}
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
float: right;
}
.ui-dialog .ui-dialog-buttonpane button {
margin: .5em .4em .5em 0;
cursor: pointer;
}
.ui-dialog .ui-resizable-n {
height: 2px;
top: 0;
}
.ui-dialog .ui-resizable-e {
width: 2px;
right: 0;
}
.ui-dialog .ui-resizable-s {
height: 2px;
bottom: 0;
}
.ui-dialog .ui-resizable-w {
width: 2px;
left: 0;
}
.ui-dialog .ui-resizable-se,
.ui-dialog .ui-resizable-sw,
.ui-dialog .ui-resizable-ne,
.ui-dialog .ui-resizable-nw {
width: 7px;
height: 7px;
}
.ui-dialog .ui-resizable-se {
right: 0;
bottom: 0;
}
.ui-dialog .ui-resizable-sw {
left: 0;
bottom: 0;
}
.ui-dialog .ui-resizable-ne {
right: 0;
top: 0;
}
.ui-dialog .ui-resizable-nw {
left: 0;
top: 0;
}
.ui-draggable .ui-dialog-titlebar {
cursor: move;
}
.ui-progressbar {
height: 2em;
text-align: left;
overflow: hidden;
}
.ui-progressbar .ui-progressbar-value {
margin: -1px;
height: 100%;
}
.ui-progressbar .ui-progressbar-overlay {
background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");
height: 100%;
-ms-filter: "alpha(opacity=25)"; /* support: IE8 */
opacity: 0.25;
}
.ui-progressbar-indeterminate .ui-progressbar-value {
background-image: none;
}
.ui-selectmenu-menu {
padding: 0;
margin: 0;
position: absolute;
top: 0;
left: 0;
display: none;
}
.ui-selectmenu-menu .ui-menu {
overflow: auto;
overflow-x: hidden;
padding-bottom: 1px;
}
.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
font-size: 1em;
font-weight: bold;
line-height: 1.5;
padding: 2px 0.4em;
margin: 0.5em 0 0 0;
height: auto;
border: 0;
}
.ui-selectmenu-open {
display: block;
}
.ui-selectmenu-text {
display: block;
margin-right: 20px;
overflow: hidden;
text-overflow: ellipsis;
}
.ui-selectmenu-button.ui-button {
text-align: left;
white-space: nowrap;
width: 14em;
}
.ui-selectmenu-icon.ui-icon {
float: right;
margin-top: 0;
}
.ui-slider {
position: relative;
text-align: left;
}
.ui-slider .ui-slider-handle {
position: absolute;
z-index: 2;
width: 1.2em;
height: 1.2em;
cursor: pointer;
-ms-touch-action: none;
touch-action: none;
}
.ui-slider .ui-slider-range {
position: absolute;
z-index: 1;
font-size: .7em;
display: block;
border: 0;
background-position: 0 0;
}
/* support: IE8 - See #6727 */
.ui-slider.ui-state-disabled .ui-slider-handle,
.ui-slider.ui-state-disabled .ui-slider-range {
filter: inherit;
}
.ui-slider-horizontal {
height: .8em;
}
.ui-slider-horizontal .ui-slider-handle {
top: -.3em;
margin-left: -.6em;
}
.ui-slider-horizontal .ui-slider-range {
top: 0;
height: 100%;
}
.ui-slider-horizontal .ui-slider-range-min {
left: 0;
}
.ui-slider-horizontal .ui-slider-range-max {
right: 0;
}
.ui-slider-vertical {
width: .8em;
height: 100px;
}
.ui-slider-vertical .ui-slider-handle {
left: -.3em;
margin-left: 0;
margin-bottom: -.6em;
}
.ui-slider-vertical .ui-slider-range {
left: 0;
width: 100%;
}
.ui-slider-vertical .ui-slider-range-min {
bottom: 0;
}
.ui-slider-vertical .ui-slider-range-max {
top: 0;
}
.ui-spinner {
position: relative;
display: inline-block;
overflow: hidden;
padding: 0;
vertical-align: middle;
}
.ui-spinner-input {
border: none;
background: none;
color: inherit;
padding: .222em 0;
margin: .2em 0;
vertical-align: middle;
margin-left: .4em;
margin-right: 2em;
}
.ui-spinner-button {
width: 1.6em;
height: 50%;
font-size: .5em;
padding: 0;
margin: 0;
text-align: center;
position: absolute;
cursor: default;
display: block;
overflow: hidden;
right: 0;
}
/* more specificity required here to override default borders */
.ui-spinner a.ui-spinner-button {
border-top-style: none;
border-bottom-style: none;
border-right-style: none;
}
.ui-spinner-up {
top: 0;
}
.ui-spinner-down {
bottom: 0;
}
.ui-tabs {
position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
padding: .2em;
}
.ui-tabs .ui-tabs-nav {
margin: 0;
padding: .2em .2em 0;
}
.ui-tabs .ui-tabs-nav li {
list-style: none;
float: left;
position: relative;
top: 0;
margin: 1px .2em 0 0;
border-bottom-width: 0;
padding: 0;
white-space: nowrap;
}
.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
float: left;
padding: .5em 1em;
text-decoration: none;
}
.ui-tabs .ui-tabs-nav li.ui-tabs-active {
margin-bottom: -1px;
padding-bottom: 1px;
}
.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,
.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,
.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
cursor: text;
}
.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {
cursor: pointer;
}
.ui-tabs .ui-tabs-panel {
display: block;
border-width: 0;
padding: 1em 1.4em;
background: none;
}
.ui-tooltip {
padding: 8px;
position: absolute;
z-index: 9999;
max-width: 300px;
}
body .ui-tooltip {
border-width: 2px;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,446 @@
/*!
* jQuery UI CSS Framework 1.13.3
* https://jqueryui.com
*
* Copyright OpenJS Foundation and other contributors
* Released under the MIT license.
* https://jquery.org/license
*
* https://api.jqueryui.com/category/theming/
*
* To view and modify this theme, visit https://jqueryui.com/themeroller/?ffDefault=Arial%2CHelvetica%2Csans-serif&fsDefault=1em&fwDefault=normal&cornerRadius=3px&bgColorHeader=e9e9e9&bgTextureHeader=flat&borderColorHeader=dddddd&fcHeader=333333&iconColorHeader=444444&bgColorContent=ffffff&bgTextureContent=flat&borderColorContent=dddddd&fcContent=333333&iconColorContent=444444&bgColorDefault=f6f6f6&bgTextureDefault=flat&borderColorDefault=c5c5c5&fcDefault=454545&iconColorDefault=777777&bgColorHover=ededed&bgTextureHover=flat&borderColorHover=cccccc&fcHover=2b2b2b&iconColorHover=555555&bgColorActive=007fff&bgTextureActive=flat&borderColorActive=003eff&fcActive=ffffff&iconColorActive=ffffff&bgColorHighlight=fffa90&bgTextureHighlight=flat&borderColorHighlight=dad55e&fcHighlight=777620&iconColorHighlight=777620&bgColorError=fddfdf&bgTextureError=flat&borderColorError=f1a899&fcError=5f3f3f&iconColorError=cc0000&bgColorOverlay=aaaaaa&bgTextureOverlay=flat&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=666666&bgTextureShadow=flat&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=5px&offsetTopShadow=0px&offsetLeftShadow=0px&cornerRadiusShadow=8px
*/
/* Component containers
----------------------------------*/
.ui-widget {
font-family: Arial,Helvetica,sans-serif;
font-size: 1em;
}
.ui-widget .ui-widget {
font-size: 1em;
}
.ui-widget input,
.ui-widget select,
.ui-widget textarea,
.ui-widget button {
font-family: Arial,Helvetica,sans-serif;
font-size: 1em;
}
.ui-widget.ui-widget-content {
border: 1px solid #c5c5c5;
}
.ui-widget-content {
border: 1px solid #dddddd;
background: #ffffff;
color: #333333;
}
.ui-widget-content a {
color: #333333;
}
.ui-widget-header {
border: 1px solid #dddddd;
background: #e9e9e9;
color: #333333;
font-weight: bold;
}
.ui-widget-header a {
color: #333333;
}
/* Interaction states
----------------------------------*/
.ui-state-default,
.ui-widget-content .ui-state-default,
.ui-widget-header .ui-state-default,
.ui-button,
/* We use html here because we need a greater specificity to make sure disabled
works properly when clicked or hovered */
html .ui-button.ui-state-disabled:hover,
html .ui-button.ui-state-disabled:active {
border: 1px solid #c5c5c5;
background: #f6f6f6;
font-weight: normal;
color: #454545;
}
.ui-state-default a,
.ui-state-default a:link,
.ui-state-default a:visited,
a.ui-button,
a:link.ui-button,
a:visited.ui-button,
.ui-button {
color: #454545;
text-decoration: none;
}
.ui-state-hover,
.ui-widget-content .ui-state-hover,
.ui-widget-header .ui-state-hover,
.ui-state-focus,
.ui-widget-content .ui-state-focus,
.ui-widget-header .ui-state-focus,
.ui-button:hover,
.ui-button:focus {
border: 1px solid #cccccc;
background: #ededed;
font-weight: normal;
color: #2b2b2b;
}
.ui-state-hover a,
.ui-state-hover a:hover,
.ui-state-hover a:link,
.ui-state-hover a:visited,
.ui-state-focus a,
.ui-state-focus a:hover,
.ui-state-focus a:link,
.ui-state-focus a:visited,
a.ui-button:hover,
a.ui-button:focus {
color: #2b2b2b;
text-decoration: none;
}
.ui-visual-focus {
box-shadow: 0 0 3px 1px rgb(94, 158, 214);
}
.ui-state-active,
.ui-widget-content .ui-state-active,
.ui-widget-header .ui-state-active,
a.ui-button:active,
.ui-button:active,
.ui-button.ui-state-active:hover {
border: 1px solid #003eff;
background: #007fff;
font-weight: normal;
color: #ffffff;
}
.ui-icon-background,
.ui-state-active .ui-icon-background {
border: #003eff;
background-color: #ffffff;
}
.ui-state-active a,
.ui-state-active a:link,
.ui-state-active a:visited {
color: #ffffff;
text-decoration: none;
}
/* Interaction Cues
----------------------------------*/
.ui-state-highlight,
.ui-widget-content .ui-state-highlight,
.ui-widget-header .ui-state-highlight {
border: 1px solid #dad55e;
background: #fffa90;
color: #777620;
}
.ui-state-checked {
border: 1px solid #dad55e;
background: #fffa90;
}
.ui-state-highlight a,
.ui-widget-content .ui-state-highlight a,
.ui-widget-header .ui-state-highlight a {
color: #777620;
}
.ui-state-error,
.ui-widget-content .ui-state-error,
.ui-widget-header .ui-state-error {
border: 1px solid #f1a899;
background: #fddfdf;
color: #5f3f3f;
}
.ui-state-error a,
.ui-widget-content .ui-state-error a,
.ui-widget-header .ui-state-error a {
color: #5f3f3f;
}
.ui-state-error-text,
.ui-widget-content .ui-state-error-text,
.ui-widget-header .ui-state-error-text {
color: #5f3f3f;
}
.ui-priority-primary,
.ui-widget-content .ui-priority-primary,
.ui-widget-header .ui-priority-primary {
font-weight: bold;
}
.ui-priority-secondary,
.ui-widget-content .ui-priority-secondary,
.ui-widget-header .ui-priority-secondary {
opacity: .7;
-ms-filter: "alpha(opacity=70)"; /* support: IE8 */
font-weight: normal;
}
.ui-state-disabled,
.ui-widget-content .ui-state-disabled,
.ui-widget-header .ui-state-disabled {
opacity: .35;
-ms-filter: "alpha(opacity=35)"; /* support: IE8 */
background-image: none;
}
.ui-state-disabled .ui-icon {
-ms-filter: "alpha(opacity=35)"; /* support: IE8 - See #6059 */
}
/* Icons
----------------------------------*/
/* states and images */
.ui-icon {
width: 16px;
height: 16px;
}
.ui-icon,
.ui-widget-content .ui-icon {
background-image: url("images/ui-icons_444444_256x240.png");
}
.ui-widget-header .ui-icon {
background-image: url("images/ui-icons_444444_256x240.png");
}
.ui-state-hover .ui-icon,
.ui-state-focus .ui-icon,
.ui-button:hover .ui-icon,
.ui-button:focus .ui-icon {
background-image: url("images/ui-icons_555555_256x240.png");
}
.ui-state-active .ui-icon,
.ui-button:active .ui-icon {
background-image: url("images/ui-icons_ffffff_256x240.png");
}
.ui-state-highlight .ui-icon,
.ui-button .ui-state-highlight.ui-icon {
background-image: url("images/ui-icons_777620_256x240.png");
}
.ui-state-error .ui-icon,
.ui-state-error-text .ui-icon {
background-image: url("images/ui-icons_cc0000_256x240.png");
}
.ui-button .ui-icon {
background-image: url("images/ui-icons_777777_256x240.png");
}
/* positioning */
/* Three classes needed to override `.ui-button:hover .ui-icon` */
.ui-icon-blank.ui-icon-blank.ui-icon-blank {
background-image: none;
}
.ui-icon-caret-1-n { background-position: 0 0; }
.ui-icon-caret-1-ne { background-position: -16px 0; }
.ui-icon-caret-1-e { background-position: -32px 0; }
.ui-icon-caret-1-se { background-position: -48px 0; }
.ui-icon-caret-1-s { background-position: -65px 0; }
.ui-icon-caret-1-sw { background-position: -80px 0; }
.ui-icon-caret-1-w { background-position: -96px 0; }
.ui-icon-caret-1-nw { background-position: -112px 0; }
.ui-icon-caret-2-n-s { background-position: -128px 0; }
.ui-icon-caret-2-e-w { background-position: -144px 0; }
.ui-icon-triangle-1-n { background-position: 0 -16px; }
.ui-icon-triangle-1-ne { background-position: -16px -16px; }
.ui-icon-triangle-1-e { background-position: -32px -16px; }
.ui-icon-triangle-1-se { background-position: -48px -16px; }
.ui-icon-triangle-1-s { background-position: -65px -16px; }
.ui-icon-triangle-1-sw { background-position: -80px -16px; }
.ui-icon-triangle-1-w { background-position: -96px -16px; }
.ui-icon-triangle-1-nw { background-position: -112px -16px; }
.ui-icon-triangle-2-n-s { background-position: -128px -16px; }
.ui-icon-triangle-2-e-w { background-position: -144px -16px; }
.ui-icon-arrow-1-n { background-position: 0 -32px; }
.ui-icon-arrow-1-ne { background-position: -16px -32px; }
.ui-icon-arrow-1-e { background-position: -32px -32px; }
.ui-icon-arrow-1-se { background-position: -48px -32px; }
.ui-icon-arrow-1-s { background-position: -65px -32px; }
.ui-icon-arrow-1-sw { background-position: -80px -32px; }
.ui-icon-arrow-1-w { background-position: -96px -32px; }
.ui-icon-arrow-1-nw { background-position: -112px -32px; }
.ui-icon-arrow-2-n-s { background-position: -128px -32px; }
.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; }
.ui-icon-arrow-2-e-w { background-position: -160px -32px; }
.ui-icon-arrow-2-se-nw { background-position: -176px -32px; }
.ui-icon-arrowstop-1-n { background-position: -192px -32px; }
.ui-icon-arrowstop-1-e { background-position: -208px -32px; }
.ui-icon-arrowstop-1-s { background-position: -224px -32px; }
.ui-icon-arrowstop-1-w { background-position: -240px -32px; }
.ui-icon-arrowthick-1-n { background-position: 1px -48px; }
.ui-icon-arrowthick-1-ne { background-position: -16px -48px; }
.ui-icon-arrowthick-1-e { background-position: -32px -48px; }
.ui-icon-arrowthick-1-se { background-position: -48px -48px; }
.ui-icon-arrowthick-1-s { background-position: -64px -48px; }
.ui-icon-arrowthick-1-sw { background-position: -80px -48px; }
.ui-icon-arrowthick-1-w { background-position: -96px -48px; }
.ui-icon-arrowthick-1-nw { background-position: -112px -48px; }
.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; }
.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; }
.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; }
.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; }
.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; }
.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; }
.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; }
.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; }
.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; }
.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; }
.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; }
.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; }
.ui-icon-arrowreturn-1-w { background-position: -64px -64px; }
.ui-icon-arrowreturn-1-n { background-position: -80px -64px; }
.ui-icon-arrowreturn-1-e { background-position: -96px -64px; }
.ui-icon-arrowreturn-1-s { background-position: -112px -64px; }
.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; }
.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; }
.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; }
.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; }
.ui-icon-arrow-4 { background-position: 0 -80px; }
.ui-icon-arrow-4-diag { background-position: -16px -80px; }
.ui-icon-extlink { background-position: -32px -80px; }
.ui-icon-newwin { background-position: -48px -80px; }
.ui-icon-refresh { background-position: -64px -80px; }
.ui-icon-shuffle { background-position: -80px -80px; }
.ui-icon-transfer-e-w { background-position: -96px -80px; }
.ui-icon-transferthick-e-w { background-position: -112px -80px; }
.ui-icon-folder-collapsed { background-position: 0 -96px; }
.ui-icon-folder-open { background-position: -16px -96px; }
.ui-icon-document { background-position: -32px -96px; }
.ui-icon-document-b { background-position: -48px -96px; }
.ui-icon-note { background-position: -64px -96px; }
.ui-icon-mail-closed { background-position: -80px -96px; }
.ui-icon-mail-open { background-position: -96px -96px; }
.ui-icon-suitcase { background-position: -112px -96px; }
.ui-icon-comment { background-position: -128px -96px; }
.ui-icon-person { background-position: -144px -96px; }
.ui-icon-print { background-position: -160px -96px; }
.ui-icon-trash { background-position: -176px -96px; }
.ui-icon-locked { background-position: -192px -96px; }
.ui-icon-unlocked { background-position: -208px -96px; }
.ui-icon-bookmark { background-position: -224px -96px; }
.ui-icon-tag { background-position: -240px -96px; }
.ui-icon-home { background-position: 0 -112px; }
.ui-icon-flag { background-position: -16px -112px; }
.ui-icon-calendar { background-position: -32px -112px; }
.ui-icon-cart { background-position: -48px -112px; }
.ui-icon-pencil { background-position: -64px -112px; }
.ui-icon-clock { background-position: -80px -112px; }
.ui-icon-disk { background-position: -96px -112px; }
.ui-icon-calculator { background-position: -112px -112px; }
.ui-icon-zoomin { background-position: -128px -112px; }
.ui-icon-zoomout { background-position: -144px -112px; }
.ui-icon-search { background-position: -160px -112px; }
.ui-icon-wrench { background-position: -176px -112px; }
.ui-icon-gear { background-position: -192px -112px; }
.ui-icon-heart { background-position: -208px -112px; }
.ui-icon-star { background-position: -224px -112px; }
.ui-icon-link { background-position: -240px -112px; }
.ui-icon-cancel { background-position: 0 -128px; }
.ui-icon-plus { background-position: -16px -128px; }
.ui-icon-plusthick { background-position: -32px -128px; }
.ui-icon-minus { background-position: -48px -128px; }
.ui-icon-minusthick { background-position: -64px -128px; }
.ui-icon-close { background-position: -80px -128px; }
.ui-icon-closethick { background-position: -96px -128px; }
.ui-icon-key { background-position: -112px -128px; }
.ui-icon-lightbulb { background-position: -128px -128px; }
.ui-icon-scissors { background-position: -144px -128px; }
.ui-icon-clipboard { background-position: -160px -128px; }
.ui-icon-copy { background-position: -176px -128px; }
.ui-icon-contact { background-position: -192px -128px; }
.ui-icon-image { background-position: -208px -128px; }
.ui-icon-video { background-position: -224px -128px; }
.ui-icon-script { background-position: -240px -128px; }
.ui-icon-alert { background-position: 0 -144px; }
.ui-icon-info { background-position: -16px -144px; }
.ui-icon-notice { background-position: -32px -144px; }
.ui-icon-help { background-position: -48px -144px; }
.ui-icon-check { background-position: -64px -144px; }
.ui-icon-bullet { background-position: -80px -144px; }
.ui-icon-radio-on { background-position: -96px -144px; }
.ui-icon-radio-off { background-position: -112px -144px; }
.ui-icon-pin-w { background-position: -128px -144px; }
.ui-icon-pin-s { background-position: -144px -144px; }
.ui-icon-play { background-position: 0 -160px; }
.ui-icon-pause { background-position: -16px -160px; }
.ui-icon-seek-next { background-position: -32px -160px; }
.ui-icon-seek-prev { background-position: -48px -160px; }
.ui-icon-seek-end { background-position: -64px -160px; }
.ui-icon-seek-start { background-position: -80px -160px; }
/* ui-icon-seek-first is deprecated, use ui-icon-seek-start instead */
.ui-icon-seek-first { background-position: -80px -160px; }
.ui-icon-stop { background-position: -96px -160px; }
.ui-icon-eject { background-position: -112px -160px; }
.ui-icon-volume-off { background-position: -128px -160px; }
.ui-icon-volume-on { background-position: -144px -160px; }
.ui-icon-power { background-position: 0 -176px; }
.ui-icon-signal-diag { background-position: -16px -176px; }
.ui-icon-signal { background-position: -32px -176px; }
.ui-icon-battery-0 { background-position: -48px -176px; }
.ui-icon-battery-1 { background-position: -64px -176px; }
.ui-icon-battery-2 { background-position: -80px -176px; }
.ui-icon-battery-3 { background-position: -96px -176px; }
.ui-icon-circle-plus { background-position: 0 -192px; }
.ui-icon-circle-minus { background-position: -16px -192px; }
.ui-icon-circle-close { background-position: -32px -192px; }
.ui-icon-circle-triangle-e { background-position: -48px -192px; }
.ui-icon-circle-triangle-s { background-position: -64px -192px; }
.ui-icon-circle-triangle-w { background-position: -80px -192px; }
.ui-icon-circle-triangle-n { background-position: -96px -192px; }
.ui-icon-circle-arrow-e { background-position: -112px -192px; }
.ui-icon-circle-arrow-s { background-position: -128px -192px; }
.ui-icon-circle-arrow-w { background-position: -144px -192px; }
.ui-icon-circle-arrow-n { background-position: -160px -192px; }
.ui-icon-circle-zoomin { background-position: -176px -192px; }
.ui-icon-circle-zoomout { background-position: -192px -192px; }
.ui-icon-circle-check { background-position: -208px -192px; }
.ui-icon-circlesmall-plus { background-position: 0 -208px; }
.ui-icon-circlesmall-minus { background-position: -16px -208px; }
.ui-icon-circlesmall-close { background-position: -32px -208px; }
.ui-icon-squaresmall-plus { background-position: -48px -208px; }
.ui-icon-squaresmall-minus { background-position: -64px -208px; }
.ui-icon-squaresmall-close { background-position: -80px -208px; }
.ui-icon-grip-dotted-vertical { background-position: 0 -224px; }
.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; }
.ui-icon-grip-solid-vertical { background-position: -32px -224px; }
.ui-icon-grip-solid-horizontal { background-position: -48px -224px; }
.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; }
.ui-icon-grip-diagonal-se { background-position: -80px -224px; }
/* Misc visuals
----------------------------------*/
/* Corner radius */
.ui-corner-all,
.ui-corner-top,
.ui-corner-left,
.ui-corner-tl {
border-top-left-radius: 3px;
}
.ui-corner-all,
.ui-corner-top,
.ui-corner-right,
.ui-corner-tr {
border-top-right-radius: 3px;
}
.ui-corner-all,
.ui-corner-bottom,
.ui-corner-left,
.ui-corner-bl {
border-bottom-left-radius: 3px;
}
.ui-corner-all,
.ui-corner-bottom,
.ui-corner-right,
.ui-corner-br {
border-bottom-right-radius: 3px;
}
/* Overlays */
.ui-widget-overlay {
background: #aaaaaa;
opacity: .3;
-ms-filter: "alpha(opacity=30)"; /* support: IE8 */
}
.ui-widget-shadow {
-webkit-box-shadow: 0px 0px 5px #666666;
box-shadow: 0px 0px 5px #666666;
}

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,3 @@
(function(a,b){if("function"==typeof define&&define.amd)define([],b);else if("undefined"!=typeof exports)b();else{b(),a.FileSaver={exports:{}}.exports}})(this,function(){"use strict";function b(a,b){return"undefined"==typeof b?b={autoBom:!1}:"object"!=typeof b&&(console.warn("Deprecated: Expected third argument to be a object"),b={autoBom:!b}),b.autoBom&&/^\s*(?:text\/\S*|application\/xml|\S*\/\S*\+xml)\s*;.*charset\s*=\s*utf-8/i.test(a.type)?new Blob(["\uFEFF",a],{type:a.type}):a}function c(a,b,c){var d=new XMLHttpRequest;d.open("GET",a),d.responseType="blob",d.onload=function(){g(d.response,b,c)},d.onerror=function(){console.error("could not download file")},d.send()}function d(a){var b=new XMLHttpRequest;b.open("HEAD",a,!1);try{b.send()}catch(a){}return 200<=b.status&&299>=b.status}function e(a){try{a.dispatchEvent(new MouseEvent("click"))}catch(c){var b=document.createEvent("MouseEvents");b.initMouseEvent("click",!0,!0,window,0,0,0,80,20,!1,!1,!1,!1,0,null),a.dispatchEvent(b)}}var f="object"==typeof window&&window.window===window?window:"object"==typeof self&&self.self===self?self:"object"==typeof global&&global.global===global?global:void 0,a=f.navigator&&/Macintosh/.test(navigator.userAgent)&&/AppleWebKit/.test(navigator.userAgent)&&!/Safari/.test(navigator.userAgent),g=f.saveAs||("object"!=typeof window||window!==f?function(){}:"download"in HTMLAnchorElement.prototype&&!a?function(b,g,h){var i=f.URL||f.webkitURL,j=document.createElement("a");g=g||b.name||"download",j.download=g,j.rel="noopener","string"==typeof b?(j.href=b,j.origin===location.origin?e(j):d(j.href)?c(b,g,h):e(j,j.target="_blank")):(j.href=i.createObjectURL(b),setTimeout(function(){i.revokeObjectURL(j.href)},4E4),setTimeout(function(){e(j)},0))}:"msSaveOrOpenBlob"in navigator?function(f,g,h){if(g=g||f.name||"download","string"!=typeof f)navigator.msSaveOrOpenBlob(b(f,h),g);else if(d(f))c(f,g,h);else{var i=document.createElement("a");i.href=f,i.target="_blank",setTimeout(function(){e(i)})}}:function(b,d,e,g){if(g=g||open("","_blank"),g&&(g.document.title=g.document.body.innerText="downloading..."),"string"==typeof b)return c(b,d,e);var h="application/octet-stream"===b.type,i=/constructor/i.test(f.HTMLElement)||f.safari,j=/CriOS\/[\d]+/.test(navigator.userAgent);if((j||h&&i||a)&&"undefined"!=typeof FileReader){var k=new FileReader;k.onloadend=function(){var a=k.result;a=j?a:a.replace(/^data:[^;]*;/,"data:attachment/file;"),g?g.location.href=a:location=a,g=null},k.readAsDataURL(b)}else{var l=f.URL||f.webkitURL,m=l.createObjectURL(b);g?g.location=m:location.href=m,g=null,setTimeout(function(){l.revokeObjectURL(m)},4E4)}});f.saveAs=g.saveAs=g,"undefined"!=typeof module&&(module.exports=g)});
//# sourceMappingURL=FileSaver.min.js.map

Binary file not shown.

After

Width:  |  Height:  |  Size: 230 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 210 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 771 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 201 B

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,886 @@
/*!
* jQuery UI CSS Framework 1.13.3
* https://jqueryui.com
*
* Copyright OpenJS Foundation and other contributors
* Released under the MIT license.
* https://jquery.org/license
*
* https://api.jqueryui.com/category/theming/
*/
.ui-draggable-handle {
-ms-touch-action: none;
touch-action: none;
}
/* Layout helpers
----------------------------------*/
.ui-helper-hidden {
display: none;
}
.ui-helper-hidden-accessible {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
.ui-helper-reset {
margin: 0;
padding: 0;
border: 0;
outline: 0;
line-height: 1.3;
text-decoration: none;
font-size: 100%;
list-style: none;
}
.ui-helper-clearfix:before,
.ui-helper-clearfix:after {
content: "";
display: table;
border-collapse: collapse;
}
.ui-helper-clearfix:after {
clear: both;
}
.ui-helper-zfix {
width: 100%;
height: 100%;
top: 0;
left: 0;
position: absolute;
opacity: 0;
-ms-filter: "alpha(opacity=0)"; /* support: IE8 */
}
.ui-front {
z-index: 100;
}
/* Interaction Cues
----------------------------------*/
.ui-state-disabled {
cursor: default !important;
pointer-events: none;
}
/* Icons
----------------------------------*/
.ui-icon {
display: inline-block;
vertical-align: middle;
margin-top: -.25em;
position: relative;
text-indent: -99999px;
overflow: hidden;
background-repeat: no-repeat;
}
.ui-widget-icon-block {
left: 50%;
margin-left: -8px;
display: block;
}
/* Misc visuals
----------------------------------*/
/* Overlays */
.ui-widget-overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.ui-resizable {
position: relative;
}
.ui-resizable-handle {
position: absolute;
font-size: 0.1px;
display: block;
-ms-touch-action: none;
touch-action: none;
}
.ui-resizable-disabled .ui-resizable-handle,
.ui-resizable-autohide .ui-resizable-handle {
display: none;
}
.ui-resizable-n {
cursor: n-resize;
height: 7px;
width: 100%;
top: -5px;
left: 0;
}
.ui-resizable-s {
cursor: s-resize;
height: 7px;
width: 100%;
bottom: -5px;
left: 0;
}
.ui-resizable-e {
cursor: e-resize;
width: 7px;
right: -5px;
top: 0;
height: 100%;
}
.ui-resizable-w {
cursor: w-resize;
width: 7px;
left: -5px;
top: 0;
height: 100%;
}
.ui-resizable-se {
cursor: se-resize;
width: 12px;
height: 12px;
right: 1px;
bottom: 1px;
}
.ui-resizable-sw {
cursor: sw-resize;
width: 9px;
height: 9px;
left: -5px;
bottom: -5px;
}
.ui-resizable-nw {
cursor: nw-resize;
width: 9px;
height: 9px;
left: -5px;
top: -5px;
}
.ui-resizable-ne {
cursor: ne-resize;
width: 9px;
height: 9px;
right: -5px;
top: -5px;
}
.ui-selectable {
-ms-touch-action: none;
touch-action: none;
}
.ui-selectable-helper {
position: absolute;
z-index: 100;
border: 1px dotted black;
}
.ui-sortable-handle {
-ms-touch-action: none;
touch-action: none;
}
.ui-accordion .ui-accordion-header {
display: block;
cursor: pointer;
position: relative;
margin: 2px 0 0 0;
padding: .5em .5em .5em .7em;
font-size: 100%;
}
.ui-accordion .ui-accordion-content {
padding: 1em 2.2em;
border-top: 0;
overflow: auto;
}
.ui-autocomplete {
position: absolute;
top: 0;
left: 0;
cursor: default;
}
.ui-menu {
list-style: none;
padding: 0;
margin: 0;
display: block;
outline: 0;
}
.ui-menu .ui-menu {
position: absolute;
}
.ui-menu .ui-menu-item {
margin: 0;
cursor: pointer;
/* support: IE10, see #8844 */
list-style-image: url("data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7");
}
.ui-menu .ui-menu-item-wrapper {
position: relative;
padding: 3px 1em 3px .4em;
}
.ui-menu .ui-menu-divider {
margin: 5px 0;
height: 0;
font-size: 0;
line-height: 0;
border-width: 1px 0 0 0;
}
.ui-menu .ui-state-focus,
.ui-menu .ui-state-active {
margin: -1px;
}
/* icon support */
.ui-menu-icons {
position: relative;
}
.ui-menu-icons .ui-menu-item-wrapper {
padding-left: 2em;
}
/* left-aligned */
.ui-menu .ui-icon {
position: absolute;
top: 0;
bottom: 0;
left: .2em;
margin: auto 0;
}
/* right-aligned */
.ui-menu .ui-menu-icon {
left: auto;
right: 0;
}
.ui-button {
padding: .4em 1em;
display: inline-block;
position: relative;
line-height: normal;
margin-right: .1em;
cursor: pointer;
vertical-align: middle;
text-align: center;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
/* Support: IE <= 11 */
overflow: visible;
}
.ui-button,
.ui-button:link,
.ui-button:visited,
.ui-button:hover,
.ui-button:active {
text-decoration: none;
}
/* to make room for the icon, a width needs to be set here */
.ui-button-icon-only {
width: 2em;
box-sizing: border-box;
text-indent: -9999px;
white-space: nowrap;
}
/* no icon support for input elements */
input.ui-button.ui-button-icon-only {
text-indent: 0;
}
/* button icon element(s) */
.ui-button-icon-only .ui-icon {
position: absolute;
top: 50%;
left: 50%;
margin-top: -8px;
margin-left: -8px;
}
.ui-button.ui-icon-notext .ui-icon {
padding: 0;
width: 2.1em;
height: 2.1em;
text-indent: -9999px;
white-space: nowrap;
}
input.ui-button.ui-icon-notext .ui-icon {
width: auto;
height: auto;
text-indent: 0;
white-space: normal;
padding: .4em 1em;
}
/* workarounds */
/* Support: Firefox 5 - 40 */
input.ui-button::-moz-focus-inner,
button.ui-button::-moz-focus-inner {
border: 0;
padding: 0;
}
.ui-controlgroup {
vertical-align: middle;
display: inline-block;
}
.ui-controlgroup > .ui-controlgroup-item {
float: left;
margin-left: 0;
margin-right: 0;
}
.ui-controlgroup > .ui-controlgroup-item:focus,
.ui-controlgroup > .ui-controlgroup-item.ui-visual-focus {
z-index: 9999;
}
.ui-controlgroup-vertical > .ui-controlgroup-item {
display: block;
float: none;
width: 100%;
margin-top: 0;
margin-bottom: 0;
text-align: left;
}
.ui-controlgroup-vertical .ui-controlgroup-item {
box-sizing: border-box;
}
.ui-controlgroup .ui-controlgroup-label {
padding: .4em 1em;
}
.ui-controlgroup .ui-controlgroup-label span {
font-size: 80%;
}
.ui-controlgroup-horizontal .ui-controlgroup-label + .ui-controlgroup-item {
border-left: none;
}
.ui-controlgroup-vertical .ui-controlgroup-label + .ui-controlgroup-item {
border-top: none;
}
.ui-controlgroup-horizontal .ui-controlgroup-label.ui-widget-content {
border-right: none;
}
.ui-controlgroup-vertical .ui-controlgroup-label.ui-widget-content {
border-bottom: none;
}
/* Spinner specific style fixes */
.ui-controlgroup-vertical .ui-spinner-input {
/* Support: IE8 only, Android < 4.4 only */
width: 75%;
width: calc( 100% - 2.4em );
}
.ui-controlgroup-vertical .ui-spinner .ui-spinner-up {
border-top-style: solid;
}
.ui-checkboxradio-label .ui-icon-background {
box-shadow: inset 1px 1px 1px #ccc;
border-radius: .12em;
border: none;
}
.ui-checkboxradio-radio-label .ui-icon-background {
width: 16px;
height: 16px;
border-radius: 1em;
overflow: visible;
border: none;
}
.ui-checkboxradio-radio-label.ui-checkboxradio-checked .ui-icon,
.ui-checkboxradio-radio-label.ui-checkboxradio-checked:hover .ui-icon {
background-image: none;
width: 8px;
height: 8px;
border-width: 4px;
border-style: solid;
}
.ui-checkboxradio-disabled {
pointer-events: none;
}
.ui-datepicker {
width: 17em;
padding: .2em .2em 0;
display: none;
}
.ui-datepicker .ui-datepicker-header {
position: relative;
padding: .2em 0;
}
.ui-datepicker .ui-datepicker-prev,
.ui-datepicker .ui-datepicker-next {
position: absolute;
top: 2px;
width: 1.8em;
height: 1.8em;
}
.ui-datepicker .ui-datepicker-prev-hover,
.ui-datepicker .ui-datepicker-next-hover {
top: 1px;
}
.ui-datepicker .ui-datepicker-prev {
left: 2px;
}
.ui-datepicker .ui-datepicker-next {
right: 2px;
}
.ui-datepicker .ui-datepicker-prev-hover {
left: 1px;
}
.ui-datepicker .ui-datepicker-next-hover {
right: 1px;
}
.ui-datepicker .ui-datepicker-prev span,
.ui-datepicker .ui-datepicker-next span {
display: block;
position: absolute;
left: 50%;
margin-left: -8px;
top: 50%;
margin-top: -8px;
}
.ui-datepicker .ui-datepicker-title {
margin: 0 2.3em;
line-height: 1.8em;
text-align: center;
}
.ui-datepicker .ui-datepicker-title select {
font-size: 1em;
margin: 1px 0;
}
.ui-datepicker select.ui-datepicker-month,
.ui-datepicker select.ui-datepicker-year {
width: 45%;
}
.ui-datepicker table {
width: 100%;
font-size: .9em;
border-collapse: collapse;
margin: 0 0 .4em;
}
.ui-datepicker th {
padding: .7em .3em;
text-align: center;
font-weight: bold;
border: 0;
}
.ui-datepicker td {
border: 0;
padding: 1px;
}
.ui-datepicker td span,
.ui-datepicker td a {
display: block;
padding: .2em;
text-align: right;
text-decoration: none;
}
.ui-datepicker .ui-datepicker-buttonpane {
background-image: none;
margin: .7em 0 0 0;
padding: 0 .2em;
border-left: 0;
border-right: 0;
border-bottom: 0;
}
.ui-datepicker .ui-datepicker-buttonpane button {
float: right;
margin: .5em .2em .4em;
cursor: pointer;
padding: .2em .6em .3em .6em;
width: auto;
overflow: visible;
}
.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current {
float: left;
}
/* with multiple calendars */
.ui-datepicker.ui-datepicker-multi {
width: auto;
}
.ui-datepicker-multi .ui-datepicker-group {
float: left;
}
.ui-datepicker-multi .ui-datepicker-group table {
width: 95%;
margin: 0 auto .4em;
}
.ui-datepicker-multi-2 .ui-datepicker-group {
width: 50%;
}
.ui-datepicker-multi-3 .ui-datepicker-group {
width: 33.3%;
}
.ui-datepicker-multi-4 .ui-datepicker-group {
width: 25%;
}
.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header,
.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header {
border-left-width: 0;
}
.ui-datepicker-multi .ui-datepicker-buttonpane {
clear: left;
}
.ui-datepicker-row-break {
clear: both;
width: 100%;
font-size: 0;
}
/* RTL support */
.ui-datepicker-rtl {
direction: rtl;
}
.ui-datepicker-rtl .ui-datepicker-prev {
right: 2px;
left: auto;
}
.ui-datepicker-rtl .ui-datepicker-next {
left: 2px;
right: auto;
}
.ui-datepicker-rtl .ui-datepicker-prev:hover {
right: 1px;
left: auto;
}
.ui-datepicker-rtl .ui-datepicker-next:hover {
left: 1px;
right: auto;
}
.ui-datepicker-rtl .ui-datepicker-buttonpane {
clear: right;
}
.ui-datepicker-rtl .ui-datepicker-buttonpane button {
float: left;
}
.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current,
.ui-datepicker-rtl .ui-datepicker-group {
float: right;
}
.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header,
.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header {
border-right-width: 0;
border-left-width: 1px;
}
/* Icons */
.ui-datepicker .ui-icon {
display: block;
text-indent: -99999px;
overflow: hidden;
background-repeat: no-repeat;
left: .5em;
top: .3em;
}
.ui-dialog {
position: absolute;
top: 0;
left: 0;
padding: .2em;
outline: 0;
}
.ui-dialog .ui-dialog-titlebar {
padding: .4em 1em;
position: relative;
}
.ui-dialog .ui-dialog-title {
float: left;
margin: .1em 0;
white-space: nowrap;
width: 90%;
overflow: hidden;
text-overflow: ellipsis;
}
.ui-dialog .ui-dialog-titlebar-close {
position: absolute;
right: .3em;
top: 50%;
width: 20px;
margin: -10px 0 0 0;
padding: 1px;
height: 20px;
}
.ui-dialog .ui-dialog-content {
position: relative;
border: 0;
padding: .5em 1em;
background: none;
overflow: auto;
}
.ui-dialog .ui-dialog-buttonpane {
text-align: left;
border-width: 1px 0 0 0;
background-image: none;
margin-top: .5em;
padding: .3em 1em .5em .4em;
}
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
float: right;
}
.ui-dialog .ui-dialog-buttonpane button {
margin: .5em .4em .5em 0;
cursor: pointer;
}
.ui-dialog .ui-resizable-n {
height: 2px;
top: 0;
}
.ui-dialog .ui-resizable-e {
width: 2px;
right: 0;
}
.ui-dialog .ui-resizable-s {
height: 2px;
bottom: 0;
}
.ui-dialog .ui-resizable-w {
width: 2px;
left: 0;
}
.ui-dialog .ui-resizable-se,
.ui-dialog .ui-resizable-sw,
.ui-dialog .ui-resizable-ne,
.ui-dialog .ui-resizable-nw {
width: 7px;
height: 7px;
}
.ui-dialog .ui-resizable-se {
right: 0;
bottom: 0;
}
.ui-dialog .ui-resizable-sw {
left: 0;
bottom: 0;
}
.ui-dialog .ui-resizable-ne {
right: 0;
top: 0;
}
.ui-dialog .ui-resizable-nw {
left: 0;
top: 0;
}
.ui-draggable .ui-dialog-titlebar {
cursor: move;
}
.ui-progressbar {
height: 2em;
text-align: left;
overflow: hidden;
}
.ui-progressbar .ui-progressbar-value {
margin: -1px;
height: 100%;
}
.ui-progressbar .ui-progressbar-overlay {
background: url("data:image/gif;base64,R0lGODlhKAAoAIABAAAAAP///yH/C05FVFNDQVBFMi4wAwEAAAAh+QQJAQABACwAAAAAKAAoAAACkYwNqXrdC52DS06a7MFZI+4FHBCKoDeWKXqymPqGqxvJrXZbMx7Ttc+w9XgU2FB3lOyQRWET2IFGiU9m1frDVpxZZc6bfHwv4c1YXP6k1Vdy292Fb6UkuvFtXpvWSzA+HycXJHUXiGYIiMg2R6W459gnWGfHNdjIqDWVqemH2ekpObkpOlppWUqZiqr6edqqWQAAIfkECQEAAQAsAAAAACgAKAAAApSMgZnGfaqcg1E2uuzDmmHUBR8Qil95hiPKqWn3aqtLsS18y7G1SzNeowWBENtQd+T1JktP05nzPTdJZlR6vUxNWWjV+vUWhWNkWFwxl9VpZRedYcflIOLafaa28XdsH/ynlcc1uPVDZxQIR0K25+cICCmoqCe5mGhZOfeYSUh5yJcJyrkZWWpaR8doJ2o4NYq62lAAACH5BAkBAAEALAAAAAAoACgAAAKVDI4Yy22ZnINRNqosw0Bv7i1gyHUkFj7oSaWlu3ovC8GxNso5fluz3qLVhBVeT/Lz7ZTHyxL5dDalQWPVOsQWtRnuwXaFTj9jVVh8pma9JjZ4zYSj5ZOyma7uuolffh+IR5aW97cHuBUXKGKXlKjn+DiHWMcYJah4N0lYCMlJOXipGRr5qdgoSTrqWSq6WFl2ypoaUAAAIfkECQEAAQAsAAAAACgAKAAAApaEb6HLgd/iO7FNWtcFWe+ufODGjRfoiJ2akShbueb0wtI50zm02pbvwfWEMWBQ1zKGlLIhskiEPm9R6vRXxV4ZzWT2yHOGpWMyorblKlNp8HmHEb/lCXjcW7bmtXP8Xt229OVWR1fod2eWqNfHuMjXCPkIGNileOiImVmCOEmoSfn3yXlJWmoHGhqp6ilYuWYpmTqKUgAAIfkECQEAAQAsAAAAACgAKAAAApiEH6kb58biQ3FNWtMFWW3eNVcojuFGfqnZqSebuS06w5V80/X02pKe8zFwP6EFWOT1lDFk8rGERh1TTNOocQ61Hm4Xm2VexUHpzjymViHrFbiELsefVrn6XKfnt2Q9G/+Xdie499XHd2g4h7ioOGhXGJboGAnXSBnoBwKYyfioubZJ2Hn0RuRZaflZOil56Zp6iioKSXpUAAAh+QQJAQABACwAAAAAKAAoAAACkoQRqRvnxuI7kU1a1UU5bd5tnSeOZXhmn5lWK3qNTWvRdQxP8qvaC+/yaYQzXO7BMvaUEmJRd3TsiMAgswmNYrSgZdYrTX6tSHGZO73ezuAw2uxuQ+BbeZfMxsexY35+/Qe4J1inV0g4x3WHuMhIl2jXOKT2Q+VU5fgoSUI52VfZyfkJGkha6jmY+aaYdirq+lQAACH5BAkBAAEALAAAAAAoACgAAAKWBIKpYe0L3YNKToqswUlvznigd4wiR4KhZrKt9Upqip61i9E3vMvxRdHlbEFiEXfk9YARYxOZZD6VQ2pUunBmtRXo1Lf8hMVVcNl8JafV38aM2/Fu5V16Bn63r6xt97j09+MXSFi4BniGFae3hzbH9+hYBzkpuUh5aZmHuanZOZgIuvbGiNeomCnaxxap2upaCZsq+1kAACH5BAkBAAEALAAAAAAoACgAAAKXjI8By5zf4kOxTVrXNVlv1X0d8IGZGKLnNpYtm8Lr9cqVeuOSvfOW79D9aDHizNhDJidFZhNydEahOaDH6nomtJjp1tutKoNWkvA6JqfRVLHU/QUfau9l2x7G54d1fl995xcIGAdXqMfBNadoYrhH+Mg2KBlpVpbluCiXmMnZ2Sh4GBqJ+ckIOqqJ6LmKSllZmsoq6wpQAAAh+QQJAQABACwAAAAAKAAoAAAClYx/oLvoxuJDkU1a1YUZbJ59nSd2ZXhWqbRa2/gF8Gu2DY3iqs7yrq+xBYEkYvFSM8aSSObE+ZgRl1BHFZNr7pRCavZ5BW2142hY3AN/zWtsmf12p9XxxFl2lpLn1rseztfXZjdIWIf2s5dItwjYKBgo9yg5pHgzJXTEeGlZuenpyPmpGQoKOWkYmSpaSnqKileI2FAAACH5BAkBAAEALAAAAAAoACgAAAKVjB+gu+jG4kORTVrVhRlsnn2dJ3ZleFaptFrb+CXmO9OozeL5VfP99HvAWhpiUdcwkpBH3825AwYdU8xTqlLGhtCosArKMpvfa1mMRae9VvWZfeB2XfPkeLmm18lUcBj+p5dnN8jXZ3YIGEhYuOUn45aoCDkp16hl5IjYJvjWKcnoGQpqyPlpOhr3aElaqrq56Bq7VAAAOw==");
height: 100%;
-ms-filter: "alpha(opacity=25)"; /* support: IE8 */
opacity: 0.25;
}
.ui-progressbar-indeterminate .ui-progressbar-value {
background-image: none;
}
.ui-selectmenu-menu {
padding: 0;
margin: 0;
position: absolute;
top: 0;
left: 0;
display: none;
}
.ui-selectmenu-menu .ui-menu {
overflow: auto;
overflow-x: hidden;
padding-bottom: 1px;
}
.ui-selectmenu-menu .ui-menu .ui-selectmenu-optgroup {
font-size: 1em;
font-weight: bold;
line-height: 1.5;
padding: 2px 0.4em;
margin: 0.5em 0 0 0;
height: auto;
border: 0;
}
.ui-selectmenu-open {
display: block;
}
.ui-selectmenu-text {
display: block;
margin-right: 20px;
overflow: hidden;
text-overflow: ellipsis;
}
.ui-selectmenu-button.ui-button {
text-align: left;
white-space: nowrap;
width: 14em;
}
.ui-selectmenu-icon.ui-icon {
float: right;
margin-top: 0;
}
.ui-slider {
position: relative;
text-align: left;
}
.ui-slider .ui-slider-handle {
position: absolute;
z-index: 2;
width: 1.2em;
height: 1.2em;
cursor: pointer;
-ms-touch-action: none;
touch-action: none;
}
.ui-slider .ui-slider-range {
position: absolute;
z-index: 1;
font-size: .7em;
display: block;
border: 0;
background-position: 0 0;
}
/* support: IE8 - See #6727 */
.ui-slider.ui-state-disabled .ui-slider-handle,
.ui-slider.ui-state-disabled .ui-slider-range {
filter: inherit;
}
.ui-slider-horizontal {
height: .8em;
}
.ui-slider-horizontal .ui-slider-handle {
top: -.3em;
margin-left: -.6em;
}
.ui-slider-horizontal .ui-slider-range {
top: 0;
height: 100%;
}
.ui-slider-horizontal .ui-slider-range-min {
left: 0;
}
.ui-slider-horizontal .ui-slider-range-max {
right: 0;
}
.ui-slider-vertical {
width: .8em;
height: 100px;
}
.ui-slider-vertical .ui-slider-handle {
left: -.3em;
margin-left: 0;
margin-bottom: -.6em;
}
.ui-slider-vertical .ui-slider-range {
left: 0;
width: 100%;
}
.ui-slider-vertical .ui-slider-range-min {
bottom: 0;
}
.ui-slider-vertical .ui-slider-range-max {
top: 0;
}
.ui-spinner {
position: relative;
display: inline-block;
overflow: hidden;
padding: 0;
vertical-align: middle;
}
.ui-spinner-input {
border: none;
background: none;
color: inherit;
padding: .222em 0;
margin: .2em 0;
vertical-align: middle;
margin-left: .4em;
margin-right: 2em;
}
.ui-spinner-button {
width: 1.6em;
height: 50%;
font-size: .5em;
padding: 0;
margin: 0;
text-align: center;
position: absolute;
cursor: default;
display: block;
overflow: hidden;
right: 0;
}
/* more specificity required here to override default borders */
.ui-spinner a.ui-spinner-button {
border-top-style: none;
border-bottom-style: none;
border-right-style: none;
}
.ui-spinner-up {
top: 0;
}
.ui-spinner-down {
bottom: 0;
}
.ui-tabs {
position: relative;/* position: relative prevents IE scroll bug (element with position: relative inside container with overflow: auto appear as "fixed") */
padding: .2em;
}
.ui-tabs .ui-tabs-nav {
margin: 0;
padding: .2em .2em 0;
}
.ui-tabs .ui-tabs-nav li {
list-style: none;
float: left;
position: relative;
top: 0;
margin: 1px .2em 0 0;
border-bottom-width: 0;
padding: 0;
white-space: nowrap;
}
.ui-tabs .ui-tabs-nav .ui-tabs-anchor {
float: left;
padding: .5em 1em;
text-decoration: none;
}
.ui-tabs .ui-tabs-nav li.ui-tabs-active {
margin-bottom: -1px;
padding-bottom: 1px;
}
.ui-tabs .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor,
.ui-tabs .ui-tabs-nav li.ui-state-disabled .ui-tabs-anchor,
.ui-tabs .ui-tabs-nav li.ui-tabs-loading .ui-tabs-anchor {
cursor: text;
}
.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-active .ui-tabs-anchor {
cursor: pointer;
}
.ui-tabs .ui-tabs-panel {
display: block;
border-width: 0;
padding: 1em 1.4em;
background: none;
}
.ui-tooltip {
padding: 8px;
position: absolute;
z-index: 9999;
max-width: 300px;
}
body .ui-tooltip {
border-width: 2px;
}

File diff suppressed because one or more lines are too long

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