new
|
|
@ -0,0 +1,5 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Part of Softhealer Technologies.
|
||||||
|
|
||||||
|
from . import controllers
|
||||||
|
from . import models
|
||||||
|
|
@ -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,
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from . import firebase_main
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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")
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -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")
|
||||||
|
|
@ -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)
|
||||||
|
|
@ -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
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:6d1a8d77b6ef765feac2dfde4611cb7533cbfb54e5d42368d1e1c10c162d4d83
|
||||||
|
size 32810
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:a3b0409d9e2fcee2d00a4c0b4f98756d131f75d0dc3ed44feff636423dc2a565
|
||||||
|
size 2167096
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:4787fe7d558850226bdf221a3924323879bbc487e97839e544046821315873bd
|
||||||
|
size 2166932
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:bc24710ffd23fd85c74d4c286e60910e0a90b89214ae091bfb69f987d804f18b
|
||||||
|
size 2167008
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:e4f073de73be01d8686fa92588c8d281f952866bbffae642dceba5add5c6d309
|
||||||
|
size 1003848
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:7e88f115b84e17b47bcf09a82b02116c16566e0c831c4af27648aa33df6f389e
|
||||||
|
size 1972196
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:751e56ff2c429fd06b8abbd25f988d96b274e9f8877562e85c2e38564d4cb8dc
|
||||||
|
size 1972032
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:51803c63042c7cae70cc6121edb95ac422fa06b95ff501d6f2371d8382e60589
|
||||||
|
size 1972108
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:d8df0c389fef55d27b0fa19d3a3033af186edd4c9b4c3a60f65de92eda38958e
|
||||||
|
size 921976
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:4dff44855f6722278ef33cc3ac727e8fc16c726b95b5a44e485e540bf143eeea
|
||||||
|
size 2257312
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:8b4e230263ec8b1bd6e11d0709279ca71244a7570c5b2ec763cb09862c8b23e9
|
||||||
|
size 2257148
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:e64c1d22db9dd5ecfe857984d50c4114e910c7d2f289bfdb9be94a4b4f6dad18
|
||||||
|
size 2257224
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
version https://git-lfs.github.com/spec/v1
|
||||||
|
oid sha256:9b1eae825eae1133932a52ed2cf1e24c811cc67ad01a19265a2b1bbca115fcd7
|
||||||
|
size 1065520
|
||||||
|
|
@ -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);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -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);
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -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;}
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from . import models
|
||||||
|
|
||||||
|
|
@ -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',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
from . import mrp
|
||||||
|
from . import sale_order_line
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
@ -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>
|
||||||
|
|
||||||
|
|
@ -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>
|
||||||
|
|
||||||
|
|
@ -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>
|
||||||
|
|
||||||
|
|
@ -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>
|
||||||
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
from . import models
|
||||||
|
|
@ -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,
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
from . import stock_dashboard
|
||||||
|
|
@ -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 []
|
||||||
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
@ -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>
|
||||||
|
|
@ -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);
|
||||||
|
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from . import models
|
||||||
|
|
@ -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,
|
||||||
|
}
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -0,0 +1,3 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
from . import grn
|
||||||
|
|
@ -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()
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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
|
||||||
|
|
After Width: | Height: | Size: 1.2 MiB |
|
|
@ -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','>',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>
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
# from . import models
|
||||||
|
|
@ -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'
|
||||||
|
],
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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>
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
|
@ -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,
|
||||||
|
}
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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.
|
||||||
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 6.9 KiB |
|
After Width: | Height: | Size: 4.5 KiB |
|
After Width: | Height: | Size: 6.2 KiB |
|
|
@ -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 "a"">
|
||||||
|
</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'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>
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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
|
||||||
|
After Width: | Height: | Size: 230 B |
|
After Width: | Height: | Size: 210 B |
|
After Width: | Height: | Size: 771 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 51 B |
|
After Width: | Height: | Size: 51 B |
|
After Width: | Height: | Size: 51 B |
|
After Width: | Height: | Size: 76 B |
|
After Width: | Height: | Size: 216 B |
|
After Width: | Height: | Size: 201 B |
|
|
@ -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;
|
||||||
|
}
|
||||||