diff --git a/.travis.yml b/.travis.yml index d66915eb44b..10a2b6e8347 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,6 +37,7 @@ php: - '5.6' - '7.0' - '7.1' +- '7.2' #- hhvm only with dist: trusty - nightly @@ -71,6 +72,8 @@ matrix: env: DB=postgresql - php: '7.0' env: DB=postgresql + - php: '7.1' + env: DB=postgresql - php: hhvm env: DB=postgresql - php: nightly @@ -79,7 +82,7 @@ matrix: notifications: email: on_success: never # [always|never|change] default: change - on_failure: change # [always|never|change] default: always + on_failure: never # [always|never|change] default: always irc: channels: - "chat.freenode.net#dolibarr" @@ -123,7 +126,10 @@ install: if [ "$TRAVIS_PHP_VERSION" = '5.3' ] || [ "$TRAVIS_PHP_VERSION" = '5.4' ] || [ "$TRAVIS_PHP_VERSION" = '5.5' ]; then composer -n require phpunit/phpunit ^4 fi - if [ "$TRAVIS_PHP_VERSION" = '5.6' ] || [ "$TRAVIS_PHP_VERSION" = '7.0' ] || [ "$TRAVIS_PHP_VERSION" = '7.1' ] || [ "$TRAVIS_PHP_VERSION" = 'nightly' ]; then + if [ "$TRAVIS_PHP_VERSION" = '5.6' ] || [ "$TRAVIS_PHP_VERSION" = '7.0' ] || [ "$TRAVIS_PHP_VERSION" = '7.1' ]; then + composer -n require phpunit/phpunit ^5 + fi + if [ "$TRAVIS_PHP_VERSION" = '7.2' ] || [ "$TRAVIS_PHP_VERSION" = 'nightly' ]; then composer -n require phpunit/phpunit ^5 fi echo @@ -163,7 +169,7 @@ before_script: #echo 'extension = apc.so' >> ~/.phpenv/versions/$PHP_VERSION_NAME/etc/php.ini echo echo "Enabling Memcached for PHP <= 5.4" - # Documentation says it should be available for all PHP versions but it's not for 5.5 and 5.6, 7.0, 7.1 and nightly! + # Documentation says it should be available for all PHP versions but it's not for 5.5 and 5.6, 7.0, 7.1, 7.2 and nightly! echo 'extension = memcached.so' >> ~/.phpenv/versions/$PHP_VERSION_NAME/etc/php.ini fi phpenv rehash @@ -237,7 +243,7 @@ before_script: echo "Setting up Apache + FPM" # enable php-fpm cp ~/.phpenv/versions/$PHP_VERSION_NAME/etc/php-fpm.conf.default ~/.phpenv/versions/$PHP_VERSION_NAME/etc/php-fpm.conf - if [ "$TRAVIS_PHP_VERSION" = '7.0' ] || [ "$TRAVIS_PHP_VERSION" = '7.1' ] || [ "$TRAVIS_PHP_VERSION" = 'nightly' ]; then + if [ "$TRAVIS_PHP_VERSION" = '7.0' ] || [ "$TRAVIS_PHP_VERSION" = '7.1' ] || [ "$TRAVIS_PHP_VERSION" = '7.2' ] || [ "$TRAVIS_PHP_VERSION" = 'nightly' ]; then # Copy the included pool cp ~/.phpenv/versions/$PHP_VERSION_NAME/etc/php-fpm.d/www.conf.default ~/.phpenv/versions/$PHP_VERSION_NAME/etc/php-fpm.d/www.conf fi @@ -313,13 +319,13 @@ script: php upgrade2.php 3.9.0 4.0.0 MAIN_MODULE_API,MAIN_MODULE_SUPPLIERPROPOSAL > $TRAVIS_BUILD_DIR/upgrade390400-2.log php step5.php 3.9.0 4.0.0 > $TRAVIS_BUILD_DIR/upgrade390400-3.log php upgrade.php 4.0.0 5.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade400500.log - php upgrade2.php 4.0.0 5.0.0 MAIN_MODULE_API,MAIN_MODULE_SUPPLIERPROPOSAL > $TRAVIS_BUILD_DIR/upgrade400500-2.log + php upgrade2.php 4.0.0 5.0.0 > $TRAVIS_BUILD_DIR/upgrade400500-2.log php step5.php 4.0.0 5.0.0 > $TRAVIS_BUILD_DIR/upgrade400500-3.log php upgrade.php 5.0.0 6.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade500600.log - php upgrade2.php 5.0.0 6.0.0 MAIN_MODULE_API,MAIN_MODULE_SUPPLIERPROPOSAL > $TRAVIS_BUILD_DIR/upgrade500600-2.log + php upgrade2.php 5.0.0 6.0.0 > $TRAVIS_BUILD_DIR/upgrade500600-2.log php step5.php 5.0.0 6.0.0 > $TRAVIS_BUILD_DIR/upgrade500600-3.log php upgrade.php 6.0.0 7.0.0 ignoredbversion > $TRAVIS_BUILD_DIR/upgrade600700.log - php upgrade2.php 6.0.0 7.0.0 MAIN_MODULE_API,MAIN_MODULE_SUPPLIERPROPOSAL > $TRAVIS_BUILD_DIR/upgrade600700-2.log + php upgrade2.php 6.0.0 7.0.0 MAIN_MODULE_WEBSITE,MAIN_MODULE_SUPPLIERPROPOSAL > $TRAVIS_BUILD_DIR/upgrade600700-2.log php step5.php 6.0.0 7.0.0 > $TRAVIS_BUILD_DIR/upgrade600700-3.log cd - set +e @@ -332,6 +338,7 @@ script: - | echo "Unit testing" + phpunit --version # Ensure we catch errors. Set this to +e if you want to go to the end to see dolibarr.log file. set -e phpunit -d memory_limit=-1 -c test/phpunit/phpunittest.xml test/phpunit/AllTests.php diff --git a/COPYRIGHT b/COPYRIGHT index 427784a1552..bd3565c3bd1 100644 --- a/COPYRIGHT +++ b/COPYRIGHT @@ -34,12 +34,11 @@ Swift Mailer 5.4.2-DEV MIT license Yes Stripe 4.7.0 MIT licence Yes Library for Stripe module JS libraries: -jQuery 1.11.3 MIT License Yes JS library -jQuery UI 1.11.4 GPL and MIT License Yes JS library plugin UI -jQuery select2 3.5.2 GPL and Apache License Yes JS library plugin for sexier multiselect +jQuery 3.1.1 MIT License Yes JS library +jQuery UI 1.12.1 GPL and MIT License Yes JS library plugin UI +jQuery select2 4.0.5 GPL and Apache License Yes JS library plugin for sexier multiselect jQuery blockUI 2.70.0 GPL and MIT License Yes JS library plugin blockUI (to use ajax popups) jQuery Colorpicker 1.1 MIT License Yes JS library for color picker for a defined list of colors -jQuery FileUpload 5.0.3 GPL and MIT License Yes JS library to upload files jQuery Flot 0.8.3 MIT License Yes JS library to build graph jQuery JCrop 0.9.8 GPL and MIT License Yes JS library plugin Crop (to crop images) jQuery Jeditable 1.7.1 GPL and MIT License Yes JS library plugin jeditable (to edit in place) @@ -49,8 +48,7 @@ jQuery jqueryFileTree 1.0.1 GPL and MIT License Yes jQuery jquerytreeview 1.4.1 MIT License Yes JS library for filetree jQuery TableDnD 0.6 GPL and MIT License Yes JS library plugin TableDnD (to reorder table rows) jQuery Timepicker 1.1.0 GPL and MIT License Yes JS library Timepicker addon for Datepicker -jQuery Tiptip 1.3 GPL and MIT License Yes JS library for tooltips -jsGanttImproved 1.7.5.2 BSD License Yes JS library (to build Gantt reports) +jsGanttImproved 1.7.5.4 BSD License Yes JS library (to build Gantt reports) JsTimezoneDetect 1.0.6 MIT License Yes JS library to detect user timezone SwaggerUI 2.0.24 GPL-2+ Yes JS library to offer the REST API explorer Ace 1.2.8 BSD Yes JS library to get code syntaxique coloration in a textarea. diff --git a/ChangeLog b/ChangeLog index 9b5eef7aca5..2a72296477c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -2,29 +2,352 @@ English Dolibarr ChangeLog -------------------------------------------------------------- - - -***** ChangeLog for 7.0.0 compared to 6.0.* ***** +***** ChangeLog for 7.0.0 compared to 6.0.5 ***** +For users: +NEW: #5711 Add shipment line deleting and editing for draft shipments. +NEW: Accept substitution key __[ABC]__ replaced with value of const ABC +NEW: Accountancy Add variant on sell account for intracommunity sales & export sales +NEW: Add a button "Activate all services" on contracts +NEW: Add a confirmation for all mass action 'delete' +NEW: Add a group task line for tasks on same level on gantt diagram +NEW: Add and edit country for chart of accounts systems +NEW: add a new notification for the signed closed event of a proposal. +NEW: Add a parameter to specify char used as separator for variant product label +NEW: Add a profile to import product translations +NEW: Add a protection so we can't journalize non balanced transactions +NEW: Add a status enabled/disabled on recurring invoices +NEW: add burger menu to list action comm +NEW: Add button cancel on shipment creation +NEW: Add chart of account for england +NEW: Add Chile accounting plan +NEW: Add class in societe/card.php +NEW: add company alias name when create company from member +NEW: Add date of birth on user card. +NEW: Add date_valid and date_pointoftax on supplier invoices. +NEW: Added Region name to state/province form field +NEW: Added regions to third party/societe lists, can be filtered +NEW: Add error message +NEW: Add expense report rules and ik +NEW: Add filter on event code on automatic filling setup page +NEW: Add filters on month/year on the accountancy binding tools +NEW: add fk_unit field into product/service import/export +NEW: add 'formObjectOptions' hook to the form setting the product selling price +NEW: Add hidden option PROJECT_DISABLE_UNLINK_FROM_OVERVIEW +NEW: add image object_phoning_mobile.png +NEW: Adding Field "First date of expire" + filter on contract list +NEW: add ldap_rename for avoid password if ldap key changed +NEW: Add mass action "validate" on supplier invoices. +NEW: add members types ldap group management +NEW: Add new property visible dy default on lists on extrafields +NEW: Add Next/Previous button on operation date of bank line +NEW: Add option EXPENSEREPORT_ALLOW_OVERLAPPING_PERIODS +NEW: Add option PROPOSAL/ORDER/INVOICE_ALLOW_EXTERNAL_DOWNLOAD +NEW: Add product unit fields for ODT substitution +NEW: Add project on a various payment +NEW: Add project related fields to ODT +NEW: Add protection to avoid to send to much emails using builk actions +NEW: Add search field for date on supplier payment page +NEW: Add search on date and accounting account in various payment list +NEW: add specific translation for title of documents (Invoice, Order, Proposal) +NEW: Adds the payment reference to the return of the function getListOfPayements +NEW: Add supplier proposals into stats of product page. +NEW: Add tab "Expense report" on user card +NEW: add the ability to regenerate a pdf for the order module +NEW: Add The accountancy Switzerland chart of accounts +NEW: Add The developed French chart of accounts 2014 +NEW: Add The Luxembourg chart of accounts +NEW: Add The Moroccan chart of accounts +NEW: Add The Switzerland chart of accounts +NEW: Add The SYSCOHADA chart of accounts +NEW: Add the total in the perday view of the time spent form. +NEW: Add The Tunisia chart of accounts +NEW: Add toolkit for StockLimit and DesiredStock +NEW: add translation and possibility to change month and year +NEW: Add view of status of template invoice +NEW: All search boxes are available on smartphone +NEW: All setup of accountancy can be done from menu "Accountancy-Setup" +NEW: Attaching doc automatically in email is now a parameter of template. +NEW: automatic activation of external module on country set +NEW: Better autoselect customer or supplier fields to save clicks +NEW: Better behaviour when using a text browser +NEW: Break lines per project on the new timesheet page +NEW: Bulk action validate on customer invoices +NEW: Bulk delete actions available on leave requests +NEW: burger menu and hooks on list action +NEW: Can add html content on right of tabs +NEW: Can add link to other element on a donation +NEW: Can create intervention from a proposal +NEW: Can create thirdparty from card proposal, order or invoice +NEW: Can download PDF document from the payment page +NEW: Can edit the language into the email templates editor. +NEW: Can edit with delete/insert a forced translation +NEW: Can export list of stock movements +NEW: Can filter on date on the page showing existing bindings +NEW: Can filter on document name in ECM module for automatic tree +NEW: can filter on status of template invoices +NEW: Can filter on the "other" column on emailing target list +NEW: Can filter on type of email template +NEW: Can filter on user on unalterable log +NEW: Can import local tax rates in prices +NEW: Can include extrafields into member card templates +NEW: Can include tag {uuu} into some numbering masks to replace with user +NEW: Can make a specific setup for SMTP sending for emailing module +NEW: Can rename (so reorder) bank receipts +NEW: Can send email from contract card +NEW: Can send email from the member card using email templates. +NEW: Can set a dedicated message on payment forms +NEW: Can set email of thirdparty as unique and/or mandatory +NEW: Can setup csv accounting export from admin config +NEW: Can show currency in list of bank accounts +NEW: Can show stock in alert even if alter is set to 0 +NEW: Can sort joined files on thirdparty and user card. +NEW: Can transfer from bank account to bank account with different currencies +NEW: Can use an url like $conf->global>-MYPARAM for menu urls +NEW: change description on click +NEW: Chart of account is loaded when selected into accounting setup +NEW: Classify the order as invoiced in the REST API +NEW: comments system on task +NEW: comment system working with all objects +NEW: Compatibility with PHP 7.2 +NEW: confirm form style to accept or reject proposal +NEW: Create an invoice using an existing order +NEW: Create an order using an existing proposal +NEW: customizable meteo in value or percentage +NEW: Days where user is on vacation use different colors in timesheet. +NEW: Deduct an available credit to an existing invoice +NEW: Default filter and sort order can use partial list of query +NEW: Deposit invoice more explicit in invoice line description +NEW: deposits can be converted even if unpaid +NEW: detection of edge browser +NEW: Each user can edit its own email template (menu tools) +NEW: Enabled sending email in bulk actions for supplier orders +NEW: Enhance the anti XSS filter +NEW: extrafield on facture_rec +NEW: Extrafields "link to object" now use a combo selection and getNomUrl +NEW: filter date for blockedlog +NEW: filter on extrafield on product list (as in company list) +NEW: General ledger : Add field date_creation and selected field +NEW: generate also document when invoice is build from recurring template +NEW: Generated files are now indexed in database +NEW: generate invoice PDF on disount application or payment +NEW: Get a list of payments terms +NEW: hrm details output on user +NEW: If max nb of generation is reached, date for next gen is striked +NEW: improvements of invoices, orders and proposals in the REST API +NEW: Include a color syntaxed HTML editor for emailing edition. +NEW: Introduce code syntax coloration with mode 'ace' for DolEditor. +NEW: Introduce experimental feature to search dolistore from application +NEW: jquery date selector become default date selector +NEW: langs +NEW: link project from other company conf +NEW: manageme extrafields with multientity +NEW: Mass PDF Merging is available on contracts +NEW: merge categories while merging thirdparties +NEW: Merge resource/add.php to resource/card.php +NEW: Module "Product variants" is moved as stable. +NEW: More picto for phone +NEW: Move accountancy features into a dedicated menu +NEW: Move contacts of a thirdparty on tab Contacts/Addresses +NEW: Move the upload input on top right in ECM module +NEW: new columns into extrafields table to get update create information +NEW: new param on load_board() function in ActionComm class to avoid duplicate code +NEW: On bulk email from a list, can uncheck "Join main document". +NEW: On reconciliation, show balance including all reconciliated fields +NEW: Option "one email per recipient" when using bulk actions emails. +NEW: Option STOCK_SUPPORTS_SERVICES become visible. +NEW: option to avoid countries to disable there blockedlog +NEW: option to fix top menu with eldy theme (hidden conf) +NEW: Popup for preview of image add a button "Original size" +NEW: post lines of an invoice using the REST API +NEW: preload comments in task +NEW: Provide a way to download a file from a public URL for files in ECM +NEW: Reduce size of HTML page by removing duplicate tooltips +NEW: Remove background on agenda view when event is a not busy event. +NEW: Retrieves available discounts and payments details from a specific invoice +NEW: Revenue stamp can be a percent +NEW: Search filters in lists are restored when using "back to list" +NEW: Send by email available in bulk for expense report +NEW: Set a proposal to draft +NEW: Show badge with nbr of shipment on shimpen tab of order +NEW: Show country and vat number into company tooltip +NEW: Show direct preview link on contract +NEW: Show expected worked hours on the timesheet form. +NEW: Show line "other filtered task" when using filter on timesheet. +NEW: Show list of tracked events into the module config page. +NEW: Show the supplier ref into supplier cards +NEW: Show user id of web process in system info - web server +NEW: Summary of last events on a card are sorted on decreasing date. +NEW: Support Italian addresses format. Fixes #7785 +NEW: Support visibility on extrafields +NEW: Template invoices are visible on the customer tab +NEW: template invoices support substition key +NEW: The bank account is visible on payment of taxes +NEW: The comment when closing a proposal is added to commercial proposal +NEW: The gantt diagram is now sensitive to hours +NEW: The lot of a product uses the link and picto when shown into list. +NEW: The "Show detail by account" accepts 3 values: yes, no, if non zero +NEW: The unalterable log can be browse by any user with he permission +NEW: Tooltip for substitutions variables on tooltips on admin pages +NEW: unexistant function load_state_board() on several objects +NEW: Update availability +NEW: Update bank account when updating an invoice +NEW: Update bank account when updating an order +NEW: Use autocompletion on selection of chart of account +NEW: view company name if different of fullname in dol_banner +NEW: warning on module blocked log reset if country code is FR For developers: +NEW: Add 2 new automatic classification in workflow module +NEW: Add API for contracts +NEW: Add API to activate/unactivate a contract +NEW: Add api validate and close on contracts +NEW: add doActions hook in admin ihm +NEW: add doActions hook in company admin +NEW: Added functionality to get order customer contact as contact_xx tags NEW: Add hook addAdminLdapOptions and doAction in ldap admin page +NEW: Add method executeCLI and a phpunit +NEW: add '$moreatt' parameter in picto_from_langcode function +NEW: Add non intrusive js library to make syntaxic coloring of textarea +NEW: Add payment line to a specific invoice using the REST API +NEW: add possibility to disabled the LDAP trigger +NEW: add possibility to hide LDAP tab for non admin +NEW: Add possibility to propose last num releve in conciliation +NEW: add possibility to remove address field +NEW: Add REST API for supplier proposals +NEW: Add REST API to add payment line to a specific invoice +NEW: Add the attribute accept to the input form for file upload +NEW: add translation column for extrafields list +NEW: Add performances indexes on calendar events +NEW: A module can change order of element in the quick search combo +NEW: Can test signature of a version from API NEW: complete_head_from_modules() in ldap_prepare_head() +NEW: Consolidates REST dictionary APIs into a single tree and a single file +NEW: Delete a line of invoice using the REST API +NEW: documents REST API return list of documents by element +NEW: Download a document using the REST API +NEW: Enhance framework so we can use html/icons into SELECT options. +NEW: External module can interact with the customer summary page +NEW: Generates the document before downloading using REST API +NEW: get and post lines of an invoice using the REST API +NEW: Get a payment list of a given invoice using the REST API +NEW: Get available assets of an invoice using the REST API +NEW: Get credit notes or deposits of a thirdparty +NEW: GET lines of an invoice in the REST API +NEW: get payment types using the REST API + consolidates REST dictionary APIs +NEW: Get the list of payments terms. +NEW: hook formObjectOptions in the form setting product selling price +NEW: hook to enrich homepage open elements dashboard +NEW: Insert a discount in a specific invoice using the REST API +NEW: Remove js library fileupload that was not used by core code. +NEW: Remove tooltip tipTip library replaced with standatd jquery tooltip +NEW: Set invoices as draft using the REST API +NEW: Sets an invoice as paid using the REST API +NEW: Tag the order as validated (opened) in the REST API +NEW: Update end of validity date of proposal using the API +NEW: Update in the order REST API +NEW: Upgrade jquery select2 to 4.0.4 -WARNING: + +WARNING: + +If you enabled (for test) the experimental BlockedLog module before 7.0, you must purge the table llx_blockedlog because +way to save data for final version has changed. Following changes may create regressions for some external modules, but were necessary to make Dolibarr better: * The methode "cloture" on contract were renamed into "closeAll". -* The substitution key for reference of object is now __REF__ whatever is the object (it replaces __ORDERREF__, +* The method "is_erasable" of invoice return a value <= 0 if not erasable (value is meaning) instead of always 0. +* The substitution key for reference of objects is now __REF__ whatever is the object (it replaces __ORDERREF__, __PROPALREF__, ...) -* The substition key __SIGNATURE__ was renamed into __USER_SIGNATURE__ to standardize naming conventions. +* The substition key __SIGNATURE__ was renamed into __USER_SIGNATURE__ to follow naming conventions. * Substitution keys with syntax %XXX% were renamed into __XXX__ to match others. -* Some REST API to access the dictionary (country, town, ...) were moved into a common API. -* Page bank/index.php and bank/bankentries.php were renamed into bank/list.php and bank/bankentries_list.php to - follow page naming conventions (so default filter/sort order features can also work). -* The trigger ORDER_SUPPLIER_STATUS_ONPROCESS was renamed into ORDER_SUPPLIER_STATUS_ORDERED -* The trigger ORDER_SUPPLIER_STATUS_RECEIVED_ALL was renamed into ORDER_SUPPLIER_STATUS_RECEIVED_COMPLETELY +* Removed old deprecated REST API (APIs found into '/root' section of the REST API explorer in Dolibarr v6). +* Some REST API to access setup features, like dictionaries (country, town, extrafields, ...) were moved into a + common API "/setup". +* The REST API /documents were renamed into /documents/download and /documents/upload. +* Page bank/index.php, bank/bankentries.php and comm/actions/listactions.php were renamed into + bank/list.php, bank/bankentries_list.php and comm/actions/list.php to follow page naming + conventions (so default filter/sort order features can also work for this pages). +* The trigger ORDER_SUPPLIER_STATUS_ONPROCESS was renamed into ORDER_SUPPLIER_STATUS_ORDERED. +* The trigger ORDER_SUPPLIER_STATUS_RECEIVED_ALL was renamed into ORDER_SUPPLIER_STATUS_RECEIVED_COMPLETELY. +* The parameter note into method cloture() is added at end of private note (previously in v6, it replaced). +* The parameter $user is now mandatory for method createFromOrder and createFromPropal. +* Removed js library 'fileupload' that was not used by core code. +* Jquery plugin tableDnd updated. You now need to use decodeURI on the return value of tableDnDSerialize() + and add 'td.' to the beginning of the dragHandle match string. +* IE8 and earlier and Firefox 12 and earlier (< 2012) are no more supported. +***** ChangeLog for 6.0.5 compared to 6.0.4 ***** +FIX: security vulnerability reported by ADLab of Venustech + CVE-2017-17897, CVE-2017-17898, CVE-2017-17899, CVE-2017-17900 +FIX: #7379: Compatibility with PRODUCT_USE_OLD_PATH_FOR_PHOTO variable +FIX: #7903 +FIX: #7933 +FIX: #8029 Unable to make leave request in holyday module +FIX: #8093 +FIX: Bad name alias showing in name of third column +FIX: Cashdesk should not sell to inactive third parties +FIX: Edit accountancy account and warning message on loan +FIX: $accounts[$bid] is a label ! +FIX: $oldvatrateclean & $newvatrateclean must be set if preg_match === false +FIX: product best price on product list +FIX: search on contact list +FIX: stats trad for customerinvoice +FIX: translate unactivate on contractline +FIX: email sent was not in HTML +FIX: missing hook invoice index +FIX: subject mail sepa + + +***** ChangeLog for 6.0.4 compared to 6.0.3 ***** +FIX: #7737 +FIX: #7751 +FIX: #7756 Add better error message +FIX: #7786 +FIX: #7806 +FIX: #7824 +FIX: add line bad price and ref +FIX: A lot of several fix on local taxes and NPR tax +FIX: createfromorder +FIX: CSS for IE10 +FIX: external user cannot be set as internal +FIX: Filter type on actioncomm with multiselect doesn't work +FIX: list of donation not filtered on multicompany +FIX: list of module not complete when module mb_strlen not available +FIX: Locatax were not propagated when cloning order or proposal +FIX: Searching translation should not be case sensitive +FIX: Search into language is ok for file into external modules two. +FIX: test for filter fk_status +FIX: too much users on holiday list +FIX: Wrong alias sql + + +***** ChangeLog for 6.0.3 compared to 6.0.2 ***** +FIX: #7211 Update qty dispatched on qty change +FIX: #7458 +FIX: #7593 +FIX: #7616 +FIX: #7619 +FIX: #7626 +FIX: #7648 +FIX: #7675 +FIX: Agenda events are not exported in the ICAL, VCAL if begin exactly with the same $datestart +FIX: API to get object does not return data of linked objects +FIX: Bad localtax apply +FIX: Bad ressource list in popup in gantt view +FIX: bankentries search conciliated if val 0 +FIX: hook formObjectOptions() must use $expe and not $object +FIX: make of link to other object during creation +FIX: Missing function getLinesArray +FIX: old batch not shown in multi shipping +FIX: paid supplier invoices are shown as abandoned +FIX: selection of thirdparty was lost on stats page of invoices +FIX: sql syntax error because of old field accountancy_journal +FIX: Stats on invoices show nothing +FIX: substitution in ODT of thirdparties documents +FIX: wrong key in selectarray +FIX: wrong personnal project time spent + ***** ChangeLog for 6.0.2 compared to 6.0.1 ***** FIX: #7148 FIX: #7288 @@ -248,6 +571,23 @@ Following changes may create regression for some external modules, but were nece content by doing a print into function, sometimes by returning content into "resprint". This has been fixed to follow hook specifications so you must return output into "resprint". + +***** ChangeLog for 5.0.7 compared to 5.0.6 ***** +FIX: #7000 Dashboard link for late pending payment supplier invoices do not work +FIX: #7148 +FIX: #7325 Default VAT rate when editing template invoices is 0% +FIX: #7366 renaming table with pgsql +FIX: #7391 +FIX: #7510 Bug: extrafield content disappear when generate pdf within intervention +FIX: Agenda events are not exported in the ICAL, VCAL if begin exactly with the same $datestart +FIX: Bad link to unpayed suppliers invoices +FIX: bankentries search conciliated if val 0 +FIX: multicompany better accuracy in rounding and with revenue stamp. +FIX: PDF output was sharing 2 different currencies in same total +FIX: Upgrade missing on field +FIX: wrong key in selectarray +FIX: wrong personnal project time spent + ***** ChangeLog for 5.0.6 compared to 5.0.5 ***** FIX: Removed a bad symbolic link into custom directory. FIX: Renaming a resource ref rename also the directory of attached files. diff --git a/build/doxygen/dolibarr-doxygen.doxyfile b/build/doxygen/dolibarr-doxygen.doxyfile index 912c72b4d69..271b64f5481 100644 --- a/build/doxygen/dolibarr-doxygen.doxyfile +++ b/build/doxygen/dolibarr-doxygen.doxyfile @@ -442,7 +442,7 @@ SORT_BY_SCOPE_NAME = NO # disable (NO) the todo list. This list is created by putting \todo # commands in the documentation. -GENERATE_TODOLIST = YES +GENERATE_TODOLIST = NO # The GENERATE_TESTLIST tag can be used to enable (YES) or # disable (NO) the test list. This list is created by putting \test @@ -639,7 +639,7 @@ EXCLUDE_SYMBOLS = # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = ../../dev/skeletons +EXAMPLE_PATH = ../../htdocs/modulebuilder/template # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp diff --git a/build/exe/doliwamp/Languages/MyEnglish.isl b/build/exe/doliwamp/Languages/MyEnglish.isl index 6e70f3c12f3..11d2e4456bd 100644 --- a/build/exe/doliwamp/Languages/MyEnglish.isl +++ b/build/exe/doliwamp/Languages/MyEnglish.isl @@ -43,3 +43,5 @@ DoliWampWillStartApacheMysql=DoliWamp installer will now start or restart Apache OldVersionFoundAndMoveInNew=An old database version has been found and moved to be used by new Dolibarr version OldVersionFoundButFailedToMoveInNew=An old database version has been found but could not be moved to be used with new Dolibarr version +DLLMissing=The "Visual C++ Redistributable for Visual Studio 2012" component is missing. Please install the 32-bit version (vcredit_x86.exe) first from https://www.microsoft.com/en-us/download/details.aspx?id=30679 and restart DoliWamp installation/upgrade. +ContinueAnyway=Continue anyway (install process may fails without this prerequisite) diff --git a/build/exe/doliwamp/doliwamp.iss b/build/exe/doliwamp/doliwamp.iss index 2ef8ab32f22..7dcb8c738bd 100644 --- a/build/exe/doliwamp/doliwamp.iss +++ b/build/exe/doliwamp/doliwamp.iss @@ -32,7 +32,7 @@ AppPublisherURL=http://www.nltechno.com AppSupportURL=http://www.dolibarr.org AppUpdatesURL=http://www.dolibarr.org AppComments=DoliWamp includes Dolibarr, Apache, PHP and Mysql softwares. -AppCopyright=Copyright (C) 2008-2016 Laurent Destailleur, NLTechno +AppCopyright=Copyright (C) 2008-2017 Laurent Destailleur (NLTechno), Fabian Rodriguez (Le Goût du Libre) DefaultDirName=c:\dolibarr DefaultGroupName=Dolibarr ;LicenseFile=COPYING @@ -202,10 +202,30 @@ var value: String; function InitializeSetup(): Boolean; begin Result := MsgBox(CustomMessage('YouWillInstallDoliWamp')+#13#13+CustomMessage('ThisAssistantInstallOrUpgrade')+#13#13+CustomMessage('IfYouHaveTechnicalKnowledge')+#13#13+CustomMessage('ButIfYouLook')+#13#13+CustomMessage('DoYouWantToStart'), mbConfirmation, MB_YESNO) = IDYES; + + if Result then + begin + + //---------------------------------------------- + // Test if msvcr110 DLL has been installed + //---------------------------------------------- + + if not FileExists ('c:/windows/system32/msvcr110.dll') and not FileExists ('c:/windows/sysWOW64/msvcr110.dll') and not FileExists ('c:/winnt/system32/msvcr110.dll') and not FileExists ('c:/winnt/sysWOW64/msvcr110.dll') then + begin + // TODO - offer to install the component by opening the URL in the default browser, abort installation if user doesn't accept + Result := MsgBox(CustomMessage('DLLMissing')+#13#13+CustomMessage('ContinueAnyway'), mbConfirmation, MB_YESNO) = IDYES; + + end; + // Pb seems similar with msvcp110.dll + //vcredist_x64.exe + + end; + end; procedure InitializeWizard(); begin + //version des applis, a modifier pour chaque version de WampServer 2 apacheVersion := '2.4.9'; phpVersion := '5.5.12' ; @@ -217,6 +237,7 @@ begin mysqlPort := '3306'; newPassword := 'changeme'; + firstinstall := true; @@ -344,19 +365,6 @@ begin exedirold := pathWithSlashes+'/bin/mysql/mysql5.0.45'; exedirnew := pathWithSlashes+'/bin/mysql/mysql5.0.45'; - - //---------------------------------------------- - // Test if msvcr110 DLL has been installed - //---------------------------------------------- - - if not FileExists ('c:/windows/system32/msvcr110.dll') and not FileExists ('c:/windows/sysWOW64/msvcr110.dll') and not FileExists ('c:/winnt/system32/msvcr110.dll') and not FileExists ('c:/winnt/sysWOW64/msvcr110.dll') then - begin - // TODO Copy file or ask to install package ? - //CustomMessage('YouWillInstallDoliWamp')+#13#13 - MsgBox('The package vcredist_x86.exe must have been installed first. It seems it is not. Please install it first from http://www.microsoft.com/en-us/download/details.aspx?id=30679 then restart DoliWamp installation/upgrade.',mbInformation,MB_OK); - end; - // Pb seems similar with msvcp110.dll - //vcredist_x64.exe // If we have a new database version, we should only copy old my.ini file into new directory diff --git a/build/exe/doliwamp/index.php.install b/build/exe/doliwamp/index.php.install index 700f0707de2..1c657b35977 100644 --- a/build/exe/doliwamp/index.php.install +++ b/build/exe/doliwamp/index.php.install @@ -535,7 +535,7 @@ a:hover {
  • {$langues[$langue]['autreLangue1']} - {$langues[$langue]['autreLangue2']}


  • -
  • Provided by NLTechno
  • +
  • Provided by NLTechno

  • @@ -580,7 +580,7 @@ a:hover { diff --git a/build/generate_filelist_xml.php b/build/generate_filelist_xml.php index 0d3d90d54d4..e6336e30e97 100755 --- a/build/generate_filelist_xml.php +++ b/build/generate_filelist_xml.php @@ -131,7 +131,7 @@ $iterator1 = new RecursiveIteratorIterator($dir_iterator1); $files = new RegexIterator($iterator1, '#^(?:[A-Z]:)?(?:/(?!(?:'.($includecustom?'':'custom\/|').'documents\/|conf\/|install\/))[^/]+)+/[^/]+\.(?:php|css|html|js|json|tpl|jpg|png|gif|sql|lang)$#i'); */ $regextoinclude='\.(php|css|html|js|json|tpl|jpg|png|gif|sql|lang)$'; -$regextoexclude='('.($includecustom?'':'custom|').'documents|conf|install)$'; // Exclude dirs +$regextoexclude='('.($includecustom?'':'custom|').'documents|conf|install|public\/test|Shared\/PCLZip|nusoap\/lib\/Mail|php\/example|php\/test|geoip\/sample.*\.php|ckeditor\/samples|ckeditor\/adapters)$'; // Exclude dirs $files = dol_dir_list(DOL_DOCUMENT_ROOT, 'files', 1, $regextoinclude, $regextoexclude, 'fullname'); $dir=''; $needtoclose=0; diff --git a/build/makepack-dolibarr.pl b/build/makepack-dolibarr.pl index e0fa89d924d..7da6d180dcb 100755 --- a/build/makepack-dolibarr.pl +++ b/build/makepack-dolibarr.pl @@ -19,7 +19,7 @@ use Term::ANSIColor; # Change this to defined target for option 98 and 99 $PROJECT="dolibarr"; $PUBLISHSTABLE="eldy,dolibarr\@frs.sourceforge.net:/home/frs/project/dolibarr"; -$PUBLISHBETARC="ldestailleur\@vmprod.dolibarr.org:/home/dolibarr/dolibarr.org/httpdocs/files"; +$PUBLISHBETARC="dolibarr\@vmprod1.dolibarr.org:/home/dolibarr/dolibarr.org/httpdocs/files"; #@LISTETARGET=("TGZ","ZIP","RPM_GENERIC","RPM_FEDORA","RPM_MANDRIVA","RPM_OPENSUSE","DEB","APS","EXEDOLIWAMP","SNAPSHOT"); # Possible packages @@ -556,9 +556,6 @@ if ($nboftargetok) { $ret=`rm -f $BUILDROOT/$PROJECT/.cvsignore $BUILDROOT/$PROJECT/*/.cvsignore $BUILDROOT/$PROJECT/*/*/.cvsignore $BUILDROOT/$PROJECT/*/*/*/.cvsignore $BUILDROOT/$PROJECT/*/*/*/*/.cvsignore $BUILDROOT/$PROJECT/*/*/*/*/*/.cvsignore $BUILDROOT/$PROJECT/*/*/*/*/*/*/.cvsignore`; $ret=`rm -f $BUILDROOT/$PROJECT/.gitignore $BUILDROOT/$PROJECT/*/.gitignore $BUILDROOT/$PROJECT/*/*/.gitignore $BUILDROOT/$PROJECT/*/*/*/.gitignore $BUILDROOT/$PROJECT/*/*/*/*/.gitignore $BUILDROOT/$PROJECT/*/*/*/*/*/.gitignore $BUILDROOT/$PROJECT/*/*/*/*/*/*/.gitignore`; $ret=`rm -f $BUILDROOT/$PROJECT/htdocs/includes/geoip/sample*.*`; - $ret=`rm -f $BUILDROOT/$PROJECT/htdocs/includes/jquery/plugins/jqueryFileTree/connectors/jqueryFileTree.pl`; # Avoid errors into rpmlint - $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/jquery/plugins/template`; # Package not valid for most linux distributions (errors reported into compile.js). Package should be embed by modules to avoid problems. - $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/phpmailer`; # Package not valid for most linux distributions (errors reported into file LICENSE). Package should be embed by modules to avoid problems. $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/ckeditor/ckeditor/adapters`; # Keep this removal in case we embed libraries $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/ckeditor/ckeditor/samples`; # Keep this removal in case we embed libraries #$ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/ckeditor/_source`; # _source must be kept into tarball @@ -571,6 +568,7 @@ if ($nboftargetok) { $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/mobiledetect/mobiledetectlib/.gitmodules`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/nusoap/lib/Mail`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/nusoap/samples`; + $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/parsedown/LICENSE.txt`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/php-iban/docs`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/phpoffice/phpexcel/.gitattributes`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/phpoffice/phpexcel/Classes/license.md`; @@ -579,6 +577,7 @@ if ($nboftargetok) { $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/phpoffice/phpexcel/Examples`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/phpoffice/phpexcel/unitTests`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/phpoffice/phpexcel/license.md`; + $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/stripe/LICENSE`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/tcpdf/fonts/dejavu-fonts-ttf-*`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/tcpdf/fonts/freefont-*`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/tcpdf/fonts/ae_fonts_*`; @@ -590,6 +589,8 @@ if ($nboftargetok) { $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/tecnickcom/tcpdf/fonts/utils`; $ret=`rm -fr $BUILDROOT/$PROJECT/htdocs/includes/tecnickcom/tcpdf/tools`; $ret=`rm -f $BUILDROOT/$PROJECT/htdocs/includes/tecnickcom/tcpdf/LICENSE.TXT`; + $ret=`rm -f $BUILDROOT/$PROJECT/htdocs/theme/common/octicons/LICENSE`; + print "Remove subdir of custom dir\n"; print "find $BUILDROOT/$PROJECT/htdocs/custom/* -type d -exec rm -fr {} \\;\n"; diff --git a/build/rpm/dolibarr_fedora.spec b/build/rpm/dolibarr_fedora.spec index 55898481691..077aaeb9483 100755 --- a/build/rpm/dolibarr_fedora.spec +++ b/build/rpm/dolibarr_fedora.spec @@ -213,7 +213,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/user %_datadir/dolibarr/htdocs/variants %_datadir/dolibarr/htdocs/webservices -%_datadir/dolibarr/htdocs/websites +%_datadir/dolibarr/htdocs/website %_datadir/dolibarr/htdocs/*.ico %_datadir/dolibarr/htdocs/*.patch %_datadir/dolibarr/htdocs/*.php diff --git a/build/rpm/dolibarr_generic.spec b/build/rpm/dolibarr_generic.spec index e5b346278ab..5b39bac7761 100755 --- a/build/rpm/dolibarr_generic.spec +++ b/build/rpm/dolibarr_generic.spec @@ -293,7 +293,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/user %_datadir/dolibarr/htdocs/variants %_datadir/dolibarr/htdocs/webservices -%_datadir/dolibarr/htdocs/websites +%_datadir/dolibarr/htdocs/website %_datadir/dolibarr/htdocs/*.ico %_datadir/dolibarr/htdocs/*.patch %_datadir/dolibarr/htdocs/*.php diff --git a/build/rpm/dolibarr_mandriva.spec b/build/rpm/dolibarr_mandriva.spec index 3c8a5097c0e..1034615c80a 100755 --- a/build/rpm/dolibarr_mandriva.spec +++ b/build/rpm/dolibarr_mandriva.spec @@ -210,7 +210,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/user %_datadir/dolibarr/htdocs/variants %_datadir/dolibarr/htdocs/webservices -%_datadir/dolibarr/htdocs/websites +%_datadir/dolibarr/htdocs/website %_datadir/dolibarr/htdocs/*.ico %_datadir/dolibarr/htdocs/*.patch %_datadir/dolibarr/htdocs/*.php diff --git a/build/rpm/dolibarr_opensuse.spec b/build/rpm/dolibarr_opensuse.spec index c77661fe420..eb1887f229f 100755 --- a/build/rpm/dolibarr_opensuse.spec +++ b/build/rpm/dolibarr_opensuse.spec @@ -221,7 +221,7 @@ done >>%{name}.lang %_datadir/dolibarr/htdocs/user %_datadir/dolibarr/htdocs/variants %_datadir/dolibarr/htdocs/webservices -%_datadir/dolibarr/htdocs/websites +%_datadir/dolibarr/htdocs/website %_datadir/dolibarr/htdocs/*.ico %_datadir/dolibarr/htdocs/*.patch %_datadir/dolibarr/htdocs/*.php diff --git a/composer.json b/composer.json index a8d6b9ee5ff..5698dd18807 100644 --- a/composer.json +++ b/composer.json @@ -13,7 +13,7 @@ "agenda" ], "homepage": "https://www.dolibarr.org", - "license": "GPL-3.0+", + "license": "GPL-3.0-or-later", "support": { "issues": "https://github.com/Dolibarr/dolibarr/issues", "forum": "https://www.dolibarr.org/forum", diff --git a/dev/dolibarr_changes.txt b/dev/dolibarr_changes.txt index 3b9ef4cc447..9e6ab3a8ddc 100644 --- a/dev/dolibarr_changes.txt +++ b/dev/dolibarr_changes.txt @@ -82,8 +82,14 @@ with // LDR To open in same window //var OpenWindow=window.open(pRef, "newwin", "height="+vHeight+",width="+vWidth); window.location.href=pRef -* Replace hard coded string with i18n["String"]; +* Replace +vTmpDiv=this.newNode(vTmpCell, 'div', null, null, vTaskList[i].getResource()); +with +var vTmpNode=this.newNode(vTmpCell, 'div', null, ''); +vTmpNode=this.newNode(vTmpNode, 'a', null, '', vLangs[vLang]['moreinfo']); +vTmpNode.setAttribute('href',vTaskList[i].getLink()); + JCROP: ------ @@ -99,7 +105,7 @@ JQUERYFILETREE: RESTLER: -------- -* Add 2 lines into function +* Add 2 lines into file AutoLoader.php to complete function private function alias($className, $currentClass) { ... @@ -110,4 +116,57 @@ to get if ($className == 'Luracast\Restler\string') return; if ($className == 'Luracast\Restler\mixed') return; ... - \ No newline at end of file + +Change also file Luracast/Restler/explorer/index.html + ++With swagger 2: + +* Add line into Util.php to complete function + + public static function getShortName($className) + { + // @CHANGE LDR + if (! is_string($className)) return; + //var_dump($className); + + + +PARSEDOWN +--------- + +* Add support of css by adding in Parsedown.php: + + // @CHANGE LDR + 'class' => $Link['element']['attributes']['class'] + + ... + + // @CHANGE LDR + if (preg_match('/{([^}]+)}/', $remainder, $matches2)) + { + $Element['attributes']['class'] = $matches2[1]; + $remainder = preg_replace('/{'.preg_quote($matches2[1],'/').'}/', '', $remainder); + } + + + // @CHANGE LDR + //$markup .= $this->{$Element['handler']}($Element['text']); + $markup .= preg_replace('/>{[^}]+}/', '>', $this->{$Element['handler']}($Element['text'])); + + + +* Fix to avoid fatal error when mb_strlen not available: + + // @CHANGE LDR Fix when mb_strlen is not available + //$shortage = 4 - mb_strlen($line, 'utf-8') % 4; + if (function_exists('mb_strlen')) $len = mb_strlen($line, 'utf-8'); + else $len = strlen($line); + $shortage = 4 - $len % 4; + + +JEDITABLE.JS +------------ + +* + jsGanttImproved + + + + + + +
    +
    +
    +

    jsGanttImproved

    +

    latest v1.7.5.4

    + Download + View on GitHub +
    +
    +
    +
    + +

    +

    100% HTML + CSS + JavaScript Gantt Chart

    +
    + +

    +

    Completely FREE

    +
    + +

    +

    Open source

    +
    +
    + +
    +
    +
    +
    +
    + +
    +
    +
    + +
    +

    Demo

    +
    + + +
    +
    + +
    +
    + +
    +
    + +
    +

    Features

    +

    jsGanttImproved is a fully featured gantt chart component built entirely in Javascript, CSS and AJAX. It is lightweight and there is no need of external libraries or additional images.

    +
    +
    +

    Basic Features

    +
      +
    • Tasks & Collapsible Task Groups
    • +
    • Multiple Dependencies
    • +
    • Task Completion
    • +
    • Task Style
    • +
    • Milestones
    • +
    • Resources
    • +
    +
    +
    +

    Advanced Features

    +
      +
    • Dynamic Loading of Tasks
    • +
    • Dynamic change of format: Hour, Day, Week, Month, Quarter
    • +
    • + Load Gantt from: +
        +
      • External XML files (including experimental support for Microsoft Project XML files)
      • +
      • JavaScript strings
      • +
      +
    • +
    • Export Gantt as XML string
    • +
    • Support for internationalization
    • +
    +
    +
    +

    Current Known Issues:

    +
      +
    • If the browser is viewing the page at anything other than 100% zoom then bars may not be sized or positioned correctly.
    • +
    +

    Changelog:

    +

    Check the full list of changes on GitHub releases page.

    +

    v1.7.5.4:

    +
      +
    • Left part of the chart is now created first on JavaScript and establishes the left floating reference
    • +
    • Minimum width updated to 632px so that the left part of the chart has a fixed width of 532px and the right part fills out the rest with a minimum of 100px
    • +
    +

    v1.7.5.3:

    +
      +
    • Fixed group completion percentage that now is a weighted average
    • +
    • Start and end dates specified on standard group tasks will now be respected if they fall outside of the calculated group date range
    • +
    • Fixed problem that would occur if Tool Tips were disabled
    • +
    • Moved example dates forward so the current date marker is visible
    • +
    +

    v1.7.5:

    +
      +
    • Project Migrated to GitHub
    • +
    • Instantiating a new JSGantt.TaskItem will now also accept Date objects for start and end dates
    • +
    • Fixed old Internet Explorer compatibilty broken by v1.7
    • +
    • Fixed bug in Iso week date format
    • +
    • Changed to solid arrows on dependency lines to be more printer friendly
    • +
    • Code refactoring and clean up
    • +
    +

    v1.7:

    +
      +
    • + Fixed nasty long-standing bug where the first Gantt chart created must be stored in a javascript variable named "g" +
        +
      • NOTE: This required a change in the method to instatiate a JSGantt.TaskItem object to pass the related chart.
      • +
      • A temporary fix is included that still assumes the use of "g" for the chart if the chart object is not passed, this will be removed in v1.8
      • +
      +
    • +
    • Altered XML export functionality so that dates are output in the specified input format for the chart
    • +
    • Added method to read XML directly from an input string
    • +
    • Prevented creation of a task with a duplicate "unique" ID
    • +
    • Fixed bug where attempting to remove the first task defined would prevent the chart from redrawing
    • +
    • Some general code clean up
    • +
    +
    + +
    +

    Usage

    +

    Following the steps below you will be able to get create a basic Gantt Chart. If you notice any bugs, please post them to GitHub issues.

    +
      +
    1. + Include JSGantt CSS and Javascript +
      <link rel="stylesheet" type="text/css" href="jsgantt.css" />
      +<script language="javascript" src="jsgantt.js"></script>
      +
    2. +
    3. + Create a div element to hold the gantt chart +
      <div style="position:relative" class="gantt" id="GanttChartDIV"></div>
      +
    4. +
    5. + Start a <script> block +
      <script type="text/javascript">
      +
    6. +
    7. + Instantiate JSGantt using GanttChart() +
      var g = new JSGantt.GanttChart(document.getElementById('GanttChartDIV'), 'day');
      +

      Method definition: + GanttChart(pDiv, pFormat) +

      +

      + + + + + + + + +
      pDiv:(required) this is a DIV object created in HTML
      pFormat:(required) - used to indicate whether chart should be drawn in "hour", "day", "week", "month", or "quarter" format

      +
    8. +
    9. +

      Customize the look and feel using configuration methods (see Configuration Options)

      +
    10. +
    11. + Add Tasks +
        +
      • + using AddTaskItem() +
        g.AddTaskItem(new JSGantt.TaskItem(1, 'Define Chart API','',          '',          'ggroupblack','', 0, 'Brian', 0,  1,0,1,'','','Some Notes text',g));
        +g.AddTaskItem(new JSGantt.TaskItem(11,'Chart Object',    '2016-02-20','2016-02-20','gmilestone', '', 1, 'Shlomy',100,0,1,1,'','','',g));
        +                
        +

        Method definition: + TaskItem(pID, pName, pStart, pEnd, pColor, pLink, pMile, pRes, pComp, pGroup, pParent, pOpen, pDepend, pCaption, pNotes, pGantt) +

        + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
        pID:(required) a unique numeric ID used to identify each row
        pName:(required) the task Label
        pStart:(required) the task start date, can enter empty date ('') for groups. You can also enter specific time (2016-02-20 12:00) for additional precision.
        pEnd:(required) the task end date, can enter empty date ('') for groups
        pClass:(required) the css class for this task
        pLink:(optional) any http link to be displayed in tool tip as the "More information" link.
        pMile:(optional) indicates whether this is a milestone task - Numeric; 1 = milestone, 0 = not milestone
        pRes:(optional) resource name
        pComp:(required) completion percent, numeric
        pGroup:(optional) indicates whether this is a group task (parent) - Numeric; 0 = normal task, 1 = standard group task, 2 = combined group task*
        pParent:(required) identifies a parent pID, this causes this task to be a child of identified task. Numeric, top level tasks should have pParent set to 0
        pOpen:(required) indicates whether a standard group task is open when chart is first drawn. Value must be set for all items but is only used by standard group tasks. Numeric, 1 = open, 0 = closed
        pDepend: + (optional) comma separated list of id's this task is dependent on. A line will be drawn from each listed task to this item
        Each id can optionally be followed by a dependency type suffix. Valid values are: +
        'FS' - Finish to Start (default if suffix is omitted)
        'SF' - Start to Finish
        'SS' - Start to Start
        'FF' - Finish to Finish
        + If present the suffix must be added directly to the id e.g. '123SS' +
        pCaption:(optional) caption that will be added after task bar if CaptionType set to "Caption"
        pNotes:(optional) Detailed task information that will be displayed in tool tip for this task
        pGantt:(required) javascript JSGantt.GanttChart object from which to take settings. Defaults to "g" for backwards compatibility
        +

        * Combined group tasks show all sub-tasks on one row. The information displayed in the task list and row caption are taken from the parent task. Tool tips are generated individually for each sub-task from its own information. Milestones are not valid as sub-tasks of a combined group task and will not be displayed. No bounds checking of start and end dates of sub-tasks is performed therefore it is possible for these task bars to overlap. Dependencies can be set to and from sub-tasks only.

        +
      • +
      • + using parseXML() with an external XML file +
        JSGantt.parseXML("project.xml",g);
        +

        Method definition: + JSGantt.parseXML(pFile, pGanttObj) +

        + + + + + + + + + +
        pFile:(required) this is the filename of the XML
        pGanttObj:(required) a GanttChart object returned by a call to JSGantt.GanttChart()
        +

        The structure of the native XML file:

        +
        <project>
        +  <task>
        +    <pID>25</pID>
        +    <pName>WCF Changes</pName>
        +    <pStart></pStart>
        +    <pEnd></pEnd>
        +    <pClass>gtaskred</pClass>
        +    <pLink></pLink>
        +    <pMile>0</pMile>
        +    <pRes></pRes>
        +    <pComp>0</pComp>
        +    <pGroup>1</pGroup>
        +    <pParent>2</pParent>
        +    <pOpen>1</pOpen>
        +    <pDepend>2,24</pDepend>
        +    <pCaption>A caption</pCaption>
        +    <pNotes>Text - can include limited HTML</pNotes>
        +  </task>
        +</project>
        +

        Field definitions are as described for the parameters to TaskItem above. The pClass element is optional in XML files and will default to "ggroupblack" for group tasks, "gtaskblue" for normal tasks and "gmilestone" for milestones. The pGantt element is not required for XML import.

        +

        JSGannt Improved will also test the provided XML file to see if it appears to be in Microsoft Project XML format. If so an attempt will be made to load up the project. This feature is experimental, the import is best effort and not guaranteed. Once loaded the project as interpreted by JSGantt Improved can be extracted using the XML Export methods provided.

        +
      • +
      • + using parseXMLString() with XML held in a javascript string object +
        JSGantt.parseXMLString("<project><task>...</task></project>",g);
        +

        Method definition: + JSGantt.parseXMLString(pStr, pGanttObj) +

        + + + + + + + + + +
        pStr:(required) this is a javascript String containing XML
        pGanttObj:(required) a GanttChart object returned by a call to JSGantt.GanttChart()
        +

        The XML provided will be parsed in exactly the same way as the contents of an external XML file and hence must match the format as described for JSGantt.parseXML() above

        +
      • +
      +
    12. +
    13. +

      Call Draw()

      +
      g.Draw();
      +
    14. +
    15. +

      Close the <script> block

      +
      </script>
      +
    16. +
    +

    It is possible to add items to the chart in realtime via javascript using either direct method calls or additional XML files. + It is also possible to delete tasks using RemoveTaskItem() method. +

    +
    g.RemoveTaskItem(11);
    +

    Method definition: + RemoveTaskItem(pID) +

    + + + + + +
    pID:(required) the unique numeric ID of the item to be removed
    +

    If the task removed is a group item, all child tasks will also be removed.

    +

    After adding or removing tasks a call to "g.Draw()" must be made to redraw the chart.

    +

    Configuration Options

    +

    Switches

    +

    Many of the features of jsGanttImproved can be customised through the use of setter methods available on the GanttChart object returned by a call to JSGantt.GanttChart()

    +

    The following options take a single numeric parameter; a value of 1 will enable the describe functionality, 0 will disable it

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    setUseToolTip():Controls the display of tool tip boxes, defaults to 1 (enabled)
    setUseFade():Controls use of the fade effect when showing/hiding tool tips, defaults to 1 (enabled)
    setUseMove():Controls use of the sliding effect when changing between different task tool tips, defaults to 1 (enabled)
    setUseRowHlt():Controls the use of row mouseover highlighting, defaults to 1 (enabled)
    setUseSort():Controls whether the task list is sorted into parent task / start time order or is simply displayed in the order created, defaults to 1 (sort enabled)
    setShowRes():Controls whether the Resource column is displayed in the task list, defaults to 1 (show column)
    setShowDur():Controls whether the Task Duration column is displayed in the task list, defaults to 1 (show column)
    setShowComp():Controls whether the Percentage Complete column is displayed in the task list, defaults to 1 (show column)
    setShowStartDate():Controls whether the Task Start Date column is displayed in the task list, defaults to 1 (show column)
    setShowEndDate():Controls whether the Task End Date column is displayed in the task list, defaults to 1 (show column)
    setShowTaskInfoRes():Controls whether the Resource information is displayed in the task tool tip, defaults to 1 (show information)
    setShowTaskInfoDur():Controls whether the Task Duration information is displayed in the task tool tip, defaults to 1 (show information)
    setShowTaskInfoComp():Controls whether the Percentage Complete information is displayed in the task tool tip, defaults to 1 (show information)
    setShowTaskInfoStartDate():Controls whether the Task Start Date information is displayed in the task tool tip, defaults to 1 (show information)
    setShowTaskInfoEndDate():Controls whether the Task End Date information is displayed in the task tool tip, defaults to 1 (show information)
    setShowTaskInfoLink():Controls whether the More Information link is displayed in the task tool tip, defaults to 0 (do NOT show link)
    setShowTaskInfoNotes():Controls whether the Additional Notes data is displayed in the task tool tip, defaults to 1 (show notes)
    setShowEndWeekDate():Controls whether the major heading in "Day" view displays the week end-date in the appropriate format (see below), defaults to 1 (show date)
    setShowDeps():Controls display of dependancy lines, defaults to 1 (show dependencies)
    +

    Key Values

    +

    The following options enable functionality using a set of specific key values

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    setShowSelector():Controls where the format selector is displayed, accepts multiple parameters.
    Valid parameter values are "Top", "Bottom".
    Defaults to "Top".
    setFormatArr():Controls which format options are shown in the format selector, accepts multiple parameters.
    Valid parameter values are "Hour", "Day", "Week", "Month", "Quarter".
    Defaults to all valid values.
    setCaptionType():Controls which task field to use as a caption on the Gantt Chart task bar, accepts a single parameter.
    Valid parameter values are "None", "Caption", "Resource", "Duration", "Complete".
    Defaults to "None"
    setDateInputFormat():Defines the input format used for dates in task creation, accepts a single parameter.
    Valid parameter values are "yyyy-mm-dd", "dd/mm/yyyy", "mm/dd/yyyy".
    Defaults to "yyyy-mm-dd"
    setScrollTo():Sets the date the Gantt Chart will be scrolled to, specified in the date input format set by setDateInputFormat() above. Also accepts the special value "today"
    Defaults to minimum display date
    setUseSingleCell():Sets the threshold total number of cells at which the task list will use a single table cell for each row rather than one cell per period. Useful to improve performance on large charts. A value of 0 disables this functionality (always use multiple cells), defaults to 25000
    setLang():Sets translation to use when drawing the chart. Defaults to "en" as this is the only language provided in the base installation (see internationalization below for details on how to add more translations.)
    +

    Layout

    +

    Most of the look and feel of the Gantt Chart can be controlled using CSS however, as the length of a task bar is determined by column width, the following methods take a single numeric parameter that defines the appropriate column width in pixels.

    +

    Note that the task bar sizing code assumes the use of collapsed table borders 1px wide.

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    setHourColWidth():Width of Gantt Chart columns in pixels when drawn in "Hour" format. Defaults to 18.
    setDayColWidth():Width of Gantt Chart columns in pixels when drawn in "Day" format. Defaults to 18.
    setWeekColWidth():Width of Gantt Chart columns in pixels when drawn in "Week" format. Defaults to 36.
    setMonthColWidth():Width of Gantt Chart columns in pixels when drawn in "Month" format. Defaults to 36.
    setQuarterColWidth():Width of Gantt Chart columns in pixels when drawn in "Quarter" format, although not mandatory it is recommended that this be set to a value divisible by 3. Defaults to 18.
    setRowHeight():Height of Gantt Chart rows in pixels. Used to route dependency lines near end points. Defaults to 20.
    setMinGpLen():Group tasks have their task bars embellished with end points, this value specifies the width of one of these end points in pixels. A short task bar's length will be rounded up to display either a single or both endpoints correctly. Defaults to 8.
    +

    Display Date Formats

    +

    Date display formats can be individually controlled. The methods used to set these display formats each take a single format string parameter. The format string can be made up of the following components (case sensitive)

    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    h:Hour (1-12)
    hh:Hour (01-12)
    pm:am/pm indicator
    PM:AM/PM indicator
    H:Hour (0-23)
    HH:Hour (01-23)
    mi:Minutes (1-59)
    MI:Minutes (01-59)
    d:Day (1-31)
    dd:Day (01-31)
    day:Abbreviated day of week
    DAY:Day of week
    m:Month (1-12)
    mm:Month (01-12)
    mon:Abbreviated month text
    month:Full month text
    yy:Year, excluding century
    yyyy:Year
    q:Quarter (1-4)
    qq:Quarter (Q1-Q4)
    w:ISO Week number (1-53)
    ww:ISO Week number (01-53)
    week:Full ISO Week date format
    +

    separated by one of the following characters: "/\-.,'<space>:

    +

    Any text between separators that does not match one of the components above will be checked using a case insensitive match for a valid internationalized string (see internationalization below). If the value is still not found the text will be output unchanged.

    +
    +

    The available date display methods are

    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    setDateTaskTableDisplayFormat():Date format used for start and end dates in the main task list. Defaults to 'dd/mm/yyyy'.
    setDateTaskDisplayFormat():Date format used for start and end dates in task tool tips. Defaults to 'dd month yyyy'.
    setHourMajorDateDisplayFormat():Date format used for Gantt Chart major date headings displayed in "Hour" format. Defaults to 'day dd month yyyy'.
    setDayMajorDateDisplayFormat():Date format used for Gantt Chart major date headings displayed in "Day" format. Defaults to 'dd/mm/yyyy'.
    setWeekMajorDateDisplayFormat():Date format used for Gantt Chart major date headings displayed in "Week" format. Defaults to 'yyyy'.
    setMonthMajorDateDisplayFormat():Date format used for Gantt Chart major date headings displayed in "Month" format. Defaults to 'yyyy'.
    setQuarterMajorDateDisplayFormat():Date format used for Gantt Chart major date headings displayed in "Year" format. Defaults to 'yyyy'.
    setHourMinorDateDisplayFormat():Date format used for Gantt Chart minor date headings displayed in "Hour" format. Defaults to 'HH'.
    setDayMinorDateDisplayFormat():Date format used for Gantt Chart minor date headings displayed in "Day" format. Defaults to 'dd'.
    setWeekMinjorDateDisplayFormat():Date format used for Gantt Chart minor date headings displayed in "Week" format. Defaults to 'dd/mm'.
    setMonthMinorDateDisplayFormat():Date format used for Gantt Chart minor date headings displayed in "Month" format. Defaults to 'mon'.
    setQuarterMinorDateDisplayFormat():Date format used for Gantt Chart minor date headings displayed in "Year" format. Defaults to 'qq'.
    +

    Internationalization

    +

    jsGanttImproved only provides English text however all hard coded strings can be replaced by calling the addLang() method available on the GanttChart object returned by a call to JSGantt.GanttChart()

    +

    The addLang() method takes two parameters. The first is a string identifier for the language, the second is a javascript object containing all the replacement text pairs, the default English settings are:

    +
    + + + + + + + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    january:January
    february:February
    march:March
    april:April
    maylong:May
    june:June
    july:July
    august:August
    september:September
    october:October
    november:November
    december:December
    jan:Jan
    feb:Feb
    mar:Mar
    apr:Apr
    may:May
    jun:Jun
    jul:Jul
    aug:Aug
    sep:Sep
    oct:Oct
    nov:Nov
    dec:Dec
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    sunday:Sunday
    monday:Monday
    tuesday:Tuesday
    wednesday:Wednesday
    thursday:Thursday
    friday:Friday
    saturday:Saturday
    sun:Sun
    mon:Mon
    tue:Tue
    wed:Wed
    thu:Thu
    fri:Fri
    sat:Sat
    resource:Resource
    duration:Duration
    comp:% Comp.
    completion:Completion
    startdate:Start Date
    enddate:End Date
    moreinfo:More Information
    notes:Notes
    +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    format:Format
    hour:Hour
    day:Day
    week:Week
    month:Month
    quarter:Quarter
    hours:Hours
    days:Days
    weeks:Weeks
    months:Months
    quarters:Quarters
    hr:Hr
    dy:Day
    wk:Wk
    mth:Mth
    qtr:Qtr
    hrs:Hrs
    dys:Days
    wks:Wks
    mths:Mths
    qtrs:Qtrs
    +
    +
    +

    When adding a language any translations that are not provided will use the default English language value. This provides a simple way to override default strings e.g.

    +
    g.addLang('en2', {'format':'Select', 'comp':'Complete'});
    +

    would create a language called 'en2' where the text in the format selector was "Select" rather than "Format" and the header for the Percentage Complete column in the task list is "Complete" rather than "% Comp."

    +

    Once a translation has been added a call must be made to setLang() with the appropriate langage identifier before calling Draw().

    +

    Example Options

    +

    The configuration options used in the example chart above are:

    +
    g.setCaptionType('Complete');  // Set to Show Caption (None,Caption,Resource,Duration,Complete)
    +g.setQuarterColWidth(36);
    +g.setDateTaskDisplayFormat('day dd month yyyy'); // Shown in tool tip box
    +g.setDayMajorDateDisplayFormat('mon yyyy - Week ww'); // Set format to display dates in the "Major" header of the "Day" view
    +g.setWeekMinorDateDisplayFormat('dd mon'); // Set format to display dates in the "Minor" header of the "Week" view
    +g.setShowTaskInfoLink(1); //Show link in tool tip (0/1)
    +g.setShowEndWeekDate(0); // Show/Hide the date for the last day of the week in header for daily view (1/0)
    +g.setUseSingleCell(10000); // Set the threshold at which we will only use one cell per table row (0 disables).  Helps with rendering performance for large charts.
    +g.setFormatArr('Day', 'Week', 'Month', 'Quarter'); // Even with setUseSingleCell using Hour format on such a large chart can cause issues in some browsers
    +        
    +

    Putting all this information together the final code to produce the chart above is as follows:

    +
    <link rel="stylesheet" type="text/css" href="jsgantt.css" />
    +<script language="javascript" src="jsgantt.js"></script>
    +<div style="position:relative" class="gantt" id="GanttChartDIV"></div>
    +<script>
    +
    +var g = new JSGantt.GanttChart('g',document.getElementById('GanttChartDIV'), 'day');
    +
    +if( g.getDivId() != null ) {
    +g.setCaptionType('Complete');
    +g.setQuarterColWidth(36);
    +g.setDateTaskDisplayFormat('day dd month yyyy');
    +g.setDayMajorDateDisplayFormat('mon yyyy - Week ww');
    +g.setWeekMinorDateDisplayFormat('dd mon');
    +g.setShowTaskInfoLink(1);
    +g.setShowEndWeekDate(0);
    +g.setUseSingleCell(10000);
    +g.setFormatArr('Day', 'Week', 'Month', 'Quarter');
    +
    +g.AddTaskItem(new JSGantt.TaskItem(1,   'Define Chart API',     '',           '',          'ggroupblack',  '',       0, 'Brian',    0,   1, 0,  1, '',      '',      'Some Notes text', g ));
    +g.AddTaskItem(new JSGantt.TaskItem(11,  'Chart Object',         '2016-02-20','2016-02-20', 'gmilestone',   '',       1, 'Shlomy',   100, 0, 1,  1, '',      '',      '',      g));
    +g.AddTaskItem(new JSGantt.TaskItem(12,  'Task Objects',         '',           '',          'ggroupblack',  '',       0, 'Shlomy',   40,  1, 1,  1, '',      '',      '',      g));
    +g.AddTaskItem(new JSGantt.TaskItem(121, 'Constructor Proc',     '2016-02-21','2016-03-09', 'gtaskblue',    '',       0, 'Brian T.', 60,  0, 12, 1, '',      '',      '',      g));
    +g.AddTaskItem(new JSGantt.TaskItem(122, 'Task Variables',       '2016-03-06','2016-03-11', 'gtaskred',     '',       0, 'Brian',    60,  0, 12, 1, 121,     '',      '',      g));
    +g.AddTaskItem(new JSGantt.TaskItem(123, 'Task by Minute/Hour',  '2016-03-09','2016-03-14 12:00', 'gtaskyellow', '',  0, 'Ilan',     60,  0, 12, 1, '',      '',      '',      g));
    +g.AddTaskItem(new JSGantt.TaskItem(124, 'Task Functions',       '2016-03-09','2016-03-29', 'gtaskred',     '',       0, 'Anyone',   60,  0, 12, 1, '123SS', 'This is a caption', null, g));
    +g.AddTaskItem(new JSGantt.TaskItem(2,   'Create HTML Shell',    '2016-03-24','2016-03-24', 'gtaskyellow',  '',       0, 'Brian',    20,  0, 0,  1, 122,     '',      '',      g));
    +g.AddTaskItem(new JSGantt.TaskItem(3,   'Code Javascript',      '',           '',          'ggroupblack',  '',       0, 'Brian',    0,   1, 0,  1, '',      '',      '',      g));
    +g.AddTaskItem(new JSGantt.TaskItem(31,  'Define Variables',     '2016-02-25','2016-03-17', 'gtaskpurple',  '',       0, 'Brian',    30,  0, 3,  1, '',      'Caption 1','',   g));
    +g.AddTaskItem(new JSGantt.TaskItem(32,  'Calculate Chart Size', '2016-03-15','2016-03-24', 'gtaskgreen',   '',       0, 'Shlomy',   40,  0, 3,  1, '',      '',      '',      g));
    +g.AddTaskItem(new JSGantt.TaskItem(33,  'Draw Task Items',      '',           '',          'ggroupblack',  '',       0, 'Someone',  40,  2, 3,  1, '',      '',      '',      g));
    +g.AddTaskItem(new JSGantt.TaskItem(332, 'Task Label Table',     '2016-03-06','2016-03-09', 'gtaskblue',    '',       0, 'Brian',    60,  0, 33, 1, '',      '',      '',      g));
    +g.AddTaskItem(new JSGantt.TaskItem(333, 'Task Scrolling Grid',  '2016-03-11','2016-03-20', 'gtaskblue',    '',       0, 'Brian',    0,   0, 33, 1, '332',   '',      '',      g));
    +g.AddTaskItem(new JSGantt.TaskItem(34,  'Draw Task Bars',       '',           '',          'ggroupblack',  '',       0, 'Anybody',  60,  1, 3,  0, '',      '',      '',      g));
    +g.AddTaskItem(new JSGantt.TaskItem(341, 'Loop each Task',       '2016-03-26','2016-04-11', 'gtaskred',     '',       0, 'Brian',    60,  0, 34, 1, '',      '',      '',      g));
    +g.AddTaskItem(new JSGantt.TaskItem(342, 'Calculate Start/Stop', '2016-04-12','2016-05-18', 'gtaskpink',    '',       0, 'Brian',    60,  0, 34, 1, '',      '',      '',      g));
    +g.AddTaskItem(new JSGantt.TaskItem(343, 'Draw Task Div',        '2016-05-13','2016-05-17', 'gtaskred',     '',       0, 'Brian',    60,  0, 34, 1, '',      '',      '',      g));
    +g.AddTaskItem(new JSGantt.TaskItem(344, 'Draw Completion Div',  '2016-05-17','2016-06-04', 'gtaskred',     '',       0, 'Brian',    60,  0, 34, 1, "342,343",'',     '',      g));
    +g.AddTaskItem(new JSGantt.TaskItem(35,  'Make Updates',         '2016-07-17','2017-09-04', 'gtaskpurple',  '',       0, 'Brian',    30,  0, 3,  1, '333',   '',      '',      g));
    +
    +g.Draw();
    +}
    +else
    +{
    +alert("Error, unable to create Gantt Chart");
    +}
    +
    +</script>
    +

    XML Export

    +

    The following methods can be used to extract details of tasks in the project in XML format

    +

    Method definition: getXMLProject()

    +

    Returns a string containing the entire project in JSGantt Improved XML format. Dates will be exported in the currently defined input format as set by setDateInputFormat()

    +

    Method definition: getXMLTask(pID, pIdx)

    + + + + + + + + + +
    pID:(required) the numeric ID that identifies the task to extract
    pIdx:(optional) Boolean - if present and set to "true" the number passed in the pID parameter is treated as an array index for the task list rather than an ID
    +

    Returns a string containing the specified task item in JSGantt Improved XML format. Dates will be exported in the currently defined input format as set by setDateInputFormat()

    +
    + +
    +

    Credits

    +
    +
    + Eduardo Rodrigues +
    +

    Eduardo Rodrigues

    +

    Developer

    +
    + +
    +
    +
    +
    + Ricardo Cardoso +
    +

    Ricardo Cardoso

    +

    Developer

    +
    + +
    +
    +
    +
    +
    + + + + + + + diff --git a/htdocs/includes/jsgantt/jsgantt.css b/htdocs/includes/jsgantt/jsgantt.css index 78a7e83e971..f8f58017cca 100644 --- a/htdocs/includes/jsgantt/jsgantt.css +++ b/htdocs/includes/jsgantt/jsgantt.css @@ -1,5 +1,5 @@ -/* Sample CSS for jsGanttImproved v1.7.3 */ -div.gantt { font-family:tahoma, arial, verdana, Sans-serif; font-size:10px; color: #2F2F2F; } +/* Sample CSS for jsGanttImproved v1.7.5.4 */ +div.gantt { font-family:tahoma, arial, verdana, Sans-serif; font-size:10px; color: #656565; } .gantt table { border-collapse: collapse; } .gantt td { padding: 0px; } @@ -42,7 +42,7 @@ td.gspanning { border-left: none; border-right: none; } .genddate { text-align: center; min-width: 70px; max-width: 70px; width: 70px; font-size: 10px; } .gtaskheading { text-align: center; } .gtaskname div, /* needed for IE8 */ -.gtaskname { min-width: 170px; max-width: 170px; width: 170px;/* font-size: 9px;*/ border-left: none; } +.gtaskname { min-width: 170px; max-width: 170px; width: 170px; font-size: 9px; border-left: none; } .gselector { text-align: left; white-space: nowrap; min-width: 170px; max-width: 170px; width: 170px; } @@ -62,7 +62,7 @@ span.gfoldercollapse { color:#000000; cursor:pointer; font-weight:bold; font-si .glineitem { background-color: #ffffff; } /* highlight row (applied to row) */ -.gitemhighlight td { background-image: none; background-color: #fffaaa;} +.gitemhighlight td { background-image: none; background-color: #fffde5;} /* task bar caption text styles */ .gmilecaption, @@ -98,34 +98,34 @@ span.gfoldercollapse { color:#000000; cursor:pointer; font-weight:bold; font-si .ggroupblackendpointright { overflow: hidden; width:0px; height:0px; top: 2px; border-top: 4px solid black; border-left: 4px solid transparent; border-bottom: 4px solid transparent; border-right: 4px solid transparent; float: right; } .ggroupblackcomplete { float:left; overflow: hidden; height:3px; filter: alpha(opacity=80); opacity:0.8; background-color:#777777; margin-top:2px; margin-bottom: 2px; } .gtaskblue { - background: rgb(58,132,195); /* Old browsers */ - background: linear-gradient(to bottom, rgba(58,132,195,1) 0%,rgba(65,154,214,1) 20%,rgba(75,184,240,1) 40%,rgba(58,139,194,1) 70%,rgba(38,85,139,1) 100%); /* W3C */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#4bb8f0', endColorstr='#3a84c3',GradientType=0 ); /* IE6-9 */ + background: rgb(58,132,195); /* Old browsers */ + background: linear-gradient(to bottom, rgba(58,132,195,1) 0%,rgba(65,154,214,1) 20%,rgba(75,184,240,1) 40%,rgba(58,139,194,1) 70%,rgba(38,85,139,1) 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#4bb8f0', endColorstr='#3a84c3',GradientType=0 ); /* IE6-9 */ } .gtaskred { - background: rgb(196,58,58); /* Old browsers */ - background: linear-gradient(to bottom, rgba(196,58,58,1) 0%,rgba(211,65,65,1) 20%,rgba(239,76,76,1) 40%,rgba(196,58,58,1) 70%,rgba(135,37,37,1) 100%); /* W3C */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ef4c4c', endColorstr='#c43a3a',GradientType=0 ); /* IE6-9 */ + background: rgb(196,58,58); /* Old browsers */ + background: linear-gradient(to bottom, rgba(196,58,58,1) 0%,rgba(211,65,65,1) 20%,rgba(239,76,76,1) 40%,rgba(196,58,58,1) 70%,rgba(135,37,37,1) 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ef4c4c', endColorstr='#c43a3a',GradientType=0 ); /* IE6-9 */ } .gtaskgreen { - background: rgb(80,193,58); /* Old browsers */ - background: linear-gradient(to bottom, rgba(80,193,58,1) 0%,rgba(88,209,64,1) 20%,rgba(102,237,75,1) 40%,rgba(80,193,58,1) 70%,rgba(53,132,37,1) 100%); /* W3C */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#66ED4B', endColorstr='#50c13a',GradientType=0 ); /* IE6-9 */ + background: rgb(80,193,58); /* Old browsers */ + background: linear-gradient(to bottom, rgba(80,193,58,1) 0%,rgba(88,209,64,1) 20%,rgba(102,237,75,1) 40%,rgba(80,193,58,1) 70%,rgba(53,132,37,1) 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#66ED4B', endColorstr='#50c13a',GradientType=0 ); /* IE6-9 */ } .gtaskyellow { - background: rgb(247,228,56); /* Old browsers */ - background: linear-gradient(to bottom, rgba(247,228,56,1) 0%,rgba(239,239,55,1) 20%,rgba(255,255,58,1) 40%,rgba(242,236,55,1) 70%,rgba(241,218,54,1) 100%); /* W3C */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffff3a', endColorstr='#f7e438',GradientType=0 ); /* IE6-9 */ + background: rgb(247,228,56); /* Old browsers */ + background: linear-gradient(to bottom, rgba(247,228,56,1) 0%,rgba(239,239,55,1) 20%,rgba(255,255,58,1) 40%,rgba(242,236,55,1) 70%,rgba(241,218,54,1) 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ffff3a', endColorstr='#f7e438',GradientType=0 ); /* IE6-9 */ } .gtaskpurple { - background: rgb(193,58,193); /* Old browsers */ - background: linear-gradient(to bottom, rgba(193,58,193,1) 0%,rgba(211,65,211,1) 20%,rgba(239,76,239,1) 40%,rgba(193,58,193,1) 70%,rgba(137,38,137,1) 100%); /* W3C */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ef4cef', endColorstr='#892689',GradientType=0 ); /* IE6-9 */ + background: rgb(193,58,193); /* Old browsers */ + background: linear-gradient(to bottom, rgba(193,58,193,1) 0%,rgba(211,65,211,1) 20%,rgba(239,76,239,1) 40%,rgba(193,58,193,1) 70%,rgba(137,38,137,1) 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#ef4cef', endColorstr='#892689',GradientType=0 ); /* IE6-9 */ } .gtaskpink { - background: rgb(249,177,245); /* Old browsers */ - background: linear-gradient(to bottom, rgba(249,177,245,1) 0%,rgba(247,192,243,1) 20%,rgba(247,202,244,1) 40%,rgba(249,192,246,1) 70%,rgba(252,174,247,1) 100%); /* W3C */ - filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f7caf4', endColorstr='#fcaef7',GradientType=0 ); /* IE6-9 */ + background: rgb(249,177,245); /* Old browsers */ + background: linear-gradient(to bottom, rgba(249,177,245,1) 0%,rgba(247,192,243,1) 20%,rgba(247,202,244,1) 40%,rgba(249,192,246,1) 70%,rgba(252,174,247,1) 100%); /* W3C */ + filter: progid:DXImageTransform.Microsoft.gradient( startColorstr='#f7caf4', endColorstr='#fcaef7',GradientType=0 ); /* IE6-9 */ } .gtaskbluecomplete, .gtaskredcomplete, @@ -137,21 +137,21 @@ span.gfoldercollapse { color:#000000; cursor:pointer; font-weight:bold; font-si /* Printer friendly styles - we could use these all the time but they are not as pretty! */ /* note that "@media print" is not supported in IE6 or 7. Fully patched IE8 should be OK */ @media print { - .ggroupblack { height:0px; border-top: 7px solid; border-color: #000000; } - .gtaskblue { height:0px; border-top: 13px solid; border-color: rgb(58,132,195); } - .gtaskred { height:0px; border-top: 13px solid; border-color: rgb(196,58,58); } - .gtaskgreen { height:0px; border-top: 13px solid; border-color: rgb(80,193,58); } - .gtaskyellow { height:0px; border-top: 13px solid; border-color: rgb(247,228,56); } - .gtaskpurple { height:0px; border-top: 13px solid; border-color: rgb(193,58,193); } - .gtaskpink { height:0px; border-top: 13px solid; border-color: rgb(249,177,245); } + .ggroupblack { height:0px; border-top: 7px solid; border-color: #000000; } + .gtaskblue { height:0px; border-top: 13px solid; border-color: rgb(58,132,195); } + .gtaskred { height:0px; border-top: 13px solid; border-color: rgb(196,58,58); } + .gtaskgreen { height:0px; border-top: 13px solid; border-color: rgb(80,193,58); } + .gtaskyellow { height:0px; border-top: 13px solid; border-color: rgb(247,228,56); } + .gtaskpurple { height:0px; border-top: 13px solid; border-color: rgb(193,58,193); } + .gtaskpink { height:0px; border-top: 13px solid; border-color: rgb(249,177,245); } - .gtaskbluecomplete, - .gtaskredcomplete, - .gtaskgreencomplete, - .gtaskyellowcomplete, - .gtaskpurplecomplete, - .gtaskpinkcomplete { height:0px; filter: alpha(opacity=40); opacity:0.4; margin-top: -9px; border-top: 5px solid; border-color: #000000; } - .ggroupblackcomplete { height: 0px; filter: alpha(opacity=80); opacity:0.8; margin-top:-5px; border-top:3px solid; border-color:#777777; } + .gtaskbluecomplete, + .gtaskredcomplete, + .gtaskgreencomplete, + .gtaskyellowcomplete, + .gtaskpurplecomplete, + .gtaskpinkcomplete { height:0px; filter: alpha(opacity=40); opacity:0.4; margin-top: -9px; border-top: 5px solid; border-color: #000000; } + .ggroupblackcomplete { height: 0px; filter: alpha(opacity=80); opacity:0.8; margin-top:-5px; border-top:3px solid; border-color:#777777; } } /* END Task bar styles */ @@ -161,11 +161,11 @@ span.gfoldercollapse { color:#000000; cursor:pointer; font-weight:bold; font-si .gDepFS, .gDepSS, .gDepSF, -.gDepFF { border-color: #26558b; } +.gDepFF { border-color: #ff0000; } .gDepFSArw, -.gDepSSArw { overflow: hidden; width:0px; height:0px; border-bottom: 4px solid transparent; border-left: 4px solid #26558b; border-top: 4px solid transparent; border-right: 4px solid transparent;} +.gDepSSArw { overflow: hidden; width:0px; height:0px; border-bottom: 4px solid transparent; border-left: 4px solid #ff0000; border-top: 4px solid transparent; border-right: 4px solid transparent;} .gDepFFArw, -.gDepSFArw { overflow: hidden; width:0px; height:0px; border-bottom: 4px solid transparent; border-left: 4px solid transparent; border-top: 4px solid transparent; border-right: 4px solid #26558b;} +.gDepSFArw { overflow: hidden; width:0px; height:0px; border-bottom: 4px solid transparent; border-left: 4px solid transparent; border-top: 4px solid transparent; border-right: 4px solid #ff0000;} .gCurDate { border-color: #0000ff; } @@ -180,29 +180,30 @@ div.gtaskbarcontainer { z-index: 1; position: absolute; top: 0px } .gTaskNotes {font-size: 11px; font-weight: normal; color: #323232; padding: 0 15px; display: block;} .gTIn {padding-top: 10px;} -.gantt { min-width: 1064px; /* 2x LC width */ } -.gchartcontainer { padding-left: 532px; /* LC width */ } -.gcontainercol { position: relative; float: left; } /* Add a max-height value here if wanted */ -.glistgrid { width: 532px; /* LC width */ margin-left: -100%; right: 532px; /* LC width */ padding-right: 0px; padding-left: 0px; padding-bottom: 0px; padding-top: 0px; background-color: #ffffff; overflow: hidden; } -.glistlbl { width: 532px; /* LC width */ margin-left: -100%; right: 532px; /* LC width */ padding-right: 0px; padding-left: 0px; padding-bottom: 0px; padding-top: 0px; background-color: #ffffff; overflow: hidden; } +.gantt { min-width: 632px; /* 2x LC width */ } +.gchartcontainer { /* padding-left: 532px; LC width */ line-height: 1; /* Overrides inherited CSS (e.g. from Bootstrap) */ } +.gcontainercol { position: relative; } /* Add a max-height value here if wanted */ +.glistgrid { width: 532px; /* LC width */ float: left; /* LC width */ padding-right: 0px; padding-left: 0px; padding-bottom: 0px; padding-top: 0px; background-color: #ffffff; overflow: hidden; } +.glistlbl { width: 532px; /* LC width */ float: left; /* LC width */ padding-right: 0px; padding-left: 0px; padding-bottom: 0px; padding-top: 0px; background-color: #ffffff; overflow: hidden; } .glabelfooter { clear: both; } .ggridfooter { clear: both; } -/*.rhscrpad { width: 150px; position: absolute; top: 0px; height: 1px; }*/ +.rhscrpad { width: 150px; position: absolute; top: 0px; height: 1px; } -.gchartgrid { width: 100%; padding-right: 0px; padding-left: 0px; padding-bottom: 0px; padding-top: 0px; background-color: #ffffff; position: relative; overflow: auto; min-height: 0%; } -.gchartlbl { width: 100%; padding-right: 0px; padding-left: 0px; padding-bottom: 0px; padding-top: 0px; background-color: #ffffff; position: relative; overflow: hidden; } +.gchartgrid { padding-right: 0px; padding-left: 0px; padding-bottom: 0px; padding-top: 0px; background-color: #ffffff; position: relative; overflow: auto; min-height: 0%; } +.gchartlbl { padding-right: 0px; padding-left: 0px; padding-bottom: 0px; padding-top: 0px; background-color: #ffffff; position: relative; overflow: hidden; } /* Old Internet Explorer version hacks */ .gantt { _height: 100% } /* otherwise the chart disappears! */ -div .gantt { _width: 1064px; } /* ie6 fixed width */ +div .gantt { /* _width: 1064px; ie6 fixed width */ } div.gchartlbl, -div.gchartgrid { _width: 532px; } /* ie6 fixed width */ +div.gchartgrid {/* _width: 532px; */} /* ie6 fixed width */ div.glistlbl, div.glistgrid { - *right: 0px; /* ie7 pulls the content too far left with the negative margin */ - _right: 532px; /* but ie6 fixed width needs this */ - _margin-left: -532px; /* ie6 fixed width */ + *right: 0px; /* ie7 pulls the content too far left with the negative margin */ + _right: 532px; /* but ie6 fixed width needs this */ + _margin-left: -532px; /* ie6 fixed width */ + float: left; } div.gchartgrid { *padding-bottom: 20px; *overflow-y: hidden; } /* variable height design, no need for vertical scroll */ td.gmajorheading div { *overflow: hidden; } /* stops resizing fixed width columns if the text is too wide */ diff --git a/htdocs/includes/jsgantt/jsgantt.js b/htdocs/includes/jsgantt/jsgantt.js index 3360d832ec6..7a26eecb9fc 100644 --- a/htdocs/includes/jsgantt/jsgantt.js +++ b/htdocs/includes/jsgantt/jsgantt.js @@ -1,68 +1,67 @@ /* - _ ___ _____ _ _____ ____ ____ - (_) / _ \ \_ \ / ||___ | ___| |___ \ - | |/ /_\/ / /\/ | | / /|___ \ __) | - | / /_\\/\/ /_ | |_ / /_ ___) | / __/ - _/ \____/\____/ |_(_)_/(_)____(_)_____| - |__/ - jsGanttImproved 1.7.5.2 - Copyright (c) 2013-2016, Paul Geldart All rights reserved. + _ ___ _ _ _____ _ + (_)___ / _ \__ _ _ __ | |_| |_ \_ \_ __ ___ _ __ _ __ _____ _____ __| | + | / __| / /_\/ _` | '_ \| __| __| / /\/ '_ ` _ \| '_ \| '__/ _ \ \ / / _ \/ _` | + | \__ \/ /_\\ (_| | | | | |_| |_/\/ /_ | | | | | | |_) | | | (_) \ V / __/ (_| | + _/ |___/\____/\__,_|_| |_|\__|\__\____/ |_| |_| |_| .__/|_| \___/ \_/ \___|\__,_| + |__/ |_| + jsGanttImproved 1.7.5.4 - The current version of this code can be found at https://code.google.com/p/jsgantt-improved/ + The current version of this code can be found at https://github.com/jsGanttImproved/jsgantt-improved/ - * Copyright (c) 2013-2016, Paul Geldart. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Paul Geldart nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY PAUL GELDART. ''AS IS'' AND ANY EXPRESS OR - * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES - * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL PAUL GELDART BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * Copyright (c) 2013-2017, Paul Geldart, Eduardo Rodrigues and Ricardo Cardoso. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Paul Geldart, Eduardo Rodrigues and Ricardo Cardoso nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY PAUL GELDART, EDUARDO RODRIGUES AND RICARDO CARDOSO ''AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL PAUL GELDART, EDUARDO RODRIGUES AND RICARDO CARDOSO BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - This project is based on jsGantt 1.2, (which can be obtained from - https://code.google.com/p/jsgantt/) and remains under the original BSD license. - The original project license follows: + This project is based on jsGantt 1.2, (which can be obtained from + https://code.google.com/p/jsgantt/) and remains under the original BSD license. + The original project license follows: - Copyright (c) 2009, Shlomy Gantz BlueBrick Inc. All rights reserved. + Copyright (c) 2009, Shlomy Gantz BlueBrick Inc. All rights reserved. - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of Shlomy Gantz or BlueBrick Inc. nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY SHLOMY GANTZ/BLUEBRICK INC. ''AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL SHLOMY GANTZ/BLUEBRICK INC. BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of Shlomy Gantz or BlueBrick Inc. nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY SHLOMY GANTZ/BLUEBRICK INC. ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL SHLOMY GANTZ/BLUEBRICK INC. BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ var JSGantt; if (!JSGantt) JSGantt={}; @@ -70,202 +69,205 @@ var vBenchTime=new Date().getTime(); JSGantt.isIE=function () { - if(typeof document.all!='undefined') - { - if ('pageXOffset' in window) return false; // give IE9 and above the benefit of the doubt! - else return true; - } - else return false; + if(typeof document.all!='undefined') + { + if ('pageXOffset' in window) return false; // give IE9 and above the benefit of the doubt! + else return true; + } + else return false; }; JSGantt.TaskItem=function(pID, pName, pStart, pEnd, pClass, pLink, pMile, pRes, pComp, pGroup, pParent, pOpen, pDepend, pCaption, pNotes, pGantt) { - var vID=parseInt(document.createTextNode(pID).data); - var vName=document.createTextNode(pName).data; - var vStart=new Date(0); - var vEnd=new Date(0); - var vGroupMinStart=null; - var vGroupMinEnd=null; - var vClass=document.createTextNode(pClass).data; - var vLink=document.createTextNode(pLink).data; - var vMile=parseInt(document.createTextNode(pMile).data); - var vRes=document.createTextNode(pRes).data; - var vComp=parseFloat(document.createTextNode(pComp).data); - var vGroup=parseInt(document.createTextNode(pGroup).data); - var vParent=document.createTextNode(pParent).data; - var vOpen=(vGroup==2)?1:parseInt(document.createTextNode(pOpen).data); - var vDepend=new Array(); - var vDependType=new Array(); - var vCaption=document.createTextNode(pCaption).data; - var vDuration=''; - var vLevel=0; - var vNumKid=0; - var vVisible=1; - var vSortIdx=0; - var vToDelete=false; - var x1, y1, x2, y2; - var vNotes; - var vParItem=null; - var vCellDiv=null; - var vGantt=(pGantt instanceof JSGantt.GanttChart)? pGantt : g; //hack for backwards compatibility - var vBarDiv=null; - var vTaskDiv=null; - var vListChildRow=null; - var vChildRow=null; - var vGroupSpan=null; + var vID=parseInt(document.createTextNode(pID).data); + var vName=document.createTextNode(pName).data; + var vStart=new Date(0); + var vEnd=new Date(0); + var vGroupMinStart=null; + var vGroupMinEnd=null; + var vClass=document.createTextNode(pClass).data; + var vLink=document.createTextNode(pLink).data; + var vMile=parseInt(document.createTextNode(pMile).data); + var vRes=document.createTextNode(pRes).data; + var vComp=parseFloat(document.createTextNode(pComp).data); + var vGroup=parseInt(document.createTextNode(pGroup).data); + var vParent=document.createTextNode(pParent).data; + var vOpen=(vGroup==2)?1:parseInt(document.createTextNode(pOpen).data); + var vDepend=new Array(); + var vDependType=new Array(); + var vCaption=document.createTextNode(pCaption).data; + var vDuration=''; + var vLevel=0; + var vNumKid=0; + var vWeight=0; + var vVisible=1; + var vSortIdx=0; + var vToDelete=false; + var x1, y1, x2, y2; + var vNotes; + var vParItem=null; + var vCellDiv=null; + var vGantt=(pGantt instanceof JSGantt.GanttChart)? pGantt : g; //hack for backwards compatibility + var vBarDiv=null; + var vTaskDiv=null; + var vListChildRow=null; + var vChildRow=null; + var vGroupSpan=null; - vNotes=document.createElement('span'); - vNotes.className='gTaskNotes'; - if (pNotes!=null) - { - vNotes.innerHTML=pNotes; - JSGantt.stripUnwanted(vNotes); - } + vNotes=document.createElement('span'); + vNotes.className='gTaskNotes'; + if (pNotes!=null) + { + vNotes.innerHTML=pNotes; + JSGantt.stripUnwanted(vNotes); + } - if (pStart!=null && pStart!='') - { - vStart=(pStart instanceof Date)?pStart:JSGantt.parseDateStr(document.createTextNode(pStart).data,vGantt.getDateInputFormat()); - vGroupMinStart=vStart; - } + if (pStart!=null && pStart!='') + { + vStart=(pStart instanceof Date)?pStart:JSGantt.parseDateStr(document.createTextNode(pStart).data,vGantt.getDateInputFormat()); + vGroupMinStart=vStart; + } - if (pEnd!=null && pEnd!='') - { - vEnd =(pEnd instanceof Date)?pEnd:JSGantt.parseDateStr(document.createTextNode(pEnd).data,vGantt.getDateInputFormat()); - vGroupMinEnd=vEnd; - } + if (pEnd!=null && pEnd!='') + { + vEnd =(pEnd instanceof Date)?pEnd:JSGantt.parseDateStr(document.createTextNode(pEnd).data,vGantt.getDateInputFormat()); + vGroupMinEnd=vEnd; + } - if (pDepend!=null) - { - var vDependStr=pDepend+''; - var vDepList=vDependStr.split(','); - var n=vDepList.length; + if (pDepend!=null) + { + var vDependStr=pDepend+''; + var vDepList=vDependStr.split(','); + var n=vDepList.length; - for(var k=0;k1) - { - vFormatArr[j++]=arguments[i].toLowerCase(); - var vRegExp=new RegExp('(?:^|\s)'+arguments[i]+'(?!\S)', 'g'); - vValidFormats=vValidFormats.replace(vRegExp, ''); - } - } - }; - this.setShowRes=function(pVal){vShowRes=pVal;}; - this.setShowDur=function(pVal){vShowDur=pVal;}; - this.setShowComp=function(pVal){vShowComp=pVal;}; - this.setShowStartDate=function(pVal){vShowStartDate=pVal;}; - this.setShowEndDate=function(pVal){vShowEndDate=pVal;}; - this.setShowTaskInfoRes=function(pVal){vShowTaskInfoRes=pVal;}; - this.setShowTaskInfoDur=function(pVal){vShowTaskInfoDur=pVal;}; - this.setShowTaskInfoComp=function(pVal){vShowTaskInfoComp=pVal;}; - this.setShowTaskInfoStartDate=function(pVal){vShowTaskInfoStartDate=pVal;}; - this.setShowTaskInfoEndDate=function(pVal){vShowTaskInfoEndDate=pVal;}; - this.setShowTaskInfoNotes=function(pVal){vShowTaskInfoNotes=pVal;}; - this.setShowTaskInfoLink=function(pVal){vShowTaskInfoLink=pVal;}; - this.setShowEndWeekDate=function(pVal){vShowEndWeekDate=pVal;}; - this.setShowSelector=function() - { - var vValidSelectors='top bottom'; - vShowSelector=new Array(); - for(var i=0, j=0; i1) - { - vShowSelector[j++]=arguments[i].toLowerCase(); - var vRegExp=new RegExp('(?:^|\s)'+arguments[i]+'(?!\S)', 'g'); - vValidSelectors=vValidSelectors.replace(vRegExp, ''); - } - } - }; - this.setShowDeps=function(pVal){vShowDeps=pVal;}; - this.setDateInputFormat=function(pVal){vDateInputFormat=pVal;}; - this.setDateTaskTableDisplayFormat=function(pVal){vDateTaskTableDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; - this.setDateTaskDisplayFormat=function(pVal){vDateTaskDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; - this.setHourMajorDateDisplayFormat=function(pVal){vHourMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; - this.setHourMinorDateDisplayFormat=function(pVal){vHourMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; - this.setDayMajorDateDisplayFormat=function(pVal){vDayMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; - this.setDayMinorDateDisplayFormat=function(pVal){vDayMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; - this.setWeekMajorDateDisplayFormat=function(pVal){vWeekMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; - this.setWeekMinorDateDisplayFormat=function(pVal){vWeekMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; - this.setMonthMajorDateDisplayFormat=function(pVal){vMonthMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; - this.setMonthMinorDateDisplayFormat=function(pVal){vMonthMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; - this.setQuarterMajorDateDisplayFormat=function(pVal){vQuarterMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; - this.setQuarterMinorDateDisplayFormat=function(pVal){vQuarterMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; - this.setCaptionType=function(pType){vCaptionType=pType;}; - this.setFormat=function(pFormat) - { - vFormat=pFormat; - this.Draw(); - }; - this.setMinGpLen=function(pMinGpLen){vMinGpLen=pMinGpLen;}; - this.setScrollTo=function(pDate){vScrollTo=pDate;}; - this.setHourColWidth=function(pWidth){vHourColWidth=pWidth;}; - this.setDayColWidth=function(pWidth){vDayColWidth=pWidth;}; - this.setWeekColWidth=function(pWidth){vWeekColWidth=pWidth;}; - this.setMonthColWidth=function(pWidth){vMonthColWidth=pWidth;}; - this.setQuarterColWidth=function(pWidth){vQuarterColWidth=pWidth;}; - this.setRowHeight=function(pHeight){vRowHeight=pHeight;}; - this.setLang=function(pLang){if(vLangs[pLang])vLang=pLang;}; - this.setChartBody=function(pDiv){if(typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)vChartBody=pDiv;}; - this.setChartHead=function(pDiv){if(typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)vChartHead=pDiv;}; - this.setListBody=function(pDiv){if(typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)vListBody=pDiv;}; - this.setChartTable=function(pTable){if(typeof HTMLTableElement !== 'function' || pTable instanceof HTMLTableElement)vChartTable=pTable;}; - this.setLines=function(pDiv){if(typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)vLines=pDiv;}; - this.setTimer=function(pVal){vTimer=pVal*1;}; - this.addLang=function(pLang, pVals){ - if(!vLangs[pLang]) - { - vLangs[pLang]=new Object(); - for(var vKey in vLangs['en'])vLangs[pLang][vKey]=(pVals[vKey])?document.createTextNode(pVals[vKey]).data:vLangs['en'][vKey]; - } - }; + this.setUseFade=function(pVal){vUseFade=pVal;}; + this.setUseMove=function(pVal){vUseMove=pVal;}; + this.setUseRowHlt=function(pVal){vUseRowHlt=pVal;}; + this.setUseToolTip=function(pVal){vUseToolTip=pVal;}; + this.setUseSort=function(pVal){vUseSort=pVal;}; + this.setUseSingleCell=function(pVal){vUseSingleCell=pVal*1;}; + this.setFormatArr=function() + { + var vValidFormats='hour day week month quarter'; + vFormatArr=new Array(); + for(var i=0, j=0; i1) + { + vFormatArr[j++]=arguments[i].toLowerCase(); + var vRegExp=new RegExp('(?:^|\s)'+arguments[i]+'(?!\S)', 'g'); + vValidFormats=vValidFormats.replace(vRegExp, ''); + } + } + }; + this.setShowRes=function(pVal){vShowRes=pVal;}; + this.setShowDur=function(pVal){vShowDur=pVal;}; + this.setShowComp=function(pVal){vShowComp=pVal;}; + this.setShowStartDate=function(pVal){vShowStartDate=pVal;}; + this.setShowEndDate=function(pVal){vShowEndDate=pVal;}; + this.setShowTaskInfoRes=function(pVal){vShowTaskInfoRes=pVal;}; + this.setShowTaskInfoDur=function(pVal){vShowTaskInfoDur=pVal;}; + this.setShowTaskInfoComp=function(pVal){vShowTaskInfoComp=pVal;}; + this.setShowTaskInfoStartDate=function(pVal){vShowTaskInfoStartDate=pVal;}; + this.setShowTaskInfoEndDate=function(pVal){vShowTaskInfoEndDate=pVal;}; + this.setShowTaskInfoNotes=function(pVal){vShowTaskInfoNotes=pVal;}; + this.setShowTaskInfoLink=function(pVal){vShowTaskInfoLink=pVal;}; + this.setShowEndWeekDate=function(pVal){vShowEndWeekDate=pVal;}; + this.setShowSelector=function() + { + var vValidSelectors='top bottom'; + vShowSelector=new Array(); + for(var i=0, j=0; i1) + { + vShowSelector[j++]=arguments[i].toLowerCase(); + var vRegExp=new RegExp('(?:^|\s)'+arguments[i]+'(?!\S)', 'g'); + vValidSelectors=vValidSelectors.replace(vRegExp, ''); + } + } + }; + this.setShowDeps=function(pVal){vShowDeps=pVal;}; + this.setDateInputFormat=function(pVal){vDateInputFormat=pVal;}; + this.setDateTaskTableDisplayFormat=function(pVal){vDateTaskTableDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; + this.setDateTaskDisplayFormat=function(pVal){vDateTaskDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; + this.setHourMajorDateDisplayFormat=function(pVal){vHourMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; + this.setHourMinorDateDisplayFormat=function(pVal){vHourMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; + this.setDayMajorDateDisplayFormat=function(pVal){vDayMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; + this.setDayMinorDateDisplayFormat=function(pVal){vDayMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; + this.setWeekMajorDateDisplayFormat=function(pVal){vWeekMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; + this.setWeekMinorDateDisplayFormat=function(pVal){vWeekMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; + this.setMonthMajorDateDisplayFormat=function(pVal){vMonthMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; + this.setMonthMinorDateDisplayFormat=function(pVal){vMonthMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; + this.setQuarterMajorDateDisplayFormat=function(pVal){vQuarterMajorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; + this.setQuarterMinorDateDisplayFormat=function(pVal){vQuarterMinorDateDisplayFormat=JSGantt.parseDateFormatStr(pVal);}; + this.setCaptionType=function(pType){vCaptionType=pType;}; + this.setFormat=function(pFormat) + { + vFormat=pFormat; + this.Draw(); + }; + this.setMinGpLen=function(pMinGpLen){vMinGpLen=pMinGpLen;}; + this.setScrollTo=function(pDate){vScrollTo=pDate;}; + this.setHourColWidth=function(pWidth){vHourColWidth=pWidth;}; + this.setDayColWidth=function(pWidth){vDayColWidth=pWidth;}; + this.setWeekColWidth=function(pWidth){vWeekColWidth=pWidth;}; + this.setMonthColWidth=function(pWidth){vMonthColWidth=pWidth;}; + this.setQuarterColWidth=function(pWidth){vQuarterColWidth=pWidth;}; + this.setRowHeight=function(pHeight){vRowHeight=pHeight;}; + this.setLang=function(pLang){if(vLangs[pLang])vLang=pLang;}; + this.setChartBody=function(pDiv){if(typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)vChartBody=pDiv;}; + this.setChartHead=function(pDiv){if(typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)vChartHead=pDiv;}; + this.setListBody=function(pDiv){if(typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)vListBody=pDiv;}; + this.setChartTable=function(pTable){if(typeof HTMLTableElement !== 'function' || pTable instanceof HTMLTableElement)vChartTable=pTable;}; + this.setLines=function(pDiv){if(typeof HTMLDivElement !== 'function' || pDiv instanceof HTMLDivElement)vLines=pDiv;}; + this.setTimer=function(pVal){vTimer=pVal*1;}; + this.addLang=function(pLang, pVals){ + if(!vLangs[pLang]) + { + vLangs[pLang]=new Object(); + for(var vKey in vLangs['en'])vLangs[pLang][vKey]=(pVals[vKey])?document.createTextNode(pVals[vKey]).data:vLangs['en'][vKey]; + } + }; - this.getDivId=function(){return vDivId;}; - this.getUseFade=function(){return vUseFade;}; - this.getUseMove=function(){return vUseMove;}; - this.getUseRowHlt=function(){return vUseRowHlt;}; - this.getUseToolTip=function(){return vUseToolTip;}; - this.getUseSort=function(){return vUseSort;}; - this.getUseSingleCell=function(){return vUseSingleCell;}; - this.getFormatArr=function(){return vFormatArr;}; - this.getShowRes=function(){return vShowRes;}; - this.getShowDur=function(){return vShowDur;}; - this.getShowComp=function(){return vShowComp;}; - this.getShowStartDate=function(){return vShowStartDate;}; - this.getShowEndDate=function(){return vShowEndDate;}; - this.getShowTaskInfoRes=function(){return vShowTaskInfoRes;}; - this.getShowTaskInfoDur=function(){return vShowTaskInfoDur;}; - this.getShowTaskInfoComp=function(){return vShowTaskInfoComp;}; - this.getShowTaskInfoStartDate=function(){return vShowTaskInfoStartDate;}; - this.getShowTaskInfoEndDate=function(){return vShowTaskInfoEndDate;}; - this.getShowTaskInfoNotes=function(){return vShowTaskInfoNotes;}; - this.getShowTaskInfoLink=function(){return vShowTaskInfoLink;}; - this.getShowEndWeekDate=function(){return vShowEndWeekDate;}; - this.getShowSelector=function(){return vShowSelector;}; - this.getShowDeps=function(){return vShowDeps;}; - this.getDateInputFormat=function(){return vDateInputFormat;}; - this.getDateTaskTableDisplayFormat=function(){return vDateTaskTableDisplayFormat;}; - this.getDateTaskDisplayFormat=function(){return vDateTaskDisplayFormat;}; - this.getHourMajorDateDisplayFormat=function(){return vHourMajorDateDisplayFormat;}; - this.getHourMinorDateDisplayFormat=function(){return vHourMinorDateDisplayFormat;}; - this.getDayMajorDateDisplayFormat=function(){return vDayMajorDateDisplayFormat;}; - this.getDayMinorDateDisplayFormat=function(){return vDayMinorDateDisplayFormat;}; - this.getWeekMajorDateDisplayFormat=function(){return vWeekMajorDateDisplayFormat;}; - this.getWeekMinorDateDisplayFormat=function(){return vWeekMinorDateDisplayFormat;}; - this.getMonthMajorDateDisplayFormat=function(){return vMonthMajorDateDisplayFormat;}; - this.getMonthMinorDateDisplayFormat=function(){return vMonthMinorDateDisplayFormat;}; - this.getQuarterMajorDateDisplayFormat=function(){return vQuarterMajorDateDisplayFormat;}; - this.getQuarterMinorDateDisplayFormat=function(){return vQuarterMinorDateDisplayFormat;}; - this.getCaptionType=function(){return vCaptionType;}; - this.getMinGpLen=function(){return vMinGpLen;}; - this.getScrollTo=function(){return vScrollTo;}; - this.getHourColWidth=function(){return vHourColWidth;}; - this.getDayColWidth=function(){return vDayColWidth;}; - this.getWeekColWidth=function(){return vWeekColWidth;}; - this.getMonthColWidth=function(){return vMonthColWidth;}; - this.getQuarterColWidth=function(){return vQuarterColWidth;}; - this.getRowHeight=function(){return vRowHeight;}; - this.getChartBody=function(){return vChartBody;}; - this.getChartHead=function(){return vChartHead;}; - this.getListBody=function(){return vListBody;}; - this.getChartTable=function(){return vChartTable;}; - this.getLines=function(){return vLines;}; - this.getTimer=function(){return vTimer;}; + this.getDivId=function(){return vDivId;}; + this.getUseFade=function(){return vUseFade;}; + this.getUseMove=function(){return vUseMove;}; + this.getUseRowHlt=function(){return vUseRowHlt;}; + this.getUseToolTip=function(){return vUseToolTip;}; + this.getUseSort=function(){return vUseSort;}; + this.getUseSingleCell=function(){return vUseSingleCell;}; + this.getFormatArr=function(){return vFormatArr;}; + this.getShowRes=function(){return vShowRes;}; + this.getShowDur=function(){return vShowDur;}; + this.getShowComp=function(){return vShowComp;}; + this.getShowStartDate=function(){return vShowStartDate;}; + this.getShowEndDate=function(){return vShowEndDate;}; + this.getShowTaskInfoRes=function(){return vShowTaskInfoRes;}; + this.getShowTaskInfoDur=function(){return vShowTaskInfoDur;}; + this.getShowTaskInfoComp=function(){return vShowTaskInfoComp;}; + this.getShowTaskInfoStartDate=function(){return vShowTaskInfoStartDate;}; + this.getShowTaskInfoEndDate=function(){return vShowTaskInfoEndDate;}; + this.getShowTaskInfoNotes=function(){return vShowTaskInfoNotes;}; + this.getShowTaskInfoLink=function(){return vShowTaskInfoLink;}; + this.getShowEndWeekDate=function(){return vShowEndWeekDate;}; + this.getShowSelector=function(){return vShowSelector;}; + this.getShowDeps=function(){return vShowDeps;}; + this.getDateInputFormat=function(){return vDateInputFormat;}; + this.getDateTaskTableDisplayFormat=function(){return vDateTaskTableDisplayFormat;}; + this.getDateTaskDisplayFormat=function(){return vDateTaskDisplayFormat;}; + this.getHourMajorDateDisplayFormat=function(){return vHourMajorDateDisplayFormat;}; + this.getHourMinorDateDisplayFormat=function(){return vHourMinorDateDisplayFormat;}; + this.getDayMajorDateDisplayFormat=function(){return vDayMajorDateDisplayFormat;}; + this.getDayMinorDateDisplayFormat=function(){return vDayMinorDateDisplayFormat;}; + this.getWeekMajorDateDisplayFormat=function(){return vWeekMajorDateDisplayFormat;}; + this.getWeekMinorDateDisplayFormat=function(){return vWeekMinorDateDisplayFormat;}; + this.getMonthMajorDateDisplayFormat=function(){return vMonthMajorDateDisplayFormat;}; + this.getMonthMinorDateDisplayFormat=function(){return vMonthMinorDateDisplayFormat;}; + this.getQuarterMajorDateDisplayFormat=function(){return vQuarterMajorDateDisplayFormat;}; + this.getQuarterMinorDateDisplayFormat=function(){return vQuarterMinorDateDisplayFormat;}; + this.getCaptionType=function(){return vCaptionType;}; + this.getMinGpLen=function(){return vMinGpLen;}; + this.getScrollTo=function(){return vScrollTo;}; + this.getHourColWidth=function(){return vHourColWidth;}; + this.getDayColWidth=function(){return vDayColWidth;}; + this.getWeekColWidth=function(){return vWeekColWidth;}; + this.getMonthColWidth=function(){return vMonthColWidth;}; + this.getQuarterColWidth=function(){return vQuarterColWidth;}; + this.getRowHeight=function(){return vRowHeight;}; + this.getChartBody=function(){return vChartBody;}; + this.getChartHead=function(){return vChartHead;}; + this.getListBody=function(){return vListBody;}; + this.getChartTable=function(){return vChartTable;}; + this.getLines=function(){return vLines;}; + this.getTimer=function(){return vTimer;}; - this.CalcTaskXY=function() - { - var vID; - var vList=this.getList(); - var vBarDiv; - var vTaskDiv; - var vParDiv; - var vLeft, vTop, vWidth; - var vHeight=Math.floor((this.getRowHeight()/2)); + this.CalcTaskXY=function() + { + var vID; + var vList=this.getList(); + var vBarDiv; + var vTaskDiv; + var vParDiv; + var vLeft, vTop, vWidth; + var vHeight=Math.floor((this.getRowHeight()/2)); - for(var i=0; i=x2 && y1!=y2) vBend=true; - break; - } + switch(pType) + { + case 'SF': + vShort*=-1; + if(x1-10<=x2 && y1!=y2) vBend=true; + vDir=-1; + break; + case 'SS': + if (x1=x2 && y1!=y2) vBend=true; + break; + } - if (vBend) - { - this.sLine(x1,y1,x1+vShort,y1,pClass); - this.sLine(x1+vShort,y1,x1+vShort,y2-vRow,pClass); - this.sLine(x1+vShort,y2-vRow,x2-(vShort*2),y2-vRow,pClass); - this.sLine(x2-(vShort*2),y2-vRow,x2-(vShort*2),y2,pClass); - this.sLine(x2-(vShort*2),y2,x2-(1*vDir),y2,pClass); - } - else if (y1!=y2) - { - this.sLine(x1,y1,x1+vShort,y1,pClass); - this.sLine(x1+vShort,y1,x1+vShort,y2,pClass); - this.sLine(x1+vShort,y2,x2-(1*vDir),y2,pClass); - } - else this.sLine(x1,y1,x2-(1*vDir),y2,pClass); + if (vBend) + { + this.sLine(x1,y1,x1+vShort,y1,pClass); + this.sLine(x1+vShort,y1,x1+vShort,y2-vRow,pClass); + this.sLine(x1+vShort,y2-vRow,x2-(vShort*2),y2-vRow,pClass); + this.sLine(x2-(vShort*2),y2-vRow,x2-(vShort*2),y2,pClass); + this.sLine(x2-(vShort*2),y2,x2-(1*vDir),y2,pClass); + } + else if (y1!=y2) + { + this.sLine(x1,y1,x1+vShort,y1,pClass); + this.sLine(x1+vShort,y1,x1+vShort,y2,pClass); + this.sLine(x1+vShort,y2,x2-(1*vDir),y2,pClass); + } + else this.sLine(x1,y1,x2-(1*vDir),y2,pClass); - var vTmpDiv=this.sLine(x2,y2,x2-3-((vDir<0)?1:0),y2-3-((vDir<0)?1:0),pClass+"Arw"); - vTmpDiv.style.width='0px'; - vTmpDiv.style.height='0px'; - }; + var vTmpDiv=this.sLine(x2,y2,x2-3-((vDir<0)?1:0),y2-3-((vDir<0)?1:0),pClass+"Arw"); + vTmpDiv.style.width='0px'; + vTmpDiv.style.height='0px'; + }; - this.DrawDependencies=function() - { - if (this.getShowDeps()==1) - { - //First recalculate the x,y - this.CalcTaskXY(); - this.clearDependencies(); + this.DrawDependencies=function() + { + if (this.getShowDeps()==1) + { + //First recalculate the x,y + this.CalcTaskXY(); + this.clearDependencies(); - var vList=this.getList(); - for(var i=0; i0 && vList[i].getVisible()==1) - { - for(var k=0;k=0 && vList[vTask].getGroup()!=2) - { - if(vList[vTask].getVisible()==1) - { - if(vDependType[k]=='SS')this.drawDependency(vList[vTask].getStartX()-1,vList[vTask].getStartY(),vList[i].getStartX()-1,vList[i].getStartY(),'SS','gDepSS'); - else if(vDependType[k]=='FF')this.drawDependency(vList[vTask].getEndX(),vList[vTask].getEndY(),vList[i].getEndX(),vList[i].getEndY(),'FF','gDepFF'); - else if(vDependType[k]=='SF')this.drawDependency(vList[vTask].getStartX()-1,vList[vTask].getStartY(),vList[i].getEndX(),vList[i].getEndY(),'SF','gDepSF'); - else if(vDependType[k]=='FS')this.drawDependency(vList[vTask].getEndX(),vList[vTask].getEndY(),vList[i].getStartX()-1,vList[i].getStartY(),'FS','gDepFS'); - } - } - } - } - } - } - // draw the current date line - if (vTodayPx>=0) this.sLine(vTodayPx, 0, vTodayPx, this.getChartTable().offsetHeight-1, 'gCurDate'); - }; + if(n>0 && vList[i].getVisible()==1) + { + for(var k=0;k=0 && vList[vTask].getGroup()!=2) + { + if(vList[vTask].getVisible()==1) + { + if(vDependType[k]=='SS')this.drawDependency(vList[vTask].getStartX()-1,vList[vTask].getStartY(),vList[i].getStartX()-1,vList[i].getStartY(),'SS','gDepSS'); + else if(vDependType[k]=='FF')this.drawDependency(vList[vTask].getEndX(),vList[vTask].getEndY(),vList[i].getEndX(),vList[i].getEndY(),'FF','gDepFF'); + else if(vDependType[k]=='SF')this.drawDependency(vList[vTask].getStartX()-1,vList[vTask].getStartY(),vList[i].getEndX(),vList[i].getEndY(),'SF','gDepSF'); + else if(vDependType[k]=='FS')this.drawDependency(vList[vTask].getEndX(),vList[vTask].getEndY(),vList[i].getStartX()-1,vList[i].getStartY(),'FS','gDepFS'); + } + } + } + } + } + } + // draw the current date line + if (vTodayPx>=0) this.sLine(vTodayPx, 0, vTodayPx, this.getChartTable().offsetHeight-1, 'gCurDate'); + }; - this.getArrayLocationByID=function(pId) - { - var vList=this.getList(); - for(var i=0; i0) - { - // Process all tasks, reset parent date and completion % if task list has altered - if (vProcessNeeded) JSGantt.processRows(vTaskList, 0, -1, 1, 1, this.getUseSort()); - vProcessNeeded=false; + if(vTaskList.length>0) + { + // Process all tasks, reset parent date and completion % if task list has altered + if (vProcessNeeded) JSGantt.processRows(vTaskList, 0, -1, 1, 1, this.getUseSort()); + vProcessNeeded=false; - // get overall min/max dates plus padding - vMinDate=JSGantt.getMinDate(vTaskList, vFormat); - vMaxDate=JSGantt.getMaxDate(vTaskList, vFormat); + // get overall min/max dates plus padding + vMinDate=JSGantt.getMinDate(vTaskList, vFormat); + vMaxDate=JSGantt.getMaxDate(vTaskList, vFormat); - // Calculate chart width variables. - if(vFormat=='day') vColWidth=vDayColWidth; - else if(vFormat=='week') vColWidth=vWeekColWidth; - else if(vFormat=='month') vColWidth=vMonthColWidth; - else if(vFormat=='quarter') vColWidth=vQuarterColWidth; - else if(vFormat=='hour') vColWidth=vHourColWidth; + // Calculate chart width variables. + if(vFormat=='day') vColWidth=vDayColWidth; + else if(vFormat=='week') vColWidth=vWeekColWidth; + else if(vFormat=='month') vColWidth=vMonthColWidth; + else if(vFormat=='quarter') vColWidth=vQuarterColWidth; + else if(vFormat=='hour') vColWidth=vHourColWidth; - // DRAW the Left-side of the chart (names, resources, comp%) - var vLeftHeader=document.createDocumentFragment(); + // DRAW the Left-side of the chart (names, resources, comp%) + var vLeftHeader=document.createDocumentFragment(); - var vTmpDiv=this.newNode(vLeftHeader, 'div', vDivId+'glisthead', 'glistlbl gcontainercol'); - var vTmpTab=this.newNode(vTmpDiv, 'table', null, 'gtasktableh'); - var vTmpTBody=this.newNode(vTmpTab, 'tbody'); - var vTmpRow=this.newNode(vTmpTBody, 'tr'); - this.newNode(vTmpRow, 'td', null, 'gtasklist', '\u00A0'); - var vTmpCell=this.newNode(vTmpRow, 'td', null, 'gspanning gtaskname'); - vTmpCell.appendChild(this.drawSelector('top')); - if(vShowRes==1)this.newNode(vTmpRow, 'td', null, 'gspanning gresource', '\u00A0'); - if(vShowDur==1)this.newNode(vTmpRow, 'td', null, 'gspanning gduration', '\u00A0'); - if(vShowComp==1)this.newNode(vTmpRow, 'td', null, 'gspanning gpccomplete', '\u00A0'); - if(vShowStartDate==1)this.newNode(vTmpRow, 'td', null, 'gspanning gstartdate', '\u00A0'); - if(vShowEndDate==1)this.newNode(vTmpRow, 'td', null, 'gspanning genddate', '\u00A0'); + var vTmpDiv=this.newNode(vLeftHeader, 'div', vDivId+'glisthead', 'glistlbl gcontainercol'); + var vTmpTab=this.newNode(vTmpDiv, 'table', null, 'gtasktableh'); + var vTmpTBody=this.newNode(vTmpTab, 'tbody'); + var vTmpRow=this.newNode(vTmpTBody, 'tr'); + this.newNode(vTmpRow, 'td', null, 'gtasklist', '\u00A0'); + var vTmpCell=this.newNode(vTmpRow, 'td', null, 'gspanning gtaskname'); + vTmpCell.appendChild(this.drawSelector('top')); + if(vShowRes==1)this.newNode(vTmpRow, 'td', null, 'gspanning gresource', '\u00A0'); + if(vShowDur==1)this.newNode(vTmpRow, 'td', null, 'gspanning gduration', '\u00A0'); + if(vShowComp==1)this.newNode(vTmpRow, 'td', null, 'gspanning gpccomplete', '\u00A0'); + if(vShowStartDate==1)this.newNode(vTmpRow, 'td', null, 'gspanning gstartdate', '\u00A0'); + if(vShowEndDate==1)this.newNode(vTmpRow, 'td', null, 'gspanning genddate', '\u00A0'); - vTmpRow=this.newNode(vTmpTBody, 'tr'); - this.newNode(vTmpRow, 'td', null, 'gtasklist', '\u00A0'); - this.newNode(vTmpRow, 'td', null, 'gtaskname', '\u00A0'); - if(vShowRes==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading gresource', vLangs[vLang]['resource']); - if(vShowDur==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading gduration', vLangs[vLang]['duration']); - if(vShowComp==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading gpccomplete', vLangs[vLang]['comp']); - if(vShowStartDate==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading gstartdate', vLangs[vLang]['startdate']); - if(vShowEndDate==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading genddate', vLangs[vLang]['enddate']); + vTmpRow=this.newNode(vTmpTBody, 'tr'); + this.newNode(vTmpRow, 'td', null, 'gtasklist', '\u00A0'); + this.newNode(vTmpRow, 'td', null, 'gtaskname', '\u00A0'); + if(vShowRes==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading gresource', vLangs[vLang]['resource']); + if(vShowDur==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading gduration', vLangs[vLang]['duration']); + if(vShowComp==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading gpccomplete', vLangs[vLang]['comp']); + if(vShowStartDate==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading gstartdate', vLangs[vLang]['startdate']); + if(vShowEndDate==1)this.newNode(vTmpRow, 'td', null, 'gtaskheading genddate', vLangs[vLang]['enddate']); - vTmpDiv=this.newNode(vLeftHeader, 'div', null, 'glabelfooter'); + var vLeftTable=document.createDocumentFragment(); + var vTmpDiv2=this.newNode(vLeftTable, 'div', vDivId+'glistbody', 'glistgrid gcontainercol'); + this.setListBody(vTmpDiv2); + vTmpTab=this.newNode(vTmpDiv2, 'table', null, 'gtasktable'); + vTmpTBody=this.newNode(vTmpTab, 'tbody'); - var vLeftTable=document.createDocumentFragment(); - var vTmpDiv2=this.newNode(vLeftTable, 'div', vDivId+'glistbody', 'glistgrid gcontainercol'); - this.setListBody(vTmpDiv2); - vTmpTab=this.newNode(vTmpDiv2, 'table', null, 'gtasktable'); - vTmpTBody=this.newNode(vTmpTab, 'tbody'); + for(i=0; i1) - { - vTmpDate.setDate(vTmpDate.getDate()+1); - } - } - else if(vFormat=='quarter') - { - if(vTmpDate<=vMaxDate) - { - vTmpCell=this.newNode(vTmpRow, 'td', null, vHeaderCellClass); - this.newNode(vTmpCell, 'div', null, null, JSGantt.formatDateStr(vTmpDate,vQuarterMinorDateDisplayFormat,vLangs[vLang]), vColWidth); - vNumCols++; - } + while(vTmpDate.getDate()>1) + { + vTmpDate.setDate(vTmpDate.getDate()+1); + } + } + else if(vFormat=='quarter') + { + if(vTmpDate<=vMaxDate) + { + vTmpCell=this.newNode(vTmpRow, 'td', null, vHeaderCellClass); + this.newNode(vTmpCell, 'div', null, null, JSGantt.formatDateStr(vTmpDate,vQuarterMinorDateDisplayFormat,vLangs[vLang]), vColWidth); + vNumCols++; + } - vTmpDate.setDate(vTmpDate.getDate()+81); + vTmpDate.setDate(vTmpDate.getDate()+81); - while(vTmpDate.getDate()>1) vTmpDate.setDate(vTmpDate.getDate()+1); - } - else if(vFormat=='hour') - { - for(i=vTmpDate.getHours();i<24;i++) - { - vTmpDate.setHours(i);//works around daylight savings but may look a little odd on days where the clock goes forward - if(vTmpDate<=vMaxDate) - { - vTmpCell=this.newNode(vTmpRow, 'td', null, vHeaderCellClass); - this.newNode(vTmpCell, 'div', null, null, JSGantt.formatDateStr(vTmpDate,vHourMinorDateDisplayFormat,vLangs[vLang]), vColWidth); - vNumCols++; - } - } - vTmpDate.setHours(0); - vTmpDate.setDate(vTmpDate.getDate()+1); - } - } - vDateRow=vTmpRow; + while(vTmpDate.getDate()>1) vTmpDate.setDate(vTmpDate.getDate()+1); + } + else if(vFormat=='hour') + { + for(i=vTmpDate.getHours();i<24;i++) + { + vTmpDate.setHours(i);//works around daylight savings but may look a little odd on days where the clock goes forward + if(vTmpDate<=vMaxDate) + { + vTmpCell=this.newNode(vTmpRow, 'td', null, vHeaderCellClass); + this.newNode(vTmpCell, 'div', null, null, JSGantt.formatDateStr(vTmpDate,vHourMinorDateDisplayFormat,vLangs[vLang]), vColWidth); + vNumCols++; + } + } + vTmpDate.setHours(0); + vTmpDate.setDate(vTmpDate.getDate()+1); + } + } + vDateRow=vTmpRow; - vTaskLeftPx=(vNumCols *(vColWidth+1))+1; + vTaskLeftPx=(vNumCols *(vColWidth+1))+1; - if(vUseSingleCell!=0 && vUseSingleCell<(vNumCols*vNumRows))vSingleCell=true; + if(vUseSingleCell!=0 && vUseSingleCell<(vNumCols*vNumRows))vSingleCell=true; - this.newNode(vTmpDiv, 'div', null, 'rhscrpad', null, null, vTaskLeftPx+1); + this.newNode(vTmpDiv, 'div', null, 'rhscrpad', null, null, vTaskLeftPx+1); - var vRightTable=document.createDocumentFragment(); - vTmpDiv=this.newNode(vRightTable, 'div', vDivId+'gchartbody', 'gchartgrid gcontainercol'); - this.setChartBody(vTmpDiv); - vTmpTab=this.newNode(vTmpDiv, 'table', vDivId+'chartTable', 'gcharttable', null, vTaskLeftPx); - this.setChartTable(vTmpTab); - this.newNode(vTmpDiv, 'div', null, 'rhscrpad', null, null, vTaskLeftPx+1); - vTmpTBody=this.newNode(vTmpTab, 'tbody'); + vTmpDiv=this.newNode(vRightHeader, 'div', null, 'glabelfooter'); - // Draw each row + var vRightTable=document.createDocumentFragment(); + vTmpDiv=this.newNode(vRightTable, 'div', vDivId+'gchartbody', 'gchartgrid gcontainercol'); + this.setChartBody(vTmpDiv); + vTmpTab=this.newNode(vTmpDiv, 'table', vDivId+'chartTable', 'gcharttable', null, vTaskLeftPx); + this.setChartTable(vTmpTab); + this.newNode(vTmpDiv, 'div', null, 'rhscrpad', null, null, vTaskLeftPx+1); + vTmpTBody=this.newNode(vTmpTab, 'tbody'); - var i=0; - var j=0; - for(i=0; ivMinGpLen && vTaskWidthvMinGpLen && vTaskWidth=vMinGpLen*2) this.newNode(vTmpDiv, 'div', null, vTaskList[i].getClass() +'endpointright'); + this.newNode(vTmpDiv2, 'div', vDivId+'complete_'+vID, vTaskList[i].getClass() +'complete', null, vTaskList[i].getCompStr()); - vCaptClass='ggroupcaption'; - } + this.newNode(vTmpDiv, 'div', null, vTaskList[i].getClass() +'endpointleft'); + if (vTaskWidth>=vMinGpLen*2) this.newNode(vTmpDiv, 'div', null, vTaskList[i].getClass() +'endpointright'); - if(!vSingleCell && !vComb) - { - vCellFormat=''; - for(j=0; j=(new Date()).getTime()) vTodayPx=JSGantt.getOffset(vMinDate, new Date(), vColWidth, vFormat); - else vTodayPx=-1; - this.DrawDependencies(); - } - }; //this.draw + if(vScrollTo.substr(0,2)=='px') + { + vScrollPx=parseInt(vScrollTo.substr(2)); + } + else + { + vScrollDate=JSGantt.parseDateStr(vScrollTo, this.getDateInputFormat()); + if(vFormat=='hour')vScrollDate.setMinutes(0,0,0); + else vScrollDate.setHours(0,0,0,0); + vScrollPx=JSGantt.getOffset(vMinDate, vScrollDate, vColWidth, vFormat); + } + this.getChartBody().scrollLeft=vScrollPx; + } - this.mouseOver=function(pObj1, pObj2) - { - if (this.getUseRowHlt()) - { - pObj1.className+=' gitemhighlight'; - pObj2.className+=' gitemhighlight'; - } - }; + if (vMinDate.getTime()<=(new Date()).getTime() && vMaxDate.getTime()>=(new Date()).getTime()) vTodayPx=JSGantt.getOffset(vMinDate, new Date(), vColWidth, vFormat); + else vTodayPx=-1; + this.DrawDependencies(); + } + }; //this.draw - this.mouseOut=function(pObj1, pObj2) - { - if (this.getUseRowHlt()) - { - pObj1.className=pObj1.className.replace(/(?:^|\s)gitemhighlight(?!\S)/g, ''); - pObj2.className=pObj2.className.replace(/(?:^|\s)gitemhighlight(?!\S)/g, ''); - } - }; + this.mouseOver=function(pObj1, pObj2) + { + if (this.getUseRowHlt()) + { + pObj1.className+=' gitemhighlight'; + pObj2.className+=' gitemhighlight'; + } + }; - this.drawSelector=function(pPos) - { - var vOutput=document.createDocumentFragment(); - var vDisplay=false; + this.mouseOut=function(pObj1, pObj2) + { + if (this.getUseRowHlt()) + { + pObj1.className=pObj1.className.replace(/(?:^|\s)gitemhighlight(?!\S)/g, ''); + pObj2.className=pObj2.className.replace(/(?:^|\s)gitemhighlight(?!\S)/g, ''); + } + }; - for (var i=0; i=0 && vIdx'; - vTask+=''+vTaskList[vIdx].getName()+''; - vTask+=''+JSGantt.formatDateStr(vTaskList[vIdx].getStart(),vOutFrmt,vLangs[vLang])+''; - vTask+=''+JSGantt.formatDateStr(vTaskList[vIdx].getEnd(),vOutFrmt,vLangs[vLang])+''; - vTask+=''+vTaskList[vIdx].getClass()+''; - vTask+=''+vTaskList[vIdx].getLink()+''; - vTask+=''+vTaskList[vIdx].getMile()+''; - if(vTaskList[vIdx].getResource()!='\u00A0') vTask+=''+vTaskList[vIdx].getResource()+''; - vTask+=''+vTaskList[vIdx].getCompVal()+''; - vTask+=''+vTaskList[vIdx].getGroup()+''; - vTask+=''+vTaskList[vIdx].getParent()+''; - vTask+=''+vTaskList[vIdx].getOpen()+''; - vTask+=''; - var vDepList=vTaskList[vIdx].getDepend(); - for (i=0;i0)vTask+=','; - if(vDepList[i]>0)vTask+=vDepList[i]+vTaskList[vIdx].getDepType()[i]; - } - vTask+=''; - vTask+=''+vTaskList[vIdx].getCaption()+''; + this.getXMLProject=function() + { + var vProject=''; + for (var i=0; i'; - vTask+=''; - } - return vTask; - }; - if (vDiv && vDiv.nodeName.toLowerCase()=='div') vDivId=vDiv.id; + this.getXMLTask=function(pID,pIdx) + { + var i=0; + var vIdx=-1; + var vTask=''; + var vOutFrmt=JSGantt.parseDateFormatStr(this.getDateInputFormat()+' HH:MI'); + if (pIdx===true)vIdx=pID; + else + { + for (i=0; i=0 && vIdx'; + vTask+=''+vTaskList[vIdx].getName()+''; + vTask+=''+JSGantt.formatDateStr(vTaskList[vIdx].getStart(),vOutFrmt,vLangs[vLang])+''; + vTask+=''+JSGantt.formatDateStr(vTaskList[vIdx].getEnd(),vOutFrmt,vLangs[vLang])+''; + vTask+=''+vTaskList[vIdx].getClass()+''; + vTask+=''+vTaskList[vIdx].getLink()+''; + vTask+=''+vTaskList[vIdx].getMile()+''; + if(vTaskList[vIdx].getResource()!='\u00A0') vTask+=''+vTaskList[vIdx].getResource()+''; + vTask+=''+vTaskList[vIdx].getCompVal()+''; + vTask+=''+vTaskList[vIdx].getGroup()+''; + vTask+=''+vTaskList[vIdx].getParent()+''; + vTask+=''+vTaskList[vIdx].getOpen()+''; + vTask+=''; + var vDepList=vTaskList[vIdx].getDepend(); + for (i=0;i0)vTask+=','; + if(vDepList[i]>0)vTask+=vDepList[i]+vTaskList[vIdx].getDepType()[i]; + } + vTask+=''; + vTask+=''+vTaskList[vIdx].getCaption()+''; + + var vTmpFrag=document.createDocumentFragment(); + var vTmpDiv=this.newNode(vTmpFrag, 'div', null, null,vTaskList[vIdx].getNotes().innerHTML); + vTask+=''+vTmpDiv.innerHTML+''; + vTask+=''; + } + return vTask; + }; + if (vDiv && vDiv.nodeName.toLowerCase()=='div') vDivId=vDiv.id; }; //GanttChart JSGantt.updateFlyingObj=function (e, pGanttChartObj, pTimer) { - var vCurTopBuf=3; - var vCurLeftBuf=5; - var vCurBotBuf=3; - var vCurRightBuf=15; - var vMouseX=(e)?e.clientX:window.event.clientX; - var vMouseY=(e)?e.clientY:window.event.clientY; - var vViewportX=document.documentElement.clientWidth||document.getElementsByTagName('body')[0].clientWidth; - var vViewportY=document.documentElement.clientHeight||document.getElementsByTagName('body')[0].clientHeight; - var vNewX=vMouseX; - var vNewY=vMouseY; + var vCurTopBuf=3; + var vCurLeftBuf=5; + var vCurBotBuf=3; + var vCurRightBuf=15; + var vMouseX=(e)?e.clientX:window.event.clientX; + var vMouseY=(e)?e.clientY:window.event.clientY; + var vViewportX=document.documentElement.clientWidth||document.getElementsByTagName('body')[0].clientWidth; + var vViewportY=document.documentElement.clientHeight||document.getElementsByTagName('body')[0].clientHeight; + var vNewX=vMouseX; + var vNewY=vMouseY; - if (navigator.appName.toLowerCase ()=='microsoft internet explorer') { - // the clientX and clientY properties include the left and top borders of the client area - vMouseX-=document.documentElement.clientLeft; - vMouseY-=document.documentElement.clientTop; + if (navigator.appName.toLowerCase ()=='microsoft internet explorer') { + // the clientX and clientY properties include the left and top borders of the client area + vMouseX-=document.documentElement.clientLeft; + vMouseY-=document.documentElement.clientTop; - var vZoomFactor=JSGantt.getZoomFactor (); - if (vZoomFactor!=1) {// IE 7 at non-default zoom level - vMouseX=Math.round (vMouseX / vZoomFactor); - vMouseY=Math.round (vMouseY / vZoomFactor); - } - } + var vZoomFactor=JSGantt.getZoomFactor (); + if (vZoomFactor!=1) {// IE 7 at non-default zoom level + vMouseX=Math.round (vMouseX / vZoomFactor); + vMouseY=Math.round (vMouseY / vZoomFactor); + } + } - var vScrollPos=JSGantt.getScrollPositions(); + var vScrollPos=JSGantt.getScrollPositions(); - /* Code for positioned right of the mouse by default*/ - /* - if (vMouseX+vCurRightBuf+pGanttChartObj.vTool.offsetWidth>vViewportX) - { - if (vMouseX-vCurLeftBuf-pGanttChartObj.vTool.offsetWidth<0) vNewX=vScrollPos.x; - else vNewX=vMouseX+vScrollPos.x-vCurLeftBuf-pGanttChartObj.vTool.offsetWidth; - } - else vNewX=vMouseX+vScrollPos.x+vCurRightBuf; - */ + /* Code for positioned right of the mouse by default*/ + /* + if (vMouseX+vCurRightBuf+pGanttChartObj.vTool.offsetWidth>vViewportX) + { + if (vMouseX-vCurLeftBuf-pGanttChartObj.vTool.offsetWidth<0) vNewX=vScrollPos.x; + else vNewX=vMouseX+vScrollPos.x-vCurLeftBuf-pGanttChartObj.vTool.offsetWidth; + } + else vNewX=vMouseX+vScrollPos.x+vCurRightBuf; + */ - /* Code for positioned left of the mouse by default */ - if (vMouseX-vCurLeftBuf-pGanttChartObj.vTool.offsetWidth<0) - { - if (vMouseX+vCurRightBuf+pGanttChartObj.vTool.offsetWidth>vViewportX) vNewX=vScrollPos.x; - else vNewX=vMouseX+vScrollPos.x+vCurRightBuf; - } - else vNewX=vMouseX+vScrollPos.x-vCurLeftBuf-pGanttChartObj.vTool.offsetWidth; + /* Code for positioned left of the mouse by default */ + if (vMouseX-vCurLeftBuf-pGanttChartObj.vTool.offsetWidth<0) + { + if (vMouseX+vCurRightBuf+pGanttChartObj.vTool.offsetWidth>vViewportX) vNewX=vScrollPos.x; + else vNewX=vMouseX+vScrollPos.x+vCurRightBuf; + } + else vNewX=vMouseX+vScrollPos.x-vCurLeftBuf-pGanttChartObj.vTool.offsetWidth; - /* Code for positioned below the mouse by default */ - if (vMouseY+vCurBotBuf+pGanttChartObj.vTool.offsetHeight>vViewportY) - { - if (vMouseY-vCurTopBuf-pGanttChartObj.vTool.offsetHeight<0) vNewY=vScrollPos.y; - else vNewY=vMouseY+vScrollPos.y-vCurTopBuf-pGanttChartObj.vTool.offsetHeight; - } - else vNewY=vMouseY+vScrollPos.y+vCurBotBuf; + /* Code for positioned below the mouse by default */ + if (vMouseY+vCurBotBuf+pGanttChartObj.vTool.offsetHeight>vViewportY) + { + if (vMouseY-vCurTopBuf-pGanttChartObj.vTool.offsetHeight<0) vNewY=vScrollPos.y; + else vNewY=vMouseY+vScrollPos.y-vCurTopBuf-pGanttChartObj.vTool.offsetHeight; + } + else vNewY=vMouseY+vScrollPos.y+vCurBotBuf; - /* Code for positioned above the mouse by default */ - /* - if (vMouseY-vCurTopBuf-pGanttChartObj.vTool.offsetHeight<0) - { - if (vMouseY+vCurBotBuf+pGanttChartObj.vTool.offsetHeight>vViewportY) vNewY=vScrollPos.y; - else vNewY=vMouseY+vScrollPos.y+vCurBotBuf; - } - else vNewY=vMouseY+vScrollPos.y-vCurTopBuf-pGanttChartObj.vTool.offsetHeight; - */ + /* Code for positioned above the mouse by default */ + /* + if (vMouseY-vCurTopBuf-pGanttChartObj.vTool.offsetHeight<0) + { + if (vMouseY+vCurBotBuf+pGanttChartObj.vTool.offsetHeight>vViewportY) vNewY=vScrollPos.y; + else vNewY=vMouseY+vScrollPos.y+vCurBotBuf; + } + else vNewY=vMouseY+vScrollPos.y-vCurTopBuf-pGanttChartObj.vTool.offsetHeight; + */ - if (pGanttChartObj.getUseMove()) - { - clearInterval(pGanttChartObj.vTool.moveInterval); - pGanttChartObj.vTool.moveInterval=setInterval(function(){JSGantt.moveToolTip(vNewX, vNewY, pGanttChartObj.vTool, pTimer);},pTimer); - } - else - { - pGanttChartObj.vTool.style.left=vNewX +'px'; - pGanttChartObj.vTool.style.top=vNewY +'px'; - } + if (pGanttChartObj.getUseMove()) + { + clearInterval(pGanttChartObj.vTool.moveInterval); + pGanttChartObj.vTool.moveInterval=setInterval(function(){JSGantt.moveToolTip(vNewX, vNewY, pGanttChartObj.vTool, pTimer);},pTimer); + } + else + { + pGanttChartObj.vTool.style.left=vNewX +'px'; + pGanttChartObj.vTool.style.top=vNewY +'px'; + } }; JSGantt.showToolTip=function(pGanttChartObj, e, pContents, pWidth, pTimer){ - var vTtDivId=pGanttChartObj.getDivId()+'JSGanttToolTip'; - var vMaxW=500; - var vMaxAlpha=100; - var vShowing=pContents.id; + var vTtDivId=pGanttChartObj.getDivId()+'JSGanttToolTip'; + var vMaxW=500; + var vMaxAlpha=100; + var vShowing=pContents.id; - if(pGanttChartObj.getUseToolTip()) - { - if(pGanttChartObj.vTool==null){ - pGanttChartObj.vTool=document.createElement('div'); - pGanttChartObj.vTool.id=vTtDivId; - pGanttChartObj.vTool.className='JSGanttToolTip'; - pGanttChartObj.vTool.vToolCont=document.createElement('div'); - pGanttChartObj.vTool.vToolCont.id=vTtDivId+'cont'; - pGanttChartObj.vTool.vToolCont.className='JSGanttToolTipcont'; - pGanttChartObj.vTool.vToolCont.setAttribute('showing',''); - pGanttChartObj.vTool.appendChild(pGanttChartObj.vTool.vToolCont); - document.body.appendChild(pGanttChartObj.vTool); - pGanttChartObj.vTool.style.opacity=0; - pGanttChartObj.vTool.setAttribute('currentOpacity',0); - pGanttChartObj.vTool.setAttribute('fadeIncrement',10); - pGanttChartObj.vTool.setAttribute('moveSpeed',10); - pGanttChartObj.vTool.style.filter='alpha(opacity=0)'; - pGanttChartObj.vTool.style.visibility='hidden'; - pGanttChartObj.vTool.style.left=Math.floor(((e)?e.clientX:window.event.clientX)/2)+'px'; - pGanttChartObj.vTool.style.top=Math.floor(((e)?e.clientY:window.event.clientY)/2)+'px'; - JSGantt.addListener('mouseover', function () {clearTimeout(pGanttChartObj.vTool.delayTimeout);}, pGanttChartObj.vTool); - JSGantt.addListener('mouseout', function () {JSGantt.delayedHide(pGanttChartObj, pGanttChartObj.vTool, pTimer);}, pGanttChartObj.vTool); - } - clearTimeout(pGanttChartObj.vTool.delayTimeout); - if(pGanttChartObj.vTool.vToolCont.getAttribute('showing')!=vShowing || pGanttChartObj.vTool.style.visibility!='visible') - { - if (pGanttChartObj.vTool.vToolCont.getAttribute('showing')!=vShowing) - { - pGanttChartObj.vTool.vToolCont.setAttribute('showing',vShowing); + if(pGanttChartObj.getUseToolTip()) + { + if(pGanttChartObj.vTool==null){ + pGanttChartObj.vTool=document.createElement('div'); + pGanttChartObj.vTool.id=vTtDivId; + pGanttChartObj.vTool.className='JSGanttToolTip'; + pGanttChartObj.vTool.vToolCont=document.createElement('div'); + pGanttChartObj.vTool.vToolCont.id=vTtDivId+'cont'; + pGanttChartObj.vTool.vToolCont.className='JSGanttToolTipcont'; + pGanttChartObj.vTool.vToolCont.setAttribute('showing',''); + pGanttChartObj.vTool.appendChild(pGanttChartObj.vTool.vToolCont); + document.body.appendChild(pGanttChartObj.vTool); + pGanttChartObj.vTool.style.opacity=0; + pGanttChartObj.vTool.setAttribute('currentOpacity',0); + pGanttChartObj.vTool.setAttribute('fadeIncrement',10); + pGanttChartObj.vTool.setAttribute('moveSpeed',10); + pGanttChartObj.vTool.style.filter='alpha(opacity=0)'; + pGanttChartObj.vTool.style.visibility='hidden'; + pGanttChartObj.vTool.style.left=Math.floor(((e)?e.clientX:window.event.clientX)/2)+'px'; + pGanttChartObj.vTool.style.top=Math.floor(((e)?e.clientY:window.event.clientY)/2)+'px'; + JSGantt.addListener('mouseover', function () {clearTimeout(pGanttChartObj.vTool.delayTimeout);}, pGanttChartObj.vTool); + JSGantt.addListener('mouseout', function () {JSGantt.delayedHide(pGanttChartObj, pGanttChartObj.vTool, pTimer);}, pGanttChartObj.vTool); + } + clearTimeout(pGanttChartObj.vTool.delayTimeout); + if(pGanttChartObj.vTool.vToolCont.getAttribute('showing')!=vShowing || pGanttChartObj.vTool.style.visibility!='visible') + { + if (pGanttChartObj.vTool.vToolCont.getAttribute('showing')!=vShowing) + { + pGanttChartObj.vTool.vToolCont.setAttribute('showing',vShowing); - pGanttChartObj.vTool.vToolCont.innerHTML=pContents.innerHTML; - // as we are allowing arbitrary HTML we should remove any tag ids to prevent duplication - JSGantt.stripIds(pGanttChartObj.vTool.vToolCont); - } + pGanttChartObj.vTool.vToolCont.innerHTML=pContents.innerHTML; + // as we are allowing arbitrary HTML we should remove any tag ids to prevent duplication + JSGantt.stripIds(pGanttChartObj.vTool.vToolCont); + } - pGanttChartObj.vTool.style.visibility='visible'; - // Rather than follow the mouse just have it stay put - JSGantt.updateFlyingObj(e, pGanttChartObj, pTimer); - pGanttChartObj.vTool.style.width=(pWidth)? pWidth+'px' : 'auto'; - if(!pWidth && JSGantt.isIE()){ - pGanttChartObj.vTool.style.width=pGanttChartObj.vTool.offsetWidth; - } - if(pGanttChartObj.vTool.offsetWidth>vMaxW){pGanttChartObj.vTool.style.width=vMaxW+'px';} - } + pGanttChartObj.vTool.style.visibility='visible'; + // Rather than follow the mouse just have it stay put + JSGantt.updateFlyingObj(e, pGanttChartObj, pTimer); + pGanttChartObj.vTool.style.width=(pWidth)? pWidth+'px' : 'auto'; + if(!pWidth && JSGantt.isIE()){ + pGanttChartObj.vTool.style.width=pGanttChartObj.vTool.offsetWidth; + } + if(pGanttChartObj.vTool.offsetWidth>vMaxW){pGanttChartObj.vTool.style.width=vMaxW+'px';} + } - if (pGanttChartObj.getUseFade()) - { - clearInterval(pGanttChartObj.vTool.fadeInterval); - pGanttChartObj.vTool.fadeInterval=setInterval(function(){JSGantt.fadeToolTip(1, pGanttChartObj.vTool, vMaxAlpha);},pTimer); - } - else - { - pGanttChartObj.vTool.style.opacity=vMaxAlpha * 0.01; - pGanttChartObj.vTool.style.filter='alpha(opacity='+vMaxAlpha+')'; - } - } + if (pGanttChartObj.getUseFade()) + { + clearInterval(pGanttChartObj.vTool.fadeInterval); + pGanttChartObj.vTool.fadeInterval=setInterval(function(){JSGantt.fadeToolTip(1, pGanttChartObj.vTool, vMaxAlpha);},pTimer); + } + else + { + pGanttChartObj.vTool.style.opacity=vMaxAlpha * 0.01; + pGanttChartObj.vTool.style.filter='alpha(opacity='+vMaxAlpha+')'; + } + } }; JSGantt.stripIds=function(pNode){ - for(var i=0; i=0 && pList[i].getID()==pID)vCurItem=pList[i]; - } + for(i=0; i=0 && pList[i].getID()==pID)vCurItem=pList[i]; + } - for(i=0; ivMaxDate) - { - vMaxDate=pList[i].getEnd(); - vMaxSet=1; - } + if(vMaxSet==0 || pList[i].getEnd()>vMaxDate) + { + vMaxDate=pList[i].getEnd(); + vMaxSet=1; + } - vCompSum+=pList[i].getCompVal(); - pList[i].setSortIdx(i*pList.length); - } - } + vNumKid++; + vWeight+=pList[i].getEnd()-pList[i].getStart()+1; + vCompSum+=pList[i].getCompVal()*(pList[i].getEnd()-pList[i].getStart()+1); + pList[i].setSortIdx(i*pList.length); + } + } - if(pRow>=0) - { - if(pList[pRow].getGroupMinStart()!=null && pList[pRow].getGroupMinStart()=0) + { + if(pList[pRow].getGroupMinStart()!=null && pList[pRow].getGroupMinStart()vMaxDate) - { - vMaxDate=pList[pRow].getGroupMinEnd(); - } - pList[pRow].setStart(vMinDate); - pList[pRow].setEnd(vMaxDate); - pList[pRow].setNumKid(vNumKid); - pList[pRow].setCompVal(Math.ceil(vCompSum/vNumKid)); - } + if(pList[pRow].getGroupMinEnd()!=null && pList[pRow].getGroupMinEnd()>vMaxDate) + { + vMaxDate=pList[pRow].getGroupMinEnd(); + } + pList[pRow].setStart(vMinDate); + pList[pRow].setEnd(vMaxDate); + pList[pRow].setNumKid(vNumKid); + pList[pRow].setWeight(vWeight); + pList[pRow].setCompVal(Math.ceil(vCompSum/vWeight)); + } - if (pID==0 && pUseSort==1) - { - JSGantt.sortTasks(pList, 0, 0); - pList.sort(function(a,b){return a.getSortIdx()-b.getSortIdx();}); - } - if (pID==0 && pUseSort!=1) // Need to sort combined tasks regardless - { - for(i=0; i0) - { - sortArr.sort(function(a,b){ var i=a.getStart().getTime()-b.getStart().getTime(); - if (i==0) i=a.getEnd().getTime()-b.getEnd().getTime(); - if (i==0) return a.getID()-b.getID(); - else return i; }); - } + if (sortArr.length>0) + { + sortArr.sort(function(a,b){ var i=a.getStart().getTime()-b.getStart().getTime(); + if (i==0) i=a.getEnd().getTime()-b.getEnd().getTime(); + if (i==0) return a.getID()-b.getID(); + else return i; }); + } - for (var j=0; j1) vDate.setDate(vDate.getDate()-1); - } - else if (pFormat=='quarter') - { - vDate.setDate(vDate.getDate()-31); - if(vDate.getMonth()==0 || vDate.getMonth()==1 || vDate.getMonth()==2) - vDate.setFullYear(vDate.getFullYear(), 0, 1); - else if(vDate.getMonth()==3 || vDate.getMonth()==4 || vDate.getMonth()==5) - vDate.setFullYear(vDate.getFullYear(), 3, 1); - else if(vDate.getMonth()==6 || vDate.getMonth()==7 || vDate.getMonth()==8) - vDate.setFullYear(vDate.getFullYear(), 6, 1); - else if(vDate.getMonth()==9 || vDate.getMonth()==10 || vDate.getMonth()==11) - vDate.setFullYear(vDate.getFullYear(), 9, 1); - } - else if (pFormat=='hour') - { - vDate.setHours(vDate.getHours()-1); - while(vDate.getHours()%6!=0) vDate.setHours(vDate.getHours()-1); - } + // Adjust min date to specific format boundaries (first of week or first of month) + if (pFormat=='day') + { + vDate.setDate(vDate.getDate()-1); + while(vDate.getDay()%7!=1) vDate.setDate(vDate.getDate()-1); + } + else if (pFormat=='week') + { + vDate.setDate(vDate.getDate()-1); + while(vDate.getDay()%7!=1) vDate.setDate(vDate.getDate()-1); + } + else if (pFormat=='month') + { + vDate.setDate(vDate.getDate()-15); + while(vDate.getDate()>1) vDate.setDate(vDate.getDate()-1); + } + else if (pFormat=='quarter') + { + vDate.setDate(vDate.getDate()-31); + if(vDate.getMonth()==0 || vDate.getMonth()==1 || vDate.getMonth()==2) + vDate.setFullYear(vDate.getFullYear(), 0, 1); + else if(vDate.getMonth()==3 || vDate.getMonth()==4 || vDate.getMonth()==5) + vDate.setFullYear(vDate.getFullYear(), 3, 1); + else if(vDate.getMonth()==6 || vDate.getMonth()==7 || vDate.getMonth()==8) + vDate.setFullYear(vDate.getFullYear(), 6, 1); + else if(vDate.getMonth()==9 || vDate.getMonth()==10 || vDate.getMonth()==11) + vDate.setFullYear(vDate.getFullYear(), 9, 1); + } + else if (pFormat=='hour') + { + vDate.setHours(vDate.getHours()-1); + while(vDate.getHours()%6!=0) vDate.setHours(vDate.getHours()-1); + } - if(pFormat=='hour')vDate.setMinutes(0,0); - else vDate.setHours(0,0,0); - return(vDate); + if(pFormat=='hour')vDate.setMinutes(0,0); + else vDate.setHours(0,0,0); + return(vDate); }; // Used to determine the maximum date of all tasks and set upper bound based on format JSGantt.getMaxDate=function (pList, pFormat) { - var vDate=new Date(); + var vDate=new Date(); - vDate.setTime(pList[0].getEnd().getTime()); + vDate.setTime(pList[0].getEnd().getTime()); - // Parse all Task End dates to find max - for(var i=0; ivDate.getTime()) vDate.setTime(pList[i].getEnd().getTime()); - } + // Parse all Task End dates to find max + for(var i=0; ivDate.getTime()) vDate.setTime(pList[i].getEnd().getTime()); + } - // Adjust max date to specific format boundaries (end of week or end of month) - if (pFormat=='day') - { - vDate.setDate(vDate.getDate()+1); + // Adjust max date to specific format boundaries (end of week or end of month) + if (pFormat=='day') + { + vDate.setDate(vDate.getDate()+1); - while(vDate.getDay()%7!=0) vDate.setDate(vDate.getDate()+1); - } - else if (pFormat=='week') - { - //For weeks, what is the last logical boundary? - vDate.setDate(vDate.getDate()+1); + while(vDate.getDay()%7!=0) vDate.setDate(vDate.getDate()+1); + } + else if (pFormat=='week') + { + //For weeks, what is the last logical boundary? + vDate.setDate(vDate.getDate()+1); - while(vDate.getDay()%7!=0) vDate.setDate(vDate.getDate()+1); - } - else if (pFormat=='month') - { - // Set to last day of current Month - while(vDate.getDate()>1) vDate.setDate(vDate.getDate()+1); - vDate.setDate(vDate.getDate()-1); - } - else if (pFormat=='quarter') - { - // Set to last day of current Quarter - if(vDate.getMonth()==0 || vDate.getMonth()==1 || vDate.getMonth()==2) - vDate.setFullYear(vDate.getFullYear(), 2, 31); - else if(vDate.getMonth()==3 || vDate.getMonth()==4 || vDate.getMonth()==5) - vDate.setFullYear(vDate.getFullYear(), 5, 30); - else if(vDate.getMonth()==6 || vDate.getMonth()==7 || vDate.getMonth()==8) - vDate.setFullYear(vDate.getFullYear(), 8, 30); - else if(vDate.getMonth()==9 || vDate.getMonth()==10 || vDate.getMonth()==11) - vDate.setFullYear(vDate.getFullYear(), 11, 31); - } - else if (pFormat=='hour') - { - if(vDate.getHours()==0)vDate.setDate(vDate.getDate()+1); - vDate.setHours(vDate.getHours()+1); + while(vDate.getDay()%7!=0) vDate.setDate(vDate.getDate()+1); + } + else if (pFormat=='month') + { + // Set to last day of current Month + while(vDate.getDate()>1) vDate.setDate(vDate.getDate()+1); + vDate.setDate(vDate.getDate()-1); + } + else if (pFormat=='quarter') + { + // Set to last day of current Quarter + if(vDate.getMonth()==0 || vDate.getMonth()==1 || vDate.getMonth()==2) + vDate.setFullYear(vDate.getFullYear(), 2, 31); + else if(vDate.getMonth()==3 || vDate.getMonth()==4 || vDate.getMonth()==5) + vDate.setFullYear(vDate.getFullYear(), 5, 30); + else if(vDate.getMonth()==6 || vDate.getMonth()==7 || vDate.getMonth()==8) + vDate.setFullYear(vDate.getFullYear(), 8, 30); + else if(vDate.getMonth()==9 || vDate.getMonth()==10 || vDate.getMonth()==11) + vDate.setFullYear(vDate.getFullYear(), 11, 31); + } + else if (pFormat=='hour') + { + if(vDate.getHours()==0)vDate.setDate(vDate.getDate()+1); + vDate.setHours(vDate.getHours()+1); - while(vDate.getHours()%6!=5) vDate.setHours(vDate.getHours()+1); - } - return(vDate); + while(vDate.getHours()%6!=5) vDate.setHours(vDate.getHours()+1); + } + return(vDate); }; // This function finds the document id of the specified object JSGantt.findObj=function (theObj, theDoc) { - var p, i, foundObj; - if(!theDoc) theDoc=document; - if(document.getElementById) foundObj=document.getElementById(theObj); - return foundObj; + var p, i, foundObj; + if(!theDoc) theDoc=document; + if(document.getElementById) foundObj=document.getElementById(theObj); + return foundObj; }; JSGantt.changeFormat=function(pFormat,ganttObj) { - if(ganttObj) ganttObj.setFormat(pFormat); - else alert('Chart undefined'); + if(ganttObj) ganttObj.setFormat(pFormat); + else alert('Chart undefined'); }; // Function to open/close and hide/show children of specified task JSGantt.folder=function (pID,ganttObj) { - var vList=ganttObj.getList(); - var vDivId=ganttObj.getDivId(); + var vList=ganttObj.getList(); + var vDivId=ganttObj.getDivId(); - ganttObj.clearDependencies(); // clear these first so slow rendering doesn't look odd + ganttObj.clearDependencies(); // clear these first so slow rendering doesn't look odd - for(var i=0; i=52 && vMonthStr==1) vYear--; + if (vWeekNum==1 && vMonthStr==12) vYear++; + if (vWeekNum<10) vWeekNum='0'+vWeekNum; - - for (var i=0; i=52 && vMonthStr==1) vYear--; - if (vWeekNum==1 && vMonthStr==12) vYear++; - if (vWeekNum<10) vWeekNum='0'+vWeekNum; - - vDateStr+=vYear+'-W'+vWeekNum+'-'+vDayOfWeek; - break; - default: - if (pL[pDateFormatArr[i].toLowerCase()]) vDateStr+=pL[pDateFormatArr[i].toLowerCase()]; - else vDateStr+=pDateFormatArr[i]; - break; - } - } - return vDateStr; + vDateStr+=vYear+'-W'+vWeekNum+'-'+vDayOfWeek; + break; + default: + if (pL[pDateFormatArr[i].toLowerCase()]) vDateStr+=pL[pDateFormatArr[i].toLowerCase()]; + else vDateStr+=pDateFormatArr[i]; + break; + } + } + return vDateStr; }; JSGantt.parseDateFormatStr=function(pFormatStr) { - var vDateStr=''; - var vComponantStr=''; - var vCurrChar=''; - var vSeparators=new RegExp('[\/\\ -.,\'":]'); - var vDateFormatArray=new Array(); + var vDateStr=''; + var vComponantStr=''; + var vCurrChar=''; + var vSeparators=new RegExp('[\/\\ -.,\'":]'); + var vDateFormatArray=new Array(); - for (var i=0; i0) project=projNode[0].getAttribute('xmlns'); + var projNode=JSGantt.findXMLNode(pXmlDoc,'Project'); + if (typeof projNode!='undefined' && projNode.length>0) project=projNode[0].getAttribute('xmlns'); - if(project=='http://schemas.microsoft.com/project') - { - vMSP=true; - pGanttVar.setDateInputFormat('yyyy-mm-dd'); - Task=JSGantt.findXMLNode(pXmlDoc,'Task'); - if (typeof Task=='undefined')n=0; - else n=Task.length; + if(project=='http://schemas.microsoft.com/project') + { + vMSP=true; + pGanttVar.setDateInputFormat('yyyy-mm-dd'); + Task=JSGantt.findXMLNode(pXmlDoc,'Task'); + if (typeof Task=='undefined')n=0; + else n=Task.length; - var resources=JSGantt.findXMLNode(pXmlDoc,'Resource'); - if (typeof resources=='undefined'){n=0; m=0;} - else m=resources.length; + var resources=JSGantt.findXMLNode(pXmlDoc,'Resource'); + if (typeof resources=='undefined'){n=0; m=0;} + else m=resources.length; - for(i=0;i0 && uid>0) res[uid]=resname; - } + if (resname.length>0 && uid>0) res[uid]=resname; + } - var assignments=JSGantt.findXMLNode(pXmlDoc,'Assignment'); - if (typeof assignments=='undefined') j=0; - else j=assignments.length; + var assignments=JSGantt.findXMLNode(pXmlDoc,'Assignment'); + if (typeof assignments=='undefined') j=0; + else j=assignments.length; - for(i=0;i0) - { - if (resUID>0) assRes[uid]=res[resUID]; - ass[uid]=assignments[i]; - } - } + if (uid>0) + { + if (resUID>0) assRes[uid]=res[resUID]; + ass[uid]=assignments[i]; + } + } - // Store information about parent UIDs in an easily searchable form - for(i=0;i0) pars[vOutlineNumber]=uid; - if (uid>maxPID)maxPID=uid; - } + if(uid!=0) var vOutlineNumber=JSGantt.getXMLNodeValue(Task[i],'OutlineNumber',2,'0'); + if (uid>0) pars[vOutlineNumber]=uid; + if (uid>maxPID)maxPID=uid; + } - for(i=0;i1) - { - vOutlineNumber=JSGantt.getXMLNodeValue(Task[i],'OutlineNumber',2,'0'); - pParent=pars[vOutlineNumber.substr(0, vOutlineNumber.lastIndexOf('.'))]; - } + var vOutlineLevel=JSGantt.getXMLNodeValue(Task[i],'OutlineLevel',1,0); + if (vOutlineLevel>1) + { + vOutlineNumber=JSGantt.getXMLNodeValue(Task[i],'OutlineNumber',2,'0'); + pParent=pars[vOutlineNumber.substr(0, vOutlineNumber.lastIndexOf('.'))]; + } - try {var pNotes=Task[i].getElementsByTagName('Notes')[0].childNodes[1].nodeValue; //this should be a CDATA node - } catch (error) - {pNotes ='';} + try {var pNotes=Task[i].getElementsByTagName('Notes')[0].childNodes[1].nodeValue; //this should be a CDATA node + } catch (error) + {pNotes ='';} - if(typeof assRes[pID]!='undefined') var pRes=assRes[pID]; - else pRes=''; + if(typeof assRes[pID]!='undefined') var pRes=assRes[pID]; + else pRes=''; - var predecessors=JSGantt.findXMLNode(Task[i],'PredecessorLink'); - if (typeof predecessors=='undefined') j=0; - else j=predecessors.length; - var pDepend=''; + var predecessors=JSGantt.findXMLNode(Task[i],'PredecessorLink'); + if (typeof predecessors=='undefined') j=0; + else j=predecessors.length; + var pDepend=''; - for(k=0;k0) - { - if (pDepend.length>0)pDepend+=','; - switch(depType) - { - case 0: pDepend+=depUID+'FF'; break; - case 1: pDepend+=depUID+'FS'; break; - case 2: pDepend+=depUID+'SF'; break; - case 3: pDepend+=depUID+'SS'; break; - default: pDepend+=depUID+'FS'; break; - } - } - } + if (depUID>0) + { + if (pDepend.length>0)pDepend+=','; + switch(depType) + { + case 0: pDepend+=depUID+'FF'; break; + case 1: pDepend+=depUID+'FS'; break; + case 2: pDepend+=depUID+'SF'; break; + case 3: pDepend+=depUID+'SS'; break; + default: pDepend+=depUID+'FS'; break; + } + } + } - var pOpen=1; - var pCaption=''; + var pOpen=1; + var pCaption=''; - if(pGroup>0) var pClass ='ggroupblack'; - else if(pMile>0) pClass ='gmilestone'; - else pClass ='gtaskblue'; + if(pGroup>0) var pClass ='ggroupblack'; + else if(pMile>0) pClass ='gmilestone'; + else pClass ='gtaskblue'; - // check for split tasks + // check for split tasks - var splits=JSGantt.findXMLNode(ass[pID],'TimephasedData'); - if (typeof splits=='undefined') j=0; - else j=splits.length; + var splits=JSGantt.findXMLNode(ass[pID],'TimephasedData'); + if (typeof splits=='undefined') j=0; + else j=splits.length; - var vSplitStart=pStart; - var vSplitEnd=pEnd; - var vSubCreated=false; - var vDepend=pDepend.replace(/,*[0-9]+[FS]F/g,''); + var vSplitStart=pStart; + var vSplitEnd=pEnd; + var vSubCreated=false; + var vDepend=pDepend.replace(/,*[0-9]+[FS]F/g,''); - for(k=0;k0) pClass ='ggroupblack'; - else if(pMile>0) pClass ='gmilestone'; - else pClass ='gtaskblue'; - } + if(pID!=0) + { + pName=JSGantt.getXMLNodeValue(Task[i],'pName',2,'No Task Name'); + pStart=JSGantt.getXMLNodeValue(Task[i],'pStart',2,''); + pEnd=JSGantt.getXMLNodeValue(Task[i],'pEnd',2,''); + pLink=JSGantt.getXMLNodeValue(Task[i],'pLink',2,''); + pMile=JSGantt.getXMLNodeValue(Task[i],'pMile',1,0); + pComp=JSGantt.getXMLNodeValue(Task[i],'pComp',1,0); + pGroup=JSGantt.getXMLNodeValue(Task[i],'pGroup',1,0); + pParent=JSGantt.getXMLNodeValue(Task[i],'pParent',1,0); + pRes=JSGantt.getXMLNodeValue(Task[i],'pRes',2,''); + pOpen=JSGantt.getXMLNodeValue(Task[i],'pOpen',1,1); + pDepend=JSGantt.getXMLNodeValue(Task[i],'pDepend',2,''); + pCaption=JSGantt.getXMLNodeValue(Task[i],'pCaption',2,''); + pNotes=JSGantt.getXMLNodeValue(Task[i],'pNotes',2,''); + pClass=JSGantt.getXMLNodeValue(Task[i],'pClass',2); + if (typeof pClass=='undefined') + { + if(pGroup>0) pClass ='ggroupblack'; + else if(pMile>0) pClass ='gmilestone'; + else pClass ='gtaskblue'; + } - // Finally add the task - pGanttVar.AddTaskItem(new JSGantt.TaskItem(pID, pName, pStart, pEnd, pClass, pLink, pMile, pRes, pComp, pGroup, pParent, pOpen, pDepend, pCaption, pNotes, pGanttVar)); - } - } - } + // Finally add the task + pGanttVar.AddTaskItem(new JSGantt.TaskItem(pID, pName, pStart, pEnd, pClass, pLink, pMile, pRes, pComp, pGroup, pParent, pOpen, pDepend, pCaption, pNotes, pGanttVar)); + } + } + } }; JSGantt.benchMark=function(pItem) { - var vEndTime=new Date().getTime(); - alert(pItem+': Elapsed time: '+((vEndTime-vBenchTime)/1000)+' seconds.'); - vBenchTime=new Date().getTime(); + var vEndTime=new Date().getTime(); + alert(pItem+': Elapsed time: '+((vEndTime-vBenchTime)/1000)+' seconds.'); + vBenchTime=new Date().getTime(); }; JSGantt.getIsoWeek=function(pDate){ - // We have to compare against the monday of the first week of the year containing 04 jan *not* 01/01 - // 60*60*24*1000=86400000 - var dayMiliseconds=86400000; - var keyDay=new Date(pDate.getFullYear(),0,4,0,0,0); - var keyDayOfWeek=(keyDay.getDay()==0) ? 6 : keyDay.getDay()-1; // define monday as 0 - var firstMondayYearTime=keyDay.getTime()-(keyDayOfWeek * dayMiliseconds); - var thisDate=new Date(pDate.getFullYear(), pDate.getMonth(),pDate.getDate(),0,0,0); // This at 00:00:00 - var thisTime=thisDate.getTime(); - var daysFromFirstMonday=Math.round(((thisTime-firstMondayYearTime) / dayMiliseconds)); - var lastWeek=99; - var thisWeek=99; + // We have to compare against the monday of the first week of the year containing 04 jan *not* 01/01 + // 60*60*24*1000=86400000 + var dayMiliseconds=86400000; + var keyDay=new Date(pDate.getFullYear(),0,4,0,0,0); + var keyDayOfWeek=(keyDay.getDay()==0) ? 6 : keyDay.getDay()-1; // define monday as 0 + var firstMondayYearTime=keyDay.getTime()-(keyDayOfWeek * dayMiliseconds); + var thisDate=new Date(pDate.getFullYear(), pDate.getMonth(),pDate.getDate(),0,0,0); // This at 00:00:00 + var thisTime=thisDate.getTime(); + var daysFromFirstMonday=Math.round(((thisTime-firstMondayYearTime) / dayMiliseconds)); + var lastWeek=99; + var thisWeek=99; - var firstMondayYear=new Date(firstMondayYearTime); + var firstMondayYear=new Date(firstMondayYearTime); - thisWeek=Math.ceil((daysFromFirstMonday+1)/7); + thisWeek=Math.ceil((daysFromFirstMonday+1)/7); - if (thisWeek<=0) thisWeek=JSGantt.getIsoWeek(new Date(pDate.getFullYear()-1,11,31,0,0,0)); - else if (thisWeek==53 && (new Date(pDate.getFullYear(),0,1,0,0,0)).getDay()!=4 && (new Date(pDate.getFullYear(),11,31,0,0,0)).getDay()!=4) thisWeek=1; - return thisWeek; + if (thisWeek<=0) thisWeek=JSGantt.getIsoWeek(new Date(pDate.getFullYear()-1,11,31,0,0,0)); + else if (thisWeek==53 && (new Date(pDate.getFullYear(),0,1,0,0,0)).getDay()!=4 && (new Date(pDate.getFullYear(),11,31,0,0,0)).getDay()!=4) thisWeek=1; + return thisWeek; }; JSGantt.addListener=function (eventName, handler, control) { - // Check if control is a string - if (control===String(control)) control=JSGantt.findObj(control); + // Check if control is a string + if (control===String(control)) control=JSGantt.findObj(control); - if(control.addEventListener) //Standard W3C - { - return control.addEventListener(eventName, handler, false); - } - else if (control.attachEvent) //IExplore - { - return control.attachEvent('on'+eventName, handler); - } - else - { - return false; - } + if(control.addEventListener) //Standard W3C + { + return control.addEventListener(eventName, handler, false); + } + else if (control.attachEvent) //IExplore + { + return control.attachEvent('on'+eventName, handler); + } + else + { + return false; + } }; JSGantt.addTooltipListeners=function(pGanttChart, pObj1, pObj2) { - JSGantt.addListener('mouseover', function (e) {JSGantt.showToolTip(pGanttChart, e, pObj2, null, pGanttChart.getTimer());}, pObj1); - JSGantt.addListener('mouseout', function (e) {JSGantt.delayedHide(pGanttChart, pGanttChart.vTool, pGanttChart.getTimer());}, pObj1); + JSGantt.addListener('mouseover', function (e) {JSGantt.showToolTip(pGanttChart, e, pObj2, null, pGanttChart.getTimer());}, pObj1); + JSGantt.addListener('mouseout', function (e) {JSGantt.delayedHide(pGanttChart, pGanttChart.vTool, pGanttChart.getTimer());}, pObj1); }; JSGantt.addThisRowListeners=function(pGanttChart, pObj1, pObj2) { - JSGantt.addListener('mouseover', function () {pGanttChart.mouseOver(pObj1, pObj2);}, pObj1); - JSGantt.addListener('mouseover', function () {pGanttChart.mouseOver(pObj1, pObj2);}, pObj2); - JSGantt.addListener('mouseout', function () {pGanttChart.mouseOut(pObj1, pObj2);}, pObj1); - JSGantt.addListener('mouseout', function () {pGanttChart.mouseOut(pObj1, pObj2);}, pObj2); + JSGantt.addListener('mouseover', function () {pGanttChart.mouseOver(pObj1, pObj2);}, pObj1); + JSGantt.addListener('mouseover', function () {pGanttChart.mouseOver(pObj1, pObj2);}, pObj2); + JSGantt.addListener('mouseout', function () {pGanttChart.mouseOut(pObj1, pObj2);}, pObj1); + JSGantt.addListener('mouseout', function () {pGanttChart.mouseOut(pObj1, pObj2);}, pObj2); }; JSGantt.addFolderListeners=function(pGanttChart, pObj, pID) { - JSGantt.addListener('click', function () {JSGantt.folder(pID, pGanttChart);}, pObj); + JSGantt.addListener('click', function () {JSGantt.folder(pID, pGanttChart);}, pObj); }; JSGantt.addFormatListeners=function(pGanttChart, pFormat, pObj) { - JSGantt.addListener('click', function () {JSGantt.changeFormat(pFormat, pGanttChart);}, pObj); + JSGantt.addListener('click', function () {JSGantt.changeFormat(pFormat, pGanttChart);}, pObj); }; JSGantt.addScrollListeners=function(pGanttChart) { - JSGantt.addListener('scroll', function () {pGanttChart.getChartBody().scrollTop=pGanttChart.getListBody().scrollTop;}, pGanttChart.getListBody()); - JSGantt.addListener('scroll', function () {pGanttChart.getListBody().scrollTop=pGanttChart.getChartBody().scrollTop;}, pGanttChart.getChartBody()); - JSGantt.addListener('scroll', function () {pGanttChart.getChartHead().scrollLeft=pGanttChart.getChartBody().scrollLeft;}, pGanttChart.getChartBody()); - JSGantt.addListener('scroll', function () {pGanttChart.getChartBody().scrollLeft=pGanttChart.getChartHead().scrollLeft;}, pGanttChart.getChartHead()); - JSGantt.addListener('resize', function () {pGanttChart.getChartHead().scrollLeft=pGanttChart.getChartBody().scrollLeft;}, window); - JSGantt.addListener('resize', function () {pGanttChart.getListBody().scrollTop=pGanttChart.getChartBody().scrollTop;}, window); + JSGantt.addListener('scroll', function () {pGanttChart.getChartBody().scrollTop=pGanttChart.getListBody().scrollTop;}, pGanttChart.getListBody()); + JSGantt.addListener('scroll', function () {pGanttChart.getListBody().scrollTop=pGanttChart.getChartBody().scrollTop;}, pGanttChart.getChartBody()); + JSGantt.addListener('scroll', function () {pGanttChart.getChartHead().scrollLeft=pGanttChart.getChartBody().scrollLeft;}, pGanttChart.getChartBody()); + JSGantt.addListener('scroll', function () {pGanttChart.getChartBody().scrollLeft=pGanttChart.getChartHead().scrollLeft;}, pGanttChart.getChartHead()); + JSGantt.addListener('resize', function () {pGanttChart.getChartHead().scrollLeft=pGanttChart.getChartBody().scrollLeft;}, window); + JSGantt.addListener('resize', function () {pGanttChart.getListBody().scrollTop=pGanttChart.getChartBody().scrollTop;}, window); }; diff --git a/htdocs/includes/jsgantt/jsgantt.min.js b/htdocs/includes/jsgantt/jsgantt.min.js deleted file mode 100644 index 9ec44995993..00000000000 --- a/htdocs/includes/jsgantt/jsgantt.min.js +++ /dev/null @@ -1,2 +0,0 @@ -var JSGantt;JSGantt||(JSGantt={});var vBenchTime=(new Date).getTime();JSGantt.isIE=function(){return"undefined"!=typeof document.all?"pageXOffset"in window?!1:!0:!1},JSGantt.TaskItem=function(t,e,n,a,o,i,s,r,l,d,u,h,c,f,p,m){var v,S,w,D,T,y=parseInt(document.createTextNode(t).data),L=document.createTextNode(e).data,N=new Date(0),G=new Date(0),M=null,J=null,k=document.createTextNode(o).data,C=document.createTextNode(i).data,I=parseInt(document.createTextNode(s).data),F=document.createTextNode(r).data,b=parseFloat(document.createTextNode(l).data),H=parseInt(document.createTextNode(d).data),x=document.createTextNode(u).data,E=2==H?1:parseInt(document.createTextNode(h).data),X=new Array,Y=new Array,O=document.createTextNode(f).data,R="",A=0,V=0,P=1,B=0,U=!1,j=null,W=null,q=m instanceof JSGantt.GanttChart?m:g,_=null,Q=null,z=null,K=null,Z=null;if(T=document.createElement("span"),T.className="gTaskNotes",null!=p&&(T.innerHTML=p,JSGantt.stripUnwanted(T)),null!=n&&""!=n&&(N=n instanceof Date?n:JSGantt.parseDateStr(document.createTextNode(n).data,q.getDateInputFormat()),M=N),null!=a&&""!=a&&(G=a instanceof Date?a:JSGantt.parseDateStr(document.createTextNode(a).data,q.getDateInputFormat()),J=G),null!=c)for(var $=c+"",tt=$.split(","),et=tt.length,nt=0;et>nt;nt++)-1!=tt[nt].toUpperCase().indexOf("SS")?(X[nt]=tt[nt].substring(0,tt[nt].toUpperCase().indexOf("SS")),Y[nt]="SS"):-1!=tt[nt].toUpperCase().indexOf("FF")?(X[nt]=tt[nt].substring(0,tt[nt].toUpperCase().indexOf("FF")),Y[nt]="FF"):-1!=tt[nt].toUpperCase().indexOf("SF")?(X[nt]=tt[nt].substring(0,tt[nt].toUpperCase().indexOf("SF")),Y[nt]="SF"):-1!=tt[nt].toUpperCase().indexOf("FS")?(X[nt]=tt[nt].substring(0,tt[nt].toUpperCase().indexOf("FS")),Y[nt]="FS"):(X[nt]=tt[nt],Y[nt]="FS");this.getID=function(){return y},this.getName=function(){return L},this.getStart=function(){return N},this.getEnd=function(){return G},this.getGroupMinStart=function(){return M},this.getGroupMinEnd=function(){return J},this.getClass=function(){return k},this.getLink=function(){return C},this.getMile=function(){return I},this.getDepend=function(){return X?X:null},this.getDepType=function(){return Y?Y:null},this.getCaption=function(){return O?O:""},this.getResource=function(){return F?F:" "},this.getCompVal=function(){return b?b:0},this.getCompStr=function(){return b?b+"%":""},this.getNotes=function(){return T},this.getSortIdx=function(){return B},this.getToDelete=function(){return U},this.getDuration=function(t,e){if(I)R="-";else{var n=new Date(this.getEnd().getTime()),a=null;switch(t){case"week":a="day";break;case"month":a="week";break;case"quarter":a="month";break;default:a=t}(n.getTime()-6e4*n.getTimezoneOffset())%864e5==0&&(n=new Date(n.getFullYear(),n.getMonth(),n.getDate()+1,n.getHours(),n.getMinutes(),n.getSeconds()));var o=JSGantt.getOffset(this.getStart(),n,999,a)/1e3;switch(Math.floor(o)!=o&&(o=Math.round(10*o)/10),a){case"hour":R=o+" "+(1!=o?e.hrs:e.hr);break;case"day":R=o+" "+(1!=o?e.dys:e.dy);break;case"week":R=o+" "+(1!=o?e.wks:e.wk);break;case"month":R=o+" "+(1!=o?e.mths:e.mth);break;case"quarter":R=o+" "+(1!=o?e.qtrs:e.qtr)}}return R},this.getParent=function(){return x},this.getGroup=function(){return H},this.getOpen=function(){return E},this.getLevel=function(){return A},this.getNumKids=function(){return V},this.getStartX=function(){return v},this.getStartY=function(){return S},this.getEndX=function(){return w},this.getEndY=function(){return D},this.getVisible=function(){return P},this.getParItem=function(){return j},this.getCellDiv=function(){return W},this.getBarDiv=function(){return _},this.getTaskDiv=function(){return Q},this.getChildRow=function(){return K},this.getListChildRow=function(){return z},this.getGroupSpan=function(){return Z},this.setStart=function(t){t instanceof Date&&(N=t)},this.setEnd=function(t){t instanceof Date&&(G=t)},this.setGroupMinStart=function(t){t instanceof Date&&(M=t)},this.setGroupMinEnd=function(t){t instanceof Date&&(J=t)},this.setLevel=function(t){A=parseInt(document.createTextNode(t).data)},this.setNumKid=function(t){V=parseInt(document.createTextNode(t).data)},this.setCompVal=function(t){b=parseFloat(document.createTextNode(t).data)},this.setStartX=function(t){v=parseInt(document.createTextNode(t).data)},this.setStartY=function(t){S=parseInt(document.createTextNode(t).data)},this.setEndX=function(t){w=parseInt(document.createTextNode(t).data)},this.setEndY=function(t){D=parseInt(document.createTextNode(t).data)},this.setOpen=function(t){E=parseInt(document.createTextNode(t).data)},this.setVisible=function(t){P=parseInt(document.createTextNode(t).data)},this.setSortIdx=function(t){B=parseInt(document.createTextNode(t).data)},this.setToDelete=function(t){U=t?!0:!1},this.setParItem=function(t){t instanceof JSGantt.TaskItem&&(j=t)},this.setCellDiv=function(t){("function"!=typeof HTMLDivElement||t instanceof HTMLDivElement)&&(W=t)},this.setGroup=function(t){H=parseInt(document.createTextNode(t).data)},this.setBarDiv=function(t){("function"!=typeof HTMLDivElement||t instanceof HTMLDivElement)&&(_=t)},this.setTaskDiv=function(t){("function"!=typeof HTMLDivElement||t instanceof HTMLDivElement)&&(Q=t)},this.setChildRow=function(t){("function"!=typeof HTMLTableRowElement||t instanceof HTMLTableRowElement)&&(K=t)},this.setListChildRow=function(t){("function"!=typeof HTMLTableRowElement||t instanceof HTMLTableRowElement)&&(z=t)},this.setGroupSpan=function(t){("function"!=typeof HTMLSpanElement||t instanceof HTMLSpanElement)&&(Z=t)}},JSGantt.GanttChart=function(t,e){var n,a=t,o=e,i=null,s=1,r=1,l=1,g=1,d=1,u=25e3,h=1,c=1,f=1,p=1,m=1,v=1,S=1,w=1,D=1,T=1,y=1,L=1,N=1,G=1,M=new Array("top"),J="yyyy-mm-dd",k=JSGantt.parseDateFormatStr("dd/mm/yyyy"),C=JSGantt.parseDateFormatStr("dd month yyyy"),I=JSGantt.parseDateFormatStr("day dd month yyyy"),F=JSGantt.parseDateFormatStr("HH"),b=JSGantt.parseDateFormatStr("dd/mm/yyyy"),H=JSGantt.parseDateFormatStr("dd"),x=JSGantt.parseDateFormatStr("yyyy"),E=JSGantt.parseDateFormatStr("dd/mm"),X=JSGantt.parseDateFormatStr("yyyy"),Y=JSGantt.parseDateFormatStr("mon"),O=JSGantt.parseDateFormatStr("yyyy"),R=JSGantt.parseDateFormatStr("qq"),A=(JSGantt.parseDateFormatStr("dd/mm/yyyy"),1),V=new Array,P=new Array("hour","day","week","month","quarter"),B=(new Array(31,28,31,30,31,30,31,31,30,31,30,31),!0),U=8,j="",W=18,q=18,_=36,Q=36,z=18,K=20,Z=-1,$=null,tt=null,et=null,nt=null,at=null,ot=20;this.setUseFade=function(t){s=t},this.setUseMove=function(t){r=t},this.setUseRowHlt=function(t){l=t},this.setUseToolTip=function(t){g=t},this.setUseSort=function(t){d=t},this.setUseSingleCell=function(t){u=1*t},this.setFormatArr=function(){var t="hour day week month quarter";P=new Array;for(var e=0,n=0;e1){P[n++]=arguments[e].toLowerCase();var a=new RegExp("(?:^|s)"+arguments[e]+"(?!S)","g");t=t.replace(a,"")}},this.setShowRes=function(t){h=t},this.setShowDur=function(t){c=t},this.setShowComp=function(t){f=t},this.setShowStartDate=function(t){p=t},this.setShowEndDate=function(t){m=t},this.setShowTaskInfoRes=function(t){S=t},this.setShowTaskInfoDur=function(t){w=t},this.setShowTaskInfoComp=function(t){D=t},this.setShowTaskInfoStartDate=function(t){T=t},this.setShowTaskInfoEndDate=function(t){y=t},this.setShowTaskInfoNotes=function(t){L=t},this.setShowTaskInfoLink=function(t){N=t},this.setShowEndWeekDate=function(t){v=t},this.setShowSelector=function(){var t="top bottom";M=new Array;for(var e=0,n=0;e1){M[n++]=arguments[e].toLowerCase();var a=new RegExp("(?:^|s)"+arguments[e]+"(?!S)","g");t=t.replace(a,"")}},this.setShowDeps=function(t){G=t},this.setDateInputFormat=function(t){J=t},this.setDateTaskTableDisplayFormat=function(t){k=JSGantt.parseDateFormatStr(t)},this.setDateTaskDisplayFormat=function(t){C=JSGantt.parseDateFormatStr(t)},this.setHourMajorDateDisplayFormat=function(t){I=JSGantt.parseDateFormatStr(t)},this.setHourMinorDateDisplayFormat=function(t){F=JSGantt.parseDateFormatStr(t)},this.setDayMajorDateDisplayFormat=function(t){b=JSGantt.parseDateFormatStr(t)},this.setDayMinorDateDisplayFormat=function(t){H=JSGantt.parseDateFormatStr(t)},this.setWeekMajorDateDisplayFormat=function(t){x=JSGantt.parseDateFormatStr(t)},this.setWeekMinorDateDisplayFormat=function(t){E=JSGantt.parseDateFormatStr(t)},this.setMonthMajorDateDisplayFormat=function(t){X=JSGantt.parseDateFormatStr(t)},this.setMonthMinorDateDisplayFormat=function(t){Y=JSGantt.parseDateFormatStr(t)},this.setQuarterMajorDateDisplayFormat=function(t){O=JSGantt.parseDateFormatStr(t)},this.setQuarterMinorDateDisplayFormat=function(t){R=JSGantt.parseDateFormatStr(t)},this.setCaptionType=function(t){n=t},this.setFormat=function(t){o=t,this.Draw()},this.setMinGpLen=function(t){U=t},this.setScrollTo=function(t){j=t},this.setHourColWidth=function(t){W=t},this.setDayColWidth=function(t){q=t},this.setWeekColWidth=function(t){_=t},this.setMonthColWidth=function(t){Q=t},this.setQuarterColWidth=function(t){z=t},this.setRowHeight=function(t){K=t},this.setLang=function(t){vLangs[t]&&(vLang=t)},this.setChartBody=function(t){("function"!=typeof HTMLDivElement||t instanceof HTMLDivElement)&&($=t)},this.setChartHead=function(t){("function"!=typeof HTMLDivElement||t instanceof HTMLDivElement)&&(tt=t)},this.setListBody=function(t){("function"!=typeof HTMLDivElement||t instanceof HTMLDivElement)&&(et=t)},this.setChartTable=function(t){("function"!=typeof HTMLTableElement||t instanceof HTMLTableElement)&&(nt=t)},this.setLines=function(t){("function"!=typeof HTMLDivElement||t instanceof HTMLDivElement)&&(at=t)},this.setTimer=function(t){ot=1*t},this.addLang=function(t,e){if(!vLangs[t]){vLangs[t]=new Object;for(var n in vLangs.en)vLangs[t][n]=e[n]?document.createTextNode(e[n]).data:vLangs.en[n]}},this.getDivId=function(){return i},this.getUseFade=function(){return s},this.getUseMove=function(){return r},this.getUseRowHlt=function(){return l},this.getUseToolTip=function(){return g},this.getUseSort=function(){return d},this.getUseSingleCell=function(){return u},this.getFormatArr=function(){return P},this.getShowRes=function(){return h},this.getShowDur=function(){return c},this.getShowComp=function(){return f},this.getShowStartDate=function(){return p},this.getShowEndDate=function(){return m},this.getShowTaskInfoRes=function(){return S},this.getShowTaskInfoDur=function(){return w},this.getShowTaskInfoComp=function(){return D},this.getShowTaskInfoStartDate=function(){return T},this.getShowTaskInfoEndDate=function(){return y},this.getShowTaskInfoNotes=function(){return L},this.getShowTaskInfoLink=function(){return N},this.getShowEndWeekDate=function(){return v},this.getShowSelector=function(){return M},this.getShowDeps=function(){return G},this.getDateInputFormat=function(){return J},this.getDateTaskTableDisplayFormat=function(){return k},this.getDateTaskDisplayFormat=function(){return C},this.getHourMajorDateDisplayFormat=function(){return I},this.getHourMinorDateDisplayFormat=function(){return F},this.getDayMajorDateDisplayFormat=function(){return b},this.getDayMinorDateDisplayFormat=function(){return H},this.getWeekMajorDateDisplayFormat=function(){return x},this.getWeekMinorDateDisplayFormat=function(){return E},this.getMonthMajorDateDisplayFormat=function(){return X},this.getMonthMinorDateDisplayFormat=function(){return Y},this.getQuarterMajorDateDisplayFormat=function(){return O},this.getQuarterMinorDateDisplayFormat=function(){return R},this.getCaptionType=function(){return n},this.getMinGpLen=function(){return U},this.getScrollTo=function(){return j},this.getHourColWidth=function(){return W},this.getDayColWidth=function(){return q},this.getWeekColWidth=function(){return _},this.getMonthColWidth=function(){return Q},this.getQuarterColWidth=function(){return z},this.getRowHeight=function(){return K},this.getChartBody=function(){return $},this.getChartHead=function(){return tt},this.getListBody=function(){return et},this.getChartTable=function(){return nt},this.getLines=function(){return at},this.getTimer=function(){return ot},this.CalcTaskXY=function(){for(var t,e,n,a,o=this.getList(),i=Math.floor(this.getRowHeight()/2),s=0;sa&&(g*=-1),o){case"SF":l*=-1,n>=t-10&&e!=a&&(r=!0),s=-1;break;case"SS":n>t?l*=-1:l=n-t-2*l;break;case"FF":n>=t&&(l=n-t+2*l),s=-1;break;default:t+10>=n&&e!=a&&(r=!0)}r?(this.sLine(t,e,t+l,e,i),this.sLine(t+l,e,t+l,a-g,i),this.sLine(t+l,a-g,n-2*l,a-g,i),this.sLine(n-2*l,a-g,n-2*l,a,i),this.sLine(n-2*l,a,n-1*s,a,i)):e!=a?(this.sLine(t,e,t+l,e,i),this.sLine(t+l,e,t+l,a,i),this.sLine(t+l,a,n-1*s,a,i)):this.sLine(t,e,n-1*s,a,i);var d=this.sLine(n,a,n-3-(0>s?1:0),a-3-(0>s?1:0),i+"Arw");d.style.width="0px",d.style.height="0px"},this.DrawDependencies=function(){if(1==this.getShowDeps()){this.CalcTaskXY(),this.clearDependencies();for(var t=this.getList(),e=0;e0&&1==t[e].getVisible())for(var i=0;o>i;i++){var s=this.getArrayLocationByID(n[i]);s>=0&&2!=t[s].getGroup()&&1==t[s].getVisible()&&("SS"==a[i]?this.drawDependency(t[s].getStartX()-1,t[s].getStartY(),t[e].getStartX()-1,t[e].getStartY(),"SS","gDepSS"):"FF"==a[i]?this.drawDependency(t[s].getEndX(),t[s].getEndY(),t[e].getEndX(),t[e].getEndY(),"FF","gDepFF"):"SF"==a[i]?this.drawDependency(t[s].getStartX()-1,t[s].getStartY(),t[e].getEndX(),t[e].getEndY(),"SF","gDepSF"):"FS"==a[i]&&this.drawDependency(t[s].getEndX(),t[s].getEndY(),t[e].getStartX()-1,t[e].getStartY(),"FS","gDepFS"))}}}Z>=0&&this.sLine(Z,0,Z,this.getChartTable().offsetHeight-1,"gCurDate")},this.getArrayLocationByID=function(t){for(var e=this.getList(),n=0;n0){B&&JSGantt.processRows(V,0,-1,1,1,this.getUseSort()),B=!1,e=JSGantt.getMinDate(V,o),t=JSGantt.getMaxDate(V,o),"day"==o?T=q:"week"==o?T=_:"month"==o?T=Q:"quarter"==o?T=z:"hour"==o&&(T=W);var y=document.createDocumentFragment(),L=this.newNode(y,"div",i+"glisthead","glistlbl gcontainercol"),N=this.newNode(L,"table",null,"gtasktableh"),G=this.newNode(N,"tbody"),M=this.newNode(G,"tr");this.newNode(M,"td",null,"gtasklist"," ");var J=this.newNode(M,"td",null,"gspanning gtaskname");J.appendChild(this.drawSelector("top")),1==h&&this.newNode(M,"td",null,"gspanning gresource"," "),1==c&&this.newNode(M,"td",null,"gspanning gduration"," "),1==f&&this.newNode(M,"td",null,"gspanning gpccomplete"," "),1==p&&this.newNode(M,"td",null,"gspanning gstartdate"," "),1==m&&this.newNode(M,"td",null,"gspanning genddate"," "),M=this.newNode(G,"tr"),this.newNode(M,"td",null,"gtasklist"," "),this.newNode(M,"td",null,"gtaskname"," "),1==h&&this.newNode(M,"td",null,"gtaskheading gresource",vLangs[vLang].resource),1==c&&this.newNode(M,"td",null,"gtaskheading gduration",vLangs[vLang].duration),1==f&&this.newNode(M,"td",null,"gtaskheading gpccomplete",vLangs[vLang].comp),1==p&&this.newNode(M,"td",null,"gtaskheading gstartdate",vLangs[vLang].startdate),1==m&&this.newNode(M,"td",null,"gtaskheading genddate",vLangs[vLang].enddate),L=this.newNode(y,"div",null,"glabelfooter");var C=document.createDocumentFragment(),A=this.newNode(C,"div",i+"glistbody","glistgrid gcontainercol");for(this.setListBody(A),N=this.newNode(A,"table",null,"gtasktable"),G=this.newNode(N,"tbody"),st=0;st=n&&(J=this.newNode(M,"td",null,at),this.newNode(J,"div",null,null,JSGantt.formatDateStr(n,H,vLangs[vLang]),T),g++),n.setDate(n.getDate()+1);else if("week"==o)t>=n&&(J=this.newNode(M,"td",null,at),this.newNode(J,"div",null,null,JSGantt.formatDateStr(n,E,vLangs[vLang]),T),g++),n.setDate(n.getDate()+7);else if("month"==o)for(t>=n&&(J=this.newNode(M,"td",null,at),this.newNode(J,"div",null,null,JSGantt.formatDateStr(n,Y,vLangs[vLang]),T),g++),n.setDate(n.getDate()+1);n.getDate()>1;)n.setDate(n.getDate()+1);else if("quarter"==o)for(t>=n&&(J=this.newNode(M,"td",null,at),this.newNode(J,"div",null,null,JSGantt.formatDateStr(n,R,vLangs[vLang]),T),g++),n.setDate(n.getDate()+81);n.getDate()>1;)n.setDate(n.getDate()+1);else if("hour"==o){for(st=n.getHours();24>st;st++)n.setHours(st),t>=n&&(J=this.newNode(M,"td",null,at),this.newNode(J,"div",null,null,JSGantt.formatDateStr(n,F,vLangs[vLang]),T),g++);n.setHours(0),n.setDate(n.getDate()+1)}}D=M,s=g*(T+1)+1,0!=u&&g*d>u&&(S=!0),this.newNode(L,"div",null,"rhscrpad",null,null,s+1);var it=document.createDocumentFragment();L=this.newNode(it,"div",i+"gchartbody","gchartgrid gcontainercol"),this.setChartBody(L),N=this.newNode(L,"table",i+"chartTable","gcharttable",null,s),this.setChartTable(N),this.newNode(L,"div",null,"rhscrpad",null,null,s+1),G=this.newNode(N,"tbody");var st=0,rt=0;for(st=0;strt;rt++)ut="day"!=o||rt%7!=4&&rt%7!=5?"gtaskcell":"gtaskcellwkend",this.newNode(M,"td",null,ut,"  ")}else if(l=r-1,V[st].getGroup()){if(l=l>U&&2*U>l?2*U:l,l=U>l?U:l,M=this.newNode(G,"tr",i+"childrow_"+w,(2==V[st].getGroup()?"glineitem gitem":"ggroupitem ggroup")+o,null,null,null,0==V[st].getVisible()?"none":null),V[st].setChildRow(M),JSGantt.addThisRowListeners(this,V[st].getListChildRow(),M),J=this.newNode(M,"td",null,"gtaskcell"),L=this.newNode(J,"div",null,"gtaskcelldiv","  "),V[st].setCellDiv(L),1==V[st].getGroup()&&(L=this.newNode(L,"div",i+"bardiv_"+w,"gtaskbarcontainer",null,l,s),V[st].setBarDiv(L),A=this.newNode(L,"div",i+"taskbar_"+w,V[st].getClass(),null,l),V[st].setTaskDiv(A),this.newNode(A,"div",i+"complete_"+w,V[st].getClass()+"complete",null,V[st].getCompStr()),this.newNode(L,"div",null,V[st].getClass()+"endpointleft"),l>=2*U&&this.newNode(L,"div",null,V[st].getClass()+"endpointright"),ft="ggroupcaption"),!S&&!dt)for(ut="",rt=0;g-1>rt;rt++)ut="day"!=o||rt%7!=4&&rt%7!=5?"gtaskcell":"gtaskcellwkend",this.newNode(M,"td",null,ut,"  ")}else if(l=0>=l?1:l,dt?L=V[st].getParItem().getCellDiv():(M=this.newNode(G,"tr",i+"childrow_"+w,"glineitem gitem"+o,null,null,null,0==V[st].getVisible()?"none":null),V[st].setChildRow(M),JSGantt.addThisRowListeners(this,V[st].getListChildRow(),M),J=this.newNode(M,"td",null,"gtaskcell"),L=this.newNode(J,"div",null,"gtaskcelldiv","  ")),L=this.newNode(L,"div",i+"bardiv_"+w,"gtaskbarcontainer",null,l,s),V[st].setBarDiv(L),A=this.newNode(L,"div",i+"taskbar_"+w,V[st].getClass(),null,l),V[st].setTaskDiv(A),this.newNode(A,"div",i+"complete_"+w,V[st].getClass()+"complete",null,V[st].getCompStr()),dt&&(ht=V[st].getParItem()),(!dt||dt&&V[st].getParItem().getEnd()==V[st].getEnd())&&(ft="gcaption"),!S&&!dt)for(ut="",rt=0;g-1>rt;rt++)ut="day"!=o||rt%7!=4&&rt%7!=5?"gtaskcell":"gtaskcellwkend",this.newNode(M,"td",null,ut,"  ");if(this.getCaptionType()&&null!==ft){switch(this.getCaptionType()){case"Caption":var ct=ht.getCaption();break;case"Resource":ct=ht.getResource();break;case"Duration":ct=ht.getDuration(o,vLangs[vLang]);break;case"Complete":ct=ht.getCompStr()}this.newNode(L,"div",null,ft,ct,120,"gmilecaption"==ft?12:0)}V[st].getTaskDiv()&&L&&(A=this.newNode(L,"div",i+"tt"+w,null,null,null,null,"none"),A.appendChild(this.createTaskInfo(V[st])),JSGantt.addTooltipListeners(this,V[st].getTaskDiv(),A))}for(S||G.appendChild(D.cloneNode(!0));a.hasChildNodes();)a.removeChild(a.firstChild);if(L=this.newNode(a,"div",null,"gchartcontainer"),L.appendChild(et),L.appendChild(y),L.appendChild(it),L.appendChild(C),this.newNode(L,"div",null,"ggridfooter"),A=this.newNode(this.getChartBody(),"div",i+"Lines","glinediv"),A.style.visibility="hidden",this.setLines(A),JSGantt.addScrollListeners(this),""!=j){var pt=new Date(e.getTime()),mt=0;"px"==j.substr(0,2)?mt=parseInt(j.substr(2)):(pt=JSGantt.parseDateStr(j,this.getDateInputFormat()),"hour"==o?pt.setMinutes(0,0,0):pt.setHours(0,0,0,0),mt=JSGantt.getOffset(e,pt,T,o)),this.getChartBody().scrollLeft=mt}Z=e.getTime()<=(new Date).getTime()&&t.getTime()>=(new Date).getTime()?JSGantt.getOffset(e,new Date,T,o):-1,this.DrawDependencies()}},this.mouseOver=function(t,e){this.getUseRowHlt()&&(t.className+=" gitemhighlight",e.className+=" gitemhighlight")},this.mouseOut=function(t,e){this.getUseRowHlt()&&(t.className=t.className.replace(/(?:^|\s)gitemhighlight(?!\S)/g,""),e.className=e.className.replace(/(?:^|\s)gitemhighlight(?!\S)/g,""))},this.drawSelector=function(t){for(var e=document.createDocumentFragment(),n=!1,a=0;a=0&&a",o+=""+V[a].getID()+"",o+=""+V[a].getName()+"",o+=""+JSGantt.formatDateStr(V[a].getStart(),i,vLangs[vLang])+"",o+=""+JSGantt.formatDateStr(V[a].getEnd(),i,vLangs[vLang])+"",o+=""+V[a].getClass()+"",o+=""+V[a].getLink()+"",o+=""+V[a].getMile()+""," "!=V[a].getResource()&&(o+=""+V[a].getResource()+""),o+=""+V[a].getCompVal()+"",o+=""+V[a].getGroup()+"",o+=""+V[a].getParent()+"",o+=""+V[a].getOpen()+"",o+="";var s=V[a].getDepend();for(n=0;n0&&(o+=","),s[n]>0&&(o+=s[n]+V[a].getDepType()[n]);o+="",o+=""+V[a].getCaption()+"";var r=document.createDocumentFragment(),l=this.newNode(r,"div",null,null,V[a].getNotes().innerHTML);o+=""+l.innerHTML+"",o+=""}return o},a&&"div"==a.nodeName.toLowerCase()&&(i=a.id)},JSGantt.updateFlyingObj=function(t,e,n){var a=3,o=5,i=3,s=15,r=t?t.clientX:window.event.clientX,l=t?t.clientY:window.event.clientY,g=document.documentElement.clientWidth||document.getElementsByTagName("body")[0].clientWidth,d=document.documentElement.clientHeight||document.getElementsByTagName("body")[0].clientHeight,u=r,h=l;if("microsoft internet explorer"==navigator.appName.toLowerCase()){r-=document.documentElement.clientLeft,l-=document.documentElement.clientTop;var c=JSGantt.getZoomFactor();1!=c&&(r=Math.round(r/c),l=Math.round(l/c))}var f=JSGantt.getScrollPositions();u=r-o-e.vTool.offsetWidth<0?r+s+e.vTool.offsetWidth>g?f.x:r+f.x+s:r+f.x-o-e.vTool.offsetWidth,h=l+i+e.vTool.offsetHeight>d?l-a-e.vTool.offsetHeight<0?f.y:l+f.y-a-e.vTool.offsetHeight:l+f.y+i,e.getUseMove()?(clearInterval(e.vTool.moveInterval),e.vTool.moveInterval=setInterval(function(){JSGantt.moveToolTip(u,h,e.vTool,n)},n)):(e.vTool.style.left=u+"px", - e.vTool.style.top=h+"px")},JSGantt.showToolTip=function(t,e,n,a,o){var i=t.getDivId()+"JSGanttToolTip",s=500,r=100,l=n.id;t.getUseToolTip()&&(null==t.vTool&&(t.vTool=document.createElement("div"),t.vTool.id=i,t.vTool.className="JSGanttToolTip",t.vTool.vToolCont=document.createElement("div"),t.vTool.vToolCont.id=i+"cont",t.vTool.vToolCont.className="JSGanttToolTipcont",t.vTool.vToolCont.setAttribute("showing",""),t.vTool.appendChild(t.vTool.vToolCont),document.body.appendChild(t.vTool),t.vTool.style.opacity=0,t.vTool.setAttribute("currentOpacity",0),t.vTool.setAttribute("fadeIncrement",10),t.vTool.setAttribute("moveSpeed",10),t.vTool.style.filter="alpha(opacity=0)",t.vTool.style.visibility="hidden",t.vTool.style.left=Math.floor((e?e.clientX:window.event.clientX)/2)+"px",t.vTool.style.top=Math.floor((e?e.clientY:window.event.clientY)/2)+"px",JSGantt.addListener("mouseover",function(){clearTimeout(t.vTool.delayTimeout)},t.vTool),JSGantt.addListener("mouseout",function(){JSGantt.delayedHide(t,t.vTool,o)},t.vTool)),clearTimeout(t.vTool.delayTimeout),(t.vTool.vToolCont.getAttribute("showing")!=l||"visible"!=t.vTool.style.visibility)&&(t.vTool.vToolCont.getAttribute("showing")!=l&&(t.vTool.vToolCont.setAttribute("showing",l),t.vTool.vToolCont.innerHTML=n.innerHTML,JSGantt.stripIds(t.vTool.vToolCont)),t.vTool.style.visibility="visible",JSGantt.updateFlyingObj(e,t,o),t.vTool.style.width=a?a+"px":"auto",!a&&JSGantt.isIE()&&(t.vTool.style.width=t.vTool.offsetWidth),t.vTool.offsetWidth>s&&(t.vTool.style.width=s+"px")),t.getUseFade()?(clearInterval(t.vTool.fadeInterval),t.vTool.fadeInterval=setInterval(function(){JSGantt.fadeToolTip(1,t.vTool,r)},o)):(t.vTool.style.opacity=.01*r,t.vTool.style.filter="alpha(opacity="+r+")"))},JSGantt.stripIds=function(t){for(var e=0;en-i&&1==t?s=n-i:a>o&&-1==t&&(s=i),o=i+s*t,e.style.opacity=.01*o,e.style.filter="alpha(opacity="+o+")",e.setAttribute("currentOpacity",o)}else clearInterval(e.fadeInterval),-1==t&&(e.style.opacity=0,e.style.filter="alpha(opacity=0)",e.style.visibility="hidden")},JSGantt.moveToolTip=function(t,e,n){var a=parseInt(n.getAttribute("moveSpeed")),o=parseInt(n.style.left),i=parseInt(n.style.top);"visible"!=n.style.visibility?(n.style.left=t+"px",n.style.top=e+"px",clearInterval(n.moveInterval)):t!=o&&e!=i?(o+=Math.ceil((t-o)/a),i+=Math.ceil((e-i)/a),n.style.left=o+"px",n.style.top=i+"px"):clearInterval(n.moveInterval)},JSGantt.getZoomFactor=function(){var t=1;if(document.body.getBoundingClientRect){var e=document.body.getBoundingClientRect(),n=e.right-e.left,a=document.body.offsetWidth;t=Math.round(n/a*100)/100}return t},JSGantt.getScrollPositions=function(){var t=window.pageXOffset,e=window.pageYOffset;if(!("pageXOffset"in window)){var n=JSGantt.getZoomFactor();t=Math.round(document.documentElement.scrollLeft/n),e=Math.round(document.documentElement.scrollTop/n)}return{x:t,y:e}},JSGantt.getOffset=function(t,e,n,a){var o=new Array(31,28,31,30,31,30,31,31,30,31,30,31),i=new Date(t.getTime()),s=new Date(e.getTime()),r=0,l=Date.UTC(i.getFullYear(),i.getMonth(),i.getDate(),i.getHours(),0,0),g=Date.UTC(s.getFullYear(),s.getMonth(),s.getDate(),s.getHours(),0,0),d=(g-l)/36e5;if("day"==a)r=Math.ceil(d/24*(n+1));else if("week"==a)r=Math.ceil(d/24*(n+1)/7);else if("month"==a){var u=12*(s.getFullYear()-i.getFullYear())+(s.getMonth()-i.getMonth()),h=new Date(s.getTime());h.setDate(i.getDate());var c=(s.getTime()-h.getTime())/864e5;r=Math.ceil(u*(n+1)+c*(n/o[s.getMonth()]))}else if("quarter"==a)u=12*(s.getFullYear()-i.getFullYear())+(s.getMonth()-i.getMonth()),h=new Date(s.getTime()),h.setDate(i.getDate()),c=(s.getTime()-h.getTime())/864e5,r=Math.ceil(u*((n+1)/3)+c*(n/90));else if("hour"==a){h=new Date(s.getTime()),h.setMinutes(i.getMinutes(),0);var f=(s.getTime()-h.getTime())/36e5;r=Math.ceil(d*(n+1)+f*n)}return r},JSGantt.processRows=function(t,e,n,a,o,i){var s=new Date,r=new Date,l=o,g=null,d=0,u=0,h=0,c=0,f=a,p=t,m=!1,v=0;for(v=0;v=0&&t[v].getID()==e&&(g=t[v]);for(v=0;vr)&&(r=t[v].getEnd(),h=1),d+=t[v].getCompVal(),t[v].setSortIdx(v*t.length)}if(n>=0&&(null!=t[n].getGroupMinStart()&&t[n].getGroupMinStart()r&&(r=t[n].getGroupMinEnd()),t[n].setStart(s),t[n].setEnd(r),t[n].setNumKid(c),t[n].setCompVal(Math.ceil(d/c))),0==e&&1==i&&(JSGantt.sortTasks(t,0,0),t.sort(function(t,e){return t.getSortIdx()-e.getSortIdx()})),0==e&&1!=i){for(v=0;v0&&o.sort(function(t,e){var n=t.getStart().getTime()-e.getStart().getTime();return 0==n&&(n=t.getEnd().getTime()-e.getEnd().getTime()),0==n?t.getID()-e.getID():n});for(var s=0;s1;)n.setDate(n.getDate()-1);else if("quarter"==e)n.setDate(n.getDate()-31),0==n.getMonth()||1==n.getMonth()||2==n.getMonth()?n.setFullYear(n.getFullYear(),0,1):3==n.getMonth()||4==n.getMonth()||5==n.getMonth()?n.setFullYear(n.getFullYear(),3,1):6==n.getMonth()||7==n.getMonth()||8==n.getMonth()?n.setFullYear(n.getFullYear(),6,1):(9==n.getMonth()||10==n.getMonth()||11==n.getMonth())&&n.setFullYear(n.getFullYear(),9,1);else if("hour"==e)for(n.setHours(n.getHours()-1);n.getHours()%6!=0;)n.setHours(n.getHours()-1);return"hour"==e?n.setMinutes(0,0):n.setHours(0,0,0),n},JSGantt.getMaxDate=function(t,e){var n=new Date;n.setTime(t[0].getEnd().getTime());for(var a=0;an.getTime()&&n.setTime(t[a].getEnd().getTime());if("day"==e)for(n.setDate(n.getDate()+1);n.getDay()%7!=0;)n.setDate(n.getDate()+1);else if("week"==e)for(n.setDate(n.getDate()+1);n.getDay()%7!=0;)n.setDate(n.getDate()+1);else if("month"==e){for(;n.getDate()>1;)n.setDate(n.getDate()+1);n.setDate(n.getDate()-1)}else if("quarter"==e)0==n.getMonth()||1==n.getMonth()||2==n.getMonth()?n.setFullYear(n.getFullYear(),2,31):3==n.getMonth()||4==n.getMonth()||5==n.getMonth()?n.setFullYear(n.getFullYear(),5,30):6==n.getMonth()||7==n.getMonth()||8==n.getMonth()?n.setFullYear(n.getFullYear(),8,30):(9==n.getMonth()||10==n.getMonth()||11==n.getMonth())&&n.setFullYear(n.getFullYear(),11,31);else if("hour"==e)for(0==n.getHours()&&n.setDate(n.getDate()+1),n.setHours(n.getHours()+1);n.getHours()%6!=5;)n.setHours(n.getHours()+1);return n},JSGantt.findObj=function(t,e){var n;return e||(e=document),document.getElementById&&(n=document.getElementById(t)),n},JSGantt.changeFormat=function(t,e){e?e.setFormat(t):alert("Chart undefined")},JSGantt.folder=function(t,e){var n=e.getList();e.getDivId();e.clearDependencies();for(var a=0;a=10&&a.length>=3){for(;a.length<5;)a.push(0);switch(e){case"mm/dd/yyyy":n=new Date(a[2],a[0]-1,a[1],a[3],a[4]);break;case"dd/mm/yyyy":n=new Date(a[2],a[1]-1,a[0],a[3],a[4]);break;case"yyyy-mm-dd":n=new Date(a[0],a[1]-1,a[2],a[3],a[4])}}return n},JSGantt.formatDateStr=function(t,e,n){for(var a="",o=t.getFullYear().toString().substring(2,4),i=t.getMonth()+1+"",s=new Array(n.january,n.february,n.march,n.april,n.maylong,n.june,n.july,n.august,n.september,n.october,n.november,n.december),r=new Array(n.sunday,n.monday,n.tuesday,n.wednesday,n.thursday,n.friday,n.saturday),l=new Array(n.jan,n.feb,n.mar,n.apr,n.may,n.jun,n.jul,n.aug,n.sep,n.oct,n.nov,n.dec),g=new Array(n.sun,n.mon,n.tue,n.wed,n.thu,n.fri,n.sat),d=0;di&&(a+="0");case"m":a+=i;break;case"mon":a+=l[t.getMonth()];break;case"month":a+=s[t.getMonth()];break;case"yyyy":a+=t.getFullYear();break;case"yy":a+=o;break;case"qq":a+="Q";case"q":a+=Math.floor(t.getMonth()/3)+1;break;case"hh":(t.getHours()%12==0?12:t.getHours()%12)<10&&(a+="0");case"h":a+=t.getHours()%12==0?12:t.getHours()%12;break;case"HH":t.getHours()<10&&(a+="0");case"H":a+=t.getHours();break;case"MI":t.getMinutes()<10&&(a+="0");case"mi":a+=t.getMinutes();break;case"pm":a+=t.getHours()<12?"am":"pm";break;case"PM":a+=t.getHours()<12?"AM":"PM";break;case"ww":JSGantt.getIsoWeek(t)<10&&(a+="0");case"w":a+=JSGantt.getIsoWeek(t);break;case"week":var u=JSGantt.getIsoWeek(t),h=t.getFullYear(),c=0==t.getDay()?7:t.getDay();u>=52&&1==i&&h--,1==u&&12==i&&h++,10>u&&(u="0"+u),a+=h+"-W"+u+"-"+c;break;default:a+=n[e[d].toLowerCase()]?n[e[d].toLowerCase()]:e[d]}return a},JSGantt.parseDateFormatStr=function(t){for(var e="",n="",a=new RegExp("[/\\ -.,'\":]"),o=new Array,i=0;i0&&(a=p[0].getAttribute("xmlns")),"http://schemas.microsoft.com/project"==a){o=!0,t.setDateInputFormat("yyyy-mm-dd"),n=JSGantt.findXMLNode(e,"Task"),i="undefined"==typeof n?0:n.length;var m=JSGantt.findXMLNode(e,"Resource");for("undefined"==typeof m?(i=0,s=0):s=m.length,r=0;s>r;r++){var v=JSGantt.getXMLNodeValue(m[r],"Name",2,""),S=JSGantt.getXMLNodeValue(m[r],"UID",1,-1);v.length>0&&S>0&&(c[S]=v)}var w=JSGantt.findXMLNode(e,"Assignment");for(l="undefined"==typeof w?0:w.length,r=0;l>r;r++){var D=JSGantt.getXMLNodeValue(w[r],"ResourceUID",1,-1);S=JSGantt.getXMLNodeValue(w[r],"TaskUID",1,-1),S>0&&(D>0&&(h[S]=c[D]),u[S]=w[r])}for(r=0;i>r;r++){if(S=JSGantt.getXMLNodeValue(n[r],"UID",1,0),0!=S)var T=JSGantt.getXMLNodeValue(n[r],"OutlineNumber",2,"0");S>0&&(f[T]=S),S>d&&(d=S)}for(r=0;i>r;r++){var y=JSGantt.getXMLNodeValue(n[r],"UID",1,0);if(0!=y){var L=JSGantt.getXMLNodeValue(n[r],"Name",2,"No Task Name"),N=JSGantt.getXMLNodeValue(n[r],"Start",2,""),G=JSGantt.getXMLNodeValue(n[r],"Finish",2,""),M=JSGantt.getXMLNodeValue(n[r],"HyperlinkAddress",2,""),J=JSGantt.getXMLNodeValue(n[r],"Milestone",1,0),k=JSGantt.getXMLNodeValue(n[r],"PercentWorkComplete",1,0),C=JSGantt.getXMLNodeValue(n[r],"Summary",1,0),I=0,F=JSGantt.getXMLNodeValue(n[r],"OutlineLevel",1,0);F>1&&(T=JSGantt.getXMLNodeValue(n[r],"OutlineNumber",2,"0"),I=f[T.substr(0,T.lastIndexOf("."))]);try{var b=n[r].getElementsByTagName("Notes")[0].childNodes[1].nodeValue}catch(H){b=""}if("undefined"!=typeof h[y])var x=h[y];else x="";var E=JSGantt.findXMLNode(n[r],"PredecessorLink");l="undefined"==typeof E?0:E.length;var X="";for(g=0;l>g;g++){var Y=JSGantt.getXMLNodeValue(E[g],"PredecessorUID",1,-1),O=JSGantt.getXMLNodeValue(E[g],"Type",1,1);if(Y>0)switch(X.length>0&&(X+=","),O){case 0:X+=Y+"FF";break;case 1:X+=Y+"FS";break;case 2:X+=Y+"SF";break;case 3:X+=Y+"SS";break;default:X+=Y+"FS"}}var R=1,A="";if(C>0)var V="ggroupblack";else V=J>0?"gmilestone":"gtaskblue";var P=JSGantt.findXMLNode(u[y],"TimephasedData");l="undefined"==typeof P?0:P.length;var B=N,U=G,j=!1,W=X.replace(/,*[0-9]+[FS]F/g,"");for(g=0;l>g;g++){var q=JSGantt.getXMLNodeValue(P[g],"Value",2,"0");q="0"+q.replace(/\D/g,""),q*=1,0==q&&!j||g+1==l&&2==C?(C=2,g+1==l&&(W=X.replace(/,*[0-9]+[FS]S/g,"")),d++,U=JSGantt.getXMLNodeValue(P[g],g+1==l?"Finish":"Start",2,""),t.AddTaskItem(new JSGantt.TaskItem(d,L,B,U,"gtaskblue",M,J,x,k,0,y,R,W,A,b,t)),j=!0,W=""):0!=q&&j&&(B=JSGantt.getXMLNodeValue(P[g],"Start",2,""),j=!1)}j&&(X=""),t.AddTaskItem(new JSGantt.TaskItem(y,L,N,G,V,M,J,x,k,C,I,R,X,A,b,t))}}}else for(n=e.getElementsByTagName("task"),i=n.length,r=0;i>r;r++)y=JSGantt.getXMLNodeValue(n[r],"pID",1,0),0!=y&&(L=JSGantt.getXMLNodeValue(n[r],"pName",2,"No Task Name"),N=JSGantt.getXMLNodeValue(n[r],"pStart",2,""),G=JSGantt.getXMLNodeValue(n[r],"pEnd",2,""),M=JSGantt.getXMLNodeValue(n[r],"pLink",2,""),J=JSGantt.getXMLNodeValue(n[r],"pMile",1,0),k=JSGantt.getXMLNodeValue(n[r],"pComp",1,0),C=JSGantt.getXMLNodeValue(n[r],"pGroup",1,0),I=JSGantt.getXMLNodeValue(n[r],"pParent",1,0),x=JSGantt.getXMLNodeValue(n[r],"pRes",2,""),R=JSGantt.getXMLNodeValue(n[r],"pOpen",1,1),X=JSGantt.getXMLNodeValue(n[r],"pDepend",2,""),A=JSGantt.getXMLNodeValue(n[r],"pCaption",2,""),b=JSGantt.getXMLNodeValue(n[r],"pNotes",2,""),V=JSGantt.getXMLNodeValue(n[r],"pClass",2),"undefined"==typeof V&&(V=C>0?"ggroupblack":J>0?"gmilestone":"gtaskblue"),t.AddTaskItem(new JSGantt.TaskItem(y,L,N,G,V,M,J,x,k,C,I,R,X,A,b,t)))},JSGantt.benchMark=function(t){var e=(new Date).getTime();alert(t+": Elapsed time: "+(e-vBenchTime)/1e3+" seconds."),vBenchTime=(new Date).getTime()},JSGantt.getIsoWeek=function(t){var e=864e5,n=new Date(t.getFullYear(),0,4,0,0,0),a=0==n.getDay()?6:n.getDay()-1,o=n.getTime()-a*e,i=new Date(t.getFullYear(),t.getMonth(),t.getDate(),0,0,0),s=i.getTime(),r=Math.round((s-o)/e),l=99;new Date(o);return l=Math.ceil((r+1)/7),0>=l?l=JSGantt.getIsoWeek(new Date(t.getFullYear()-1,11,31,0,0,0)):53==l&&4!=new Date(t.getFullYear(),0,1,0,0,0).getDay()&&4!=new Date(t.getFullYear(),11,31,0,0,0).getDay()&&(l=1),l},JSGantt.addListener=function(t,e,n){return n===String(n)&&(n=JSGantt.findObj(n)),n.addEventListener?n.addEventListener(t,e,!1):n.attachEvent?n.attachEvent("on"+t,e):!1},JSGantt.addTooltipListeners=function(t,e,n){JSGantt.addListener("mouseover",function(e){JSGantt.showToolTip(t,e,n,null,t.getTimer())},e),JSGantt.addListener("mouseout",function(e){JSGantt.delayedHide(t,t.vTool,t.getTimer())},e)},JSGantt.addThisRowListeners=function(t,e,n){JSGantt.addListener("mouseover",function(){t.mouseOver(e,n)},e),JSGantt.addListener("mouseover",function(){t.mouseOver(e,n)},n),JSGantt.addListener("mouseout",function(){t.mouseOut(e,n)},e),JSGantt.addListener("mouseout",function(){t.mouseOut(e,n)},n)},JSGantt.addFolderListeners=function(t,e,n){JSGantt.addListener("click",function(){JSGantt.folder(n,t)},e)},JSGantt.addFormatListeners=function(t,e,n){JSGantt.addListener("click",function(){JSGantt.changeFormat(e,t)},n)},JSGantt.addScrollListeners=function(t){JSGantt.addListener("scroll",function(){t.getChartBody().scrollTop=t.getListBody().scrollTop},t.getListBody()),JSGantt.addListener("scroll",function(){t.getListBody().scrollTop=t.getChartBody().scrollTop},t.getChartBody()),JSGantt.addListener("scroll",function(){t.getChartHead().scrollLeft=t.getChartBody().scrollLeft},t.getChartBody()),JSGantt.addListener("scroll",function(){t.getChartBody().scrollLeft=t.getChartHead().scrollLeft},t.getChartHead()),JSGantt.addListener("resize",function(){t.getChartHead().scrollLeft=t.getChartBody().scrollLeft},window),JSGantt.addListener("resize",function(){t.getListBody().scrollTop=t.getChartBody().scrollTop},window)}; \ No newline at end of file diff --git a/htdocs/includes/jsgantt/jsgantt_Minutes.html b/htdocs/includes/jsgantt/jsgantt_Minutes.html deleted file mode 100644 index f49f8a2f5c5..00000000000 --- a/htdocs/includes/jsgantt/jsgantt_Minutes.html +++ /dev/null @@ -1,548 +0,0 @@ - - - - - - -FREE javascript gantt - JSGantt HTML and CSS only - - - - - - - - - - - - - - - - - - - - - - - - - -
      jsGantt - 1.2
      Bugs/Issues    Download    License    Usage    Examples    Documenation    Subscribe    Credits
    -

    -
    -
    - - -  100% Free Javascript / CSS/ HTML Gantt chart control. Completely buzzword compliant including AJAX !

    - - -
    - -
    - -Basic Features
    -
      -
    • Tasks & Collapsible Task Groups
    • -
    • Multiple Dependencies
    • -
    • Task Completion
    • -
    • Task Color
    • -
    • Milestones
    • -
    • Resources
    • -
    • No images needed
    • -
    - -Advanced Features
    -
      -
    • Dynamic Loading of Tasks
    • -
    • Dynamic change of format -
        -
      • Day
      • -
      • Week
      • -
      • Month
      • -
      • Quarter
      • -
      • Hour
      • -
      • Minute
      • -
      -
    • -
    • Load Gantt from XML file
    • -
    -
    -
    - -
    -Current Issues: -
      -
    1. Currently only one gantt chart is allowed per page.
    2. - -

    -New in 1.2: -
      -
    • Support for half-days
    • -
    • Hour/Minute format
    • -
    -
    -
    -Click here to download the jsgantt
    -You can download the latest bleeding edge version, request features and report issues at http://code.google.com/p/jsgantt/ -

    - -JSGantt is released under BSD license. If you require another license please contact shlomygantz@hotmail.com
    -If you plan to use it in a commercial product please consider donating the first sale to charity. -

    -

    - -

    1. Include JSGantt CSS and Javascript

    -
    -<link rel="stylesheet" type="text/css" href="jsgantt.css" />
    -<script language="javascript" src="jsgantt.js"></script>
    -
    - -

    2. Create a div element to hold the gantt chart

    -
    <div style="position:relative" class="gantt" id="GanttChartDIV"></div>
    -

    3. Start a <script> block

    -
    <script language="javascript">
    -

    4. Instantiate JSGantt using GanttChart()

    -
    var g = new JSGantt.GanttChart('g',document.getElementById('GanttChartDIV'), 'day');
    -
    -    
    - -

    GanttChart(pGanttVar, pDiv, pFormat)
    - pGanttVar: (required) name of the variable assigned
    - pDiv: (required) this is a DIV object created in HTML
    - pFormat: (required) - used to indicate whether chart should be drawn in "day", "week", "month", or "quarter" format

    -

    Customize the look and feel using the following setters

    -

    g.setShowRes(1); // Show/Hide Responsible (0/1)
    -g.setShowDur(1); // Show/Hide Duration (0/1)
    -g.setShowComp(1); // Show/Hide % Complete(0/1)
    -g.setCaptionType('Resource');  // Set to Show Caption (None,Caption,Resource,Duration,Complete)
    -g.setShowStartDate(1); // Show/Hide Start Date(0/1)
    -g.setShowEndDate(1); // Show/Hide End Date(0/1)
    -g.setDateInputFormat('mm/dd/yyyy')  // Set format of input dates ('mm/dd/yyyy', 'dd/mm/yyyy', 'yyyy-mm-dd')
    -g.setDateDisplayFormat('mm/dd/yyyy') // Set format to display dates ('mm/dd/yyyy', 'dd/mm/yyyy', 'yyyy-mm-dd')
    -g.setFormatArr("day","week","month","quarter") // Set format options (up to 4 : "minute","hour","day","week","month","quarter")
    -
    - -

    -

    5. Add Tasks using AddTaskItem()

    -
     
    -g.AddTaskItem(new JSGantt.TaskItem(1,   'Define Chart API',     '',          '',          'ff0000', 'http://help.com', 0, 'Brian',     0, 1, 0, 1));
    -g.AddTaskItem(new JSGantt.TaskItem(11,  'Chart Object',         '2/10/2008', '2/10/2008', 'ff00ff', 'http://www.yahoo.com', 1, 'Shlomy',  100, 0, 1, 1, "121,122", "My Caption"));
    -
    - -TaskItem(pID, pName, pStart, pEnd, pColor, pLink, pMile, pRes, pComp, pGroup, pParent, pOpen, pDepend)
    -pID: (required) is a unique ID used to identify each row for parent functions and for setting dom id for hiding/showing
    -pName: (required) is the task Label
    -pStart: (required) the task start date, can enter empty date ('') for groups. You can also enter specific time (2/10/2008 12:00) for additional percision or half days.
    -pEnd: (required) the task end date, can enter empty date ('') for groups
    -pColor: (required) the html color for this task; e.g. '00ff00'
    -pLink: (optional) any http link navigated to when task bar is clicked.
    -pMile:(optional) represent a milestone
    -pRes: (optional) resource name
    -pComp: (required) completion percent
    -pGroup: (optional) indicates whether this is a group(parent) - 0=NOT Parent; 1=IS Parent
    -pParent: (required) identifies a parent pID, this causes this task to be a child of identified task
    -pOpen: can be initially set to close folder when chart is first drawn
    -pDepend: optional list of id's this task is dependent on ... line drawn from dependent to this item
    -pCaption: optional caption that will be added after task bar if CaptionType set to "Caption"
    - -*You should be able to add items to the chart in realtime via javascript and issuing "g.Draw()" command. - -

    5a. Another way to add tasks is to use an external XML file with parseXML()

    -
     
    -JSGantt.parseXML("project.xml",g);
    -
    -The structure of the XML file:
    - - -

    6. Call Draw() and DrawDependencies()

    -
     
    -
    -g.Draw();	
    -g.DrawDependencies();
    -
    -
    - -
    -

    7. Close the <script> block

    -
    </script>
    - -

    -Final code should look like - -

    -
    - -

    -

    -

    - - - -

    -Enter your email address to receive JSGantt announcements
    -

    - - -

    -

    - -
    - -

    Developed by Shlomy Gantz and Brian Twidt
    -Contributed: Paul Labuschagne, Kevin Badgett, Ilan Admon
    -

    - - - - \ No newline at end of file diff --git a/htdocs/includes/jsgantt/jsgantt_exExternalXML.html b/htdocs/includes/jsgantt/jsgantt_exExternalXML.html deleted file mode 100644 index da571e056c8..00000000000 --- a/htdocs/includes/jsgantt/jsgantt_exExternalXML.html +++ /dev/null @@ -1,533 +0,0 @@ - - - - - - -FREE javascript gantt - JSGantt HTML and CSS only - - - - - - - - - - - - - - - - - - - - - - - - - -
      jsGantt - 1.2
      Bugs/Issues    Download    License    Usage    Examples    Documenation    Subscribe    Credits
    -

    -
    -
    - - -  100% Free Javascript / CSS/ HTML Gantt chart control. Completely buzzword compliant including AJAX !

    - - -
    - -
    - -Basic Features
    -
      -
    • Tasks & Collapsible Task Groups
    • -
    • Multiple Dependencies
    • -
    • Task Completion
    • -
    • Task Color
    • -
    • Milestones
    • -
    • Resources
    • -
    • No images needed
    • -
    - -Advanced Features
    -
      -
    • Dynamic Loading of Tasks
    • -
    • Dynamic change of format -
        -
      • Day
      • -
      • Week
      • -
      • Month
      • -
      • Quarter
      • -
      • Hour
      • -
      • Minute
      • -
      -
    • -
    • Load Gantt from XML file
    • -
    -
    -
    -
    -
    -Current Issues: -
      -
    1. Currently only one gantt chart is allowed per page.
    2. - -

    -New in 1.2: -
      -
    • Support for half-days
    • -
    • Hour/Minute format
    • -
    -
    -
    -Click here to download the jsgantt
    -You can download the latest bleeding edge version, request features and report issues at http://code.google.com/p/jsgantt/ -

    - -JSGantt is released under BSD license. If you require another license please contact shlomygantz@hotmail.com
    -If you plan to use it in a commercial product please consider donating the first sale to charity. -

    -

    - -

    1. Include JSGantt CSS and Javascript

    -
    -<link rel="stylesheet" type="text/css" href="jsgantt.css" />
    -<script language="javascript" src="jsgantt.js"></script>
    -
    - -

    2. Create a div element to hold the gantt chart

    -
    <div style="position:relative" class="gantt" id="GanttChartDIV"></div>
    -

    3. Start a <script> block

    -
    <script language="javascript">
    -

    4. Instantiate JSGantt using GanttChart()

    -
    var g = new JSGantt.GanttChart('g',document.getElementById('GanttChartDIV'), 'day');
    -
    -    
    - -

    GanttChart(pGanttVar, pDiv, pFormat)
    - pGanttVar: (required) name of the variable assigned
    - pDiv: (required) this is a DIV object created in HTML
    - pFormat: (required) - used to indicate whether chart should be drawn in "day", "week", "month", or "quarter" format

    -

    Customize the look and feel using the following setters

    -

    g.setShowRes(1); // Show/Hide Responsible (0/1)
    -g.setShowDur(1); // Show/Hide Duration (0/1)
    -g.setShowComp(1); // Show/Hide % Complete(0/1)
    -g.setCaptionType('Resource');  // Set to Show Caption (None,Caption,Resource,Duration,Complete)
    -g.setShowStartDate(1); // Show/Hide Start Date(0/1)
    -g.setShowEndDate(1); // Show/Hide End Date(0/1)
    -g.setDateInputFormat('mm/dd/yyyy')  // Set format of input dates ('mm/dd/yyyy', 'dd/mm/yyyy', 'yyyy-mm-dd')
    -g.setDateDisplayFormat('mm/dd/yyyy') // Set format to display dates ('mm/dd/yyyy', 'dd/mm/yyyy', 'yyyy-mm-dd')
    -g.setFormatArr("day","week","month","quarter") // Set format options (up to 4 : "minute","hour","day","week","month","quarter")
    -
    - -

    -

    5. Add Tasks using AddTaskItem()

    -
     
    -g.AddTaskItem(new JSGantt.TaskItem(1,   'Define Chart API',     '',          '',          'ff0000', 'http://help.com', 0, 'Brian',     0, 1, 0, 1));
    -g.AddTaskItem(new JSGantt.TaskItem(11,  'Chart Object',         '2/10/2008', '2/10/2008', 'ff00ff', 'http://www.yahoo.com', 1, 'Shlomy',  100, 0, 1, 1, "121,122", "My Caption"));
    -
    - -TaskItem(pID, pName, pStart, pEnd, pColor, pLink, pMile, pRes, pComp, pGroup, pParent, pOpen, pDepend)
    -pID: (required) is a unique ID used to identify each row for parent functions and for setting dom id for hiding/showing
    -pName: (required) is the task Label
    -pStart: (required) the task start date, can enter empty date ('') for groups. You can also enter specific time (2/10/2008 12:00) for additional percision or half days.
    -pEnd: (required) the task end date, can enter empty date ('') for groups
    -pColor: (required) the html color for this task; e.g. '00ff00'
    -pLink: (optional) any http link navigated to when task bar is clicked.
    -pMile:(optional) represent a milestone
    -pRes: (optional) resource name
    -pComp: (required) completion percent
    -pGroup: (optional) indicates whether this is a group(parent) - 0=NOT Parent; 1=IS Parent
    -pParent: (required) identifies a parent pID, this causes this task to be a child of identified task
    -pOpen: can be initially set to close folder when chart is first drawn
    -pDepend: optional list of id's this task is dependent on ... line drawn from dependent to this item
    -pCaption: optional caption that will be added after task bar if CaptionType set to "Caption"
    - -*You should be able to add items to the chart in realtime via javascript and issuing "g.Draw()" command. - -

    5a. Another way to add tasks is to use an external XML file with parseXML()

    -
     
    -JSGantt.parseXML("project.xml",g);
    -
    -The structure of the XML file:
    - - -

    6. Call Draw() and DrawDependencies()

    -
     
    -
    -g.Draw();	
    -g.DrawDependencies();
    -
    -
    - -
    -

    7. Close the <script> block

    -
    </script>
    - -

    -Final code should look like - -

    -
    - -

    -

    -

    - - - -

    -Enter your email address to receive JSGantt announcements
    -

    - - -

    -

    - -
    - -

    Developed by Shlomy Gantz and Brian Twidt
    -Contributed: Paul Labuschagne, Kevin Badgett, Ilan Admon
    -

    - - - - \ No newline at end of file diff --git a/htdocs/includes/jsgantt/main.css b/htdocs/includes/jsgantt/main.css new file mode 100644 index 00000000000..544192b1b2d --- /dev/null +++ b/htdocs/includes/jsgantt/main.css @@ -0,0 +1,126 @@ +body { + position: relative; +} + +.product-name { + font-family: Satisfy; +} + +#my-navbar-nav { + font-size: 16px; +} + +#my-nav-brand { + font-size: 24px; + margin: 2px 40px 0 10px; + color: #ffffff; +} + +#home { + background: #323232 url(home-bg.jpg) center 0 no-repeat; + background-attachment: fixed; + background-size: cover; + min-height: 660px; + color: #ffffff; +} +#home-title { + font-size: 70px; + margin-top: 180px; +} +#home-subtitle { + font-size: 36px; + margin-top: 40px; + margin-bottom: 50px; +} +#learn-more { + padding: 0; + width: 50px; + height: 50px; + border-radius: 50%; + font-size: 38px; + margin-top: 60px; +} +@media screen and (max-width: 991px) { + #learn-more { + display: none; + } +} + +.section { + margin: 0 15vw; + padding: 5px 0 0; +} + +h1 { + font-family: Kelly Slab; + font-size: 56px; + margin: 50px 0 20px; +} + +h2 { + font-family: Kelly Slab; + margin: 20px 0 10px; +} + +h3 { + font-family: Kelly Slab; +} +#embedded-Gantt, #external-Gantt { +} + +.code-block { + background-color: #222222; +} + +.contact-card { + max-width: 200px; + margin: auto; +} + +.contact-link { + font-size: 28px; +} + +.footer { + margin-top: 10px; + padding-top: 10px; + border-top: solid #bbbbbb 1px; +} + +#slide-card { + background: transparent; + border: none; + margin: 180px 50px 50px; +} +#slide-dots { + background: transparent; + border: none; +} +.dot { + cursor:pointer; + height: 13px; + width: 13px; + margin: 0 2px; + background-color: #ffffff; + opacity: 0.3; + border-radius: 50%; + display: inline-block; + -webkit-transition: all .5s; /* Safari */ + transition: all .5s; +} +.dot:hover { + opacity: 1; +} +.dot.active { + opacity: 1; +} +.slide { + width: 100%; + height: 150px; + font-size: 20px; + display: none; + opacity: 0; +} +.slide-icon { + font-size: 60px; +} diff --git a/htdocs/includes/jsgantt/main.js b/htdocs/includes/jsgantt/main.js new file mode 100644 index 00000000000..53f5f8f0c10 --- /dev/null +++ b/htdocs/includes/jsgantt/main.js @@ -0,0 +1,85 @@ +$(document).ready(function() { + + // Scrollspy changes navbar active links + $("body").scrollspy({target:"#my-navbar-nav", offset:50}); + + // Smooth scroll + $("a").click(function(event) { + if (this.hash !== "") { + event.preventDefault(); + var linkOffset = 0; + if ($.inArray(this.hash,["#options","#xmlExport","#optionsLanguage","#setDayMajorDateDisplayFormat"]) != -1) { + linkOffset = -25; + } + $("html, body").animate({ + scrollTop: $(this.hash).offset().top - $(".navbar").height() + linkOffset + }, 600); + } + }); + + // Demo buttons + $("#embedded-Gantt").hide(0); + $("#external-Gantt").hide(0); + + $(".btn-demo").click(function() { + if ($(this).html().indexOf("Embedded Code") != -1) { + if ($("#external-Gantt").is(":visible")) { + $("#external-Gantt").animate({ + height: "toggle", + opacity: "toggle"}, 300, function () { + $("#embedded-Gantt").animate({ + height: "toggle", + opacity: "toggle"}, 600 + ); + } + ); + $(".btn-demo:nth-child(2)").removeClass("active"); + } else { + $("#embedded-Gantt").animate({ + height: "toggle", + opacity: "toggle"}, 600 + ); + } + } else { + if ($("#embedded-Gantt").is(":visible")) { + $("#embedded-Gantt").animate({ + height: "toggle", + opacity: "toggle"}, 300, function() { + $("#external-Gantt").animate({ + height: "toggle", + opacity: "toggle"}, 600 + ); + } + ); + $(".btn-demo:nth-child(1)").removeClass("active"); + } else { + $("#external-Gantt").animate({ + height: "toggle", + opacity: "toggle"}, 600 + ); + } + } + }); + + // Slideshow + var slideIndex = 0; + carousel(); + + function carousel() { + var i; + var x = document.getElementsByClassName("slide"); + var d = document.getElementsByClassName("dot"); + for (i = 0; i < x.length; i++) { + x[i].style.display = "none"; + } + slideIndex++; + if (slideIndex > x.length) {slideIndex = 1} + x[slideIndex-1].style.display = "inline-block"; + $(".slide:nth-child(" + (slideIndex).toString() + ")").animate({ + opacity: 1 + }, 500); + $(".dot").removeClass("active"); + $(".dot:nth-child(" + (slideIndex).toString() + ")").addClass("active"); + setTimeout(carousel, 2000); // Change image every 2 seconds + } + }); diff --git a/htdocs/includes/jsgantt/project.xml b/htdocs/includes/jsgantt/project.xml index d43110a6a38..80637aa7cae 100644 --- a/htdocs/includes/jsgantt/project.xml +++ b/htdocs/includes/jsgantt/project.xml @@ -1,65 +1,131 @@ - - - 10 - WCF Changes - - - 0000ff - - 0 - - 0 - 1 - 0 - 1 - - - - 20 - Move to WCF from remoting - 9/11/2008 - 9/15/2008 - 0000ff - - 0 - Rich - 10 - 0 - 10 - 1 - - Brian - - - 30 - add Auditing - 9/19/2008 - 9/21/2008 - 0000ff - - 0 - Shlomy - 50 - 0 - 10 - 1 - 20 - Shlomy - - - 40 - Yet another task - 9/23/2008 - 9/24/2008 - 0000ff - - 0 - Shlomy - 30 - 0 - 0 - 1 - 20,30 - Shlomy - - \ No newline at end of file + + + + 10 + WCF Changes + + + ggroupblack + + 0 + + 0 + 1 + 0 + 1 + + + + 20 + Move to WCF from remoting + 2017-05-11 09:00 + 2017-05-15 + gtaskblue + + 0 + Paul + 10 + 0 + 10 + 1 + + Paul + This text is only available in tool tips + + + 30 + add Auditing + 2017-05-18 10:30 + 2017-05-20 12:00 + gtaskblue + + 0 + Eduardo + 50 + 0 + 10 + 1 + 20 + Eduardo + + + 40 + Yet another task + 2017-05-24 + 2017-05-25 + gtaskblue + + 0 + Ricardo + 30 + 0 + 0 + 1 + 20,30 + Ricardo + + + 50 + Another Group + + + ggroupblack + + 0 + + 0 + 1 + 0 + 1 + + + + 60 + Move to GitHub + 2017-05-14 09:00 + 2017-05-16 + gtaskblue + + 0 + Ricardo + 10 + 0 + 50 + 1 + + Ricardo + This text is only available in tool tips + + + 70 + Updating files + 2017-05-18 10:30 + 2017-05-21 12:00 + gtaskred + + 0 + Paul + 50 + 0 + 50 + 1 + 60 + Paul + + + 80 + Yet another task + 2017-05-23 + 2017-05-25 + gtaskyellow + + 0 + Eduardo + 30 + 0 + 50 + 1 + 60,70 + Eduardo + + diff --git a/htdocs/includes/nusoap/lib/nusoap.php b/htdocs/includes/nusoap/lib/nusoap.php index 56d1cf4c1a8..6bd651e512c 100644 --- a/htdocs/includes/nusoap/lib/nusoap.php +++ b/htdocs/includes/nusoap/lib/nusoap.php @@ -6374,7 +6374,9 @@ class wsdl extends nusoap_base { $elements = $eElements; } - if (count($attrs) > 0) { + // @CHANGE LDR FIX for PHP7.2 + //if (count($attrs) > 0) { + if (is_array($attrs) && count($attrs) > 0) { foreach($attrs as $n => $a){ // expand each attribute foreach ($a as $k => $v) { diff --git a/htdocs/includes/odtphp/Segment.php b/htdocs/includes/odtphp/Segment.php index f9a44b996b2..8cea06db50b 100644 --- a/htdocs/includes/odtphp/Segment.php +++ b/htdocs/includes/odtphp/Segment.php @@ -173,19 +173,20 @@ class Segment implements IteratorAggregate, Countable */ public function macroReplace($text) { + include_once DOL_DOCUMENT_ROOT.'/core/lib/date.lib.php'; global $langs; $hoy = dol_getdate(dol_now('tzuser')); $dateinonemontharray = dol_get_next_month($hoy['mon'], $hoy['year']); $nextMonth = $dateinonemontharray['month']; - + $patterns=array( '/__CURRENTDAY__/u','/__CURENTWEEKDAY__/u', '/__CURRENTMONTH__/u','/__CURRENTMONTHLONG__/u', '/__NEXTMONTH__/u','/__NEXTMONTHLONG__/u', '/__CURRENTYEAR__/u','/__NEXTYEAR__/u' ); - $values=array( $hoy['mday'], $langs->transnoentitiesnoconv($hoy['weekday']), - $hoy['mon'], $langs->transnoentitiesnoconv($hoy['month']), - $nextMonth, monthArray($langs)[$nextMonth], + $values=array( $hoy['mday'], $langs->transnoentitiesnoconv($hoy['weekday']), + $hoy['mon'], $langs->transnoentitiesnoconv($hoy['month']), + $nextMonth, monthArray($langs)[$nextMonth], $hoy['year'], $hoy['year']+1 ); $text=preg_replace($patterns, $values, $text); diff --git a/htdocs/includes/parsedown/Parsedown.php b/htdocs/includes/parsedown/Parsedown.php index 20863a7537a..df718bce111 100644 --- a/htdocs/includes/parsedown/Parsedown.php +++ b/htdocs/includes/parsedown/Parsedown.php @@ -141,7 +141,11 @@ class Parsedown foreach ($parts as $part) { - $shortage = 4 - mb_strlen($line, 'utf-8') % 4; + // @CHANGE LDR Fix when mb_strlen is not available + //$shortage = 4 - mb_strlen($line, 'utf-8') % 4; + if (function_exists('mb_strlen')) $len = mb_strlen($line, 'utf-8'); + else $len = strlen($line); + $shortage = 4 - $len % 4; $line .= str_repeat(' ', $shortage); $line .= $part; @@ -515,10 +519,10 @@ class Parsedown ), ); - if($name === 'ol') + if($name === 'ol') { $listStart = stristr($matches[0], '.', true); - + if($listStart !== '1') { $Block['element']['attributes'] = array('start' => $listStart); @@ -1176,7 +1180,9 @@ class Parsedown 'name' => 'img', 'attributes' => array( 'src' => $Link['element']['attributes']['href'], - 'alt' => $Link['element']['text'], + 'alt' => $Link['element']['text'], + // @CHANGE LDR + 'class' => $Link['element']['attributes']['class'] ), ), ); @@ -1227,6 +1233,13 @@ class Parsedown } $extent += strlen($matches[0]); + + // @CHANGE LDR + if (preg_match('/{([^}]+)}/', $remainder, $matches2)) + { + $Element['attributes']['class'] = $matches2[1]; + $remainder = preg_replace('/{'.preg_quote($matches2[1],'/').'}/', '', $remainder); + } } else { @@ -1422,7 +1435,9 @@ class Parsedown if (isset($Element['handler'])) { - $markup .= $this->{$Element['handler']}($Element['text']); + // @CHANGE LDR + //$markup .= $this->{$Element['handler']}($Element['text']); + $markup .= preg_replace('/>{[^}]+}/', '>', $this->{$Element['handler']}($Element['text'])); } else { diff --git a/htdocs/includes/restler/framework/Luracast/Restler/AutoLoader.php b/htdocs/includes/restler/framework/Luracast/Restler/AutoLoader.php index 20a33ee3b70..300eadb0f70 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/AutoLoader.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/AutoLoader.php @@ -307,10 +307,10 @@ class AutoLoader */ private function alias($className, $currentClass) { - // @CHANGE LDR + // @CHANGE LDR if ($className == 'Luracast\Restler\string') return; if ($className == 'Luracast\Restler\mixed') return; - + if ($className != $currentClass && false !== strpos($className, $currentClass)) if (!class_exists($currentClass, false) diff --git a/htdocs/includes/restler/framework/Luracast/Restler/CommentParser.php b/htdocs/includes/restler/framework/Luracast/Restler/CommentParser.php index 8a3023cab20..e8248a385fa 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/CommentParser.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/CommentParser.php @@ -505,7 +505,7 @@ class CommentParser $data = explode('|', $data); $r['type'] = count($data) == 1 ? $data[0] : $data; } - if (isset($r['type']) && is_string($r['type']) && Text::endsWith($r['type'], '[]')) { + if (isset($r['type']) && Text::endsWith($r['type'], '[]')) { $r[static::$embeddedDataName]['type'] = substr($r['type'], 0, -2); $r['type'] = 'array'; } diff --git a/htdocs/includes/restler/framework/Luracast/Restler/Data/Object.php b/htdocs/includes/restler/framework/Luracast/Restler/Data/Obj.php similarity index 99% rename from htdocs/includes/restler/framework/Luracast/Restler/Data/Object.php rename to htdocs/includes/restler/framework/Luracast/Restler/Data/Obj.php index 5ef5850b86e..003f1df8794 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/Data/Object.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/Data/Obj.php @@ -13,7 +13,7 @@ namespace Luracast\Restler\Data; * @link http://luracast.com/products/restler/ * @version 3.0.0rc6 */ -class Object +class Obj { /** * @var bool|string|callable diff --git a/htdocs/includes/restler/framework/Luracast/Restler/Data/Validator.php b/htdocs/includes/restler/framework/Luracast/Restler/Data/Validator.php index be2ef28f40a..28202efb7ad 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/Data/Validator.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/Data/Validator.php @@ -454,7 +454,10 @@ class Validator implements iValidate } if (isset ($info->choice)) { - if (is_array($input)) { + if (!$info->required && empty($input)) { + //since its optional, and empty let it pass. + $input = null; + } elseif (is_array($input)) { foreach ($input as $i) { if (!in_array($i, $info->choice)) { $error .= ". Expected one of (" . implode(',', $info->choice) . ")."; @@ -468,6 +471,11 @@ class Validator implements iValidate } if (method_exists($class = get_called_class(), $info->type) && $info->type != 'validate') { + if(!$info->required && empty($input)) + { + //optional parameter with a empty value assume null + return null; + } try { return call_user_func("$class::$info->type", $input, $info); } catch (Invalid $e) { @@ -669,4 +677,4 @@ class Validator implements iValidate throw $e; } } -} \ No newline at end of file +} diff --git a/htdocs/includes/restler/framework/Luracast/Restler/EventDispatcher.php b/htdocs/includes/restler/framework/Luracast/Restler/EventDispatcher.php index 1c173d38baa..f8cd883af46 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/EventDispatcher.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/EventDispatcher.php @@ -44,7 +44,7 @@ class EventDispatcher public function __call($eventName, $params) { if (0 === strpos($eventName, 'on')) { - if (!@is_array($this->listeners[$eventName])) + if (!isset($this->listeners[$eventName]) || !is_array($this->listeners[$eventName])) $this->listeners[$eventName] = array(); $this->listeners[$eventName][] = $params[0]; } diff --git a/htdocs/includes/restler/framework/Luracast/Restler/Explorer.php b/htdocs/includes/restler/framework/Luracast/Restler/Explorer.php index 9522441c5b0..686c4c2fc23 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/Explorer.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/Explorer.php @@ -16,7 +16,12 @@ use Luracast\Restler\Scope; */ class Explorer implements iProvideMultiVersionApi { - const SWAGGER_VERSION = '1.2'; + const SWAGGER = '2.0'; + + /** + * @var array http schemes supported. http or https or both http and https + */ + public static $schemes = array(); /** * @var bool should protected resources be shown to unauthenticated users? */ @@ -70,17 +75,17 @@ class Explorer implements iProvideMultiVersionApi */ public static $dataTypeAlias = array( //'string' => 'string', - 'int' => 'integer', - 'number' => 'number', - 'float' => array('number', 'float'), - 'bool' => 'boolean', + 'int' => 'integer', + 'number' => 'number', + 'float' => array('number', 'float'), + 'bool' => 'boolean', //'boolean' => 'boolean', //'NULL' => 'null', - 'array' => 'array', + 'array' => 'array', //'object' => 'object', 'stdClass' => 'object', - 'mixed' => 'string', - 'date' => array('string', 'date'), + 'mixed' => 'string', + 'date' => array('string', 'date'), 'datetime' => array('string', 'date-time'), ); @@ -89,9 +94,9 @@ class Explorer implements iProvideMultiVersionApi * protected api */ public static $apiDescriptionSuffixSymbols = array( - 0 => '  ', //public api - 1 => '  ', //hybrid api - 2 => '  ', //protected api + 0 => ' 🔓', //'  ', //public api + 1 => ' ◑', //'  ', //hybrid api + 2 => ' 🔐', //'  ', //protected api ); protected $models = array(); @@ -100,27 +105,23 @@ class Explorer implements iProvideMultiVersionApi */ protected $_fullDataRequested = false; protected $crud = array( - 'POST' => 'create', - 'GET' => 'retrieve', - 'PUT' => 'update', + 'POST' => 'create', + 'GET' => 'retrieve', + 'PUT' => 'update', 'DELETE' => 'delete', - 'PATCH' => 'partial update' + 'PATCH' => 'partial update' ); protected static $prefixes = array( - 'get' => 'retrieve', - 'index' => 'list', - 'post' => 'create', - 'put' => 'update', - 'patch' => 'modify', + 'get' => 'retrieve', + 'index' => 'list', + 'post' => 'create', + 'put' => 'update', + 'patch' => 'modify', 'delete' => 'remove', ); protected $_authenticated = false; protected $cacheName = ''; - public function __construct() - { - - } /** * Serve static files for exploring @@ -131,7 +132,7 @@ class Explorer implements iProvideMultiVersionApi */ public function get() { - if (func_num_args() > 1 && func_get_arg(0) == 'resources') { + if (func_num_args() > 1 && func_get_arg(0) == 'swagger') { /** * BUGFIX: * If we use common resourcePath (e.g. $r->addAPIClass([api-class], 'api/shop')), than we must determine resource-ID of e.g. 'api/shop'! @@ -141,6 +142,7 @@ class Explorer implements iProvideMultiVersionApi array_shift($arguments); // create ID $id = implode('/', $arguments); + return $this->getResources($id); } $filename = implode('/', func_get_args()); @@ -161,125 +163,75 @@ class Explorer implements iProvideMultiVersionApi ) { $filename .= '.js'; } - PassThrough::file(__DIR__ . '/explorer/' . (empty($filename) ? 'index.html' : $filename), false, 0); //60 * 60 * 24); + PassThrough::file(__DIR__ . '/explorer/' . (empty($filename) ? 'index.html' : $filename), false, + 0); //60 * 60 * 24); } - public function resources() + /** + * @return stdClass + */ + public function swagger() { $r = new stdClass(); - $r->apiVersion = (string)$this->restler->getRequestedApiVersion(); - $r->swaggerVersion = static::SWAGGER_VERSION; - $r->apis = $this->apis($r->apiVersion); - $r->authorizations = $this->authorizations(); - $r->info = array_filter(get_class_vars(static::$infoClass)); - return $r; - } + $version = (string)$this->restler->getRequestedApiVersion(); + $r->swagger = static::SWAGGER; - public function getResources($id) - { - $r = new stdClass(); - $r->apiVersion = (string)$this->restler->getRequestedApiVersion(); - $r->swaggerVersion = static::SWAGGER_VERSION; - $r->basePath = $this->restler->getBaseUrl(); - $r->resourcePath = "/$id"; - - $r->apis = $this->apis($r->apiVersion, $id); - $r->models = (object)$this->models; + $info = parse_url($this->restler->getBaseUrl()); + $r->host = $info['host']; + if (isset($info['port'])) { + $r->host .= ':' . $info['port']; + } + $r->basePath = isset($info['path']) ? $info['path'] : ''; + if (!empty(static::$schemes)) { + $r->schemes = static::$schemes; + } $r->produces = $this->restler->getWritableMimeTypes(); $r->consumes = $this->restler->getReadableMimeTypes(); - $r->authorizations = $this->authorizations(); + + $r->paths = $this->paths($version); + $r->definitions = (object)$this->models; + $r->securityDefinitions = $this->securityDefinitions(); + $r->info = compact('version') + array_filter(get_class_vars(static::$infoClass)); + return $r; } - private function apis($version = 1, $resource = false) + private function paths($version = 1) { $map = Routes::findAll(static::$excludedPaths + array($this->base()), static::$excludedHttpMethods, $version); - $r = array(); - $a = array(); + $paths = array(); foreach ($map as $path => $data) { - $route = $data[0]['route']; $access = $data[0]['access']; - if ($access && !Text::contains($path, '{')) { - $r[] = array( - 'path' => empty($path) ? '/root' : "/$path", - //'description' => '' - //TODO: Util::nestedValue($route, 'metadata', 'classDescription') ? : '' - ); - } - if (static::$hideProtected && !$access) + if (static::$hideProtected && !$access) { continue; - $grouper = array(); + } foreach ($data as $item) { $route = $item['route']; $access = $item['access']; - if (static::$hideProtected && !$access) + if (static::$hideProtected && !$access) { continue; + } $url = $route['url']; - if (isset($grouper[$url])) { - $grouper[$url]['operations'][] = $this->operation($route); - } else { - $api = array( - 'path' => "/$url", - 'description' => - Util::nestedValue($route, 'metadata', 'classDescription') ? : '', - 'operations' => array($this->operation($route)) - ); - static::$groupOperations - ? $grouper[$url] = $api - : $a[$path][] = $api; - } + $paths["/$url"][strtolower($route['httpMethod'])] = $this->operation($route); } - if (!empty($grouper)) { - $a[$path] = array_values($grouper); - // sort REST-endpoints by path - foreach ($a as & $b) { - usort( - $b, - function ($x, $y) { - return $x['path'] > $y['path']; - } - ); - } - } else { - $order = array( - 'GET' => 1, - 'POST' => 2, - 'PUT' => 3, - 'PATCH' => 4, - 'DELETE' => 5 - ); - foreach ($a as & $b) { - usort( - $b, - function ($x, $y) use ($order) { - return - $x['operations'][0]->method == - $y['operations'][0]->method - ? $x['path'] > $y['path'] - : $order[$x['operations'][0]->method] > - $order[$y['operations'][0]->method]; + } - } - ); - } - } - } - if (false !== $resource) { - if ($resource == 'root') $resource = ''; - if (isset($a[$resource])) return $a[$resource]; - } - return $r; + return $paths; } private function operation($route) { $r = new stdClass(); - $r->method = $route['httpMethod']; - $r->nickname = $this->nickname($route); + $m = $route['metadata']; + $r->operationId = $this->operationId($route); + $base = strtok($route['url'], '/'); + if (empty($base)) { + $base = 'root'; + } + $r->tags = array($base); $r->parameters = $this->parameters($route); - $m = $route['metadata']; $r->summary = isset($m['description']) ? $m['description'] @@ -287,13 +239,18 @@ class Explorer implements iProvideMultiVersionApi $r->summary .= $route['accessLevel'] > 2 ? static::$apiDescriptionSuffixSymbols[2] : static::$apiDescriptionSuffixSymbols[$route['accessLevel']]; - $r->notes = isset($m['longDescription']) + $r->description = isset($m['longDescription']) ? $m['longDescription'] : ''; - $r->responseMessages = $this->responseMessages($route); + $r->responses = $this->responses($route); + //TODO: avoid hard coding. Properly detect security + if ($route['accessLevel']) { + $r->security = array(array('api_key' => array())); + } + /* $this->setType( $r, - new ValidationInfo(Util::nestedValue($m, 'return') ? : array()) + new ValidationInfo(Util::nestedValue($m, 'return') ?: array()) ); if (is_null($r->type) || 'mixed' == $r->type) { $r->type = 'array'; @@ -302,7 +259,7 @@ class Explorer implements iProvideMultiVersionApi } elseif (Text::contains($r->type, '|')) { $r->type = 'array'; } - + */ //TODO: add $r->authorizations //A list of authorizations required to execute this operation. While not mandatory, if used, it overrides //the value given at the API Declaration's authorizations. In order to completely remove API Declaration's @@ -324,8 +281,9 @@ class Explorer implements iProvideMultiVersionApi $info = new ValidationInfo($param); $description = isset($param['description']) ? $param['description'] : ''; if ('body' == $info->from) { - if ($info->required) + if ($info->required) { $required = true; + } $param['description'] = $description; $children[] = $param; } else { @@ -341,31 +299,31 @@ class Explorer implements iProvideMultiVersionApi if (empty($firstChild['children'])) { $description = $firstChild['description']; } else { - $description = '
    '; + $description = ''; //'
    '; foreach ($firstChild['children'] as $child) { $description .= isset($child['required']) && $child['required'] - ? '' . $child['name'] . ' (required)
    ' - : $child['name'] . '
    '; + ? '**' . $child['name'] . '** (required) '.PHP_EOL + : $child['name'] . ' '.PHP_EOL; } - $description .= '
    '; + //$description .= '
    '; } $r[] = $this->parameter(new ValidationInfo($firstChild), $description); } else { - $description = '
    '; + $description = ''; //'
    '; foreach ($children as $child) { - $description .= isset($child['required']) && $child['required'] - ? '' . $child['name'] . ' (required)
    ' - : $child['name'] . '
    '; + $description .= isset($child['required']) && $child['required'] + ? '**' . $child['name'] . '** (required) '.PHP_EOL + : $child['name'] . ' '.PHP_EOL; } - $description .= '
    '; + //$description .= '
    '; //lets group all body parameters under a generated model name - $name = $this->nameModel($route); + $name = $this->modelName($route); $r[] = $this->parameter( new ValidationInfo(array( - 'name' => $name, - 'type' => $name, - 'from' => 'body', + 'name' => $name, + 'type' => $name, + 'from' => 'body', 'required' => $required, 'children' => $children )), @@ -373,196 +331,224 @@ class Explorer implements iProvideMultiVersionApi ); } } + return $r; } private function parameter(ValidationInfo $info, $description = '') { $p = new stdClass(); - if(isset($info->rules['model'])){ - $info->type = $info->rules['model']; + if (isset($info->rules['model'])) { + //$info->type = $info->rules['model']; } $p->name = $info->name; $this->setType($p, $info); if (empty($info->children) || $info->type != 'array') { //primitives - if ($info->default) + if ($info->default) { $p->defaultValue = $info->default; - if ($info->choice) + } + if ($info->choice) { $p->enum = $info->choice; - if ($info->min) + } + if ($info->min) { $p->minimum = $info->min; - if ($info->max) + } + if ($info->max) { $p->maximum = $info->max; + } //TODO: $p->items and $p->uniqueItems boolean } $p->description = $description; - $p->paramType = $info->from; //$info->from == 'body' ? 'form' : $info->from; + $p->in = $info->from; //$info->from == 'body' ? 'form' : $info->from; $p->required = $info->required; - $p->allowMultiple = false; + + //$p->allowMultiple = false; + + if (isset($p->{'$ref'})) { + $p->schema = (object)array('$ref' => ($p->{'$ref'})); + unset($p->{'$ref'}); + } + return $p; } - private function responseMessages(array $route) + private function responses(array $route) { - $r = array(); + $code = '200'; + $r = array( + $code => (object)array( + 'description' => 'Success', + 'schema' => new stdClass() + ) + ); + $return = Util::nestedValue($route, 'metadata', 'return'); + if (!empty($return)) { + $this->setType($r[$code]->schema, new ValidationInfo($return)); + } + if (is_array($throws = Util::nestedValue($route, 'metadata', 'throws'))) { foreach ($throws as $message) { - $m = (object)$message; - //TODO: add $m->responseModel from composer class - $r[] = $m; + $r[$message['code']] = array('description' => $message['message']); } } + return $r; } private function model($type, array $children) { - /** - * Bugfix: - * If we use namespaces, than the model will not be correct, if we use a short name for the type! - * - * Example (phpDoc/annotations in API-class, which uses custom domain-model with namespace): - * @param Car $car {@from body} {@type Aoe\RestServices\Domain\Model\Car} - * @return Car {@type Aoe\RestServices\Domain\Model\Car} - * Than, the model (in swagger-spec) must also be 'Aoe\RestServices\Domain\Model\Car' and not 'Car' - * - * When we use namespaces, than we must use the @type-annotation, otherwise the automatic reconstitution - * from request-data (e.g. when it is a POST-request) to custom domain-model-object will not work! - * - * Summary: - * - When we use no namespaces, than the type would not be changed, if we would call 'Util::getShortName' - * - When we use namespaces, than the model will not be correct, if we would call 'Util::getShortName' - * ...so this method-call is either needless or will create a bug/error - */ - //$type = Util::getShortName($type); - if (isset($this->models[$type])) + if (isset($this->models[$type])) { return $this->models[$type]; + } $r = new stdClass(); - $r->id = $type; - $r->description = "$type Model"; //TODO: enhance this on Router - $r->required = array(); $r->properties = array(); + $required = array(); foreach ($children as $child) { $info = new ValidationInfo($child); $p = new stdClass(); $this->setType($p, $info); $p->description = isset($child['description']) ? $child['description'] : ''; - if ($info->default) + if ($info->default) { $p->defaultValue = $info->default; - if ($info->choice) + } + if ($info->choice) { $p->enum = $info->choice; - if ($info->min) + } + if ($info->min) { $p->minimum = $info->min; - if ($info->max) + } + if ($info->max) { $p->maximum = $info->max; - if ($info->required) - $r->required[] = $info->name; + } + if ($info->required) { + $required[] = $info->name; + } $r->properties[$info->name] = $p; } + if (!empty($required)) { + $r->required = $required; + } //TODO: add $r->subTypes https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#527-model-object //TODO: add $r->discriminator https://github.com/wordnik/swagger-spec/blob/master/versions/1.2.md#527-model-object $this->models[$type] = $r; + return $r; } private function setType(&$object, ValidationInfo $info) { //TODO: proper type management + $type = Util::getShortName($info->type); if ($info->type == 'array') { + $object->type = 'array'; if ($info->children) { - $this->model($info->contentType, $info->children); + $contentType = Util::getShortName($info->contentType); + $model = $this->model($contentType, $info->children); $object->items = (object)array( - '$ref' => $info->contentType + '$ref' => "#/definitions/$contentType" ); } elseif ($info->contentType && $info->contentType == 'associative') { unset($info->contentType); $this->model($info->type = 'Object', array( array( - 'name' => 'property', - 'type' => 'string', - 'default' => '', - 'required' => false, + 'name' => 'property', + 'type' => 'string', + 'default' => '', + 'required' => false, 'description' => '' ) )); } elseif ($info->contentType && $info->contentType != 'indexed') { - $object->items = (object)array( - 'type' => $info->contentType - ); + if (is_string($info->contentType) && $t = Util::nestedValue(static::$dataTypeAlias, + strtolower($info->contentType))) { + if (is_array($t)) { + $object->items = (object)array( + 'type' => $t[0], + 'format' => $t[1], + ); + } else { + $object->items = (object)array( + 'type' => $t, + ); + } + } else { + $contentType = Util::getShortName($info->contentType); + $object->items = (object)array( + '$ref' => "#/definitions/$contentType" + ); + } } else { $object->items = (object)array( 'type' => 'string' ); } } elseif ($info->children) { - $this->model($info->type, $info->children); + $this->model($type, $info->children); + $object->{'$ref'} = "#/definitions/$type"; } elseif (is_string($info->type) && $t = Util::nestedValue(static::$dataTypeAlias, strtolower($info->type))) { if (is_array($t)) { - list($info->type, $object->format) = $t; + $object->type = $t[0]; + $object->format = $t[1]; } else { - $info->type = $t; + $object->type = $t; } } else { - $info->type = 'string'; + $object->type = 'string'; } - $object->type = $info->type; $has64bit = PHP_INT_MAX > 2147483647; - if ($object->type == 'integer') { - $object->format = $has64bit - ? 'int64' - : 'int32'; - } elseif ($object->type == 'number') { - $object->format = $has64bit - ? 'double' - : 'float'; + if (isset($object->type)) { + if ($object->type == 'integer') { + $object->format = $has64bit + ? 'int64' + : 'int32'; + } elseif ($object->type == 'number') { + $object->format = $has64bit + ? 'double' + : 'float'; + } } } - private function nickname(array $route) + private function operationId(array $route) { static $hash = array(); + $id = $route['httpMethod'] . ' ' . $route['url']; + if (isset($hash[$id])) { + return $hash[$id]; + } + $class = Util::getShortName($route['className']); $method = $route['methodName']; + if (isset(static::$prefixes[$method])) { - $method = static::$prefixes[$method]; + $method = static::$prefixes[$method] . $class; } else { $method = str_replace( array_keys(static::$prefixes), array_values(static::$prefixes), $method ); + $method = lcfirst($class) . ucfirst($method); } - while (isset($hash[$method]) && $route['url'] != $hash[$method]) { - //create another one - $method .= '_'; - } - $hash[$method] = $route['url']; + $hash[$id] = $method; + return $method; } - private function nameModel(array $route) + private function modelName(array $route) { - static $hash = array(); - $count = 1; - //$name = str_replace('/', '-', $route['url']) . 'Model'; - $name = $route['className'] . 'Model'; - while (isset($hash[$name . $count])) { - //create another one - $count++; - } - $name .= $count; - $hash[$name] = $route['url']; - return $name; + return $this->operationId($route) . 'Model'; } - private function authorizations() + private function securityDefinitions() { $r = new stdClass(); - $r->apiKey = (object)array( + $r->api_key = (object)array( 'type' => 'apiKey', - 'passAs' => 'query', - 'keyname' => 'api_key', + 'name' => 'api_key', + 'in' => 'query', ); + return $r; } diff --git a/htdocs/includes/restler/framework/Luracast/Restler/ExplorerInfo.php b/htdocs/includes/restler/framework/Luracast/Restler/ExplorerInfo.php index 41d969f65d9..b55c5943fed 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/ExplorerInfo.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/ExplorerInfo.php @@ -2,16 +2,22 @@ /** * Class ExplorerInfo - * @package Luracast\Restler - * + * @package Luracast\Restler + * * @version 3.0.0rc6 */ class ExplorerInfo { public static $title = 'Restler API Explorer'; public static $description = 'Live API Documentation'; - public static $termsOfServiceUrl = null; - public static $contact = 'arul@luracast.com'; - public static $license = 'LGPL-2.1'; - public static $licenseUrl = 'https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html'; + public static $termsOfService = null; + public static $contact = array( + 'name' => 'Restler Support', + 'url' => 'luracast.com/products/restler', + 'email' => 'arul@luracast.com', + ); + public static $license = array( + 'name' => 'LGPL-2.1', + 'url' => 'https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html', + ); } \ No newline at end of file diff --git a/htdocs/includes/restler/framework/Luracast/Restler/Format/CsvFormat.php b/htdocs/includes/restler/framework/Luracast/Restler/Format/CsvFormat.php index d6cdb63a943..4bed88251c8 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/Format/CsvFormat.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/Format/CsvFormat.php @@ -2,7 +2,7 @@ namespace Luracast\Restler\Format; -use Luracast\Restler\Data\Object; +use Luracast\Restler\Data\Obj; use Luracast\Restler\RestException; /** @@ -44,10 +44,10 @@ class CsvFormat extends Format implements iDecodeStream */ public function encode($data, $humanReadable = false) { - $char = Object::$separatorChar; - Object::$separatorChar = false; - $data = Object::toArray($data); - Object::$separatorChar = $char; + $char = Obj::$separatorChar; + Obj::$separatorChar = false; + $data = Obj::toArray($data); + Obj::$separatorChar = $char; if (is_array($data) && array_values($data) == $data) { //if indexed array $lines = array(); @@ -109,10 +109,10 @@ class CsvFormat extends Format implements iDecodeStream while (($row = static::getRow(array_shift($lines), $keys)) !== FALSE) $decoded [] = $row; - $char = Object::$separatorChar; - Object::$separatorChar = false; - $decoded = Object::toArray($decoded); - Object::$separatorChar = $char; + $char = Obj::$separatorChar; + Obj::$separatorChar = false; + $decoded = Obj::toArray($decoded); + Obj::$separatorChar = $char; return $decoded; } @@ -172,10 +172,10 @@ class CsvFormat extends Format implements iDecodeStream while (($row = static::getRow(stream_get_line($stream, 0, PHP_EOL), $keys)) !== FALSE) $decoded [] = $row; - $char = Object::$separatorChar; - Object::$separatorChar = false; - $decoded = Object::toArray($decoded); - Object::$separatorChar = $char; + $char = Obj::$separatorChar; + Obj::$separatorChar = false; + $decoded = Obj::toArray($decoded); + Obj::$separatorChar = $char; return $decoded; } } \ No newline at end of file diff --git a/htdocs/includes/restler/framework/Luracast/Restler/Format/HtmlFormat.php b/htdocs/includes/restler/framework/Luracast/Restler/Format/HtmlFormat.php index 6e7d4b7303e..e871186c446 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/Format/HtmlFormat.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/Format/HtmlFormat.php @@ -11,7 +11,7 @@ use Illuminate\View\Engines\EngineResolver; use Illuminate\View\Factory; use Illuminate\View\FileViewFinder; use Illuminate\View\View; -use Luracast\Restler\Data\Object; +use Luracast\Restler\Data\Obj; use Luracast\Restler\Defaults; use Luracast\Restler\RestException; use Luracast\Restler\Restler; @@ -315,7 +315,7 @@ class HtmlFormat extends DependentFormat $error = $success ? null : $exception->getMessage(); $data = array( 'response' => static::$convertResponseToArray - ? Object::toArray($data) + ? Obj::toArray($data) : $data, 'stages' => $this->restler->getEvents(), 'success' => $success, diff --git a/htdocs/includes/restler/framework/Luracast/Restler/Format/JsonFormat.php b/htdocs/includes/restler/framework/Luracast/Restler/Format/JsonFormat.php index 6986ce65c90..28dfd560969 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/Format/JsonFormat.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/Format/JsonFormat.php @@ -1,7 +1,7 @@ handleJsonError(); return $result; } - $result = json_encode(Object::toArray($data, true)); + $result = json_encode(Obj::toArray($data, true)); $this->handleJsonError(); if ($humanReadable) { @@ -116,6 +127,10 @@ class JsonFormat extends Format public function decode($data) { + if(empty($data)){ + return null; + } + $options = 0; if (self::$bigIntAsString) { if ((PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) // PHP >= 5.4 @@ -142,7 +157,7 @@ class JsonFormat extends Format throw new RestException(400, 'Error parsing JSON'); } - return Object::toArray($decoded); + return Obj::toArray($decoded); } /** @@ -259,4 +274,4 @@ class JsonFormat extends Format throw new \RuntimeException('Error encoding/decoding JSON: '. $message); } } -} \ No newline at end of file +} diff --git a/htdocs/includes/restler/framework/Luracast/Restler/Format/PlistFormat.php b/htdocs/includes/restler/framework/Luracast/Restler/Format/PlistFormat.php index 2f4faa0769f..cc07066a33c 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/Format/PlistFormat.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/Format/PlistFormat.php @@ -1,7 +1,7 @@ toCFType( - Object::toArray($data) + Obj::toArray($data) ); $plist->add($guessedStructure); diff --git a/htdocs/includes/restler/framework/Luracast/Restler/Format/UploadFormat.php b/htdocs/includes/restler/framework/Luracast/Restler/Format/UploadFormat.php index f785beeaa02..de41bf98c71 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/Format/UploadFormat.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/Format/UploadFormat.php @@ -25,7 +25,9 @@ class UploadFormat extends Format 2 => "The uploaded file exceeds the maximum allowed size", 3 => "The uploaded file was only partially uploaded", 4 => "No file was uploaded", - 6 => "Missing a temporary folder" + 6 => "Missing a temporary folder", + 7 => "Failed to write file to disk", + 8 => "A PHP extension stopped the file upload" ); /** * use it if you need to restrict uploads based on file type diff --git a/htdocs/includes/restler/framework/Luracast/Restler/Format/XmlFormat.php b/htdocs/includes/restler/framework/Luracast/Restler/Format/XmlFormat.php index b006409e800..b51fa707a53 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/Format/XmlFormat.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/Format/XmlFormat.php @@ -1,7 +1,7 @@ openMemory(); $xml->startDocument('1.0', $this->charset); diff --git a/htdocs/includes/restler/framework/Luracast/Restler/Format/YamlFormat.php b/htdocs/includes/restler/framework/Luracast/Restler/Format/YamlFormat.php index 0cb1564f4ed..07baae88b6f 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/Format/YamlFormat.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/Format/YamlFormat.php @@ -2,7 +2,7 @@ namespace Luracast\Restler\Format; use Symfony\Component\Yaml\Yaml; -use Luracast\Restler\Data\Object; +use Luracast\Restler\Data\Obj; /** * YAML Format for Restler Framework @@ -26,7 +26,7 @@ class YamlFormat extends DependentFormat public function encode($data, $humanReadable = false) { - return @Yaml::dump(Object::toArray($data), $humanReadable ? 10 : 4); + return @Yaml::dump(Obj::toArray($data), $humanReadable ? 10 : 4); } public function decode($data) diff --git a/htdocs/includes/restler/framework/Luracast/Restler/PassThrough.php b/htdocs/includes/restler/framework/Luracast/Restler/PassThrough.php index e1fc21eae6b..a77e533b722 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/PassThrough.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/PassThrough.php @@ -34,7 +34,6 @@ class PassThrough * @param bool $isPublic cache control, is it public or private * * @throws RestException - * @internal param string $pragma * */ public static function file($filename, $forceDownload = false, $expires = 0, $isPublic = true) diff --git a/htdocs/includes/restler/framework/Luracast/Restler/Restler.php b/htdocs/includes/restler/framework/Luracast/Restler/Restler.php index 0cef46a7e41..c2e9b1acb73 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/Restler.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/Restler.php @@ -538,7 +538,7 @@ class Restler extends EventDispatcher if ($version && $version <= $this->apiVersion) { $this->requestedApiVersion = $version; $path = explode('/', $path, 2); - $path = $path[1]; + $path = count($path) == 2 ? $path[1] : ''; } } else { $this->requestedApiVersion = $this->apiMinimumVersion; @@ -718,7 +718,8 @@ class Restler extends EventDispatcher . $_SERVER['HTTP_ACCESS_CONTROL_REQUEST_HEADERS']); header('Access-Control-Allow-Origin: ' . - (Defaults::$accessControlAllowOrigin == '*' ? $_SERVER['HTTP_ORIGIN'] : Defaults::$accessControlAllowOrigin)); + ((Defaults::$accessControlAllowOrigin == '*' && isset($_SERVER['HTTP_ORIGIN'])) + ? $_SERVER['HTTP_ORIGIN'] : Defaults::$accessControlAllowOrigin)); header('Access-Control-Allow-Credentials: true'); exit(0); @@ -1195,7 +1196,7 @@ class Restler extends EventDispatcher foreach ($this->errorClasses as $className) { if (method_exists($className, $method)) { $obj = Scope::get($className); - if ($obj->$method()) + if ($obj->$method($exception)) $handled = true; } } @@ -1397,6 +1398,135 @@ class Restler extends EventDispatcher $this->errorClasses[] = $className; } + /** + * protected methods will need at least one authentication class to be set + * in order to allow that method to be executed. When multiple authentication + * classes are in use, this function provides better performance by setting + * all auth classes through a single function call. + * + * @param array $classNames array of associative arrays containing + * the authentication class name & optional + * url prefix for mapping. + */ + public function setAuthClasses(array $classNames) + { + $this->authClasses = array_merge($this->authClasses, array_values($classNames)); + } + + /** + * Add multiple api classes through this method. + * + * This method provides better performance when large number + * of API classes are in use as it processes them all at once, + * as opposed to hundreds (or more) addAPIClass calls. + * + * + * All the public methods that do not start with _ (underscore) + * will be will be exposed as the public api by default. + * + * All the protected methods that do not start with _ (underscore) + * will exposed as protected api which will require authentication + * + * @param array $map array of associative arrays containing + * the class name & optional url prefix + * for mapping. + * + * @return null + * + * @throws Exception when supplied with invalid class name + */ + public function mapAPIClasses(array $map) + { + try { + if ($this->productionMode && is_null($this->cached)) { + $routes = $this->cache->get('routes'); + if (isset($routes) && is_array($routes)) { + $this->apiVersionMap = $routes['apiVersionMap']; + unset($routes['apiVersionMap']); + Routes::fromArray($routes); + $this->cached = true; + } else { + $this->cached = false; + } + } + $maxVersionMethod = '__getMaximumSupportedVersion'; + if (!$this->productionMode || !$this->cached) { + foreach ($map as $className => $resourcePath) { + if (is_numeric($className)) { + $className = $resourcePath; + $resourcePath = null; + } + if (isset(Scope::$classAliases[$className])) { + $className = Scope::$classAliases[$className]; + } + if (class_exists($className)) { + if (method_exists($className, $maxVersionMethod)) { + $max = $className::$maxVersionMethod(); + for ($i = 1; $i <= $max; $i++) { + $this->apiVersionMap[$className][$i] = $className; + } + } else { + $this->apiVersionMap[$className][1] = $className; + } + } + //versioned api + if (false !== ($index = strrpos($className, '\\'))) { + $name = substr($className, 0, $index) + . '\\v{$version}' . substr($className, $index); + } else { + if (false !== ($index = strrpos($className, '_'))) { + $name = substr($className, 0, $index) + . '_v{$version}' . substr($className, $index); + } else { + $name = 'v{$version}\\' . $className; + } + } + + for ($version = $this->apiMinimumVersion; + $version <= $this->apiVersion; + $version++) { + + $versionedClassName = str_replace('{$version}', $version, + $name); + if (class_exists($versionedClassName)) { + Routes::addAPIClass($versionedClassName, + Util::getResourcePath( + $className, + $resourcePath + ), + $version + ); + if (method_exists($versionedClassName, $maxVersionMethod)) { + $max = $versionedClassName::$maxVersionMethod(); + for ($i = $version; $i <= $max; $i++) { + $this->apiVersionMap[$className][$i] = $versionedClassName; + } + } else { + $this->apiVersionMap[$className][$version] = $versionedClassName; + } + } elseif (isset($this->apiVersionMap[$className][$version])) { + Routes::addAPIClass($this->apiVersionMap[$className][$version], + Util::getResourcePath( + $className, + $resourcePath + ), + $version + ); + } + } + } + } + } catch (Exception $e) { + $e = new Exception( + "mapAPIClasses failed. " . $e->getMessage(), + $e->getCode(), + $e + ); + $this->setSupportedFormats('JsonFormat'); + $this->message($e); + } + } + /** * Associated array that maps formats to their respective format class name * @@ -1484,6 +1614,19 @@ class Restler extends EventDispatcher public function __destruct() { if ($this->productionMode && !$this->cached) { + if (empty($this->url) && empty($this->requestMethod)) { + // url and requestMethod is NOT set: + // This can only happen, when an exception was thrown outside of restler, so that the method Restler::handle was NOT called. + // In this case, the routes can now be corrupt/incomplete, because we don't know, if all API-classes could be registered + // before the exception was thrown. So, don't cache the routes, because the routes can now be corrupt/incomplete! + return; + } + if ($this->exception instanceof RestException && $this->exception->getStage() === 'setup') { + // An exception has occured during configuration of restler. Maybe we could not add all API-classes correctly! + // So, don't cache the routes, because the routes can now be corrupt/incomplete! + return; + } + $this->cache->set( 'routes', Routes::toArray() + diff --git a/htdocs/includes/restler/framework/Luracast/Restler/Routes.php b/htdocs/includes/restler/framework/Luracast/Restler/Routes.php index 067603a0f58..73e78dc0039 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/Routes.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/Routes.php @@ -293,8 +293,6 @@ class Routes } $url = empty($methodUrl) ? rtrim($resourcePath, '/') : $resourcePath . $methodUrl; - $lastPathParam = array_keys($pathParams); - $lastPathParam = end($lastPathParam); for ($position = 0; $position < count($params); $position++) { $from = $metadata['param'][$position][$dataName]['from']; if ($from == 'body' && ($httpMethod == 'GET' || @@ -307,6 +305,7 @@ class Routes if (empty($pathParams) || $allowAmbiguity) { static::addPath($url, $call, $httpMethod, $version); } + $lastPathParam = end($pathParams); foreach ($pathParams as $position) { if (!empty($url)) $url .= '/'; diff --git a/htdocs/includes/restler/framework/Luracast/Restler/Scope.php b/htdocs/includes/restler/framework/Luracast/Restler/Scope.php index 91eea3ef6a1..fd4b41ff98d 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/Scope.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/Scope.php @@ -52,7 +52,7 @@ class Scope 'MemcacheCache' => 'Luracast\Restler\MemcacheCache', //Utility classes - 'Object' => 'Luracast\Restler\Data\Object', + 'Obj' => 'Luracast\Restler\Data\Obj', 'Text' => 'Luracast\Restler\Data\Text', 'Arr' => 'Luracast\Restler\Data\Arr', @@ -194,6 +194,11 @@ class Scope { if (empty($className) || !is_string($className)) return false; + + if (self::isPrimitiveDataType($className)) { + return false; + } + $divider = '\\'; $qualified = false; if ($className{0} == $divider) { @@ -212,4 +217,14 @@ class Scope } return false; } + + /** + * @param string $stringName + * @return boolean + */ + private static function isPrimitiveDataType($stringName) + { + $primitiveDataTypes = array('Array', 'array', 'bool', 'boolean', 'float', 'int', 'integer', 'string'); + return in_array($stringName, $primitiveDataTypes); + } } diff --git a/htdocs/includes/restler/framework/Luracast/Restler/Util.php b/htdocs/includes/restler/framework/Luracast/Restler/Util.php index e1c6f60c317..e7324a3a620 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/Util.php +++ b/htdocs/includes/restler/framework/Luracast/Restler/Util.php @@ -226,6 +226,10 @@ class Util public static function getShortName($className) { + // @CHANGE LDR + if (! is_string($className)) return ''; + //var_dump($className); + $className = explode('\\', $className); return end($className); } diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/css/print.css b/htdocs/includes/restler/framework/Luracast/Restler/explorer/css/print.css new file mode 100644 index 00000000000..2e6b310300b --- /dev/null +++ b/htdocs/includes/restler/framework/Luracast/Restler/explorer/css/print.css @@ -0,0 +1,1187 @@ +/* Original style from softwaremaniacs.org (c) Ivan Sagalaev */ +.swagger-section pre code { + display: block; + padding: 0.5em; + background: #F0F0F0; +} +.swagger-section pre code, +.swagger-section pre .subst, +.swagger-section pre .tag .title, +.swagger-section pre .lisp .title, +.swagger-section pre .clojure .built_in, +.swagger-section pre .nginx .title { + color: black; +} +.swagger-section pre .string, +.swagger-section pre .title, +.swagger-section pre .constant, +.swagger-section pre .parent, +.swagger-section pre .tag .value, +.swagger-section pre .rules .value, +.swagger-section pre .rules .value .number, +.swagger-section pre .preprocessor, +.swagger-section pre .ruby .symbol, +.swagger-section pre .ruby .symbol .string, +.swagger-section pre .aggregate, +.swagger-section pre .template_tag, +.swagger-section pre .django .variable, +.swagger-section pre .smalltalk .class, +.swagger-section pre .addition, +.swagger-section pre .flow, +.swagger-section pre .stream, +.swagger-section pre .bash .variable, +.swagger-section pre .apache .tag, +.swagger-section pre .apache .cbracket, +.swagger-section pre .tex .command, +.swagger-section pre .tex .special, +.swagger-section pre .erlang_repl .function_or_atom, +.swagger-section pre .markdown .header { + color: #800; +} +.swagger-section pre .comment, +.swagger-section pre .annotation, +.swagger-section pre .template_comment, +.swagger-section pre .diff .header, +.swagger-section pre .chunk, +.swagger-section pre .markdown .blockquote { + color: #888; +} +.swagger-section pre .number, +.swagger-section pre .date, +.swagger-section pre .regexp, +.swagger-section pre .literal, +.swagger-section pre .smalltalk .symbol, +.swagger-section pre .smalltalk .char, +.swagger-section pre .go .constant, +.swagger-section pre .change, +.swagger-section pre .markdown .bullet, +.swagger-section pre .markdown .link_url { + color: #080; +} +.swagger-section pre .label, +.swagger-section pre .javadoc, +.swagger-section pre .ruby .string, +.swagger-section pre .decorator, +.swagger-section pre .filter .argument, +.swagger-section pre .localvars, +.swagger-section pre .array, +.swagger-section pre .attr_selector, +.swagger-section pre .important, +.swagger-section pre .pseudo, +.swagger-section pre .pi, +.swagger-section pre .doctype, +.swagger-section pre .deletion, +.swagger-section pre .envvar, +.swagger-section pre .shebang, +.swagger-section pre .apache .sqbracket, +.swagger-section pre .nginx .built_in, +.swagger-section pre .tex .formula, +.swagger-section pre .erlang_repl .reserved, +.swagger-section pre .prompt, +.swagger-section pre .markdown .link_label, +.swagger-section pre .vhdl .attribute, +.swagger-section pre .clojure .attribute, +.swagger-section pre .coffeescript .property { + color: #8888ff; +} +.swagger-section pre .keyword, +.swagger-section pre .id, +.swagger-section pre .phpdoc, +.swagger-section pre .title, +.swagger-section pre .built_in, +.swagger-section pre .aggregate, +.swagger-section pre .css .tag, +.swagger-section pre .javadoctag, +.swagger-section pre .phpdoc, +.swagger-section pre .yardoctag, +.swagger-section pre .smalltalk .class, +.swagger-section pre .winutils, +.swagger-section pre .bash .variable, +.swagger-section pre .apache .tag, +.swagger-section pre .go .typename, +.swagger-section pre .tex .command, +.swagger-section pre .markdown .strong, +.swagger-section pre .request, +.swagger-section pre .status { + font-weight: bold; +} +.swagger-section pre .markdown .emphasis { + font-style: italic; +} +.swagger-section pre .nginx .built_in { + font-weight: normal; +} +.swagger-section pre .coffeescript .javascript, +.swagger-section pre .javascript .xml, +.swagger-section pre .tex .formula, +.swagger-section pre .xml .javascript, +.swagger-section pre .xml .vbscript, +.swagger-section pre .xml .css, +.swagger-section pre .xml .cdata { + opacity: 0.5; +} +.swagger-section .swagger-ui-wrap { + line-height: 1; + font-family: "Droid Sans", sans-serif; + max-width: 960px; + margin-left: auto; + margin-right: auto; + /* JSONEditor specific styling */ +} +.swagger-section .swagger-ui-wrap b, +.swagger-section .swagger-ui-wrap strong { + font-family: "Droid Sans", sans-serif; + font-weight: bold; +} +.swagger-section .swagger-ui-wrap q, +.swagger-section .swagger-ui-wrap blockquote { + quotes: none; +} +.swagger-section .swagger-ui-wrap p { + line-height: 1.4em; + padding: 0 0 10px; + color: #333333; +} +.swagger-section .swagger-ui-wrap q:before, +.swagger-section .swagger-ui-wrap q:after, +.swagger-section .swagger-ui-wrap blockquote:before, +.swagger-section .swagger-ui-wrap blockquote:after { + content: none; +} +.swagger-section .swagger-ui-wrap .heading_with_menu h1, +.swagger-section .swagger-ui-wrap .heading_with_menu h2, +.swagger-section .swagger-ui-wrap .heading_with_menu h3, +.swagger-section .swagger-ui-wrap .heading_with_menu h4, +.swagger-section .swagger-ui-wrap .heading_with_menu h5, +.swagger-section .swagger-ui-wrap .heading_with_menu h6 { + display: block; + clear: none; + float: left; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + width: 60%; +} +.swagger-section .swagger-ui-wrap table { + border-collapse: collapse; + border-spacing: 0; +} +.swagger-section .swagger-ui-wrap table thead tr th { + padding: 5px; + font-size: 0.9em; + color: #666666; + border-bottom: 1px solid #999999; +} +.swagger-section .swagger-ui-wrap table tbody tr:last-child td { + border-bottom: none; +} +.swagger-section .swagger-ui-wrap table tbody tr.offset { + background-color: #f0f0f0; +} +.swagger-section .swagger-ui-wrap table tbody tr td { + padding: 6px; + font-size: 0.9em; + border-bottom: 1px solid #cccccc; + vertical-align: top; + line-height: 1.3em; +} +.swagger-section .swagger-ui-wrap ol { + margin: 0px 0 10px; + padding: 0 0 0 18px; + list-style-type: decimal; +} +.swagger-section .swagger-ui-wrap ol li { + padding: 5px 0px; + font-size: 0.9em; + color: #333333; +} +.swagger-section .swagger-ui-wrap ol, +.swagger-section .swagger-ui-wrap ul { + list-style: none; +} +.swagger-section .swagger-ui-wrap h1 a, +.swagger-section .swagger-ui-wrap h2 a, +.swagger-section .swagger-ui-wrap h3 a, +.swagger-section .swagger-ui-wrap h4 a, +.swagger-section .swagger-ui-wrap h5 a, +.swagger-section .swagger-ui-wrap h6 a { + text-decoration: none; +} +.swagger-section .swagger-ui-wrap h1 a:hover, +.swagger-section .swagger-ui-wrap h2 a:hover, +.swagger-section .swagger-ui-wrap h3 a:hover, +.swagger-section .swagger-ui-wrap h4 a:hover, +.swagger-section .swagger-ui-wrap h5 a:hover, +.swagger-section .swagger-ui-wrap h6 a:hover { + text-decoration: underline; +} +.swagger-section .swagger-ui-wrap h1 span.divider, +.swagger-section .swagger-ui-wrap h2 span.divider, +.swagger-section .swagger-ui-wrap h3 span.divider, +.swagger-section .swagger-ui-wrap h4 span.divider, +.swagger-section .swagger-ui-wrap h5 span.divider, +.swagger-section .swagger-ui-wrap h6 span.divider { + color: #aaaaaa; +} +.swagger-section .swagger-ui-wrap a { + color: #547f00; +} +.swagger-section .swagger-ui-wrap a img { + border: none; +} +.swagger-section .swagger-ui-wrap article, +.swagger-section .swagger-ui-wrap aside, +.swagger-section .swagger-ui-wrap details, +.swagger-section .swagger-ui-wrap figcaption, +.swagger-section .swagger-ui-wrap figure, +.swagger-section .swagger-ui-wrap footer, +.swagger-section .swagger-ui-wrap header, +.swagger-section .swagger-ui-wrap hgroup, +.swagger-section .swagger-ui-wrap menu, +.swagger-section .swagger-ui-wrap nav, +.swagger-section .swagger-ui-wrap section, +.swagger-section .swagger-ui-wrap summary { + display: block; +} +.swagger-section .swagger-ui-wrap pre { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + background-color: #fcf6db; + border: 1px solid #e5e0c6; + padding: 10px; +} +.swagger-section .swagger-ui-wrap pre code { + line-height: 1.6em; + background: none; +} +.swagger-section .swagger-ui-wrap .content > .content-type > div > label { + clear: both; + display: block; + color: #0F6AB4; + font-size: 1.1em; + margin: 0; + padding: 15px 0 5px; +} +.swagger-section .swagger-ui-wrap .content pre { + font-size: 12px; + margin-top: 5px; + padding: 5px; +} +.swagger-section .swagger-ui-wrap .icon-btn { + cursor: pointer; +} +.swagger-section .swagger-ui-wrap .info_title { + padding-bottom: 10px; + font-weight: bold; + font-size: 25px; +} +.swagger-section .swagger-ui-wrap .footer { + margin-top: 20px; +} +.swagger-section .swagger-ui-wrap p.big, +.swagger-section .swagger-ui-wrap div.big p { + font-size: 1em; + margin-bottom: 10px; +} +.swagger-section .swagger-ui-wrap form.fullwidth ol li.string input, +.swagger-section .swagger-ui-wrap form.fullwidth ol li.url input, +.swagger-section .swagger-ui-wrap form.fullwidth ol li.text textarea, +.swagger-section .swagger-ui-wrap form.fullwidth ol li.numeric input { + width: 500px !important; +} +.swagger-section .swagger-ui-wrap .info_license { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .info_tos { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .message-fail { + color: #cc0000; +} +.swagger-section .swagger-ui-wrap .info_url { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .info_email { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .info_name { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .info_description { + padding-bottom: 10px; + font-size: 15px; +} +.swagger-section .swagger-ui-wrap .markdown ol li, +.swagger-section .swagger-ui-wrap .markdown ul li { + padding: 3px 0px; + line-height: 1.4em; + color: #333333; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.string input, +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.url input, +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.numeric input { + display: block; + padding: 4px; + width: auto; + clear: both; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.string input.title, +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.url input.title, +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.numeric input.title { + font-size: 1.3em; +} +.swagger-section .swagger-ui-wrap table.fullwidth { + width: 100%; +} +.swagger-section .swagger-ui-wrap .model-signature { + font-family: "Droid Sans", sans-serif; + font-size: 1em; + line-height: 1.5em; +} +.swagger-section .swagger-ui-wrap .model-signature .signature-nav a { + text-decoration: none; + color: #AAA; +} +.swagger-section .swagger-ui-wrap .model-signature .signature-nav a:hover { + text-decoration: underline; + color: black; +} +.swagger-section .swagger-ui-wrap .model-signature .signature-nav .selected { + color: black; + text-decoration: none; +} +.swagger-section .swagger-ui-wrap .model-signature .propType { + color: #5555aa; +} +.swagger-section .swagger-ui-wrap .model-signature pre:hover { + background-color: #ffffdd; +} +.swagger-section .swagger-ui-wrap .model-signature pre { + font-size: .85em; + line-height: 1.2em; + overflow: auto; + max-height: 200px; + cursor: pointer; +} +.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav { + display: block; + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav li:last-child { + padding-right: 0; + border-right: none; +} +.swagger-section .swagger-ui-wrap .model-signature ul.signature-nav li { + float: left; + margin: 0 5px 5px 0; + padding: 2px 5px 2px 0; + border-right: 1px solid #ddd; +} +.swagger-section .swagger-ui-wrap .model-signature .propOpt { + color: #555; +} +.swagger-section .swagger-ui-wrap .model-signature .snippet small { + font-size: 0.75em; +} +.swagger-section .swagger-ui-wrap .model-signature .propOptKey { + font-style: italic; +} +.swagger-section .swagger-ui-wrap .model-signature .description .strong { + font-weight: bold; + color: #000; + font-size: .9em; +} +.swagger-section .swagger-ui-wrap .model-signature .description div { + font-size: 0.9em; + line-height: 1.5em; + margin-left: 1em; +} +.swagger-section .swagger-ui-wrap .model-signature .description .stronger { + font-weight: bold; + color: #000; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper { + border-spacing: 0; + position: absolute; + background-color: #ffffff; + border: 1px solid #bbbbbb; + display: none; + font-size: 11px; + max-width: 400px; + line-height: 30px; + color: black; + padding: 5px; + margin-left: 10px; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper th { + text-align: center; + background-color: #eeeeee; + border: 1px solid #bbbbbb; + font-size: 11px; + color: #666666; + font-weight: bold; + padding: 5px; + line-height: 15px; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper .optionName { + font-weight: bold; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown > p:first-child, +.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown > p:last-child { + display: inline; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown > p:not(:first-child):before { + display: block; + content: ''; +} +.swagger-section .swagger-ui-wrap .model-signature .description span:last-of-type.propDesc.markdown > p:only-child { + margin-right: -3px; +} +.swagger-section .swagger-ui-wrap .model-signature .propName { + font-weight: bold; +} +.swagger-section .swagger-ui-wrap .model-signature .signature-container { + clear: both; +} +.swagger-section .swagger-ui-wrap .body-textarea { + width: 300px; + height: 100px; + border: 1px solid #aaa; +} +.swagger-section .swagger-ui-wrap .markdown p code, +.swagger-section .swagger-ui-wrap .markdown li code { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + background-color: #f0f0f0; + color: black; + padding: 1px 3px; +} +.swagger-section .swagger-ui-wrap .required { + font-weight: bold; +} +.swagger-section .swagger-ui-wrap .editor_holder { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap .editor_holder label { + font-weight: normal!important; + /* JSONEditor uses bold by default for all labels, we revert that back to normal to not give the impression that by default fields are required */ +} +.swagger-section .swagger-ui-wrap .editor_holder label.required { + font-weight: bold!important; +} +.swagger-section .swagger-ui-wrap input.parameter { + width: 300px; + border: 1px solid #aaa; +} +.swagger-section .swagger-ui-wrap h1 { + color: black; + font-size: 1.5em; + line-height: 1.3em; + padding: 10px 0 10px 0; + font-family: "Droid Sans", sans-serif; + font-weight: bold; +} +.swagger-section .swagger-ui-wrap .heading_with_menu { + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-section .swagger-ui-wrap .heading_with_menu ul { + display: block; + clear: none; + float: right; + -moz-box-sizing: border-box; + -webkit-box-sizing: border-box; + -ms-box-sizing: border-box; + box-sizing: border-box; + margin-top: 10px; +} +.swagger-section .swagger-ui-wrap h2 { + color: black; + font-size: 1.3em; + padding: 10px 0 10px 0; +} +.swagger-section .swagger-ui-wrap h2 a { + color: black; +} +.swagger-section .swagger-ui-wrap h2 span.sub { + font-size: 0.7em; + color: #999999; + font-style: italic; +} +.swagger-section .swagger-ui-wrap h2 span.sub a { + color: #777777; +} +.swagger-section .swagger-ui-wrap span.weak { + color: #666666; +} +.swagger-section .swagger-ui-wrap .message-success { + color: #89BF04; +} +.swagger-section .swagger-ui-wrap caption, +.swagger-section .swagger-ui-wrap th, +.swagger-section .swagger-ui-wrap td { + text-align: left; + font-weight: normal; + vertical-align: middle; +} +.swagger-section .swagger-ui-wrap .code { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.text textarea { + font-family: "Droid Sans", sans-serif; + height: 250px; + padding: 4px; + display: block; + clear: both; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.select select { + display: block; + clear: both; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean { + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean label { + display: block; + float: left; + clear: none; + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.boolean input { + display: block; + float: left; + clear: none; + margin: 0 5px 0 0; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li.required label { + color: black; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li label { + display: block; + clear: both; + width: auto; + padding: 0 0 3px; + color: #666666; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li label abbr { + padding-left: 3px; + color: #888888; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.inputs ol li p.inline-hints { + margin-left: 0; + font-style: italic; + font-size: 0.9em; + margin: 0; +} +.swagger-section .swagger-ui-wrap form.formtastic fieldset.buttons { + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap span.blank, +.swagger-section .swagger-ui-wrap span.empty { + color: #888888; + font-style: italic; +} +.swagger-section .swagger-ui-wrap .markdown h3 { + color: #547f00; +} +.swagger-section .swagger-ui-wrap .markdown h4 { + color: #666666; +} +.swagger-section .swagger-ui-wrap .markdown pre { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + background-color: #fcf6db; + border: 1px solid #e5e0c6; + padding: 10px; + margin: 0 0 10px 0; +} +.swagger-section .swagger-ui-wrap .markdown pre code { + line-height: 1.6em; +} +.swagger-section .swagger-ui-wrap div.gist { + margin: 20px 0 25px 0 !important; +} +.swagger-section .swagger-ui-wrap ul#resources { + font-family: "Droid Sans", sans-serif; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource { + border-bottom: 1px solid #dddddd; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource:hover div.heading h2 a, +.swagger-section .swagger-ui-wrap ul#resources li.resource.active div.heading h2 a { + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource:hover div.heading ul.options li a, +.swagger-section .swagger-ui-wrap ul#resources li.resource.active div.heading ul.options li a { + color: #555555; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource:last-child { + border-bottom: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading { + border: 1px solid transparent; + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options { + overflow: hidden; + padding: 0; + display: block; + clear: none; + float: right; + margin: 14px 10px 0 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li { + float: left; + clear: none; + margin: 0; + padding: 2px 10px; + border-right: 1px solid #dddddd; + color: #666666; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a { + color: #aaaaaa; + text-decoration: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:hover { + text-decoration: underline; + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:hover, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a:active, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li a.active { + text-decoration: underline; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li:first-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li.first { + padding-left: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options li.last { + padding-right: 0; + border-right: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options:first-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options.first { + padding-left: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 { + color: #999999; + padding-left: 0; + display: block; + clear: none; + float: left; + font-family: "Droid Sans", sans-serif; + font-weight: bold; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a { + color: #999999; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a:hover { + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation { + float: none; + clear: both; + overflow: hidden; + display: block; + margin: 0 0 10px; + padding: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading { + float: none; + clear: both; + overflow: hidden; + display: block; + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 { + display: block; + clear: none; + float: left; + width: auto; + margin: 0; + padding: 0; + line-height: 1.1em; + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path { + padding-left: 10px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a { + color: black; + text-decoration: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.path a:hover { + text-decoration: underline; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span.http_method a { + text-transform: uppercase; + text-decoration: none; + color: white; + display: inline-block; + width: 50px; + font-size: 0.7em; + text-align: center; + padding: 7px 0 4px; + -moz-border-radius: 2px; + -webkit-border-radius: 2px; + -o-border-radius: 2px; + -ms-border-radius: 2px; + -khtml-border-radius: 2px; + border-radius: 2px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading h3 span { + margin: 0; + padding: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options { + overflow: hidden; + padding: 0; + display: block; + clear: none; + float: right; + margin: 6px 10px 0 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li { + float: left; + clear: none; + margin: 0; + padding: 2px 10px; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li a { + text-decoration: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.heading ul.options li.access { + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content { + border-top: none; + padding: 10px; + -moz-border-radius-bottomleft: 6px; + -webkit-border-bottom-left-radius: 6px; + -o-border-bottom-left-radius: 6px; + -ms-border-bottom-left-radius: 6px; + -khtml-border-bottom-left-radius: 6px; + border-bottom-left-radius: 6px; + -moz-border-radius-bottomright: 6px; + -webkit-border-bottom-right-radius: 6px; + -o-border-bottom-right-radius: 6px; + -ms-border-bottom-right-radius: 6px; + -khtml-border-bottom-right-radius: 6px; + border-bottom-right-radius: 6px; + margin: 0 0 20px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content h4 { + font-size: 1.1em; + margin: 0; + padding: 15px 0 5px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header { + float: none; + clear: both; + overflow: hidden; + display: block; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header a { + padding: 4px 0 0 10px; + display: inline-block; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header input.submit { + display: block; + clear: none; + float: left; + padding: 6px 8px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.sandbox_header span.response_throbber { + background-image: url('../images/throbber.gif'); + width: 128px; + height: 16px; + display: block; + clear: none; + float: right; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form input[type='text'].error { + outline: 2px solid black; + outline-color: #cc0000; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form select[name='parameterContentType'] { + max-width: 300px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.response div.block pre { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + padding: 10px; + font-size: 0.9em; + max-height: 400px; + overflow-y: auto; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading { + background-color: #f9f2e9; + border: 1px solid #f0e0ca; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading h3 span.http_method a { + background-color: #c5862b; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #f0e0ca; + color: #c5862b; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li a { + color: #c5862b; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content { + background-color: #faf5ee; + border: 1px solid #f0e0ca; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content h4 { + color: #c5862b; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content div.sandbox_header a { + color: #dcb67f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading { + background-color: #fcffcd; + border: 1px solid black; + border-color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading h3 span.http_method a { + text-transform: uppercase; + background-color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #ffd20f; + color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li a { + color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content { + background-color: #fcffcd; + border: 1px solid black; + border-color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content h4 { + color: #ffd20f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content div.sandbox_header a { + color: #6fc992; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading { + background-color: #f5e8e8; + border: 1px solid #e8c6c7; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading h3 span.http_method a { + text-transform: uppercase; + background-color: #a41e22; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #e8c6c7; + color: #a41e22; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li a { + color: #a41e22; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content { + background-color: #f7eded; + border: 1px solid #e8c6c7; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content h4 { + color: #a41e22; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content div.sandbox_header a { + color: #c8787a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading { + background-color: #e7f6ec; + border: 1px solid #c3e8d1; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading h3 span.http_method a { + background-color: #10a54a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #c3e8d1; + color: #10a54a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li a { + color: #10a54a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content { + background-color: #ebf7f0; + border: 1px solid #c3e8d1; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content h4 { + color: #10a54a; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content div.sandbox_header a { + color: #6fc992; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading { + background-color: #FCE9E3; + border: 1px solid #F5D5C3; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading h3 span.http_method a { + background-color: #D38042; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #f0cecb; + color: #D38042; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li a { + color: #D38042; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content { + background-color: #faf0ef; + border: 1px solid #f0cecb; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content h4 { + color: #D38042; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content div.sandbox_header a { + color: #dcb67f; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading { + background-color: #e7f0f7; + border: 1px solid #c3d9ec; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading h3 span.http_method a { + background-color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #c3d9ec; + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li a { + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content { + background-color: #ebf3f9; + border: 1px solid #c3d9ec; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content h4 { + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content div.sandbox_header a { + color: #6fa5d2; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading { + background-color: #e7f0f7; + border: 1px solid #c3d9ec; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading h3 span.http_method a { + background-color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading ul.options li { + border-right: 1px solid #dddddd; + border-right-color: #c3d9ec; + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.heading ul.options li a { + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content { + background-color: #ebf3f9; + border: 1px solid #c3d9ec; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content h4 { + color: #0f6ab4; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.options div.content div.sandbox_header a { + color: #6fa5d2; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.content, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.content { + border-top: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li:last-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.get div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.post div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.head div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.put div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.patch div.heading ul.options li.last, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation.delete div.heading ul.options li.last { + padding-right: 0; + border-right: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a:hover, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a:active, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li a.active { + text-decoration: underline; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li:first-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations ul.options li.first { + padding-left: 0; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations:first-child, +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations.first { + padding-left: 0; +} +.swagger-section .swagger-ui-wrap p#colophon { + margin: 0 15px 40px 15px; + padding: 10px 0; + font-size: 0.8em; + border-top: 1px solid #dddddd; + font-family: "Droid Sans", sans-serif; + color: #999999; + font-style: italic; +} +.swagger-section .swagger-ui-wrap p#colophon a { + text-decoration: none; + color: #547f00; +} +.swagger-section .swagger-ui-wrap h3 { + color: black; + font-size: 1.1em; + padding: 10px 0 10px 0; +} +.swagger-section .swagger-ui-wrap .markdown ol, +.swagger-section .swagger-ui-wrap .markdown ul { + font-family: "Droid Sans", sans-serif; + margin: 5px 0 10px; + padding: 0 0 0 18px; + list-style-type: disc; +} +.swagger-section .swagger-ui-wrap form.form_box { + background-color: #ebf3f9; + border: 1px solid #c3d9ec; + padding: 10px; +} +.swagger-section .swagger-ui-wrap form.form_box label { + color: #0f6ab4 !important; +} +.swagger-section .swagger-ui-wrap form.form_box input[type=submit] { + display: block; + padding: 10px; +} +.swagger-section .swagger-ui-wrap form.form_box p.weak { + font-size: 0.8em; +} +.swagger-section .swagger-ui-wrap form.form_box p { + font-size: 0.9em; + padding: 0 0 15px; + color: #7e7b6d; +} +.swagger-section .swagger-ui-wrap form.form_box p a { + color: #646257; +} +.swagger-section .swagger-ui-wrap form.form_box p strong { + color: black; +} +.swagger-section .swagger-ui-wrap .operation-status td.markdown > p:last-child { + padding-bottom: 0; +} +.swagger-section .title { + font-style: bold; +} +.swagger-section .secondary_form { + display: none; +} +.swagger-section .main_image { + display: block; + margin-left: auto; + margin-right: auto; +} +.swagger-section .oauth_body { + margin-left: 100px; + margin-right: 100px; +} +.swagger-section .oauth_submit { + text-align: center; +} +.swagger-section .api-popup-dialog { + z-index: 10000; + position: absolute; + width: 500px; + background: #FFF; + padding: 20px; + border: 1px solid #ccc; + border-radius: 5px; + display: none; + font-size: 13px; + color: #777; +} +.swagger-section .api-popup-dialog .api-popup-title { + font-size: 24px; + padding: 10px 0; +} +.swagger-section .api-popup-dialog .api-popup-title { + font-size: 24px; + padding: 10px 0; +} +.swagger-section .api-popup-dialog .error-msg { + padding-left: 5px; + padding-bottom: 5px; +} +.swagger-section .api-popup-dialog .api-popup-authbtn { + height: 30px; +} +.swagger-section .api-popup-dialog .api-popup-cancel { + height: 30px; +} +.swagger-section .api-popup-scopes { + padding: 10px 20px; +} +.swagger-section .api-popup-scopes li { + padding: 5px 0; + line-height: 20px; +} +.swagger-section .api-popup-scopes li input { + position: relative; + top: 2px; +} +.swagger-section .api-popup-scopes .api-scope-desc { + padding-left: 20px; + font-style: italic; +} +.swagger-section .api-popup-actions { + padding-top: 10px; +} +#header { + display: none; +} +.swagger-section .swagger-ui-wrap .model-signature pre { + max-height: none; +} +.swagger-section .swagger-ui-wrap .body-textarea { + width: 100px; +} +.swagger-section .swagger-ui-wrap input.parameter { + width: 100px; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading ul.options { + display: none; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints { + display: block !important; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content { + display: block !important; +} diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/css/screen.css b/htdocs/includes/restler/framework/Luracast/Restler/explorer/css/screen.css index 478b99837d7..dc02468fdc0 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/explorer/css/screen.css +++ b/htdocs/includes/restler/framework/Luracast/Restler/explorer/css/screen.css @@ -126,6 +126,7 @@ max-width: 960px; margin-left: auto; margin-right: auto; + /* JSONEditor specific styling */ } .swagger-section .swagger-ui-wrap b, .swagger-section .swagger-ui-wrap strong { @@ -274,6 +275,9 @@ font-weight: bold; font-size: 25px; } +.swagger-section .swagger-ui-wrap .footer { + margin-top: 20px; +} .swagger-section .swagger-ui-wrap p.big, .swagger-section .swagger-ui-wrap div.big p { font-size: 1em; @@ -294,7 +298,13 @@ .swagger-section .swagger-ui-wrap .message-fail { color: #cc0000; } -.swagger-section .swagger-ui-wrap .info_contact { +.swagger-section .swagger-ui-wrap .info_url { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .info_email { + padding-bottom: 5px; +} +.swagger-section .swagger-ui-wrap .info_name { padding-bottom: 5px; } .swagger-section .swagger-ui-wrap .info_description { @@ -350,7 +360,7 @@ font-size: .85em; line-height: 1.2em; overflow: auto; - max-height: 200px; + max-height: 400px; cursor: pointer; } .swagger-section .swagger-ui-wrap .model-signature ul.signature-nav { @@ -391,6 +401,43 @@ font-weight: bold; color: #000; } +.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper { + border-spacing: 0; + position: absolute; + background-color: #ffffff; + border: 1px solid #bbbbbb; + display: none; + font-size: 11px; + max-width: 400px; + line-height: 30px; + color: black; + padding: 5px; + margin-left: 10px; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper th { + text-align: center; + background-color: #eeeeee; + border: 1px solid #bbbbbb; + font-size: 11px; + color: #666666; + font-weight: bold; + padding: 5px; + line-height: 15px; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propWrap .optionsWrapper .optionName { + font-weight: bold; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown > p:first-child, +.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown > p:last-child { + display: inline; +} +.swagger-section .swagger-ui-wrap .model-signature .description .propDesc.markdown > p:not(:first-child):before { + display: block; + content: ''; +} +.swagger-section .swagger-ui-wrap .model-signature .description span:last-of-type.propDesc.markdown > p:only-child { + margin-right: -3px; +} .swagger-section .swagger-ui-wrap .model-signature .propName { font-weight: bold; } @@ -412,6 +459,17 @@ .swagger-section .swagger-ui-wrap .required { font-weight: bold; } +.swagger-section .swagger-ui-wrap .editor_holder { + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + font-size: 0.9em; +} +.swagger-section .swagger-ui-wrap .editor_holder label { + font-weight: normal!important; + /* JSONEditor uses bold by default for all labels, we revert that back to normal to not give the impression that by default fields are required */ +} +.swagger-section .swagger-ui-wrap .editor_holder label.required { + font-weight: bold!important; +} .swagger-section .swagger-ui-wrap input.parameter { width: 300px; border: 1px solid #aaa; @@ -761,6 +819,9 @@ outline: 2px solid black; outline-color: #cc0000; } +.swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content form select[name='parameterContentType'] { + max-width: 300px; +} .swagger-section .swagger-ui-wrap ul#resources li.resource ul.endpoints li.endpoint ul.operations li.operation div.content div.response div.block pre { font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; padding: 10px; @@ -1034,6 +1095,9 @@ .swagger-section .swagger-ui-wrap form.form_box p strong { color: black; } +.swagger-section .swagger-ui-wrap .operation-status td.markdown > p:last-child { + padding-bottom: 0; +} .swagger-section .title { font-style: bold; } @@ -1072,14 +1136,14 @@ font-size: 24px; padding: 10px 0; } -.swagger-section .api-popup-dialog p.error-msg { +.swagger-section .api-popup-dialog .error-msg { padding-left: 5px; padding-bottom: 5px; } -.swagger-section .api-popup-dialog button.api-popup-authbtn { +.swagger-section .api-popup-dialog .api-popup-authbtn { height: 30px; } -.swagger-section .api-popup-dialog button.api-popup-cancel { +.swagger-section .api-popup-dialog .api-popup-cancel { height: 30px; } .swagger-section .api-popup-scopes { @@ -1089,14 +1153,14 @@ padding: 5px 0; line-height: 20px; } -.swagger-section .api-popup-scopes .api-scope-desc { - padding-left: 20px; - font-style: italic; -} .swagger-section .api-popup-scopes li input { position: relative; top: 2px; } +.swagger-section .api-popup-scopes .api-scope-desc { + padding-left: 20px; + font-style: italic; +} .swagger-section .api-popup-actions { padding-top: 10px; } @@ -1106,8 +1170,16 @@ .swagger-section .auth { float: right; } -.swagger-section #api_information_panel { - position: absolute; +.swagger-section .api-ic { + height: 18px; + vertical-align: middle; + display: inline-block; + background: url(../images/explorer_icons.png) no-repeat; +} +.swagger-section .api-ic .api_information_panel { + position: relative; + margin-top: 20px; + margin-left: -5px; background: #FFF; border: 1px solid #ccc; border-radius: 5px; @@ -1118,34 +1190,32 @@ color: black; padding: 5px; } -.swagger-section #api_information_panel p .api-msg-enabled { +.swagger-section .api-ic .api_information_panel p .api-msg-enabled { color: green; } -.swagger-section #api_information_panel p .api-msg-disabled { +.swagger-section .api-ic .api_information_panel p .api-msg-disabled { color: red; } -.swagger-section .api-ic { - height: 18px; - vertical-align: middle; - display: inline-block; - background: url(../images/explorer_icons.png) no-repeat; +.swagger-section .api-ic:hover .api_information_panel { + position: absolute; + display: block; } .swagger-section .ic-info { background-position: 0 0; width: 18px; - margin-top: -7px; + margin-top: -6px; margin-left: 4px; } .swagger-section .ic-warning { background-position: -60px 0; width: 18px; - margin-top: -7px; + margin-top: -6px; margin-left: 4px; } .swagger-section .ic-error { background-position: -30px 0; width: 18px; - margin-top: -7px; + margin-top: -6px; margin-left: 4px; } .swagger-section .ic-off { @@ -1161,42 +1231,39 @@ cursor: pointer; } .swagger-section #header { - background-color: #89bf04; + background-color: #646257; padding: 14px; } -.swagger-section #header a#logo { - font-size: 1.5em; - font-weight: bold; - text-decoration: none; - background: transparent url(../images/logo_small.png) no-repeat left center; - padding: 20px 0 20px 40px; - color: white; +.swagger-section #input_baseUrl { + width: 400px; } -.swagger-section #header form#api_selector { +.swagger-section #api_selector { display: block; clear: none; float: right; } -.swagger-section #header form#api_selector .input { +.swagger-section #api_selector .input { display: block; clear: none; float: left; margin: 0 10px 0 0; } -.swagger-section #header form#api_selector .input input#input_apiKey { +.swagger-section #api_selector input { + font-size: 0.9em; + padding: 3px; + margin: 0; +} +.swagger-section #input_apiKey { width: 200px; } -.swagger-section #header form#api_selector .input input#input_baseUrl { - width: 400px; -} -.swagger-section #header form#api_selector .input a#explore { +.swagger-section #explore { display: block; text-decoration: none; font-weight: bold; padding: 6px 8px; font-size: 0.9em; color: white; - background-color: #547f00; + background-color: #000000; -moz-border-radius: 4px; -webkit-border-radius: 4px; -o-border-radius: 4px; @@ -1204,13 +1271,16 @@ -khtml-border-radius: 4px; border-radius: 4px; } -.swagger-section #header form#api_selector .input a#explore:hover { - background-color: #547f00; +.swagger-section #explore:hover { + background-color: #a41e22; } -.swagger-section #header form#api_selector .input input { - font-size: 0.9em; - padding: 3px; - margin: 0; +.swagger-section #header #logo { + font-size: 1.5em; + font-weight: bold; + text-decoration: none; + background: transparent url(../images/logo_small.png) no-repeat left center; + padding: 20px 0 20px 40px; + color: white; } .swagger-section #content_message { margin: 10px 15px; @@ -1222,3 +1292,13 @@ text-align: center; padding-top: 10px; } +.swagger-section .swagger-collapse:before { + content: "-"; +} +.swagger-section .swagger-expand:before { + content: "+"; +} + +#input_baseUrl { + display: none; +} diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/css/style.css b/htdocs/includes/restler/framework/Luracast/Restler/explorer/css/style.css new file mode 100644 index 00000000000..fc21a31db54 --- /dev/null +++ b/htdocs/includes/restler/framework/Luracast/Restler/explorer/css/style.css @@ -0,0 +1,250 @@ +.swagger-section #header a#logo { + font-size: 1.5em; + font-weight: bold; + text-decoration: none; + background: transparent url(../images/logo.png) no-repeat left center; + padding: 20px 0 20px 40px; +} +#text-head { + font-size: 80px; + font-family: 'Roboto', sans-serif; + color: #ffffff; + float: right; + margin-right: 20%; +} +.navbar-fixed-top .navbar-nav { + height: auto; +} +.navbar-fixed-top .navbar-brand { + height: auto; +} +.navbar-header { + height: auto; +} +.navbar-inverse { + background-color: #000; + border-color: #000; +} +#navbar-brand { + margin-left: 20%; +} +.navtext { + font-size: 10px; +} +.h1, +h1 { + font-size: 60px; +} +.navbar-default .navbar-header .navbar-brand { + color: #a2dfee; +} +/* tag titles */ +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a { + color: #393939; + font-family: 'Arvo', serif; + font-size: 1.5em; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 a:hover { + color: black; +} +.swagger-section .swagger-ui-wrap ul#resources li.resource div.heading h2 { + color: #525252; + padding-left: 0px; + display: block; + clear: none; + float: left; + font-family: 'Arvo', serif; + font-weight: bold; +} +.navbar-default .navbar-collapse, +.navbar-default .navbar-form { + border-color: #0A0A0A; +} +.container1 { + width: 1500px; + margin: auto; + margin-top: 0; + background-image: url('../images/shield.png'); + background-repeat: no-repeat; + background-position: -40px -20px; + margin-bottom: 210px; +} +.container-inner { + width: 1200px; + margin: auto; + background-color: rgba(223, 227, 228, 0.75); + padding-bottom: 40px; + padding-top: 40px; + border-radius: 15px; +} +.header-content { + padding: 0; + width: 1000px; +} +.title1 { + font-size: 80px; + font-family: 'Vollkorn', serif; + color: #404040; + text-align: center; + padding-top: 40px; + padding-bottom: 100px; +} +#icon { + margin-top: -18px; +} +.subtext { + font-size: 25px; + font-style: italic; + color: #08b; + text-align: right; + padding-right: 250px; +} +.bg-primary { + background-color: #00468b; +} +.navbar-default .nav > li > a, +.navbar-default .nav > li > a:focus { + color: #08b; +} +.navbar-default .nav > li > a, +.navbar-default .nav > li > a:hover { + color: #08b; +} +.navbar-default .nav > li > a, +.navbar-default .nav > li > a:focus:hover { + color: #08b; +} +.text-faded { + font-size: 25px; + font-family: 'Vollkorn', serif; +} +.section-heading { + font-family: 'Vollkorn', serif; + font-size: 45px; + padding-bottom: 10px; +} +hr { + border-color: #00468b; + padding-bottom: 10px; +} +.description { + margin-top: 20px; + padding-bottom: 200px; +} +.description li { + font-family: 'Vollkorn', serif; + font-size: 25px; + color: #525252; + margin-left: 28%; + padding-top: 5px; +} +.gap { + margin-top: 200px; +} +.troubleshootingtext { + color: rgba(255, 255, 255, 0.7); + padding-left: 30%; +} +.troubleshootingtext li { + list-style-type: circle; + font-size: 25px; + padding-bottom: 5px; +} +.overlay { + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1000; +} +.block.response_body.json:hover { + cursor: pointer; +} +.backdrop { + color: blue; +} +#myModal { + height: 100%; +} +.modal-backdrop { + bottom: 0; + position: fixed; +} +.curl { + padding: 10px; + font-family: "Anonymous Pro", "Menlo", "Consolas", "Bitstream Vera Sans Mono", "Courier New", monospace; + font-size: 0.9em; + max-height: 400px; + margin-top: 5px; + overflow-y: auto; + background-color: #fcf6db; + border: 1px solid #e5e0c6; + border-radius: 4px; +} +.curl_title { + font-size: 1.1em; + margin: 0; + padding: 15px 0 5px; + font-family: 'Open Sans', 'Helvetica Neue', Arial, sans-serif; + font-weight: 500; + line-height: 1.1; +} +.footer { + display: none; +} +.swagger-section .swagger-ui-wrap h2 { + padding: 0; +} +h2 { + margin: 0; + margin-bottom: 5px; +} +.markdown p { + font-size: 15px; + font-family: 'Arvo', serif; +} +.swagger-section .swagger-ui-wrap .code { + font-size: 15px; + font-family: 'Arvo', serif; +} +.swagger-section .swagger-ui-wrap b { + font-family: 'Arvo', serif; +} +#signin:hover { + cursor: pointer; +} +.dropdown-menu { + padding: 15px; +} +.navbar-right .dropdown-menu { + left: 0; + right: auto; +} +#signinbutton { + width: 100%; + height: 32px; + font-size: 13px; + font-weight: bold; + color: #08b; +} +.navbar-default .nav > li .details { + color: #000000; + text-transform: none; + font-size: 15px; + font-weight: normal; + font-family: 'Open Sans', sans-serif; + font-style: italic; + line-height: 20px; + top: -2px; +} +.navbar-default .nav > li .details:hover { + color: black; +} +#signout { + width: 100%; + height: 32px; + font-size: 13px; + font-weight: bold; + color: #08b; +} diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/css/typography.css b/htdocs/includes/restler/framework/Luracast/Restler/explorer/css/typography.css new file mode 100644 index 00000000000..3235edd9503 --- /dev/null +++ b/htdocs/includes/restler/framework/Luracast/Restler/explorer/css/typography.css @@ -0,0 +1,14 @@ +/* Google Font's Droid Sans */ +@font-face { + font-family: 'Droid Sans'; + font-style: normal; + font-weight: 400; + src: local('Droid Sans'), local('DroidSans'), url('../fonts/DroidSans.ttf') format('truetype'); +} +/* Google Font's Droid Sans Bold */ +@font-face { + font-family: 'Droid Sans'; + font-style: normal; + font-weight: 700; + src: local('Droid Sans Bold'), local('DroidSans-Bold'), url('../fonts/DroidSans-Bold.ttf') format('truetype'); +} diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/fonts/DroidSans-Bold.ttf b/htdocs/includes/restler/framework/Luracast/Restler/explorer/fonts/DroidSans-Bold.ttf new file mode 100644 index 00000000000..942bbf5ba3a Binary files /dev/null and b/htdocs/includes/restler/framework/Luracast/Restler/explorer/fonts/DroidSans-Bold.ttf differ diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/fonts/DroidSans.ttf b/htdocs/includes/restler/framework/Luracast/Restler/explorer/fonts/DroidSans.ttf new file mode 100644 index 00000000000..efd1f8bbd88 Binary files /dev/null and b/htdocs/includes/restler/framework/Luracast/Restler/explorer/fonts/DroidSans.ttf differ diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/images/collapse.gif b/htdocs/includes/restler/framework/Luracast/Restler/explorer/images/collapse.gif new file mode 100644 index 00000000000..8843e8ce5a4 Binary files /dev/null and b/htdocs/includes/restler/framework/Luracast/Restler/explorer/images/collapse.gif differ diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/images/expand.gif b/htdocs/includes/restler/framework/Luracast/Restler/explorer/images/expand.gif new file mode 100644 index 00000000000..477bf13718d Binary files /dev/null and b/htdocs/includes/restler/framework/Luracast/Restler/explorer/images/expand.gif differ diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/images/logo_small.png b/htdocs/includes/restler/framework/Luracast/Restler/explorer/images/logo_small.png index 5496a65579a..2ed3cf64be7 100644 Binary files a/htdocs/includes/restler/framework/Luracast/Restler/explorer/images/logo_small.png and b/htdocs/includes/restler/framework/Luracast/Restler/explorer/images/logo_small.png differ diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/images/pet_store_api.png b/htdocs/includes/restler/framework/Luracast/Restler/explorer/images/pet_store_api.png deleted file mode 100644 index f9f9cd4aeb3..00000000000 Binary files a/htdocs/includes/restler/framework/Luracast/Restler/explorer/images/pet_store_api.png and /dev/null differ diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/images/wordnik_api.png b/htdocs/includes/restler/framework/Luracast/Restler/explorer/images/wordnik_api.png deleted file mode 100644 index dca4f1455ac..00000000000 Binary files a/htdocs/includes/restler/framework/Luracast/Restler/explorer/images/wordnik_api.png and /dev/null differ diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/index.html b/htdocs/includes/restler/framework/Luracast/Restler/explorer/index.html index 0d73f19447e..c73f1981cc9 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/explorer/index.html +++ b/htdocs/includes/restler/framework/Luracast/Restler/explorer/index.html @@ -1,85 +1,126 @@ + + Api Explorer - + - - + + - + - - - + + + + + + + + @@ -87,22 +128,14 @@
    -
     
    +
     
    diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/en.js b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/en.js new file mode 100644 index 00000000000..9ccd65ad1d7 --- /dev/null +++ b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/en.js @@ -0,0 +1,55 @@ +'use strict'; + +/* jshint quotmark: double */ +window.SwaggerTranslator.learn({ + "Warning: Deprecated":"Warning: Deprecated", + "Implementation Notes":"Implementation Notes", + "Response Class":"Response Class", + "Status":"Status", + "Parameters":"Parameters", + "Parameter":"Parameter", + "Value":"Value", + "Description":"Description", + "Parameter Type":"Parameter Type", + "Data Type":"Data Type", + "Response Messages":"Response Messages", + "HTTP Status Code":"HTTP Status Code", + "Reason":"Reason", + "Response Model":"Response Model", + "Request URL":"Request URL", + "Response Body":"Response Body", + "Response Code":"Response Code", + "Response Headers":"Response Headers", + "Hide Response":"Hide Response", + "Headers":"Headers", + "Try it out!":"Try it out!", + "Show/Hide":"Show/Hide", + "List Operations":"List Operations", + "Expand Operations":"Expand Operations", + "Raw":"Raw", + "can't parse JSON. Raw result":"can't parse JSON. Raw result", + "Model Schema":"Model Schema", + "Model":"Model", + "Click to set as parameter value":"Click to set as parameter value", + "apply":"apply", + "Username":"Username", + "Password":"Password", + "Terms of service":"Terms of service", + "Created by":"Created by", + "See more at":"See more at", + "Contact the developer":"Contact the developer", + "api version":"api version", + "Response Content Type":"Response Content Type", + "Parameter content type:":"Parameter content type:", + "fetching resource":"fetching resource", + "fetching resource list":"fetching resource list", + "Explore":"Explore", + "Show Swagger Petstore Example Apis":"Show Swagger Petstore Example Apis", + "Can't read from server. It may not have the appropriate access-control-origin settings.":"Can't read from server. It may not have the appropriate access-control-origin settings.", + "Please specify the protocol for":"Please specify the protocol for", + "Can't read swagger JSON from":"Can't read swagger JSON from", + "Finished Loading Resource Information. Rendering Swagger UI":"Finished Loading Resource Information. Rendering Swagger UI", + "Unable to read api":"Unable to read api", + "from path":"from path", + "server returned":"server returned" +}); diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/es.js b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/es.js new file mode 100644 index 00000000000..a8dff60b6a9 --- /dev/null +++ b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/es.js @@ -0,0 +1,52 @@ +'use strict'; + +/* jshint quotmark: double */ +window.SwaggerTranslator.learn({ + "Warning: Deprecated":"Advertencia: Obsoleto", + "Implementation Notes":"Notas de implementación", + "Response Class":"Clase de la Respuesta", + "Status":"Status", + "Parameters":"Parámetros", + "Parameter":"Parámetro", + "Value":"Valor", + "Description":"Descripción", + "Parameter Type":"Tipo del Parámetro", + "Data Type":"Tipo del Dato", + "Response Messages":"Mensajes de la Respuesta", + "HTTP Status Code":"Código de Status HTTP", + "Reason":"Razón", + "Response Model":"Modelo de la Respuesta", + "Request URL":"URL de la Solicitud", + "Response Body":"Cuerpo de la Respuesta", + "Response Code":"Código de la Respuesta", + "Response Headers":"Encabezados de la Respuesta", + "Hide Response":"Ocultar Respuesta", + "Try it out!":"Pruébalo!", + "Show/Hide":"Mostrar/Ocultar", + "List Operations":"Listar Operaciones", + "Expand Operations":"Expandir Operaciones", + "Raw":"Crudo", + "can't parse JSON. Raw result":"no puede parsear el JSON. Resultado crudo", + "Model Schema":"Esquema del Modelo", + "Model":"Modelo", + "apply":"aplicar", + "Username":"Nombre de usuario", + "Password":"Contraseña", + "Terms of service":"Términos de Servicio", + "Created by":"Creado por", + "See more at":"Ver más en", + "Contact the developer":"Contactar al desarrollador", + "api version":"versión de la api", + "Response Content Type":"Tipo de Contenido (Content Type) de la Respuesta", + "fetching resource":"buscando recurso", + "fetching resource list":"buscando lista del recurso", + "Explore":"Explorar", + "Show Swagger Petstore Example Apis":"Mostrar Api Ejemplo de Swagger Petstore", + "Can't read from server. It may not have the appropriate access-control-origin settings.":"No se puede leer del servidor. Tal vez no tiene la configuración de control de acceso de origen (access-control-origin) apropiado.", + "Please specify the protocol for":"Por favor, especificar el protocola para", + "Can't read swagger JSON from":"No se puede leer el JSON de swagger desde", + "Finished Loading Resource Information. Rendering Swagger UI":"Finalizada la carga del recurso de Información. Mostrando Swagger UI", + "Unable to read api":"No se puede leer la api", + "from path":"desde ruta", + "server returned":"el servidor retornó" +}); diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/fr.js b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/fr.js new file mode 100644 index 00000000000..2e095ad0948 --- /dev/null +++ b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/fr.js @@ -0,0 +1,53 @@ +'use strict'; + +/* jshint quotmark: double */ +window.SwaggerTranslator.learn({ + "Warning: Deprecated":"Avertissement : Obsolète", + "Implementation Notes":"Notes d'implementation", + "Response Class":"Classe de la réponse", + "Status":"Statut", + "Parameters":"Paramètres", + "Parameter":"Paramètre", + "Value":"Valeur", + "Description":"Description", + "Parameter Type":"Type du paramètre", + "Data Type":"Type de données", + "Response Messages":"Messages de la réponse", + "HTTP Status Code":"Code de statut HTTP", + "Reason":"Raison", + "Response Model":"Modèle de réponse", + "Request URL":"URL appelée", + "Response Body":"Corps de la réponse", + "Response Code":"Code de la réponse", + "Response Headers":"En-têtes de la réponse", + "Hide Response":"Cacher la réponse", + "Headers":"En-têtes", + "Try it out!":"Testez !", + "Show/Hide":"Afficher/Masquer", + "List Operations":"Liste des opérations", + "Expand Operations":"Développer les opérations", + "Raw":"Brut", + "can't parse JSON. Raw result":"impossible de décoder le JSON. Résultat brut", + "Model Schema":"Définition du modèle", + "Model":"Modèle", + "apply":"appliquer", + "Username":"Nom d'utilisateur", + "Password":"Mot de passe", + "Terms of service":"Conditions de service", + "Created by":"Créé par", + "See more at":"Voir plus sur", + "Contact the developer":"Contacter le développeur", + "api version":"version de l'api", + "Response Content Type":"Content Type de la réponse", + "fetching resource":"récupération de la ressource", + "fetching resource list":"récupération de la liste de ressources", + "Explore":"Explorer", + "Show Swagger Petstore Example Apis":"Montrer les Apis de l'exemple Petstore de Swagger", + "Can't read from server. It may not have the appropriate access-control-origin settings.":"Impossible de lire à partir du serveur. Il se peut que les réglages access-control-origin ne soient pas appropriés.", + "Please specify the protocol for":"Veuillez spécifier un protocole pour", + "Can't read swagger JSON from":"Impossible de lire le JSON swagger à partir de", + "Finished Loading Resource Information. Rendering Swagger UI":"Chargement des informations terminé. Affichage de Swagger UI", + "Unable to read api":"Impossible de lire l'api", + "from path":"à partir du chemin", + "server returned":"réponse du serveur" +}); diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/it.js b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/it.js new file mode 100644 index 00000000000..8529c2a90bc --- /dev/null +++ b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/it.js @@ -0,0 +1,52 @@ +'use strict'; + +/* jshint quotmark: double */ +window.SwaggerTranslator.learn({ + "Warning: Deprecated":"Attenzione: Deprecato", + "Implementation Notes":"Note di implementazione", + "Response Class":"Classe della risposta", + "Status":"Stato", + "Parameters":"Parametri", + "Parameter":"Parametro", + "Value":"Valore", + "Description":"Descrizione", + "Parameter Type":"Tipo di parametro", + "Data Type":"Tipo di dato", + "Response Messages":"Messaggi della risposta", + "HTTP Status Code":"Codice stato HTTP", + "Reason":"Motivo", + "Response Model":"Modello di risposta", + "Request URL":"URL della richiesta", + "Response Body":"Corpo della risposta", + "Response Code":"Oggetto della risposta", + "Response Headers":"Intestazioni della risposta", + "Hide Response":"Nascondi risposta", + "Try it out!":"Provalo!", + "Show/Hide":"Mostra/Nascondi", + "List Operations":"Mostra operazioni", + "Expand Operations":"Espandi operazioni", + "Raw":"Grezzo (raw)", + "can't parse JSON. Raw result":"non è possibile parsare il JSON. Risultato grezzo (raw).", + "Model Schema":"Schema del modello", + "Model":"Modello", + "apply":"applica", + "Username":"Nome utente", + "Password":"Password", + "Terms of service":"Condizioni del servizio", + "Created by":"Creato da", + "See more at":"Informazioni aggiuntive:", + "Contact the developer":"Contatta lo sviluppatore", + "api version":"versione api", + "Response Content Type":"Tipo di contenuto (content type) della risposta", + "fetching resource":"recuperando la risorsa", + "fetching resource list":"recuperando lista risorse", + "Explore":"Esplora", + "Show Swagger Petstore Example Apis":"Mostra le api di esempio di Swagger Petstore", + "Can't read from server. It may not have the appropriate access-control-origin settings.":"Non è possibile leggere dal server. Potrebbe non avere le impostazioni di controllo accesso origine (access-control-origin) appropriate.", + "Please specify the protocol for":"Si prega di specificare il protocollo per", + "Can't read swagger JSON from":"Impossibile leggere JSON swagger da:", + "Finished Loading Resource Information. Rendering Swagger UI":"Lettura informazioni risorse termianta. Swagger UI viene mostrata", + "Unable to read api":"Impossibile leggere la api", + "from path":"da cartella", + "server returned":"il server ha restituito" +}); diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/ja.js b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/ja.js new file mode 100644 index 00000000000..3207bfc0baf --- /dev/null +++ b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/ja.js @@ -0,0 +1,53 @@ +'use strict'; + +/* jshint quotmark: double */ +window.SwaggerTranslator.learn({ + "Warning: Deprecated":"警告: 廃止予定", + "Implementation Notes":"実装メモ", + "Response Class":"レスポンスクラス", + "Status":"ステータス", + "Parameters":"パラメータ群", + "Parameter":"パラメータ", + "Value":"値", + "Description":"説明", + "Parameter Type":"パラメータタイプ", + "Data Type":"データタイプ", + "Response Messages":"レスポンスメッセージ", + "HTTP Status Code":"HTTPステータスコード", + "Reason":"理由", + "Response Model":"レスポンスモデル", + "Request URL":"リクエストURL", + "Response Body":"レスポンスボディ", + "Response Code":"レスポンスコード", + "Response Headers":"レスポンスヘッダ", + "Hide Response":"レスポンスを隠す", + "Headers":"ヘッダ", + "Try it out!":"実際に実行!", + "Show/Hide":"表示/非表示", + "List Operations":"操作一覧", + "Expand Operations":"操作の展開", + "Raw":"Raw", + "can't parse JSON. Raw result":"JSONへ解釈できません. 未加工の結果", + "Model Schema":"モデルスキーマ", + "Model":"モデル", + "apply":"実行", + "Username":"ユーザ名", + "Password":"パスワード", + "Terms of service":"サービス利用規約", + "Created by":"Created by", + "See more at":"See more at", + "Contact the developer":"開発者に連絡", + "api version":"APIバージョン", + "Response Content Type":"レスポンス コンテンツタイプ", + "fetching resource":"リソースの取得", + "fetching resource list":"リソース一覧の取得", + "Explore":"Explore", + "Show Swagger Petstore Example Apis":"SwaggerペットストアAPIの表示", + "Can't read from server. It may not have the appropriate access-control-origin settings.":"サーバから読み込めません. 適切なaccess-control-origin設定を持っていない可能性があります.", + "Please specify the protocol for":"プロトコルを指定してください", + "Can't read swagger JSON from":"次からswagger JSONを読み込めません", + "Finished Loading Resource Information. Rendering Swagger UI":"リソース情報の読み込みが完了しました. Swagger UIを描画しています", + "Unable to read api":"APIを読み込めません", + "from path":"次のパスから", + "server returned":"サーバからの返答" +}); diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/pl.js b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/pl.js new file mode 100644 index 00000000000..ce41e91799d --- /dev/null +++ b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/pl.js @@ -0,0 +1,53 @@ +'use strict'; + +/* jshint quotmark: double */ +window.SwaggerTranslator.learn({ + "Warning: Deprecated":"Uwaga: Wycofane", + "Implementation Notes":"Uwagi Implementacji", + "Response Class":"Klasa Odpowiedzi", + "Status":"Status", + "Parameters":"Parametry", + "Parameter":"Parametr", + "Value":"Wartość", + "Description":"Opis", + "Parameter Type":"Typ Parametru", + "Data Type":"Typ Danych", + "Response Messages":"Wiadomości Odpowiedzi", + "HTTP Status Code":"Kod Statusu HTTP", + "Reason":"Przyczyna", + "Response Model":"Model Odpowiedzi", + "Request URL":"URL Wywołania", + "Response Body":"Treść Odpowiedzi", + "Response Code":"Kod Odpowiedzi", + "Response Headers":"Nagłówki Odpowiedzi", + "Hide Response":"Ukryj Odpowiedź", + "Headers":"Nagłówki", + "Try it out!":"Wypróbuj!", + "Show/Hide":"Pokaż/Ukryj", + "List Operations":"Lista Operacji", + "Expand Operations":"Rozwiń Operacje", + "Raw":"Nieprzetworzone", + "can't parse JSON. Raw result":"nie można przetworzyć pliku JSON. Nieprzetworzone dane", + "Model Schema":"Schemat Modelu", + "Model":"Model", + "apply":"użyj", + "Username":"Nazwa użytkownika", + "Password":"Hasło", + "Terms of service":"Warunki używania", + "Created by":"Utworzone przez", + "See more at":"Zobacz więcej na", + "Contact the developer":"Kontakt z deweloperem", + "api version":"wersja api", + "Response Content Type":"Typ Zasobu Odpowiedzi", + "fetching resource":"ładowanie zasobu", + "fetching resource list":"ładowanie listy zasobów", + "Explore":"Eksploruj", + "Show Swagger Petstore Example Apis":"Pokaż Przykładowe Api Swagger Petstore", + "Can't read from server. It may not have the appropriate access-control-origin settings.":"Brak połączenia z serwerem. Może on nie mieć odpowiednich ustawień access-control-origin.", + "Please specify the protocol for":"Proszę podać protokół dla", + "Can't read swagger JSON from":"Nie można odczytać swagger JSON z", + "Finished Loading Resource Information. Rendering Swagger UI":"Ukończono Ładowanie Informacji o Zasobie. Renderowanie Swagger UI", + "Unable to read api":"Nie można odczytać api", + "from path":"ze ścieżki", + "server returned":"serwer zwrócił" +}); diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/pt.js b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/pt.js new file mode 100644 index 00000000000..f2e7c13d413 --- /dev/null +++ b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/pt.js @@ -0,0 +1,53 @@ +'use strict'; + +/* jshint quotmark: double */ +window.SwaggerTranslator.learn({ + "Warning: Deprecated":"Aviso: Depreciado", + "Implementation Notes":"Notas de Implementação", + "Response Class":"Classe de resposta", + "Status":"Status", + "Parameters":"Parâmetros", + "Parameter":"Parâmetro", + "Value":"Valor", + "Description":"Descrição", + "Parameter Type":"Tipo de parâmetro", + "Data Type":"Tipo de dados", + "Response Messages":"Mensagens de resposta", + "HTTP Status Code":"Código de status HTTP", + "Reason":"Razão", + "Response Model":"Modelo resposta", + "Request URL":"URL requisição", + "Response Body":"Corpo da resposta", + "Response Code":"Código da resposta", + "Response Headers":"Cabeçalho da resposta", + "Headers":"Cabeçalhos", + "Hide Response":"Esconder resposta", + "Try it out!":"Tente agora!", + "Show/Hide":"Mostrar/Esconder", + "List Operations":"Listar operações", + "Expand Operations":"Expandir operações", + "Raw":"Cru", + "can't parse JSON. Raw result":"Falha ao analisar JSON. Resulto cru", + "Model Schema":"Modelo esquema", + "Model":"Modelo", + "apply":"Aplicar", + "Username":"Usuário", + "Password":"Senha", + "Terms of service":"Termos do serviço", + "Created by":"Criado por", + "See more at":"Veja mais em", + "Contact the developer":"Contate o desenvolvedor", + "api version":"Versão api", + "Response Content Type":"Tipo de conteúdo da resposta", + "fetching resource":"busca recurso", + "fetching resource list":"buscando lista de recursos", + "Explore":"Explorar", + "Show Swagger Petstore Example Apis":"Show Swagger Petstore Example Apis", + "Can't read from server. It may not have the appropriate access-control-origin settings.":"Não é possível ler do servidor. Pode não ter as apropriadas configurações access-control-origin", + "Please specify the protocol for":"Por favor especifique o protocolo", + "Can't read swagger JSON from":"Não é possível ler o JSON Swagger de", + "Finished Loading Resource Information. Rendering Swagger UI":"Carregar informação de recurso finalizada. Renderizando Swagger UI", + "Unable to read api":"Não foi possível ler api", + "from path":"do caminho", + "server returned":"servidor retornou" +}); diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/ru.js b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/ru.js new file mode 100644 index 00000000000..381f1b3fd0d --- /dev/null +++ b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/ru.js @@ -0,0 +1,55 @@ +'use strict'; + +/* jshint quotmark: double */ +window.SwaggerTranslator.learn({ + "Warning: Deprecated":"Предупреждение: Устарело", + "Implementation Notes":"Заметки", + "Response Class":"Пример ответа", + "Status":"Статус", + "Parameters":"Параметры", + "Parameter":"Параметр", + "Value":"Значение", + "Description":"Описание", + "Parameter Type":"Тип параметра", + "Data Type":"Тип данных", + "HTTP Status Code":"HTTP код", + "Reason":"Причина", + "Response Model":"Структура ответа", + "Request URL":"URL запроса", + "Response Body":"Тело ответа", + "Response Code":"HTTP код ответа", + "Response Headers":"Заголовки ответа", + "Hide Response":"Спрятать ответ", + "Headers":"Заголовки", + "Response Messages":"Что может прийти в ответ", + "Try it out!":"Попробовать!", + "Show/Hide":"Показать/Скрыть", + "List Operations":"Операции кратко", + "Expand Operations":"Операции подробно", + "Raw":"В сыром виде", + "can't parse JSON. Raw result":"Не удается распарсить ответ:", + "Model Schema":"Структура", + "Model":"Описание", + "Click to set as parameter value":"Нажмите, чтобы испльзовать в качестве значения параметра", + "apply":"применить", + "Username":"Имя пользователя", + "Password":"Пароль", + "Terms of service":"Условия использования", + "Created by":"Разработано", + "See more at":"Еще тут", + "Contact the developer":"Связаться с разработчиком", + "api version":"Версия API", + "Response Content Type":"Content Type ответа", + "Parameter content type:":"Content Type параметра:", + "fetching resource":"Получение ресурса", + "fetching resource list":"Получение ресурсов", + "Explore":"Показать", + "Show Swagger Petstore Example Apis":"Показать примеры АПИ", + "Can't read from server. It may not have the appropriate access-control-origin settings.":"Не удается получить ответ от сервера. Возможно, проблема с настройками доступа", + "Please specify the protocol for":"Пожалуйста, укажите протокол для", + "Can't read swagger JSON from":"Не получается прочитать swagger json из", + "Finished Loading Resource Information. Rendering Swagger UI":"Загрузка информации о ресурсах завершена. Рендерим", + "Unable to read api":"Не удалось прочитать api", + "from path":"по адресу", + "server returned":"сервер сказал" +}); diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/tr.js b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/tr.js new file mode 100644 index 00000000000..16426a9c34b --- /dev/null +++ b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/tr.js @@ -0,0 +1,53 @@ +'use strict'; + +/* jshint quotmark: double */ +window.SwaggerTranslator.learn({ + "Warning: Deprecated":"Uyarı: Deprecated", + "Implementation Notes":"Gerçekleştirim Notları", + "Response Class":"Dönen Sınıf", + "Status":"Statü", + "Parameters":"Parametreler", + "Parameter":"Parametre", + "Value":"Değer", + "Description":"Açıklama", + "Parameter Type":"Parametre Tipi", + "Data Type":"Veri Tipi", + "Response Messages":"Dönüş Mesajı", + "HTTP Status Code":"HTTP Statü Kodu", + "Reason":"Gerekçe", + "Response Model":"Dönüş Modeli", + "Request URL":"İstek URL", + "Response Body":"Dönüş İçeriği", + "Response Code":"Dönüş Kodu", + "Response Headers":"Dönüş Üst Bilgileri", + "Hide Response":"Dönüşü Gizle", + "Headers":"Üst Bilgiler", + "Try it out!":"Dene!", + "Show/Hide":"Göster/Gizle", + "List Operations":"Operasyonları Listele", + "Expand Operations":"Operasyonları Aç", + "Raw":"Ham", + "can't parse JSON. Raw result":"JSON çözümlenemiyor. Ham sonuç", + "Model Schema":"Model Şema", + "Model":"Model", + "apply":"uygula", + "Username":"Kullanıcı Adı", + "Password":"Parola", + "Terms of service":"Servis şartları", + "Created by":"Oluşturan", + "See more at":"Daha fazlası için", + "Contact the developer":"Geliştirici ile İletişime Geçin", + "api version":"api versiyon", + "Response Content Type":"Dönüş İçerik Tipi", + "fetching resource":"kaynak getiriliyor", + "fetching resource list":"kaynak listesi getiriliyor", + "Explore":"Keşfet", + "Show Swagger Petstore Example Apis":"Swagger Petstore Örnek Api'yi Gör", + "Can't read from server. It may not have the appropriate access-control-origin settings.":"Sunucudan okuma yapılamıyor. Sunucu access-control-origin ayarlarınızı kontrol edin.", + "Please specify the protocol for":"Lütfen istenen adres için protokol belirtiniz", + "Can't read swagger JSON from":"Swagger JSON bu kaynaktan okunamıyor", + "Finished Loading Resource Information. Rendering Swagger UI":"Kaynak baglantısı tamamlandı. Swagger UI gösterime hazırlanıyor", + "Unable to read api":"api okunamadı", + "from path":"yoldan", + "server returned":"sunucuya dönüldü" +}); diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/translator.js b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/translator.js new file mode 100644 index 00000000000..591f6d40943 --- /dev/null +++ b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/translator.js @@ -0,0 +1,39 @@ +'use strict'; + +/** + * Translator for documentation pages. + * + * To enable translation you should include one of language-files in your index.html + * after . + * For example - + * + * If you wish to translate some new texsts you should do two things: + * 1. Add a new phrase pair ("New Phrase": "New Translation") into your language file (for example lang/ru.js). It will be great if you add it in other language files too. + * 2. Mark that text it templates this way New Phrase or . + * The main thing here is attribute data-sw-translate. Only inner html, title-attribute and value-attribute are going to translate. + * + */ +window.SwaggerTranslator = { + + _words:[], + + translate: function(sel) { + var $this = this; + sel = sel || '[data-sw-translate]'; + + $(sel).each(function() { + $(this).html($this._tryTranslate($(this).html())); + + $(this).val($this._tryTranslate($(this).val())); + $(this).attr('title', $this._tryTranslate($(this).attr('title'))); + }); + }, + + _tryTranslate: function(word) { + return this._words[$.trim(word)] !== undefined ? this._words[$.trim(word)] : word; + }, + + learn: function(wordsMap) { + this._words = wordsMap; + } +}; diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/zh-cn.js b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/zh-cn.js new file mode 100644 index 00000000000..570319ba156 --- /dev/null +++ b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lang/zh-cn.js @@ -0,0 +1,53 @@ +'use strict'; + +/* jshint quotmark: double */ +window.SwaggerTranslator.learn({ + "Warning: Deprecated":"警告:已过时", + "Implementation Notes":"实现备注", + "Response Class":"响应类", + "Status":"状态", + "Parameters":"参数", + "Parameter":"参数", + "Value":"值", + "Description":"描述", + "Parameter Type":"参数类型", + "Data Type":"数据类型", + "Response Messages":"响应消息", + "HTTP Status Code":"HTTP状态码", + "Reason":"原因", + "Response Model":"响应模型", + "Request URL":"请求URL", + "Response Body":"响应体", + "Response Code":"响应码", + "Response Headers":"响应头", + "Hide Response":"隐藏响应", + "Headers":"头", + "Try it out!":"试一下!", + "Show/Hide":"显示/隐藏", + "List Operations":"显示操作", + "Expand Operations":"展开操作", + "Raw":"原始", + "can't parse JSON. Raw result":"无法解析JSON. 原始结果", + "Model Schema":"模型架构", + "Model":"模型", + "apply":"应用", + "Username":"用户名", + "Password":"密码", + "Terms of service":"服务条款", + "Created by":"创建者", + "See more at":"查看更多:", + "Contact the developer":"联系开发者", + "api version":"api版本", + "Response Content Type":"响应Content Type", + "fetching resource":"正在获取资源", + "fetching resource list":"正在获取资源列表", + "Explore":"浏览", + "Show Swagger Petstore Example Apis":"显示 Swagger Petstore 示例 Apis", + "Can't read from server. It may not have the appropriate access-control-origin settings.":"无法从服务器读取。可能没有正确设置access-control-origin。", + "Please specify the protocol for":"请指定协议:", + "Can't read swagger JSON from":"无法读取swagger JSON于", + "Finished Loading Resource Information. Rendering Swagger UI":"已加载资源信息。正在渲染Swagger UI", + "Unable to read api":"无法读取api", + "from path":"从路径", + "server returned":"服务器返回" +}); diff --git a/htdocs/includes/restler/framework/Luracast/Restler/explorer/lib/backbone-min.js b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lib/backbone-min.js index c1c0d4fff28..a3f544be6d9 100644 --- a/htdocs/includes/restler/framework/Luracast/Restler/explorer/lib/backbone-min.js +++ b/htdocs/includes/restler/framework/Luracast/Restler/explorer/lib/backbone-min.js @@ -1,38 +1,15 @@ -// Backbone.js 0.9.2 +// Backbone.js 1.1.2 -// (c) 2010-2012 Jeremy Ashkenas, DocumentCloud Inc. -// Backbone may be freely distributed under the MIT license. -// For all details and documentation: -// http://backbonejs.org -(function(){var l=this,y=l.Backbone,z=Array.prototype.slice,A=Array.prototype.splice,g;g="undefined"!==typeof exports?exports:l.Backbone={};g.VERSION="0.9.2";var f=l._;!f&&"undefined"!==typeof require&&(f=require("underscore"));var i=l.jQuery||l.Zepto||l.ender;g.setDomLibrary=function(a){i=a};g.noConflict=function(){l.Backbone=y;return this};g.emulateHTTP=!1;g.emulateJSON=!1;var p=/\s+/,k=g.Events={on:function(a,b,c){var d,e,f,g,j;if(!b)return this;a=a.split(p);for(d=this._callbacks||(this._callbacks= -{});e=a.shift();)f=(j=d[e])?j.tail:{},f.next=g={},f.context=c,f.callback=b,d[e]={tail:g,next:j?j.next:f};return this},off:function(a,b,c){var d,e,h,g,j,q;if(e=this._callbacks){if(!a&&!b&&!c)return delete this._callbacks,this;for(a=a?a.split(p):f.keys(e);d=a.shift();)if(h=e[d],delete e[d],h&&(b||c))for(g=h.tail;(h=h.next)!==g;)if(j=h.callback,q=h.context,b&&j!==b||c&&q!==c)this.on(d,j,q);return this}},trigger:function(a){var b,c,d,e,f,g;if(!(d=this._callbacks))return this;f=d.all;a=a.split(p);for(g= -z.call(arguments,1);b=a.shift();){if(c=d[b])for(e=c.tail;(c=c.next)!==e;)c.callback.apply(c.context||this,g);if(c=f){e=c.tail;for(b=[b].concat(g);(c=c.next)!==e;)c.callback.apply(c.context||this,b)}}return this}};k.bind=k.on;k.unbind=k.off;var o=g.Model=function(a,b){var c;a||(a={});b&&b.parse&&(a=this.parse(a));if(c=n(this,"defaults"))a=f.extend({},c,a);b&&b.collection&&(this.collection=b.collection);this.attributes={};this._escapedAttributes={};this.cid=f.uniqueId("c");this.changed={};this._silent= -{};this._pending={};this.set(a,{silent:!0});this.changed={};this._silent={};this._pending={};this._previousAttributes=f.clone(this.attributes);this.initialize.apply(this,arguments)};f.extend(o.prototype,k,{changed:null,_silent:null,_pending:null,idAttribute:"id",initialize:function(){},toJSON:function(){return f.clone(this.attributes)},get:function(a){return this.attributes[a]},escape:function(a){var b;if(b=this._escapedAttributes[a])return b;b=this.get(a);return this._escapedAttributes[a]=f.escape(null== -b?"":""+b)},has:function(a){return null!=this.get(a)},set:function(a,b,c){var d,e;f.isObject(a)||null==a?(d=a,c=b):(d={},d[a]=b);c||(c={});if(!d)return this;d instanceof o&&(d=d.attributes);if(c.unset)for(e in d)d[e]=void 0;if(!this._validate(d,c))return!1;this.idAttribute in d&&(this.id=d[this.idAttribute]);var b=c.changes={},h=this.attributes,g=this._escapedAttributes,j=this._previousAttributes||{};for(e in d){a=d[e];if(!f.isEqual(h[e],a)||c.unset&&f.has(h,e))delete g[e],(c.silent?this._silent: -b)[e]=!0;c.unset?delete h[e]:h[e]=a;!f.isEqual(j[e],a)||f.has(h,e)!=f.has(j,e)?(this.changed[e]=a,c.silent||(this._pending[e]=!0)):(delete this.changed[e],delete this._pending[e])}c.silent||this.change(c);return this},unset:function(a,b){(b||(b={})).unset=!0;return this.set(a,null,b)},clear:function(a){(a||(a={})).unset=!0;return this.set(f.clone(this.attributes),a)},fetch:function(a){var a=a?f.clone(a):{},b=this,c=a.success;a.success=function(d,e,f){if(!b.set(b.parse(d,f),a))return!1;c&&c(b,d)}; -a.error=g.wrapError(a.error,b,a);return(this.sync||g.sync).call(this,"read",this,a)},save:function(a,b,c){var d,e;f.isObject(a)||null==a?(d=a,c=b):(d={},d[a]=b);c=c?f.clone(c):{};if(c.wait){if(!this._validate(d,c))return!1;e=f.clone(this.attributes)}a=f.extend({},c,{silent:!0});if(d&&!this.set(d,c.wait?a:c))return!1;var h=this,i=c.success;c.success=function(a,b,e){b=h.parse(a,e);if(c.wait){delete c.wait;b=f.extend(d||{},b)}if(!h.set(b,c))return false;i?i(h,a):h.trigger("sync",h,a,c)};c.error=g.wrapError(c.error, -h,c);b=this.isNew()?"create":"update";b=(this.sync||g.sync).call(this,b,this,c);c.wait&&this.set(e,a);return b},destroy:function(a){var a=a?f.clone(a):{},b=this,c=a.success,d=function(){b.trigger("destroy",b,b.collection,a)};if(this.isNew())return d(),!1;a.success=function(e){a.wait&&d();c?c(b,e):b.trigger("sync",b,e,a)};a.error=g.wrapError(a.error,b,a);var e=(this.sync||g.sync).call(this,"delete",this,a);a.wait||d();return e},url:function(){var a=n(this,"urlRoot")||n(this.collection,"url")||t(); -return this.isNew()?a:a+("/"==a.charAt(a.length-1)?"":"/")+encodeURIComponent(this.id)},parse:function(a){return a},clone:function(){return new this.constructor(this.attributes)},isNew:function(){return null==this.id},change:function(a){a||(a={});var b=this._changing;this._changing=!0;for(var c in this._silent)this._pending[c]=!0;var d=f.extend({},a.changes,this._silent);this._silent={};for(c in d)this.trigger("change:"+c,this,this.get(c),a);if(b)return this;for(;!f.isEmpty(this._pending);){this._pending= -{};this.trigger("change",this,a);for(c in this.changed)!this._pending[c]&&!this._silent[c]&&delete this.changed[c];this._previousAttributes=f.clone(this.attributes)}this._changing=!1;return this},hasChanged:function(a){return!arguments.length?!f.isEmpty(this.changed):f.has(this.changed,a)},changedAttributes:function(a){if(!a)return this.hasChanged()?f.clone(this.changed):!1;var b,c=!1,d=this._previousAttributes,e;for(e in a)if(!f.isEqual(d[e],b=a[e]))(c||(c={}))[e]=b;return c},previous:function(a){return!arguments.length|| -!this._previousAttributes?null:this._previousAttributes[a]},previousAttributes:function(){return f.clone(this._previousAttributes)},isValid:function(){return!this.validate(this.attributes)},_validate:function(a,b){if(b.silent||!this.validate)return!0;var a=f.extend({},this.attributes,a),c=this.validate(a,b);if(!c)return!0;b&&b.error?b.error(this,c,b):this.trigger("error",this,c,b);return!1}});var r=g.Collection=function(a,b){b||(b={});b.model&&(this.model=b.model);b.comparator&&(this.comparator=b.comparator); -this._reset();this.initialize.apply(this,arguments);a&&this.reset(a,{silent:!0,parse:b.parse})};f.extend(r.prototype,k,{model:o,initialize:function(){},toJSON:function(a){return this.map(function(b){return b.toJSON(a)})},add:function(a,b){var c,d,e,g,i,j={},k={},l=[];b||(b={});a=f.isArray(a)?a.slice():[a];c=0;for(d=a.length;c=b))this.iframe=i('\') + .dialog({ + autoOpen: false, + modal: true, + height: 500, + width: \'80%\', + title: "'.dol_escape_js($langs->trans("FileManager")).'" + }); + $dialog.dialog(\'open\'); + }); + }); + '; + */ } print ''; - // Button for websites + // Button for website print ''; $urlext=$virtualurl; - $urlint=$urlwithroot.'/public/websites/index.php?website='.$website; + $urlint=$urlwithroot.'/public/website/index.php?website='.$website; print 'transnoentitiesnoconv("Site"), $langs->transnoentitiesnoconv("Site"), $dataroot, $urlext)).'">'; print $form->textwithpicto('', $langs->trans("PreviewSiteServedByWebServer", $langs->transnoentitiesnoconv("Site"), $langs->transnoentitiesnoconv("Site"), $dataroot, $urlext?$urlext:''.$langs->trans("VirtualHostUrlNotDefined").''), 1, 'preview_ext'); print ''; } - if (in_array($action, array('editcss','editmenu','editmedias'))) + if (in_array($action, array('editcss','editmenu','file_manager'))) { - if (preg_match('/^create/',$action) && $action != 'editmedias') print ''; - if (preg_match('/^edit/',$action) && $action != 'editmedias') print ''; + if (preg_match('/^create/',$action) && $action != 'file_manager') print ''; + if (preg_match('/^edit/',$action) && $action != 'file_manager') print ''; if ($action != 'preview') print ''; } @@ -1235,7 +1415,7 @@ if (count($object->records) > 0) // ***** Part for pages - if ($website && ! in_array($action, array('editcss','editmenu','editmedias'))) + if ($website && ! in_array($action, array('editcss','editmenu'))) { print ''; // Close current websitebar to open a new one @@ -1245,22 +1425,23 @@ if (count($object->records) > 0) print '
    '; - print '
    '; - print ''; + print '
    '; + print $langs->trans("PageContainer").': '; print '
    '; print '
    '; - print $langs->trans("Page").': '; + print ''; print '
    '; + print '
    '; - if ($action != 'add') + if ($action != 'addcontainer') { $out=''; $out.=''; + //print ''; + print ''; if ($action == 'preview' || $action == 'createfromclone' || $action == 'createpagefromclone') { $disabled=''; - if (empty($user->rights->websites->write)) $disabled=' disabled="disabled"'; + if (empty($user->rights->website->write)) $disabled=' disabled="disabled"'; // Confirmation to clone if ($action == 'createfromclone') { // Create an array for form $formquestion = array( - array('type' => 'text', 'name' => 'siteref', 'label'=> $langs->trans("Website") ,'value'=> 'copy_of_'.$object->ref), + array('type' => 'text', 'name' => 'siteref', 'label'=> $langs->trans("WebSite") ,'value'=> 'copy_of_'.$object->ref), //array('type' => 'checkbox', 'name' => 'is_a_translation', 'label' => $langs->trans("SiteIsANewTranslation"), 'value' => 0), //array('type' => 'other','name' => 'newlang','label' => $langs->trans("Language"), 'value' => $formadmin->select_language(GETPOST('newlang', 'az09')?GETPOST('newlang', 'az09'):$langs->defaultlang, 'newlang', 0, null, '', 0, 0, 'minwidth200')), - //array('type' => 'other','name' => 'newwebsite','label' => $langs->trans("Website"), 'value' => $formwebsite->selectWebsite($object->id, 'newwebsite', 0)) + //array('type' => 'other','name' => 'newwebsite','label' => $langs->trans("WebSite"), 'value' => $formwebsite->selectWebsite($object->id, 'newwebsite', 0)) ); $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id='.$object->id, $langs->trans('CloneSite'), '', 'confirm_createfromclone', $formquestion, 0, 1, 200); @@ -1321,23 +1504,23 @@ if (count($object->records) > 0) $formquestion = array( array('type' => 'text', 'name' => 'pageurl', 'label'=> $langs->trans("WEBSITE_PAGENAME") ,'value'=> 'copy_of_'.$objectpage->pageurl), array('type' => 'checkbox', 'name' => 'is_a_translation', 'label' => $langs->trans("PageIsANewTranslation"), 'value' => 0), - array('type' => 'other','name' => 'newlang','label' => $langs->trans("Language"), 'value' => $formadmin->select_language(GETPOST('newlang', 'az09')?GETPOST('newlang', 'az09'):$langs->defaultlang, 'newlang', 0, null, '', 0, 0, 'minwidth200')), - array('type' => 'other','name' => 'newwebsite','label' => $langs->trans("Website"), 'value' => $formwebsite->selectWebsite($object->id, 'newwebsite', 0)) + array('type' => 'other','name' => 'newlang','label' => $langs->trans("Language"), 'value' => $formadmin->select_language(GETPOST('newlang', 'az09')?GETPOST('newlang', 'az09'):$langs->defaultlang, 'newlang', 0, null, 1, 0, 0, 'minwidth200')), + array('type' => 'other','name' => 'newwebsite','label' => $langs->trans("WebSite"), 'value' => $formwebsite->selectWebsite($object->id, 'newwebsite', 0)), ); - $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?pageid=' . $pageid, $langs->trans('ClonePage'), '', 'confirm_createpagefromclone', $formquestion, 0, 1, 250); + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?website='.$object->ref.'&pageid=' . $pageid, $langs->trans('ClonePage'), '', 'confirm_createpagefromclone', $formquestion, 0, 1, 300, 550); print $formconfirm; } print '   '; - print ''; - print ''; - print ''; - if ($object->fk_default_home > 0 && $pageid == $object->fk_default_home) print ''; - else print ''; - print ''; + print ''; + print ''; + print ''; + if ($object->fk_default_home > 0 && $pageid == $object->fk_default_home) print ''; + else print ''; + print ''; print ''; } } @@ -1351,7 +1534,7 @@ if (count($object->records) > 0) $websitepage = new WebSitePage($db); $websitepage->fetch($pageid); - $realpage=$urlwithroot.'/public/websites/index.php?website='.$website.'&pageref='.$websitepage->pageurl; + $realpage=$urlwithroot.'/public/website/index.php?website='.$website.'&pageref='.$websitepage->pageurl; $pagealias = $websitepage->pageurl; print 'transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $realpage)).'">'; @@ -1365,7 +1548,7 @@ if (count($object->records) > 0) print '
    '; $urlext=$virtualurl.'/'.$pagealias.'.php'; - $urlint=$urlwithroot.'/public/websites/index.php?website='.$website; + $urlint=$urlwithroot.'/public/website/index.php?website='.$website; print 'transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $dataroot, $urlext)).'">'; print $form->textwithpicto('', $langs->trans("PreviewSiteServedByWebServer", $langs->transnoentitiesnoconv("Page"), $langs->transnoentitiesnoconv("Page"), $dataroot, $virtualurl?$urlext:''.$langs->trans("VirtualHostUrlNotDefined").''), 1, 'preview_ext'); print ''; @@ -1373,7 +1556,7 @@ if (count($object->records) > 0) // TODO Add js to save alias like we save virtual host name and use dynamic virtual host for url of id=previewpageext } - if (! in_array($action, array('editcss','editmenu','editmedias','createsite','create','createpagefromclone'))) + if (! in_array($action, array('editcss','editmenu','file_manager','createsite','createcontainer','createpagefromclone'))) { if (preg_match('/^create/',$action)) print ''; if (preg_match('/^edit/',$action)) print ''; @@ -1385,8 +1568,8 @@ if (count($object->records) > 0) print '
    '; if (GETPOST('editsource', 'alpha') || GETPOST('editcontent', 'alpha')) { - $htmltext=$langs->transnoentitiesnoconv("YouCanEditHtmlSource"); - print $form->textwithpicto($langs->trans("SyntaxHelp"), $htmltext, 1, 'help', 'inline-block', 0, 2, 'tooltipsubstitution'); + $htmltext=$langs->transnoentitiesnoconv("YouCanEditHtmlSource").'
    '; + print $form->textwithpicto($langs->trans("SyntaxHelp"), $htmltext, 1, 'help', 'inline-block', 1, 2, 'tooltipsubstitution'); } print '
    '; // end websitehelp @@ -1414,7 +1597,7 @@ if (count($object->records) > 0) url: "'.DOL_URL_ROOT.'/core/ajax/saveinplace.php", data: { field: \'editval_virtualhost\', - element: \'websites\', + element: \'website\', table_element: \'website\', fk_element: '.$object->id.', value: newurl, @@ -1440,14 +1623,16 @@ else $action=''; } - print '
    '; // end current websitebar +} + + $head = array(); /* - * Edit mode + * Edit Site HTML header and CSS */ if ($action == 'editcss') @@ -1455,28 +1640,63 @@ if ($action == 'editcss') print '
    '; print '
    '; + if (GETPOST('editcss','alpha') || GETPOST('refreshpage','alpha')) + { + $csscontent = @file_get_contents($filecss); + // Clean the php css file to remove php code and get only css part + $csscontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP \?>\n*/ims', '', $csscontent); + } + else + { + $csscontent = GETPOST('WEBSITE_CSS_INLINE'); + } + if (! trim($csscontent)) $csscontent='/* CSS content (all pages) */'."\n"."body.bodywebsite { margin: 0; font-family: 'Open Sans', sans-serif; }\n.bodywebsite h1 { margin-top: 0; margin-bottom: 0; padding: 10px;}"; - $csscontent = @file_get_contents($filecss); - // Clean the php css file to remove php code and get only css part - $csscontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP \?>\n*/ims', '', $csscontent); - $csscontent.= GETPOST('WEBSITE_CSS_INLINE'); - if (! trim($csscontent)) $csscontent='/* CSS content (all pages) */'."\n".'body.bodywebsite { margin: 0; }'; - - $jscontent = @file_get_contents($filejs); - // Clean the php js file to remove php code and get only js part - $jscontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP \?>\n*/ims', '', $jscontent); - $jscontent.= GETPOST('WEBSITE_JS_INLINE'); + if (GETPOST('editcss','alpha') || GETPOST('refreshpage','alpha')) + { + $jscontent = @file_get_contents($filejs); + // Clean the php js file to remove php code and get only js part + $jscontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP \?>\n*/ims', '', $jscontent); + } + else + { + $jscontent = GETPOST('WEBSITE_JS_INLINE'); + } if (! trim($jscontent)) $jscontent='/* JS content (all pages) */'."\n"; - $htmlheader = @file_get_contents($filehtmlheader); - // Clean the php htmlheader file to remove php code and get only html part - $htmlheader = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP \?>\n*/ims', '', $htmlheader); - if (! trim($htmlheader)) $htmlheader=''; - else $htmlheader=''."\n".trim($htmlheader)."\n".''; + if (GETPOST('editcss','alpha') || GETPOST('refreshpage','alpha')) + { + $htmlheadercontent = @file_get_contents($filehtmlheader); + // Clean the php htmlheader file to remove php code and get only html part + $htmlheadercontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP \?>\n*/ims', '', $htmlheadercontent); + } + else + { + $htmlheadercontent = GETPOST('WEBSITE_HTML_HEADER'); + } + if (! trim($htmlheadercontent)) + { + $htmlheadercontent ="\n"; + $htmlheadercontent.=$htmlheadercontentdefault; + $htmlheadercontent.=""; + } + else + { + $htmlheadercontent = preg_replace('/^\s*/ims', '', $htmlheadercontent); + $htmlheadercontent = preg_replace('/<\/html>\s*$/ims', '', $htmlheadercontent); + $htmlheadercontent=''."\n".trim($htmlheadercontent)."\n".''; + } - $robotcontent = @file_get_contents($filerobot); - // Clean the php htmlheader file to remove php code and get only html part - $robotcontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP \?>\n*/ims', '', $robotcontent); + if (GETPOST('editcss','alpha') || GETPOST('refreshpage','alpha')) + { + $robotcontent = @file_get_contents($filerobot); + // Clean the php htmlheader file to remove php code and get only html part + $robotcontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP \?>\n*/ims', '', $robotcontent); + } + else + { + $robotcontent = GETPOST('WEBSITE_ROBOT'); + } if (! trim($robotcontent)) { $robotcontent.="# Robot file. Generated with ".DOL_APPLICATION_TITLE."\n"; @@ -1485,9 +1705,16 @@ if ($action == 'editcss') $robotcontent.="Disallow: /administrator/\n"; } - $htaccesscontent = @file_get_contents($filehtaccess); - // Clean the php htaccesscontent file to remove php code and get only html part - $htaccesscontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP \?>\n*/ims', '', $htaccesscontent); + if (GETPOST('editcss','alpha') || GETPOST('refreshpage','alpha')) + { + $htaccesscontent = @file_get_contents($filehtaccess); + // Clean the php htaccesscontent file to remove php code and get only html part + $htaccesscontent = preg_replace('/<\?php \/\/ BEGIN PHP[^\?]*END PHP \?>\n*/ims', '', $htaccesscontent); + } + else + { + $htaccesscontent = GETPOST('WEBSITE_HTACCESS'); + } if (! trim($htaccesscontent)) { $htaccesscontent.="# Order allow,deny\n"; @@ -1529,10 +1756,12 @@ if ($action == 'editcss') // Common HTML header print ''; - print $langs->trans('WEBSITE_HTML_HEADER'); + $htmlhelp=$langs->trans("Example").' :
    '; + $htmlhelp.=dol_htmlentitiesbr($htmlheadercontentdefault); + print $form->textwithpicto($langs->trans('WEBSITE_HTML_HEADER'), $htmlhelp, 1, 'help', '', 0, 2, 'htmlheadertooltip'); print ''; - $doleditor=new DolEditor('WEBSITE_HTML_HEADER', $htmlheader, '', '220', 'ace', 'In', true, false, 'ace', 0, '100%', ''); + $doleditor=new DolEditor('WEBSITE_HTML_HEADER', $htmlheadercontent, '', '220', 'ace', 'In', true, false, 'ace', 0, '100%', ''); print $doleditor->Create(1, '', true, 'HTML Header', 'html'); print ''; @@ -1543,7 +1772,7 @@ if ($action == 'editcss') print ''; $doleditor=new DolEditor('WEBSITE_ROBOT', $robotcontent, '', '220', 'ace', 'In', true, false, 'ace', 0, '100%', ''); - print $doleditor->Create(1, '', true, 'Robot file', 'txt'); + print $doleditor->Create(1, '', true, 'Robot file', 'text'); print ''; @@ -1553,7 +1782,7 @@ if ($action == 'editcss') print ''; $doleditor=new DolEditor('WEBSITE_HTACCESS', $htaccesscontent, '', '220', 'ace', 'In', true, false, 'ace', 0, '100%', ''); - print $doleditor->Create(1, '', true, $langs->trans("File").' .htaccess', 'txt'); + print $doleditor->Create(1, '', true, $langs->trans("File").' .htaccess', 'text'); print ''; @@ -1575,14 +1804,14 @@ if ($action == 'createsite') /*$h = 0; $head = array(); - $head[$h][0] = dol_buildpath('/websites/index.php',1).'?id='.$object->id; + $head[$h][0] = dol_buildpath('/website/index.php',1).'?id='.$object->id; $head[$h][1] = $langs->trans("AddSite"); $head[$h][2] = 'card'; $h++; dol_fiche_head($head, 'card', $langs->trans("AddSite"), -1, 'globe'); */ - if ($action == 'create') print_fiche_titre($langs->trans("AddSite")); + if ($action == 'createcontainer') print_fiche_titre($langs->trans("AddSite")); print ''."\n"; //print '
    '; @@ -1605,7 +1834,7 @@ if ($action == 'createsite') print ''; print ''; - print $form->textwithpicto($langs->trans('Virtualhost'), $langs->trans("SetHereVirtualHost", DOL_DATA_ROOT.'/websites/websiteref'), 1, 'help', '', 0, 2, 'tooltipvirtual'); + print $form->textwithpicto($langs->trans('Virtualhost'), $langs->trans("SetHereVirtualHost", DOL_DATA_ROOT.'/website/websiteref'), 1, 'help', '', 0, 2, 'tooltipvirtual'); print ''; print ''; print ''; @@ -1617,7 +1846,7 @@ if ($action == 'createsite') { print '
    '; - print ''; + print ''; print ''; print '
    '; @@ -1633,7 +1862,7 @@ if ($action == 'createsite') print '
    '; } -if ($action == 'editmeta' || $action == 'create') +if ($action == 'editmeta' || $action == 'createcontainer') { print '
    '; @@ -1642,42 +1871,45 @@ if ($action == 'editmeta' || $action == 'create') /*$h = 0; $head = array(); - $head[$h][0] = dol_buildpath('/websites/index.php',1).'?id='.$object->id; + $head[$h][0] = dol_buildpath('/website/index.php',1).'?id='.$object->id; $head[$h][1] = $langs->trans("AddPage"); $head[$h][2] = 'card'; $h++; dol_fiche_head($head, 'card', $langs->trans("AddPage"), -1, 'globe'); */ - if ($action == 'create') print_fiche_titre($langs->trans("AddPage")); + if ($action == 'createcontainer') print_fiche_titre($langs->trans("AddPage")); - print ''."\n"; + print ''."\n"; //print '
    '; - if ($action == 'create') + if ($conf->global->MAIN_FEATURES_LEVEL >= 1) { - print '
    '; + if ($action == 'createcontainer') + { + print '
    '; - print ' * '.$langs->trans("CreateByFetchingExternalPage").'

    '; - print ''; - print ''; - print '
    '; - print $langs->trans("URL"); - print ''; - print ' '; - print ''; - print '
    '; + print ' * '.$langs->trans("CreateByFetchingExternalPage").'

    '; + print ''; + print ''; + print '
    '; + print $langs->trans("URL"); + print ''; + print ' '; + print ''; + print '
    '; - print '
    '; + print '
    '; - print ' * '.$langs->trans("OrEnterPageInfoManually").'

    '; + print ' * '.$langs->trans("OrEnterPageInfoManually").'

    '; + } } print ''; - if ($action != 'create') + if ($action != 'createcontainer') { - print ''; /* @@ -1697,6 +1929,7 @@ if ($action == 'editmeta' || $action == 'create') print ''; */ + $type_container=$objectpage->type_container; $pageurl=$objectpage->pageurl; $pagetitle=$objectpage->title; $pagedescription=$objectpage->description; @@ -1711,6 +1944,13 @@ if ($action == 'editmeta' || $action == 'create') if (GETPOST('WEBSITE_LANG','aZ09')) $pagelang=GETPOST('WEBSITE_LANG','aZ09'); if (GETPOST('htmlheader','none')) $pagehtmlheader=GETPOST('htmlheader','none'); + print ''; + print ''; - print '
    '; + print '
    '; print $langs->trans('IDOfPage'); print ''; print $pageid; @@ -1686,7 +1918,7 @@ if ($action == 'editmeta' || $action == 'create') print '
    '; print $langs->trans('WEBSITE_PAGEURL'); print ''; - print '/public/websites/index.php?website='.urlencode($website).'&pageid='.urlencode($pageid); + print '/public/website/index.php?website='.urlencode($website).'&pageid='.urlencode($pageid); print '
    '; + print $langs->trans('WEBSITE_TYPE_CONTAINER'); + print ''; + $arrayoftype=array('page'=>$langs->trans("Page"), 'banner'=>$langs->trans("Banner"), 'blogpost'=>$langs->trans("BlogPost"), 'other'=>$langs->trans("Other")); + print $form->selectarray('WEBSITE_TYPE_CONTAINER', $arrayoftype, $type_container); + print '
    '; print $langs->trans('WEBSITE_PAGENAME'); print ''; @@ -1738,11 +1978,16 @@ if ($action == 'editmeta' || $action == 'create') print '
    '; print $langs->trans('Language'); print ''; - print $formadmin->select_language($pagelang?$pagelang:$langs->defaultlang, 'WEBSITE_LANG'); + print $formadmin->select_language($pagelang?$pagelang:$langs->defaultlang, 'WEBSITE_LANG', 0, null, '1'); print '
    '; - print $langs->trans('HtmlHeaderPage'); + print '
    '; + $htmlhelp=$langs->trans("EditTheWebSiteForACommonHeader").'

    '; + + $htmlhelp=$langs->trans("Example").' :
    '; + $htmlhelp.=dol_htmlentitiesbr($htmlheadercontentdefault); + + print $form->textwithpicto($langs->trans('HtmlHeaderPage'), $htmlhelp, 1, 'help', '', 0, 2, 'htmlheadertooltip'); print '
    '; $doleditor=new DolEditor('htmlheader', $pagehtmlheader, '', '220', 'ace', 'In', true, false, 'ace', 0, '100%', ''); print $doleditor->Create(1, '', true, 'HTML Header', 'html'); @@ -1750,11 +1995,11 @@ if ($action == 'editmeta' || $action == 'create') print '
    '; - if ($action == 'create') + if ($action == 'createcontainer') { print '
    '; - print ''; + print ''; print ''; print '
    '; @@ -1770,10 +2015,18 @@ if ($action == 'editmeta' || $action == 'create') print '
    '; } -if ($action == 'editmedias') +if ($action == 'editfile' || $action == 'file_manager') { print ''."\n"; - print '
    '.$langs->trans("FeatureNotYetAvailable").''; + print '


    '; + //print '
    '.$langs->trans("FeatureNotYetAvailable").''; + + $module = 'medias'; + if (empty($url)) $url=DOL_URL_ROOT.'/website/index.php'; // Must be an url without param + include DOL_DOCUMENT_ROOT.'/core/tpl/filemanager.tpl.php'; + + print '
    '; + } if ($action == 'editmenu') @@ -1834,27 +2087,47 @@ if ($action == 'preview' || $action == 'createfromclone' || $action == 'createpa $out = ''."\n"; $out.='
    '."\n"; + // TODO Use contenteditable="true" / document.getElementById("myP").contentEditable="true" for part coming from CKEditor // REPLACEMENT OF LINKS When page called by website editor - $out.=')', $objectpage->htmlheader); + $tmpstyleinheader =''; + $i=0; + foreach($tmp as $valtmp) + { + $i++; + if ($i % 2 == 0) $tmpstyleinheader.=$valtmp."\n"; + } + $tmpout.= $tmpstyleinheader."\n"; + // Clean style that may affect global style of Dolibarr + $tmpout=preg_replace('/}[\s\n]*body\s*{[^}]+}/ims','}',$tmpout); + $out.=$tmpout; $out.=''."\n"; + // Do not enable the contenteditable when page was grabbed, ckeditor is removing span and adding borders, + // so editable will be available from container created from scratch + //$out.='
    grabbed_from ? ' contenteditable="true"' : '').'>'."\n"; $out.='
    '."\n"; $out.=dolWebsiteReplacementOfLinks($object, $objectpage->content)."\n"; $out.='
    '; - $out.='
    '; + $out.='
    '; $out.= "\n".''."\n\n"; + // For jqueryscoped (does not work as expected) + //$out.=""; + print $out; /*file_put_contents($filetpl, $out); @@ -1875,7 +2148,7 @@ if ($action == 'preview' || $action == 'createfromclone' || $action == 'createpa //include_once $original_file_osencoded; */ - /*print '';*/ } else @@ -1890,236 +2163,3 @@ if ($action == 'preview' || $action == 'createfromclone' || $action == 'createpa llxFooter(); $db->close(); - - - - -/** - * Save content of a page on disk - * - * @param string $filealias Full path of filename to generate - * @param Website $object Object website - * @param WebsitePage $objectpage Object websitepage - * @return boolean True if OK - */ -function dolSavePageAlias($filealias, $object, $objectpage) -{ - global $conf; - - // Now create the .tpl file (duplicate code with actions updatesource or updatecontent but we need this to save new header) - dol_syslog("We regenerate the alias page filealias=".$filealias); - - $aliascontent = 'id.'.tpl.php\'; '; - $aliascontent.= 'else require $dolibarr_main_data_root.\'/websites/\'.$website->ref.\'/page'.$objectpage->id.'.tpl.php\';'."\n"; - $aliascontent.= '?>'."\n"; - $result = file_put_contents($filealias, $aliascontent); - if (! empty($conf->global->MAIN_UMASK)) - @chmod($filealias, octdec($conf->global->MAIN_UMASK)); - - return ($result?true:false); -} - - -/** - * Save content of a page on disk - * - * @param string $filetpl Full path of filename to generate - * @param Website $object Object website - * @param WebsitePage $objectpage Object websitepage - * @return boolean True if OK - */ -function dolSavePageContent($filetpl, $object, $objectpage) -{ - global $conf; - - // Now create the .tpl file (duplicate code with actions updatesource or updatecontent but we need this to save new header) - dol_syslog("We regenerate the tpl page filetpl=".$filetpl); - - dol_delete_file($filetpl); - - $shortlangcode = ''; - if ($objectpage->lang) $shortlangcode=preg_replace('/[_-].*$/', '', $objectpage->lang); // en_US or en-US -> en - - $tplcontent =''; - $tplcontent.= "\n"; - $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= ''.dol_string_nohtmltag($objectpage->title, 0, 'UTF-8').''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= 'ref.'/htmlheader.html"); ?>'."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= $objectpage->htmlheader."\n"; - $tplcontent.= ''."\n"; - - $tplcontent.= ''."\n"; - $tplcontent.= ''."\n"; - $tplcontent.= $objectpage->content."\n"; - $tplcontent.= ''."\n"; - - $tplcontent.= '"."\n"; - - //var_dump($filetpl);exit; - $result = file_put_contents($filetpl, $tplcontent); - if (! empty($conf->global->MAIN_UMASK)) - @chmod($filetpl, octdec($conf->global->MAIN_UMASK)); - - return $result; -} - - -/** - * Save content of a page on disk - * - * @param string $filehtmlheader Full path of filename to generate - * @param string $htmlheadercontent Content of file - * @return boolean True if OK - */ -function dolSaveHtmlHeader($filehtmlheader, $htmlheadercontent) -{ - global $conf, $pathofwebsite; - - dol_syslog("Save html header into ".$filehtmlheader); - - dol_mkdir($pathofwebsite); - $result = file_put_contents($filehtmlheader, $htmlheadercontent); - if (! empty($conf->global->MAIN_UMASK)) - @chmod($filehtmlheader, octdec($conf->global->MAIN_UMASK)); - - if (! $result) - { - setEventMessages('Failed to write file '.$filehtmlheader, null, 'errors'); - return false; - } - - return true; -} - -/** - * Save content of a page on disk - * - * @param string $filecss Full path of filename to generate - * @param string $csscontent Content of file - * @return boolean True if OK - */ -function dolSaveCssFile($filecss, $csscontent) -{ - global $conf, $pathofwebsite; - - dol_syslog("Save html header into ".$filecss); - - dol_mkdir($pathofwebsite); - $result = file_put_contents($filecss, $csscontent); - if (! empty($conf->global->MAIN_UMASK)) - @chmod($filecss, octdec($conf->global->MAIN_UMASK)); - - if (! $result) - { - setEventMessages('Failed to write file '.$filecss, null, 'errors'); - return false; - } - - return true; -} - -/** - * Save content of a page on disk - * - * @param string $filejs Full path of filename to generate - * @param string $jscontent Content of file - * @return boolean True if OK - */ -function dolSaveJsFile($filejs, $jscontent) -{ - global $conf, $pathofwebsite; - - dol_syslog("Save html header into ".$filejs); - - dol_mkdir($pathofwebsite); - $result = file_put_contents($filejs, $jscontent); - if (! empty($conf->global->MAIN_UMASK)) - @chmod($filejs, octdec($conf->global->MAIN_UMASK)); - - if (! $result) - { - setEventMessages('Failed to write file '.$filejs, null, 'errors'); - return false; - } - - return true; -} - -/** - * Save content of a page on disk - * - * @param string $filerobot Full path of filename to generate - * @param string $robotcontent Content of file - * @return boolean True if OK - */ -function dolSaveRobotFile($filerobot, $robotcontent) -{ - global $conf, $pathofwebsite; - - dol_syslog("Save html header into ".$filerobot); - - dol_mkdir($pathofwebsite); - $result = file_put_contents($filerobot, $robotcontent); - if (! empty($conf->global->MAIN_UMASK)) - @chmod($filerobot, octdec($conf->global->MAIN_UMASK)); - - if (! $result) - { - setEventMessages('Failed to write file '.$filerobot, null, 'errors'); - return false; - } - - return true; -} - -/** - * Save content of a page on disk - * - * @param string $filehtaccess Full path of filename to generate - * @param string $htaccess Content of file - * @return boolean True if OK - */ -function dolSaveHtaccessFile($filehtaccess, $htaccess) -{ - global $conf, $pathofwebsite; - - dol_syslog("Save html header into ".$filehtaccess); - - dol_mkdir($pathofwebsite); - $result = file_put_contents($filehtaccess, $htaccess); - if (! empty($conf->global->MAIN_UMASK)) - @chmod($filehtaccess, octdec($conf->global->MAIN_UMASK)); - - if (! $result) - { - setEventMessages('Failed to write file '.$filehtaccess, null, 'errors'); - return false; - } - - return true; -} - diff --git a/htdocs/website/lib/websiteaccount.lib.php b/htdocs/website/lib/websiteaccount.lib.php new file mode 100644 index 00000000000..95ae071d971 --- /dev/null +++ b/htdocs/website/lib/websiteaccount.lib.php @@ -0,0 +1,85 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/website/lib/websiteaccount.lib.php + * \ingroup website + * \brief Library files with common functions for WebsiteAccount + */ + +/** + * Prepare array of tabs for WebsiteAccount + * + * @param WebsiteAccount $object WebsiteAccount + * @return array Array of tabs + */ +function websiteaccountPrepareHead($object) +{ + global $db, $langs, $conf; + + $langs->load("monmodule@monmodule"); + + $h = 0; + $head = array(); + + $head[$h][0] = dol_buildpath("/website/websiteaccount_card.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans("Card"); + $head[$h][2] = 'card'; + $h++; + + /*if (isset($object->fields['note_public']) || isset($object->fields['note_private'])) + { + $nbNote = 0; + if(!empty($object->fields['note_private'])) $nbNote++; + if(!empty($object->fields['note_public'])) $nbNote++; + $head[$h][0] = dol_buildpath('/monmodule/websiteaccount_note.php', 1).'?id='.$object->id; + $head[$h][1] = $langs->trans('Notes'); + if ($nbNote > 0) $head[$h][1].= ' '.$nbNote.''; + $head[$h][2] = 'note'; + $h++; + }*/ + + /* + require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; + require_once DOL_DOCUMENT_ROOT.'/core/class/link.class.php'; + $upload_dir = $conf->monmodule->dir_output . "/websiteaccount/" . dol_sanitizeFileName($object->ref); + $nbFiles = count(dol_dir_list($upload_dir,'files',0,'','(\.meta|_preview.*\.png)$')); + $nbLinks=Link::count($db, $object->element, $object->id); + $head[$h][0] = dol_buildpath("/monmodule/websiteaccount_document.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans('Documents'); + if (($nbFiles+$nbLinks) > 0) $head[$h][1].= ' '.($nbFiles+$nbLinks).''; + $head[$h][2] = 'document'; + $h++; + + $head[$h][0] = dol_buildpath("/monmodule/websiteaccount_agenda.php", 1).'?id='.$object->id; + $head[$h][1] = $langs->trans("Events"); + $head[$h][2] = 'agenda'; + $h++; + */ + + // Show more tabs from modules + // Entries must be declared in modules descriptor with line + //$this->tabs = array( + // 'entity:+tabname:Title:@monmodule:/monmodule/mypage.php?id=__ID__' + //); // to add new tab + //$this->tabs = array( + // 'entity:-tabname:Title:@monmodule:/monmodule/mypage.php?id=__ID__' + //); // to remove a tab + complete_head_from_modules($conf, $langs, $object, $head, $h, 'websiteaccount@website'); + + return $head; +} diff --git a/htdocs/website/pagetemplate.html b/htdocs/website/pagetemplate.html new file mode 100644 index 00000000000..a6e4e64c871 --- /dev/null +++ b/htdocs/website/pagetemplate.html @@ -0,0 +1,15 @@ +
    +

    __[MAIN_INFO_SOCIETE_NOM]__


    +__(MyContainerTitle)__ +
    +
    +
    +
    +
    __(AnotherContainer)__
    +
    +
    +
    +
    +
    __WEBSITE_CREATE_BY__
    +
    +
    \ No newline at end of file diff --git a/htdocs/website/websiteaccount_card.php b/htdocs/website/websiteaccount_card.php new file mode 100644 index 00000000000..9918b0b3022 --- /dev/null +++ b/htdocs/website/websiteaccount_card.php @@ -0,0 +1,428 @@ + +* + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file htdocs/Website/websiteaccount_card.php + * \ingroup website + * \brief Page to create/edit/view websiteaccount + */ + +//if (! defined('NOREQUIREUSER')) define('NOREQUIREUSER','1'); +//if (! defined('NOREQUIREDB')) define('NOREQUIREDB','1'); +//if (! defined('NOREQUIRESOC')) define('NOREQUIRESOC','1'); +//if (! defined('NOREQUIRETRAN')) define('NOREQUIRETRAN','1'); +//if (! defined('NOSCANGETFORINJECTION')) define('NOSCANGETFORINJECTION','1'); // Do not check anti CSRF attack test +//if (! defined('NOSCANPOSTFORINJECTION')) define('NOSCANPOSTFORINJECTION','1'); // Do not check anti CSRF attack test +//if (! defined('NOCSRFCHECK')) define('NOCSRFCHECK','1'); // Do not check anti CSRF attack test done when option MAIN_SECURITY_CSRF_WITH_TOKEN is on. +//if (! defined('NOSTYLECHECK')) define('NOSTYLECHECK','1'); // Do not check style html tag into posted data +//if (! defined('NOTOKENRENEWAL')) define('NOTOKENRENEWAL','1'); // Do not check anti POST attack test +//if (! defined('NOREQUIREMENU')) define('NOREQUIREMENU','1'); // If there is no need to load and show top and left menu +//if (! defined('NOREQUIREHTML')) define('NOREQUIREHTML','1'); // If we don't need to load the html.form.class.php +//if (! defined('NOREQUIREAJAX')) define('NOREQUIREAJAX','1'); // Do not load ajax.lib.php library +//if (! defined("NOLOGIN")) define("NOLOGIN",'1'); // If this page is public (can be called outside logged session) + +// Load Dolibarr environment +$res=0; +// Try main.inc.php into web root known defined into CONTEXT_DOCUMENT_ROOT (not always defined) +if (! $res && ! empty($_SERVER["CONTEXT_DOCUMENT_ROOT"])) $res=@include($_SERVER["CONTEXT_DOCUMENT_ROOT"]."/main.inc.php"); +// Try main.inc.php into web root detected using web root caluclated from SCRIPT_FILENAME +$tmp=empty($_SERVER['SCRIPT_FILENAME'])?'':$_SERVER['SCRIPT_FILENAME'];$tmp2=realpath(__FILE__); $i=strlen($tmp)-1; $j=strlen($tmp2)-1; +while($i > 0 && $j > 0 && isset($tmp[$i]) && isset($tmp2[$j]) && $tmp[$i]==$tmp2[$j]) { $i--; $j--; } +if (! $res && $i > 0 && file_exists(substr($tmp, 0, ($i+1))."/main.inc.php")) $res=@include(substr($tmp, 0, ($i+1))."/main.inc.php"); +if (! $res && $i > 0 && file_exists(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php")) $res=@include(dirname(substr($tmp, 0, ($i+1)))."/main.inc.php"); +// Try main.inc.php using relative path +if (! $res && file_exists("../main.inc.php")) $res=@include("../main.inc.php"); +if (! $res && file_exists("../../main.inc.php")) $res=@include("../../main.inc.php"); +if (! $res && file_exists("../../../main.inc.php")) $res=@include("../../../main.inc.php"); +if (! $res) die("Include of main fails"); + +include_once(DOL_DOCUMENT_ROOT.'/core/class/html.formcompany.class.php'); +include_once(DOL_DOCUMENT_ROOT.'/core/class/html.formfile.class.php'); +include_once(DOL_DOCUMENT_ROOT.'/website/class/websiteaccount.class.php'); +include_once(DOL_DOCUMENT_ROOT.'/website/lib/websiteaccount.lib.php'); + +// Load traductions files requiredby by page +$langs->loadLangs(array("website","other")); + +// Get parameters +$id = GETPOST('id', 'int'); +$ref = GETPOST('ref', 'alpha'); +$action = GETPOST('action', 'alpha'); +$cancel = GETPOST('cancel', 'aZ09'); +$backtopage = GETPOST('backtopage', 'alpha'); + +// Initialize technical objects +$object=new WebsiteAccount($db); +$extrafields = new ExtraFields($db); +$diroutputmassaction=$conf->website->dir_output . '/temp/massgeneration/'.$user->id; +$hookmanager->initHooks(array('websiteaccountcard')); // Note that conf->hooks_modules contains array +// Fetch optionals attributes and labels +$extralabels = $extrafields->fetch_name_optionals_label('websiteaccount'); +$search_array_options=$extrafields->getOptionalsFromPost($extralabels,'','search_'); + +// Initialize array of search criterias +$search_all=trim(GETPOST("search_all",'alpha')); +$search=array(); +foreach($object->fields as $key => $val) +{ + if (GETPOST('search_'.$key,'alpha')) $search[$key]=GETPOST('search_'.$key,'alpha'); +} + +if (empty($action) && empty($id) && empty($ref)) $action='view'; + +// Security check - Protection if external user +//if ($user->societe_id > 0) access_forbidden(); +//if ($user->societe_id > 0) $socid = $user->societe_id; +//$result = restrictedArea($user, 'website', $id); + +// fetch optionals attributes and labels +$extralabels = $extrafields->fetch_name_optionals_label($object->table_element); + +// Load object +include DOL_DOCUMENT_ROOT.'/core/actions_fetchobject.inc.php'; // Must be include, not include_once // Must be include, not include_once. Include fetch and fetch_thirdparty but not fetch_optionals + + + +/* + * Actions + */ + +$parameters=array(); +$reshook=$hookmanager->executeHooks('doActions',$parameters,$object,$action); // Note that $action and $object may have been modified by some hooks +if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + +if (empty($reshook)) +{ + $error=0; + + $permissiontoadd = $user->rights->website->write; + $permissiontodelete = $user->rights->website->delete; + $backurlforlist = dol_buildpath('/website/websiteaccount_list.php',1); + + // Actions cancel, add, update or delete + include DOL_DOCUMENT_ROOT.'/core/actions_addupdatedelete.inc.php'; + + // Actions when printing a doc from card + include DOL_DOCUMENT_ROOT.'/core/actions_printing.inc.php'; + + // Actions to send emails + $trigger_name='MYOBJECT_SENTBYMAIL'; + $autocopy='MAIN_MAIL_AUTOCOPY_MYOBJECT_TO'; + $trackid='websiteaccount'.$object->id; + include DOL_DOCUMENT_ROOT.'/core/actions_sendmails.inc.php'; +} + + +/* + * View + */ + +$form=new Form($db); +$formfile=new FormFile($db); + +llxHeader('','WebsiteAccount',''); + +// Example : Adding jquery code +print ''; + + +// Part to create +if ($action == 'create') +{ + print load_fiche_titre($langs->trans("NewObject", $langs->transnoentitiesnoconv("WebsiteAccount"))); + + print '
    '; + print ''; + print ''; + print ''; + + dol_fiche_head(); + + print ''."\n"; + + // Common attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_add.tpl.php'; + + // Other attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_add.tpl.php'; + + print '
    '."\n"; + + dol_fiche_end(); + + print '
    '; + print ''; + print '  '; + print ''; // Cancel for create does not post form if we don't know the backtopage + print '
    '; + + print '
    '; +} + +// Part to edit record +if (($id || $ref) && $action == 'edit') +{ + print load_fiche_titre($langs->trans("WebsiteAccount")); + + print '
    '; + print ''; + print ''; + print ''; + + dol_fiche_head(); + + print ''."\n"; + + // Common attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_edit.tpl.php'; + + // Other attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_edit.tpl.php'; + + print '
    '; + + dol_fiche_end(); + + print '
    '; + print '   '; + print '
    '; + + print '
    '; +} + +// Part to show record +if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'create'))) +{ + if ($object->fk_soc >0 && empty($socid)) $socid = $object->fk_soc; + + $res = $object->fetch_optionals($object->id, $extralabels); + + $head = websiteaccountPrepareHead($object); + dol_fiche_head($head, 'card', $langs->trans("WebsiteAccount"), -1, 'websiteaccount@website'); + + $formconfirm = ''; + + // Confirmation to delete + if ($action == 'delete') { + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('DeleteWebsiteAccount'), $langs->trans('ConfirmDeleteWebsiteAccount'), 'confirm_delete', '', 0, 1); + } + + // Confirmation of action xxxx + if ($action == 'xxx') + { + $formquestion=array(); + /* + $formquestion = array( + // 'text' => $langs->trans("ConfirmClone"), + // array('type' => 'checkbox', 'name' => 'clone_content', 'label' => $langs->trans("CloneMainAttributes"), 'value' => 1), + // array('type' => 'checkbox', 'name' => 'update_prices', 'label' => $langs->trans("PuttingPricesUpToDate"), 'value' => 1), + // array('type' => 'other', 'name' => 'idwarehouse', 'label' => $langs->trans("SelectWarehouseForStockDecrease"), 'value' => $formproduct->selectWarehouses(GETPOST('idwarehouse')?GETPOST('idwarehouse'):'ifone', 'idwarehouse', '', 1))); + }*/ + $formconfirm = $form->formconfirm($_SERVER["PHP_SELF"] . '?id=' . $object->id, $langs->trans('XXX'), $text, 'confirm_xxx', $formquestion, 0, 1, 220); + } + + if (! $formconfirm) { + $parameters = array('lineid' => $lineid); + $reshook = $hookmanager->executeHooks('formConfirm', $parameters, $object, $action); // Note that $action and $object may have been modified by hook + if (empty($reshook)) $formconfirm.=$hookmanager->resPrint; + elseif ($reshook > 0) $formconfirm=$hookmanager->resPrint; + } + + // Print form confirm + print $formconfirm; + + + // Object card + // ------------------------------------------------------------ + $linkback=''; + if ($socid) $linkback = '' . $langs->trans("BackToListOfThirdParty") . ''; + if ($fk_website) $linkback = '' . $langs->trans("BackToList") . ''; + + $morehtmlref='
    '; + /* + // Ref bis + $morehtmlref.=$form->editfieldkey("RefBis", 'ref_client', $object->ref_client, $object, $user->rights->website->creer, 'string', '', 0, 1); + $morehtmlref.=$form->editfieldval("RefBis", 'ref_client', $object->ref_client, $object, $user->rights->website->creer, 'string', '', null, null, '', 1); + // Thirdparty + $morehtmlref.='
    '.$langs->trans('ThirdParty') . ' : ' . $soc->getNomUrl(1); + // Project + if (! empty($conf->projet->enabled)) + { + $langs->load("projects"); + $morehtmlref.='
    '.$langs->trans('Project') . ' '; + if ($user->rights->website->creer) + { + if ($action != 'classify') + { + $morehtmlref.='' . img_edit($langs->transnoentitiesnoconv('SetProject')) . ' : '; + if ($action == 'classify') { + //$morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'projectid', 0, 0, 1, 1); + $morehtmlref.='
    '; + $morehtmlref.=''; + $morehtmlref.=''; + $morehtmlref.=$formproject->select_projects($object->socid, $object->fk_project, 'projectid', $maxlength, 0, 1, 0, 1, 0, 0, '', 1); + $morehtmlref.=''; + $morehtmlref.='
    '; + } else { + $morehtmlref.=$form->form_project($_SERVER['PHP_SELF'] . '?id=' . $object->id, $object->socid, $object->fk_project, 'none', 0, 0, 0, 1); + } + } + } else { + if (! empty($object->fk_project)) { + $proj = new Project($db); + $proj->fetch($object->fk_project); + $morehtmlref.=''; + $morehtmlref.=$proj->ref; + $morehtmlref.=''; + } else { + $morehtmlref.=''; + } + } + } + */ + $morehtmlref.='
    '; + + if ($socid > 0) $object->next_prev_filter = 'te.fk_soc = '.$socid; + + dol_banner_tab($object, 'id', $linkback, 1, 'rowid', 'rowid', $morehtmlref); + + + print '
    '; + print '
    '; + print '
    '; + print ''."\n"; + + // Common attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/commonfields_view.tpl.php'; + + // Other attributes + include DOL_DOCUMENT_ROOT . '/core/tpl/extrafields_view.tpl.php'; + + print '
    '; + print '
    '; + print '
    '; + print '
    '; + + print '

    '; + + dol_fiche_end(); + + + // Buttons for actions + if ($action != 'presend' && $action != 'editline') { + print '
    '."\n"; + $parameters=array(); + $reshook=$hookmanager->executeHooks('addMoreActionsButtons',$parameters,$object,$action); // Note that $action and $object may have been modified by hook + if ($reshook < 0) setEventMessages($hookmanager->error, $hookmanager->errors, 'errors'); + + if (empty($reshook)) + { + // Send + print ''."\n"; + + if ($user->rights->website->write) + { + print ''."\n"; + } + + /* + if ($user->rights->sellyoursaas->create) + { + if ($object->status == 1) + { + print ''."\n"; + } + else + { + print ''."\n"; + } + } + */ + + if ($user->rights->website->delete) + { + print ''."\n"; + } + } + print '
    '."\n"; + } + + + // Select mail models is same action as presend + if (GETPOST('modelselected')) { + $action = 'presend'; + } + + if ($action != 'presend') + { + print '
    '; + print ''; // ancre + + // Documents + /*$comref = dol_sanitizeFileName($object->ref); + $relativepath = $comref . '/' . $comref . '.pdf'; + $filedir = $conf->website->dir_output . '/' . $comref; + $urlsource = $_SERVER["PHP_SELF"] . "?id=" . $object->id; + $genallowed = $user->rights->website->read; // If you can read, you can build the PDF to read content + $delallowed = $user->rights->website->create; // If you can create/edit, you can remove a file on card + print $formfile->showdocuments('website', $comref, $filedir, $urlsource, $genallowed, $delallowed, $object->modelpdf, 1, 0, 0, 28, 0, '', '', '', $soc->default_lang); + */ + + // Show links to link elements + /*$linktoelem = $form->showLinkToObjectBlock($object, null, array('websiteaccount')); + $somethingshown = $form->showLinkedObjectBlock($object, $linktoelem); + */ + + print '
    '; + + $MAXEVENT = 10; + + // List of actions on element + /* + include_once DOL_DOCUMENT_ROOT . '/core/class/html.formactions.class.php'; + $formactions = new FormActions($db); + $somethingshown = $formactions->showactions($object, 'websiteaccount', $socid, 1, '', $MAXEVENT); + */ + + print '
    '; + } + + // Presend form + $modelmail='websiteaccount'; + $defaulttopic='Information'; + $diroutput = $conf->website->dir_output; + $trackid = 'websiteaccount'.$object->id; + + include DOL_DOCUMENT_ROOT.'/core/tpl/card_presend.tpl.php'; +} + + +// End of page +llxFooter(); +$db->close(); diff --git a/scripts/bank/export-bank-receipts.php b/scripts/bank/export-bank-receipts.php index ad70190b689..398ec1d7a19 100755 --- a/scripts/bank/export-bank-receipts.php +++ b/scripts/bank/export-bank-receipts.php @@ -262,7 +262,7 @@ if ($resql) $totalbefore = $total; $total = $total + $objp->amount; - + // Date operation $dateop=$db->jdate($objp->do); @@ -289,22 +289,28 @@ if ($resql) { $paymentstatic->fetch($links[$key]['url_id']); $tmparray=$paymentstatic->getBillsArray(''); - foreach($tmparray as $key => $val) + if (is_array($tmparray)) { - $invoicestatic->fetch($val); - if ($accountelem) $accountelem.= ', '; - $accountelem.=$invoicestatic->ref; + foreach($tmparray as $key => $val) + { + $invoicestatic->fetch($val); + if ($accountelem) $accountelem.= ', '; + $accountelem.=$invoicestatic->ref; + } } } elseif ($links[$key]['type']=='payment_supplier') { $paymentsupplierstatic->fetch($links[$key]['url_id']); $tmparray=$paymentsupplierstatic->getBillsArray(''); - foreach($tmparray as $key => $val) + if (is_array($tmparray)) { - $invoicesupplierstatic->fetch($val); - if ($accountelem) $accountelem.= ', '; - $accountelem.=$invoicesupplierstatic->ref; + foreach($tmparray as $key => $val) + { + $invoicesupplierstatic->fetch($val); + if ($accountelem) $accountelem.= ', '; + $accountelem.=$invoicesupplierstatic->ref; + } } } elseif ($links[$key]['type']=='payment_sc') diff --git a/scripts/emailings/mailing-send.php b/scripts/emailings/mailing-send.php index a56c2be2055..ef9a35fc1ed 100755 --- a/scripts/emailings/mailing-send.php +++ b/scripts/emailings/mailing-send.php @@ -113,7 +113,7 @@ if ($resql) // On choisit les mails non deja envoyes pour ce mailing (statut=0) // ou envoyes en erreur (statut=-1) - $sql2 = "SELECT mc.rowid, mc.lastname as lastname, mc.firstname as firstname, mc.email, mc.other, mc.source_url, mc.source_id, mc.source_type, mc.tag"; + $sql2 = "SELECT mc.rowid, mc.fk_mailing, mc.lastname, mc.firstname, mc.email, mc.other, mc.source_url, mc.source_id, mc.source_type, mc.tag"; $sql2.= " FROM ".MAIN_DB_PREFIX."mailing_cibles as mc"; $sql2.= " WHERE mc.statut < 1 AND mc.fk_mailing = ".$id; if ($conf->global->MAILING_LIMIT_SENDBYCLI > 0) @@ -149,13 +149,13 @@ if ($resql) $res=1; $now=dol_now(); - $obj2 = $db->fetch_object($resql2); + $obj = $db->fetch_object($resql2); // sendto en RFC2822 - $sendto = str_replace(',',' ',dolGetFirstLastname($obj2->firstname, $obj2->lastname) ." <".$obj2->email.">"); + $sendto = str_replace(',',' ',dolGetFirstLastname($obj->firstname, $obj->lastname) ." <".$obj->email.">"); // Make subtsitutions on topic and body - $other=explode(';',$obj2->other); + $other=explode(';',$obj->other); $tmpfield=explode('=',$other[0],2); $other1=(isset($tmpfield[1])?$tmpfield[1]:$tmpfield[0]); $tmpfield=explode('=',$other[1],2); $other2=(isset($tmpfield[1])?$tmpfield[1]:$tmpfield[0]); $tmpfield=explode('=',$other[2],2); $other3=(isset($tmpfield[1])?$tmpfield[1]:$tmpfield[0]); @@ -230,7 +230,7 @@ if ($resql) $substitutionisok=true; // Fabrication du mail - $trackid='emailing-'.$obj2->source_type.$obj2->source_id; + $trackid='emailing-'.$obj->fk_mailing.'-'.$obj->rowid; $mail = new CMailFile( $newsubject, $sendto, @@ -277,13 +277,13 @@ if ($resql) // We must union table llx_mailing_taget for event tab OR enter 1 event with a special table link (id of email in event) // Run trigger /* - if ($obj2->source_type == 'contact') + if ($obj->source_type == 'contact') { - $emailing->sendtoid = $obj2->source_id; + $emailing->sendtoid = $obj->source_id; } - if ($obj2->source_type == 'thirdparty') + if ($obj->source_type == 'thirdparty') { - $emailing->socid = $obj2->source_id; + $emailing->socid = $obj->source_id; } // Call trigger $result=$emailing->call_trigger('EMAILING_SENTBYMAIL',$user); @@ -292,7 +292,7 @@ if ($resql) */ $sqlok ="UPDATE ".MAIN_DB_PREFIX."mailing_cibles"; - $sqlok.=" SET statut=1, date_envoi='".$db->idate($now)."' WHERE rowid=".$obj2->rowid; + $sqlok.=" SET statut=1, date_envoi='".$db->idate($now)."' WHERE rowid=".$obj->rowid; $resqlok=$db->query($sqlok); if (! $resqlok) { @@ -305,7 +305,7 @@ if ($resql) if (strpos($message, '__CHECK_READ__') !== false) { //Update status communication of thirdparty prospect - $sqlx = "UPDATE ".MAIN_DB_PREFIX."societe SET fk_stcomm=2 WHERE rowid IN (SELECT source_id FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE rowid=".$obj2->rowid.")"; + $sqlx = "UPDATE ".MAIN_DB_PREFIX."societe SET fk_stcomm=2 WHERE rowid IN (SELECT source_id FROM ".MAIN_DB_PREFIX."mailing_cibles WHERE rowid=".$obj->rowid.")"; dol_syslog("card.php: set prospect thirdparty status", LOG_DEBUG); $resqlx=$db->query($sqlx); if (! $resqlx) @@ -315,7 +315,7 @@ if ($resql) } //Update status communication of contact prospect - $sqlx = "UPDATE ".MAIN_DB_PREFIX."societe SET fk_stcomm=2 WHERE rowid IN (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."socpeople AS sc INNER JOIN ".MAIN_DB_PREFIX."mailing_cibles AS mc ON mc.rowid=".$obj2->rowid." AND mc.source_type = 'contact' AND mc.source_id = sc.rowid)"; + $sqlx = "UPDATE ".MAIN_DB_PREFIX."societe SET fk_stcomm=2 WHERE rowid IN (SELECT sc.fk_soc FROM ".MAIN_DB_PREFIX."socpeople AS sc INNER JOIN ".MAIN_DB_PREFIX."mailing_cibles AS mc ON mc.rowid=".$obj->rowid." AND mc.source_type = 'contact' AND mc.source_id = sc.rowid)"; dol_syslog("card.php: set prospect contact status", LOG_DEBUG); $resqlx=$db->query($sqlx); @@ -340,7 +340,7 @@ if ($resql) dol_syslog("error for emailing id ".$id." #".$i.($mail->error?' - '.$mail->error:''), LOG_DEBUG); $sqlerror="UPDATE ".MAIN_DB_PREFIX."mailing_cibles"; - $sqlerror.=" SET statut=-1, date_envoi=".$db->idate($now)." WHERE rowid=".$obj2->rowid; + $sqlerror.=" SET statut=-1, date_envoi=".$db->idate($now)." WHERE rowid=".$obj->rowid; $resqlerror=$db->query($sqlerror); if (! $resqlerror) { diff --git a/scripts/modulebuilder/builddoc.php b/scripts/modulebuilder/builddoc.php index 2ac8d97ac32..f2c0eef421f 100755 --- a/scripts/modulebuilder/builddoc.php +++ b/scripts/modulebuilder/builddoc.php @@ -40,18 +40,49 @@ if (substr($sapi_type, 0, 3) == 'cgi') { } if (! isset($argv[1]) || ! $argv[1]) { - print "Usage: ".$script_file." inputfile1\n"; + print "Usage: ".$script_file." ModuleName\n"; exit(-1); } -$inputfile1=$argv[1]; +$modulename=$argv[1]; require_once ($path."../../htdocs/master.inc.php"); +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/modulebuilder.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/utils.class.php'; + +$langs->loadLangs(array("admin", "modulebuilder", "other", "cron")); // Global variables $version=DOL_VERSION; $error=0; +// Dir for custom dirs +$tmp=explode(',', $dolibarr_main_document_root_alt); +$dirins = $tmp[0]; +$dirread = $dirins; +$forceddirread = 0; + +$tmpdir = explode('@', $module); +if (! empty($tmpdir[1])) +{ + $module=$tmpdir[0]; + $dirread=$tmpdir[1]; + $forceddirread=1; +} + +$FILEFLAG='modulebuilder.txt'; + +$now=dol_now(); +$newmask = 0; +if (empty($newmask) && ! empty($conf->global->MAIN_UMASK)) $newmask=$conf->global->MAIN_UMASK; +if (empty($newmask)) // This should no happen +{ + $newmask='0664'; +} /* @@ -60,8 +91,21 @@ $error=0; @set_time_limit(0); print "***** ".$script_file." (".$version.") pid=".dol_getmypid()." *****\n"; -print $inputfile1."
    "; +print "modulename=".$modulename."\n"; +print "dirins=".$dirins."\n"; +$FILENAMEDOC=strtolower($module).'.html'; // TODO Use/text PDF +$dirofmodule = dol_buildpath(strtolower($module), 0).'/doc'; +$outputfiledoc = $dirofmodule.'/'.$FILENAMEDOC; +$util = new Utils($db); +$result = $util->generateDoc($module); +if ($result <= 0) +{ + print $util->errors; + exit(1); +} +print $langs->trans("DocFileGeneratedInto", $outputfiledoc); +exit(0); diff --git a/scripts/modulebuilder/initmodule.php b/scripts/modulebuilder/initmodule.php new file mode 100755 index 00000000000..6c9801878d3 --- /dev/null +++ b/scripts/modulebuilder/initmodule.php @@ -0,0 +1,175 @@ +#!/usr/bin/env php + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +/** + * \file scripts/modulebuilder/initmodule.php + * \ingroup modulebuilder + * \brief Script to initialize a module. + */ + + +$sapi_type = php_sapi_name(); +$script_file = basename(__FILE__); +$path=dirname(__FILE__).'/'; + +// Test if batch mode +if (substr($sapi_type, 0, 3) == 'cgi') { + echo "Error: You are using PHP for CGI. To execute ".$script_file." from command line, you must use PHP for CLI mode.\n"; + exit(-1); +} + +if (! isset($argv[1]) || ! $argv[1]) { + print "Usage: ".$script_file." ModuleName\n"; + exit(-1); +} +$modulename=$argv[1]; + +require_once ($path."../../htdocs/master.inc.php"); +require_once DOL_DOCUMENT_ROOT.'/core/lib/files.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/admin.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/html.formadmin.class.php'; +require_once DOL_DOCUMENT_ROOT.'/core/lib/modulebuilder.lib.php'; +require_once DOL_DOCUMENT_ROOT.'/core/class/doleditor.class.php'; + +$langs->loadLangs(array("admin", "modulebuilder", "other", "cron")); + + +// Global variables +$version=DOL_VERSION; +$error=0; + +// Dir for custom dirs +$tmp=explode(',', $dolibarr_main_document_root_alt); +$dirins = $tmp[0]; +$dirread = $dirins; +$forceddirread = 0; + +$tmpdir = explode('@', $module); +if (! empty($tmpdir[1])) +{ + $module=$tmpdir[0]; + $dirread=$tmpdir[1]; + $forceddirread=1; +} + +$FILEFLAG='modulebuilder.txt'; + +$now=dol_now(); +$newmask = 0; +if (empty($newmask) && ! empty($conf->global->MAIN_UMASK)) $newmask=$conf->global->MAIN_UMASK; +if (empty($newmask)) // This should no happen +{ + $newmask='0664'; +} + + +/* + * Main + */ + +@set_time_limit(0); +print "***** ".$script_file." (".$version.") pid=".dol_getmypid()." *****\n"; +print "modulename=".$modulename."\n"; +print "dirins=".$dirins."\n"; + +if (preg_match('/[^a-z0-9_]/i', $modulename)) +{ + $error++; + print 'Error '.$langs->trans("SpaceOrSpecialCharAreNotAllowed")."\n"; + exit(1); +} + +if (! $error) +{ + $srcdir = DOL_DOCUMENT_ROOT.'/modulebuilder/template'; + $destdir = $dirins.'/'.strtolower($modulename); + + $arrayreplacement=array( + 'mymodule'=>strtolower($modulename), + 'MyModule'=>$modulename + ); + + $result = dolCopyDir($srcdir, $destdir, 0, 0, $arrayreplacement); + //dol_mkdir($destfile); + if ($result <= 0) + { + if ($result < 0) + { + $error++; + $langs->load("errors"); + print $langs->trans("ErrorFailToCopyDir", $srcdir, $destdir)."\n"; + exit(2); + } + else // $result == 0 + { + print $langs->trans("AllFilesDidAlreadyExist", $srcdir, $destdir)."\n"; + } + } + + // Delete some files + dol_delete_file($destdir.'/myobject_card.php'); + dol_delete_file($destdir.'/myobject_note.php'); + dol_delete_file($destdir.'/myobject_document.php'); + dol_delete_file($destdir.'/myobject_agenda.php'); + dol_delete_file($destdir.'/myobject_list.php'); + dol_delete_file($destdir.'/lib/myobject.lib.php'); + dol_delete_file($destdir.'/test/phpunit/MyObjectTest.php'); + dol_delete_file($destdir.'/sql/llx_mymodule_myobject.sql'); + dol_delete_file($destdir.'/sql/llx_mymodule_myobject_extrafields.sql'); + dol_delete_file($destdir.'/sql/llx_mymodule_myobject.key.sql'); + dol_delete_file($destdir.'/scripts/myobject.php'); + dol_delete_file($destdir.'/img/object_myobject.png'); + dol_delete_file($destdir.'/class/myobject.class.php'); + dol_delete_file($destdir.'/class/api_mymodule.class.php'); +} + +// Edit PHP files +if (! $error) +{ + $listofphpfilestoedit = dol_dir_list($destdir, 'files', 1, '\.(php|MD|js|sql|txt|xml|lang)$', '', 'fullname', SORT_ASC, 0, 1); + foreach($listofphpfilestoedit as $phpfileval) + { + //var_dump($phpfileval['fullname']); + $arrayreplacement=array( + 'mymodule'=>strtolower($modulename), + 'MyModule'=>$modulename, + 'MYMODULE'=>strtoupper($modulename), + 'My module'=>$modulename, + 'my module'=>$modulename, + 'Mon module'=>$modulename, + 'mon module'=>$modulename, + 'htdocs/modulebuilder/template'=>strtolower($modulename), + '---Put here your own copyright and developer email---'=>dol_print_date($now,'%Y').' '.$user->getFullName($langs).($user->email?' <'.$user->email.'>':'') + ); + + + $result=dolReplaceInFile($phpfileval['fullname'], $arrayreplacement); + //var_dump($result); + if ($result < 0) + { + print $langs->trans("ErrorFailToMakeReplacementInto", $phpfileval['fullname'])."\n"; + exit(3); + } + } +} + +print 'Module initialized'."\n"; +exit(0); + diff --git a/test/phpunit/AllTests.php b/test/phpunit/AllTests.php index 56c5541d0bb..d1f0e8b5158 100644 --- a/test/phpunit/AllTests.php +++ b/test/phpunit/AllTests.php @@ -85,12 +85,16 @@ class AllTests $suite->addTestSuite('CompanyLibTest'); require_once dirname(__FILE__).'/DateLibTest.php'; $suite->addTestSuite('DateLibTest'); + require_once dirname(__FILE__).'/UtilsTest.php'; + $suite->addTestSuite('UtilsTest'); //require_once dirname(__FILE__).'/DateLibTzFranceTest.php'; //$suite->addTestSuite('DateLibTzFranceTest'); require_once dirname(__FILE__).'/MarginsLibTest.php'; $suite->addTestSuite('MarginsLibTest'); require_once dirname(__FILE__).'/FilesLibTest.php'; $suite->addTestSuite('FilesLibTest'); + require_once dirname(__FILE__).'/GetUrlLibTest.php'; + $suite->addTestSuite('GetUrlLibTest'); require_once dirname(__FILE__).'/JsonLibTest.php'; $suite->addTestSuite('JsonLibTest'); require_once dirname(__FILE__).'/ImagesLibTest.php'; @@ -113,6 +117,11 @@ class AllTests require_once dirname(__FILE__).'/SecurityTest.php'; $suite->addTestSuite('SecurityTest'); + require_once dirname(__FILE__).'/UserTest.php'; + $suite->addTestSuite('UserTest'); + require_once dirname(__FILE__).'/UserGroupTest.php'; + $suite->addTestSuite('UserGroupTest'); + require_once dirname(__FILE__).'/NumberingModulesTest.php'; $suite->addTestSuite('NumberingModulesTest'); require_once dirname(__FILE__).'/PgsqlTest.php'; @@ -151,6 +160,9 @@ class AllTests require_once dirname(__FILE__).'/PropalTest.php'; $suite->addTestSuite('PropalTest'); + require_once dirname(__FILE__).'/SupplierProposalTest.php'; + $suite->addTestSuite('SupplierProposalTest'); + require_once dirname(__FILE__).'/CommandeTest.php'; $suite->addTestSuite('CommandeTest'); @@ -166,10 +178,6 @@ class AllTests require_once dirname(__FILE__).'/FactureFournisseurTest.php'; $suite->addTestSuite('FactureFournisseurTest'); - require_once dirname(__FILE__).'/UserTest.php'; - $suite->addTestSuite('UserTest'); - require_once dirname(__FILE__).'/UserGroupTest.php'; - $suite->addTestSuite('UserGroupTest'); require_once dirname(__FILE__).'/BankAccountTest.php'; $suite->addTestSuite('BankAccountTest'); require_once dirname(__FILE__).'/CompanyBankAccountTest.php'; @@ -195,18 +203,22 @@ class AllTests require_once dirname(__FILE__).'/RestAPIUserTest.php'; $suite->addTestSuite('RestAPIUserTest'); - require_once dirname(__FILE__).'/WebservicesProductsTest.php'; - $suite->addTestSuite('WebservicesProductsTest'); - require_once dirname(__FILE__).'/WebservicesInvoicesTest.php'; - $suite->addTestSuite('WebservicesInvoicesTest'); - require_once dirname(__FILE__).'/WebservicesOrdersTest.php'; - $suite->addTestSuite('WebservicesOrdersTest'); - require_once dirname(__FILE__).'/WebservicesOtherTest.php'; - $suite->addTestSuite('WebservicesOtherTest'); - require_once dirname(__FILE__).'/WebservicesThirdpartyTest.php'; - $suite->addTestSuite('WebservicesThirdpartyTest'); - require_once dirname(__FILE__).'/WebservicesUserTest.php'; - $suite->addTestSuite('WebservicesUserTest'); + // Test only with php7.2 or less + //if ((float) phpversion() < 7.3) + //{ + require_once dirname(__FILE__).'/WebservicesProductsTest.php'; + $suite->addTestSuite('WebservicesProductsTest'); + require_once dirname(__FILE__).'/WebservicesInvoicesTest.php'; + $suite->addTestSuite('WebservicesInvoicesTest'); + require_once dirname(__FILE__).'/WebservicesOrdersTest.php'; + $suite->addTestSuite('WebservicesOrdersTest'); + require_once dirname(__FILE__).'/WebservicesOtherTest.php'; + $suite->addTestSuite('WebservicesOtherTest'); + require_once dirname(__FILE__).'/WebservicesThirdpartyTest.php'; + $suite->addTestSuite('WebservicesThirdpartyTest'); + require_once dirname(__FILE__).'/WebservicesUserTest.php'; + $suite->addTestSuite('WebservicesUserTest'); + //} require_once dirname(__FILE__).'/ExportTest.php'; $suite->addTestSuite('ExportTest'); diff --git a/test/phpunit/BuildDocTest.php b/test/phpunit/BuildDocTest.php index 25b7bd15c03..c30bf1b9a96 100644 --- a/test/phpunit/BuildDocTest.php +++ b/test/phpunit/BuildDocTest.php @@ -172,7 +172,7 @@ class BuildDocTest extends PHPUnit_Framework_TestCase $localobjectcom->initAsSpecimen(); $localobject=new Facture($this->savdb); - $localobject->createFromOrder($localobjectcom); + $localobject->createFromOrder($localobjectcom, $user); $localobject->date_lim_reglement = dol_now() + 3600 * 24 *30; // Crabe (english) diff --git a/test/phpunit/CodingPhpTest.php b/test/phpunit/CodingPhpTest.php index 073adc8ef9a..2e4deb372eb 100644 --- a/test/phpunit/CodingPhpTest.php +++ b/test/phpunit/CodingPhpTest.php @@ -221,21 +221,20 @@ class CodingPhpTest extends PHPUnit_Framework_TestCase $this->assertTrue($ok, 'Found a use of print_liste_field_titre with fist parameter that is a translated value instead of just the translation key in file '.$file['fullname'].'. Bad.'); - // Test that output of $_SERVER\[\'PHP_SELF\'\] is escaped (not done for the moment, did not found a way to forge value of $_SERVER['PHP_SELF'] by extern access). - /*$ok=true; + // Test we don't have
    + $ok=true; $matches=array(); // Check string ='".$this->xxx with xxx that is not 'escape'. It means we forget a db->escape when forging sql request. - preg_match_all('/(...................)\$_SERVER\[\'PHP_SELF\'\]/', $filecontent, $matches, PREG_SET_ORDER); + preg_match_all('/
    /', $filecontent, $matches, PREG_SET_ORDER); foreach($matches as $key => $val) { - if ($val[1] != 'dol_escape_htmltag(') + if ($file['name'] != 'functions.lib.php') { $ok=false; break; } } - $this->assertTrue($ok, 'Found a $_SERVER[\'PHP_SELF\'] without dol_escape_htmltag around in file '.$file['fullname'].' ('.$val[1].'$_SERVER[\'PHP_SELF\']). Bad.'); - */ + $this->assertTrue($ok, 'Found a tag
    that is for xml in file '.$file['fullname'].' You may use
    instead.'); } return; diff --git a/test/phpunit/CommandeTest.php b/test/phpunit/CommandeTest.php index aaba882cc87..1d0e4fbf616 100644 --- a/test/phpunit/CommandeTest.php +++ b/test/phpunit/CommandeTest.php @@ -165,13 +165,38 @@ class CommandeTest extends PHPUnit_Framework_TestCase return $localobject; } + /** + * testCommandeUpdate + * + * @param Object $localobject Commande + * @return Commande + * + * @depends testCommandeFetch + * The depends says test is run only if previous is ok + */ + public function testCommandUpdate($localobject) + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + $localobject->note_private='New note private after update'; + $result=$localobject->update($user); + + $this->assertLessThan($result, 0); + print __METHOD__." id=".$id." result=".$result."\n"; + return $localobject; + } + /** * testCommandeValid * * @param Object $localobject Order - * @return void + * @return Commande * - * @depends testCommandeFetch + * @depends testCommandUpdate * The depends says test is run only if previous is ok */ public function testCommandeValid($localobject) @@ -193,7 +218,7 @@ class CommandeTest extends PHPUnit_Framework_TestCase * testCommandeCancel * * @param Object $localobject Order - * @return void + * @return Commande * * @depends testCommandeValid * The depends says test is run only if previous is ok @@ -217,7 +242,7 @@ class CommandeTest extends PHPUnit_Framework_TestCase * testCommandeOther * * @param Object $localobject Order - * @return void + * @return int Order id * * @depends testCommandeCancel * The depends says test is run only if previous is ok diff --git a/test/phpunit/FunctionsLibTest.php b/test/phpunit/FunctionsLibTest.php index 77953ed0141..d2dce75b4a5 100644 --- a/test/phpunit/FunctionsLibTest.php +++ b/test/phpunit/FunctionsLibTest.php @@ -812,15 +812,11 @@ class FunctionsLibTest extends PHPUnit_Framework_TestCase $s=img_picto('title','/fullpath/img.png','',1); print __METHOD__." s=".$s."\n"; - $this->assertEquals('',$s,'testImgPicto3'); + $this->assertEquals('',$s,'testImgPicto3'); $s=img_picto('title','/fullpath/img.png','',true); print __METHOD__." s=".$s."\n"; - $this->assertEquals('',$s,'testImgPicto4'); - - $s=img_picto('title:alt','/fullpath/img.png','',true); - print __METHOD__." s=".$s."\n"; - $this->assertEquals('alt',$s,'testImgPicto5'); + $this->assertEquals('',$s,'testImgPicto4'); } /** @@ -1144,4 +1140,23 @@ class FunctionsLibTest extends PHPUnit_Framework_TestCase return true; } + + /** + * testDolGetDate + * + * @return boolean + */ + public function testMakeSubstitutions() + { + global $conf, $langs; + $langs->load("main"); + + $substit=array("AAA"=>'Not used', "BBB"=>'Not used', "CCC"=>"C replaced"); + $chaine='This is a string with __[MAIN_THEME]__ and __(DIRECTION)__ and __CCC__'; + $newstring = make_substitutions($chaine, $substit); + $this->assertEquals($newstring, 'This is a string with eldy and ltr and __C replaced__'); + + return true; + } + } diff --git a/test/phpunit/GetUrlLibTest.php b/test/phpunit/GetUrlLibTest.php new file mode 100644 index 00000000000..21dacd5a0f1 --- /dev/null +++ b/test/phpunit/GetUrlLibTest.php @@ -0,0 +1,192 @@ + + * Copyright (C) 2012 Regis Houssin + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see http://www.gnu.org/ + */ + +/** + * \file test/phpunit/GetUrlLibTest.php + * \ingroup test + * \brief PHPUnit test + * \remarks To run this script as CLI: phpunit filename.php + */ + +global $conf,$user,$langs,$db; +//define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver +//require_once 'PHPUnit/Autoload.php'; +require_once dirname(__FILE__).'/../../htdocs/master.inc.php'; +require_once dirname(__FILE__).'/../../htdocs/core/lib/geturl.lib.php'; + +if (empty($user->id)) +{ + print "Load permissions for admin user nb 1\n"; + $user->fetch(1); + $user->getrights(); +} +$conf->global->MAIN_DISABLE_ALL_MAILS=1; + + +/** + * Class for PHPUnit tests + * + * @backupGlobals disabled + * @backupStaticAttributes enabled + * @remarks backupGlobals must be disabled to have db,conf,user and lang not erased. + */ +class GetUrlLibTest extends PHPUnit_Framework_TestCase +{ + protected $savconf; + protected $savuser; + protected $savlangs; + protected $savdb; + + /** + * Constructor + * We save global variables into local variables + * + * @return FilesLibTest + */ + function __construct() + { + //$this->sharedFixture + global $conf,$user,$langs,$db; + $this->savconf=$conf; + $this->savuser=$user; + $this->savlangs=$langs; + $this->savdb=$db; + + print __METHOD__." db->type=".$db->type." user->id=".$user->id; + //print " - db ".$db->db; + print "\n"; + } + + // Static methods + public static function setUpBeforeClass() + { + global $conf,$user,$langs,$db; + $db->begin(); // This is to have all actions inside a transaction even if test launched without suite. + + print __METHOD__."\n"; + } + + // tear down after class + public static function tearDownAfterClass() + { + global $conf,$user,$langs,$db; + $db->rollback(); + + print __METHOD__."\n"; + } + + /** + * Init phpunit tests + * + * @return void + */ + protected function setUp() + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + print __METHOD__."\n"; + } + /** + * End phpunit tests + * + * @return void + */ + protected function tearDown() + { + print __METHOD__."\n"; + } + + + /** + * testGetRootURLFromURL + * + * @return int + */ + public function testGetRootURLFromURL() + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + $result=getRootURLFromURL('http://www.dolimed.com/screenshots/afile'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('http://www.dolimed.com',$result,'Test 1'); + + $result=getRootURLFromURL('https://www.dolimed.com/screenshots/afile'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('https://www.dolimed.com',$result,'Test 2'); + + $result=getRootURLFromURL('http://www.dolimed.com/screenshots'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('http://www.dolimed.com',$result); + + $result=getRootURLFromURL('https://www.dolimed.com/screenshots'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('https://www.dolimed.com',$result); + + $result=getRootURLFromURL('http://www.dolimed.com/'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('http://www.dolimed.com',$result); + + $result=getRootURLFromURL('https://www.dolimed.com/'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('https://www.dolimed.com',$result); + + $result=getRootURLFromURL('http://www.dolimed.com'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('http://www.dolimed.com',$result); + + $result=getRootURLFromURL('https://www.dolimed.com'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('https://www.dolimed.com',$result); + + return 1; + } + + + /** + * testRemoveHtmlComment + * + * @return int + */ + public function testRemoveHtmlComment() + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + $result=removeHtmlComment('abcdef'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('abcdef',$result,'Test 1'); + + $result=removeHtmlComment('abcbbdef'); + print __METHOD__." result=".$result."\n"; + $this->assertEquals('abcbbdef',$result,'Test 1'); + + return 1; + } +} diff --git a/test/phpunit/HolidayTest.php b/test/phpunit/HolidayTest.php index a04646a8a14..3204e9f07b1 100644 --- a/test/phpunit/HolidayTest.php +++ b/test/phpunit/HolidayTest.php @@ -201,11 +201,11 @@ class HolidayTest extends PHPUnit_Framework_TestCase $localobject->email='newemail@newemail.com'; $localobject->jabberid='New im id'; $localobject->default_lang='es_ES'; - + $result=$localobject->update($localobject->id,$user); print __METHOD__." id=".$localobject->id." result=".$result."\n"; $this->assertLessThan($result, 0, 'Holiday::update error'); - + $result=$localobject->update_note($localobject->note_private,'_private'); print __METHOD__." id=".$localobject->id." result=".$result."\n"; $this->assertLessThan($result, 0, 'Holiday::update_note (private) error'); @@ -213,7 +213,7 @@ class HolidayTest extends PHPUnit_Framework_TestCase $result=$localobject->update_note($localobject->note_public, '_public'); print __METHOD__." id=".$localobject->id." result=".$result."\n"; $this->assertLessThan($result, 0, 'Holiday::update_note (public) error'); - + $newobject=new Holiday($this->savdb); $result=$newobject->fetch($localobject->id); @@ -291,4 +291,63 @@ class HolidayTest extends PHPUnit_Framework_TestCase return $result; } + /** + * testVerifDateHolidayCP + * + * @return void + */ + public function testVerifDateHolidayCP() + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + // Create a leave request the 1st morning only + $localobjecta=new Holiday($this->savdb); + $localobjecta->initAsSpecimen(); + $localobjecta->date_debut = dol_mktime(0, 0, 0, 1, 1, 2020); + $localobjecta->date_fin = dol_mktime(0, 0, 0, 1, 1, 2020); + $localobjecta->halfday = 1; + $result=$localobjecta->create($user); + + // Create a leave request the 2 afternoon only + $localobjectb=new Holiday($this->savdb); + $localobjectb->initAsSpecimen(); + $localobjectb->date_debut = dol_mktime(0, 0, 0, 1, 2, 2020); + $localobjectb->date_fin = dol_mktime(0, 0, 0, 1, 2, 2020); + $localobjectb->halfday = -1; + $result=$localobjectb->create($user); + + $date_debut = dol_mktime(0, 0, 0, 1, 1, 2020); + $date_fin = dol_mktime(0, 0, 0, 1, 2, 2020); + + $localobjectc=new Holiday($this->savdb); + + $result=$localobjectc->verifDateHolidayCP($user->id, $date_debut, $date_debut, 0); + $this->assertFalse($result, 'result should be false, there is overlapping, full day is not available.'); + $result=$localobjectc->verifDateHolidayCP($user->id, $date_debut, $date_fin, 0); + $this->assertFalse($result, 'result should be false, there is overlapping, full day is not available.'); + $result=$localobjectc->verifDateHolidayCP($user->id, $date_fin, $date_fin, 0); + $this->assertFalse($result, 'result should be false, there is overlapping, full day is not available.'); + + $result=$localobjectc->verifDateHolidayCP($user->id, $date_debut, $date_debut, 1); + $this->assertFalse($result, 'result should be false, there is overlapping, morning of first day is not available.'); + $result=$localobjectc->verifDateHolidayCP($user->id, $date_debut, $date_fin, 1); + $this->assertFalse($result, 'result should be false, there is overlapping, morning of first day is not available.'); + $result=$localobjectc->verifDateHolidayCP($user->id, $date_fin, $date_fin, 1); + $this->assertTrue($result, 'result should be true, there is no overlapping'); + + $result=$localobjectc->verifDateHolidayCP($user->id, $date_debut, $date_debut, -1); + $this->assertTrue($result, 'result should be true, there is no overlapping'); + $result=$localobjectc->verifDateHolidayCP($user->id, $date_debut, $date_fin, -1); + $this->assertFalse($result, 'result should be false, there is overlapping, afternoon of second day is not available'); + $result=$localobjectc->verifDateHolidayCP($user->id, $date_fin, $date_fin, -1); + $this->assertFalse($result, 'result should be false, there is overlapping, afternoon of second day is not available'); + + $result=$localobjectc->verifDateHolidayCP($user->id, $date_debut, $date_fin, 2); // start afternoon and end morning + $this->assertTrue($result, 'result should be true, there is no overlapping'); + } + } diff --git a/test/phpunit/ModulesTest.php b/test/phpunit/ModulesTest.php index a4ff51333e0..3c62ed52c70 100755 --- a/test/phpunit/ModulesTest.php +++ b/test/phpunit/ModulesTest.php @@ -127,13 +127,13 @@ class ModulesTest extends PHPUnit_Framework_TestCase $langs=$this->savlangs; $db=$this->savdb; - $modulelist=array('Accounting','Adherent','Agenda','Banque','Barcode','Bookmark', - 'CashDesk','Categorie','ClickToDial','Commande','Comptabilite','Contrat','Cron','Deplacement','DocumentGeneration','Don','DynamicPrices', - 'ECM','Expedition','Export','ExternalRss','ExternalSite', + $modulelist=array('Accounting','Adherent','Agenda','Banque','Barcode','BlockedLog','Bookmark', + 'CashDesk','Categorie','ClickToDial','Collab','Commande','Comptabilite','Contrat','Cron','Deplacement','DocumentGeneration','Don','DynamicPrices', + 'ECM','Expedition','ExpenseReport','Export','ExternalRss','ExternalSite', 'Facture','Fckeditor','Ficheinter','Fournisseur','FTP','GeoIPMaxmind','Gravatar','Holiday','HRM','Import','Incoterm','Label','Ldap','Loan', - 'Mailing','MailmanSpip','Margin', - 'Notification','Oauth','OpenSurvey','Paybox','Paypal','Prelevement','Product','ProductBatch','Projet','Propale','ReceiptPrinter','Resource', - 'Salaries','Service','Skype','Societe','Stock','SupplierProposal','Syslog','Tax','User','WebServices','WebServicesClient','Websites','Workflow'); + 'Mailing','MailmanSpip','Margin','ModuleBuilder','MultiCurrency', + 'Notification','Oauth','OpenSurvey','Paybox','Paypal','Prelevement','Printing','Product','ProductBatch','Projet','Propale','ReceiptPrinter','Resource', + 'Salaries','Service','Skype','Societe','Stock','Stripe','SupplierProposal','Syslog','Tax','User','Variants','WebServices','WebServicesClient','Website','Workflow'); foreach($modulelist as $modlabel) { require_once(DOL_DOCUMENT_ROOT.'/core/modules/mod'.$modlabel.'.class.php'); @@ -143,7 +143,7 @@ class ModulesTest extends PHPUnit_Framework_TestCase $result=$mod->init(); $this->assertLessThan($result, 0, $modlabel); print __METHOD__." test remove/init for module ".$modlabel.", result=".$result."\n"; - + if (in_array($modlabel, array('Ldap', 'MailmanSpip'))) { $result=$mod->remove(); diff --git a/test/phpunit/NumberingModulesTest.php b/test/phpunit/NumberingModulesTest.php index 72229b1c598..4a3dfb7c1c9 100644 --- a/test/phpunit/NumberingModulesTest.php +++ b/test/phpunit/NumberingModulesTest.php @@ -174,7 +174,7 @@ class NumberingModulesTest extends PHPUnit_Framework_TestCase $this->assertGreaterThanOrEqual(1, $result); // Can be deleted $result=$localobject->is_erasable(); print __METHOD__." is_erasable=".$result."\n"; - $this->assertEquals(0, $result, 'Test for {yyyy}-{0000} that is_erasable is 0 for 1st invoice'); // 1 can no more be deleted (2 is more recent) + $this->assertLessThanOrEqual(0, $result, 'Test for {yyyy}-{0000} that is_erasable is 0 for 1st invoice'); // 1 can no more be deleted (2 is more recent) // Now we try with a reset $conf->global->FACTURE_MERCURE_MASK_CREDIT='{yyyy}-{0000@1}'; @@ -264,7 +264,7 @@ class NumberingModulesTest extends PHPUnit_Framework_TestCase $this->assertGreaterThanOrEqual(1, $result); // Can be deleted $result=$localobject->is_erasable(); print __METHOD__." is_erasable=".$result."\n"; - $this->assertEquals(0, $result); // Case 1 can not be deleted (because there is an invoice 2) + $this->assertLessThanOrEqual(0, $result); // Case 1 can not be deleted (because there is an invoice 2) $localobject3=new Facture($this->savdb); $localobject3->initAsSpecimen(); $localobject3->date=dol_mktime(12, 0, 0, 1, 1, 1926); // we use following year for third invoice (and there is a reset required) diff --git a/test/phpunit/PropalTest.php b/test/phpunit/PropalTest.php index 707673e0d0f..3d45673074a 100644 --- a/test/phpunit/PropalTest.php +++ b/test/phpunit/PropalTest.php @@ -142,7 +142,7 @@ class PropalTest extends PHPUnit_Framework_TestCase * testPropalFetch * * @param int $id Id of object - * @return void + * @return Propal * * @depends testPropalCreate * The depends says test is run only if previous is ok @@ -164,14 +164,39 @@ class PropalTest extends PHPUnit_Framework_TestCase } /** - * testPropalAddLine + * testPropalUpdate * - * @param int $localobject Proposal - * @return void + * @param Propal $localobject Proposal + * @return Propal * * @depends testPropalFetch * The depends says test is run only if previous is ok */ + public function testPropalUpdate($localobject) + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + $localobject->note_private='New note private after update'; + $result=$localobject->update($user); + + $this->assertLessThan($result, 0); + print __METHOD__." id=".$id." result=".$result."\n"; + return $localobject; + } + + /** + * testPropalAddLine + * + * @param Propal $localobject Proposal + * @return Propal + * + * @depends testPropalUpdate + * The depends says test is run only if previous is ok + */ public function testPropalAddLine($localobject) { global $conf,$user,$langs,$db; @@ -180,6 +205,7 @@ class PropalTest extends PHPUnit_Framework_TestCase $langs=$this->savlangs; $db=$this->savdb; + $localobject->fetch_thirdparty(); $result=$localobject->addline('Added line', 10, 2, 19.6); $this->assertLessThan($result, 0); @@ -190,8 +216,8 @@ class PropalTest extends PHPUnit_Framework_TestCase /** * testPropalValid * - * @param Proposal $localobject Proposal - * @return Proposal + * @param Propal $localobject Proposal + * @return Propal * * @depends testPropalAddLine * The depends says test is run only if previous is ok @@ -214,7 +240,7 @@ class PropalTest extends PHPUnit_Framework_TestCase /** * testPropalOther * - * @param Proposal $localobject Proposal + * @param Propal $localobject Proposal * @return int * * @depends testPropalValid diff --git a/test/phpunit/SecurityTest.php b/test/phpunit/SecurityTest.php index 288a15c317e..87a5fdeb905 100644 --- a/test/phpunit/SecurityTest.php +++ b/test/phpunit/SecurityTest.php @@ -148,7 +148,7 @@ class SecurityTest extends PHPUnit_Framework_TestCase $_GET["param3"]='"a/b#e(pr)qq-rr\cc'; // Same than param2 + " $_GET["param4"]='../dir'; $_GET["param5"]="a_1-b"; - + // Test int $result=GETPOST('id','int'); // Must return nothing print __METHOD__." result=".$result."\n"; @@ -179,19 +179,19 @@ class SecurityTest extends PHPUnit_Framework_TestCase $result=GETPOST("param1",'aZ09'); // Must return '' as there is a forbidden char ../ print __METHOD__." result=".$result."\n"; $this->assertEquals($result,$_GET["param1"]); - + $result=GETPOST("param2",'aZ09'); // Must return '' as there is a forbidden char ../ print __METHOD__." result=".$result."\n"; $this->assertEquals($result,''); - + $result=GETPOST("param3",'aZ09'); // Must return '' as there is a forbidden char ../ print __METHOD__." result=".$result."\n"; $this->assertEquals($result,''); - + $result=GETPOST("param4",'aZ09'); // Must return '' as there is a forbidden char ../ print __METHOD__." result=".$result."\n"; $this->assertEquals($result,''); - + $result=GETPOST("param5",'aZ09'); print __METHOD__." result=".$result."\n"; $this->assertEquals($result,$_GET["param5"]); @@ -255,17 +255,17 @@ class SecurityTest extends PHPUnit_Framework_TestCase $genpass1=getRandomPassword(true); // Should be a string return by dol_hash (if no option set, will be md5) print __METHOD__." genpass1=".$genpass1."\n"; - $this->assertEquals(strlen($genpass1),32); + $this->assertEquals(strlen($genpass1), 32); $conf->global->USER_PASSWORD_GENERATED='None'; $genpass2=getRandomPassword(false); // Should be an empty string print __METHOD__." genpass2=".$genpass2."\n"; - $this->assertEquals($genpass2,''); + $this->assertEquals($genpass2, ''); $conf->global->USER_PASSWORD_GENERATED='Standard'; $genpass3=getRandomPassword(false); print __METHOD__." genpass3=".$genpass3."\n"; - $this->assertEquals(strlen($genpass3),8); + $this->assertEquals(strlen($genpass3), 8); return 0; } diff --git a/test/phpunit/SupplierProposalTest.php b/test/phpunit/SupplierProposalTest.php new file mode 100644 index 00000000000..ee4729ed47f --- /dev/null +++ b/test/phpunit/SupplierProposalTest.php @@ -0,0 +1,275 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see http://www.gnu.org/ + */ + +/** + * \file test/phpunit/SupplierProposalTest.php + * \ingroup test + * \brief PHPUnit test + * \remarks To run this script as CLI: phpunit filename.php + */ + +global $conf,$user,$langs,$db; +//define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver +//require_once 'PHPUnit/Autoload.php'; +require_once dirname(__FILE__).'/../../htdocs/master.inc.php'; +require_once dirname(__FILE__).'/../../htdocs/supplier_proposal/class/supplier_proposal.class.php'; + +if (empty($user->id)) +{ + print "Load permissions for admin user nb 1\n"; + $user->fetch(1); + + //$user->addrights(0, 'supplier_proposal'); + + $user->getrights(); +} +$conf->global->MAIN_DISABLE_ALL_MAILS=1; + + +/** + * Class for PHPUnit tests + * + * @backupGlobals disabled + * @backupStaticAttributes enabled + * @remarks backupGlobals must be disabled to have db,conf,user and lang not erased. + */ +class SupplierProposalTest extends PHPUnit_Framework_TestCase +{ + protected $savconf; + protected $savuser; + protected $savlangs; + protected $savdb; + + /** + * Constructor + * We save global variables into local variables + * + * @return PropalTest + */ + function __construct() + { + //$this->sharedFixture + global $conf,$user,$langs,$db; + $this->savconf=$conf; + $this->savuser=$user; + $this->savlangs=$langs; + $this->savdb=$db; + + print __METHOD__." db->type=".$db->type." user->id=".$user->id; + //print " - db ".$db->db; + print "\n"; + } + + // Static methods + public static function setUpBeforeClass() + { + global $conf,$user,$langs,$db; + $db->begin(); // This is to have all actions inside a transaction even if test launched without suite. + + if (empty($conf->global->MAIN_MODULE_SUPPLIERPROPOSAL)) { print "\n".__METHOD__." module Supplier proposal must be enabled.\n"; die(); } + + print __METHOD__."\n"; + } + + // tear down after class + public static function tearDownAfterClass() + { + global $conf,$user,$langs,$db; + $db->rollback(); + + print __METHOD__."\n"; + } + + /** + * Init phpunit tests + * + * @return void + */ + protected function setUp() + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + print __METHOD__."\n"; + //print $db->getVersion()."\n"; + } + /** + * End phpunit tests + * + * @return void + */ + protected function tearDown() + { + print __METHOD__."\n"; + } + + /** + * testSupplierProposalCreate + * + * @return void + */ + public function testSupplierProposalCreate() + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + $localobject=new SupplierProposal($this->savdb); + $localobject->initAsSpecimen(); + $result=$localobject->create($user); + + $this->assertLessThan($result, 0); + print __METHOD__." result=".$result."\n"; + return $result; + } + + /** + * testSupplierProposalFetch + * + * @param int $id Id of object + * @return void + * + * @depends testSupplierProposalCreate + * The depends says test is run only if previous is ok + */ + public function testSupplierProposalFetch($id) + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + $localobject=new SupplierProposal($this->savdb); + $result=$localobject->fetch($id); + + $this->assertLessThan($result, 0); + print __METHOD__." id=".$id." result=".$result."\n"; + return $localobject; + } + + /** + * testSupplierProposalAddLine + * + * @param int $localobject Proposal + * @return void + * + * @depends testSupplierProposalFetch + * The depends says test is run only if previous is ok + */ + public function testSupplierProposalAddLine($localobject) + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + $localobject->fetch_thirdparty(); + $result=$localobject->addline('Added line', 10, 2, 19.6); + + $this->assertLessThan($result, 0); + print __METHOD__." id=".$localobject->id." result=".$result."\n"; + return $localobject; + } + + /** + * testSupplierProposalValid + * + * @param Proposal $localobject Proposal + * @return Proposal + * + * @depends testSupplierProposalAddLine + * The depends says test is run only if previous is ok + */ + public function testSupplierProposalValid($localobject) + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + $result=$localobject->valid($user); + + print __METHOD__." id=".$localobject->id." result=".$result."\n"; + $this->assertLessThan($result, 0); + return $localobject; + } + + /** + * testSupplierProposalOther + * + * @param Proposal $localobject Proposal + * @return int + * + * @depends testSupplierProposalValid + * The depends says test is run only if previous is ok + */ + public function testSupplierProposalOther($localobject) + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + /*$result=$localobject->setstatus(0); + print __METHOD__." id=".$localobject->id." result=".$result."\n"; + $this->assertLessThan($result, 0); + */ + + $localobject->info($localobject->id); + print __METHOD__." localobject->date_creation=".$localobject->date_creation."\n"; + $this->assertNotEquals($localobject->date_creation, ''); + + return $localobject->id; + } + + /** + * testSupplierProposalDelete + * + * @param int $id Id of proposal + * @return void + * + * @depends testSupplierProposalOther + * The depends says test is run only if previous is ok + */ + public function testSupplierProposalDelete($id) + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + $localobject=new SupplierProposal($this->savdb); + $result=$localobject->fetch($id); + $result=$localobject->delete($user); + + print __METHOD__." id=".$id." result=".$result."\n"; + $this->assertLessThan($result, 0); + return $result; + } + +} diff --git a/test/phpunit/UserTest.php b/test/phpunit/UserTest.php index b932d2e2221..8eaa1888412 100644 --- a/test/phpunit/UserTest.php +++ b/test/phpunit/UserTest.php @@ -77,7 +77,7 @@ class UserTest extends PHPUnit_Framework_TestCase global $conf,$user,$langs,$db; if (! empty($conf->global->MAIN_MODULE_LDAP)) { print "\n".__METHOD__." module LDAP must be disabled.\n"; die(); } - + $db->begin(); // This is to have all actions inside a transaction even if test launched without suite. print __METHOD__."\n"; @@ -272,6 +272,32 @@ class UserTest extends PHPUnit_Framework_TestCase return $result; } + /** + * testUserAddPermission + * + * @param Object $id User + * @return void + * @depends testUserDelete + * The depends says test is run only if previous is ok + */ + public function testUserAddPermission($id) + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + $localobject=new User($this->savdb); + $result=$localobject->fetch(1); // Other tests use the user id 1 + $result=$localobject->addrights(0, 'supplier_proposal'); + + print __METHOD__." id=".$id." result=".$result."\n"; + $this->assertLessThan($result, 0); + return $result; + } + + /** * Edit an object to test updates diff --git a/test/phpunit/UtilsTest.php b/test/phpunit/UtilsTest.php new file mode 100644 index 00000000000..b80ce84f624 --- /dev/null +++ b/test/phpunit/UtilsTest.php @@ -0,0 +1,152 @@ + + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * or see http://www.gnu.org/ + */ + +/** + * \file test/phpunit/UtilsTest.php + * \ingroup test + * \brief PHPUnit test + * \remarks To run this script as CLI: phpunit filename.php + */ + +global $conf,$user,$langs,$db; +//define('TEST_DB_FORCE_TYPE','mysql'); // This is to force using mysql driver +//require_once 'PHPUnit/Autoload.php'; +require_once dirname(__FILE__).'/../../htdocs/master.inc.php'; +require_once dirname(__FILE__).'/../../htdocs/core/class/utils.class.php'; + +if (empty($user->id)) { + print "Load permissions for admin user nb 1\n"; + $user->fetch(1); + $user->getrights(); +} +$conf->global->MAIN_DISABLE_ALL_MAILS=1; + + +/** + * Class for PHPUnit tests + * + * @backupGlobals disabled + * @backupStaticAttributes enabled + * @remarks backupGlobals must be disabled to have db,conf,user and lang not erased. + */ +class UtilsTest extends PHPUnit_Framework_TestCase +{ + protected $savconf; + protected $savuser; + protected $savlangs; + protected $savdb; + + /** + * Constructor + * We save global variables into local variables + * + * @return UserTest + */ + function __construct() + { + //$this->sharedFixture + global $conf,$user,$langs,$db; + $this->savconf=$conf; + $this->savuser=$user; + $this->savlangs=$langs; + $this->savdb=$db; + + print __METHOD__." db->type=".$db->type." user->id=".$user->id; + //print " - db ".$db->db; + print "\n"; + } + + // Static methods + public static function setUpBeforeClass() + { + global $conf,$user,$langs,$db; + + $db->begin(); // This is to have all actions inside a transaction even if test launched without suite. + + print __METHOD__."\n"; + } + + // tear down after class + public static function tearDownAfterClass() + { + global $conf,$user,$langs,$db; + $db->rollback(); + + print __METHOD__."\n"; + } + + /** + * Init phpunit tests + * + * @return void + */ + protected function setUp() + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + print __METHOD__."\n"; + } + + /** + * End phpunit tests + * + * @return void + */ + protected function tearDown() + { + print __METHOD__."\n"; + } + + /** + * testExecuteCLI + * + * @return void + */ + public function testExecuteCLI() + { + global $conf,$user,$langs,$db; + $conf=$this->savconf; + $user=$this->savuser; + $langs=$this->savlangs; + $db=$this->savdb; + + $localobject=new Utils($this->savdb); + $result = $localobject->executeCLI('ls', $conf->admin->dir_temp.'/out.tmp', 1); + print var_export($result, true); + $this->assertEquals($result['result'], 0); + $this->assertEquals($result['error'], ''); + //$this->assertEquals(preg_match('/phpunit/', $result['output']), 1); + + $localobject=new Utils($this->savdb); + $result = $localobject->executeCLI('ls', $conf->admin->dir_temp.'/out.tmp', 2); + print var_export($result, true); + $this->assertEquals($result['result'], 0); + $this->assertEquals($result['error'], ''); + //$this->assertEquals(preg_match('/phpunit/', $result['output']), 1); + + print __METHOD__." result=".$result."\n"; + return $result; + } + + + +} diff --git a/test/phpunit/WebservicesInvoicesTest.php b/test/phpunit/WebservicesInvoicesTest.php index 07bd95e01f2..75cc767b8ee 100644 --- a/test/phpunit/WebservicesInvoicesTest.php +++ b/test/phpunit/WebservicesInvoicesTest.php @@ -56,11 +56,11 @@ class WebservicesInvoicesTest extends PHPUnit_Framework_TestCase protected $savlangs; protected $savdb; protected $soapclient; - + private static $socid; - + protected $ns = 'http://www.dolibarr.org/ns/'; - + /** * Constructor * We save global variables into local variables @@ -75,7 +75,7 @@ class WebservicesInvoicesTest extends PHPUnit_Framework_TestCase $this->savuser=$user; $this->savlangs=$langs; $this->savdb=$db; - + // Set the WebService URL $WS_DOL_URL = DOL_MAIN_URL_ROOT.'/webservices/server_invoice.php'; print __METHOD__." create nusoap_client for URL=".$WS_DOL_URL."\n"; @@ -85,7 +85,7 @@ class WebservicesInvoicesTest extends PHPUnit_Framework_TestCase $this->soapclient->soap_defencoding='UTF-8'; $this->soapclient->decodeUTF8(false); } - + print __METHOD__." db->type=".$db->type." user->id=".$user->id; //print " - db ".$db->db; print "\n"; @@ -114,11 +114,13 @@ class WebservicesInvoicesTest extends PHPUnit_Framework_TestCase $societe->ref_ext='ref-phpunit'; $societe->status=1; $societe->client=1; + $societe->code_client='CU0901-1234'; + $societe->code_fournisseur='SU0901-1234'; $societe->fournisseur=0; $societe->date_creation=$now; $societe->tva_assuj=0; $societe->particulier=0; - + $societe->create($user); self::$socid = $societe->id; @@ -259,13 +261,13 @@ class WebservicesInvoicesTest extends PHPUnit_Framework_TestCase return $result; } - + /** * testWSInvoicesGetInvoiceByRefExt - * + * * Retrieve an invoice using ref_ext * @depends testWSInvoicesCreateInvoice - * + * * @param array $result Invoice created by create method * @return array Invoice */ @@ -315,13 +317,13 @@ class WebservicesInvoicesTest extends PHPUnit_Framework_TestCase return $result; } - + /** * testWSInvoicesUpdateInvoiceByRefExt - * + * * Update an invoice using ref_ext * @depends testWSInvoicesCreateInvoice - * + * * @param array $result invoice created by create method * @return array Invoice */ diff --git a/test/phpunit/WebservicesThirdpartyTest.php b/test/phpunit/WebservicesThirdpartyTest.php index 59907b36194..e0e22125afe 100644 --- a/test/phpunit/WebservicesThirdpartyTest.php +++ b/test/phpunit/WebservicesThirdpartyTest.php @@ -55,12 +55,12 @@ class WebservicesThirdpartyTest extends PHPUnit_Framework_TestCase protected $savlangs; protected $savdb; protected $soapclient; - + private $_WS_DOL_URL; private $_ns='http://www.dolibarr.org/ns/'; - - - + + + /** * Constructor @@ -76,9 +76,9 @@ class WebservicesThirdpartyTest extends PHPUnit_Framework_TestCase $this->savuser=$user; $this->savlangs=$langs; $this->savdb=$db; - + $this->_WS_DOL_URL = DOL_MAIN_URL_ROOT.'/webservices/server_thirdparty.php'; - + // Set the WebService URL print __METHOD__." create nusoap_client for URL=".$this->_WS_DOL_URL."\n"; $this->soapclient = new nusoap_client($this->_WS_DOL_URL); @@ -148,10 +148,10 @@ class WebservicesThirdpartyTest extends PHPUnit_Framework_TestCase $user=$this->savuser; $langs=$this->savlangs; $db=$this->savdb; - + $WS_METHOD = 'createThirdParty'; - - + + // Call the WebService method and store its result in $result. $authentication=array( 'dolibarrkey'=>$conf->global->WEBSERVICES_KEY, @@ -159,7 +159,7 @@ class WebservicesThirdpartyTest extends PHPUnit_Framework_TestCase 'login'=>'admin', 'password'=>'admin', 'entity'=>''); - + $body = array ( "id" => NULL, "ref" => "name", @@ -168,8 +168,8 @@ class WebservicesThirdpartyTest extends PHPUnit_Framework_TestCase "status" => NULL, "client" => 1, "supplier" => 0, - "customer_code" => "", - "supplier_code" => "", + "customer_code" => "CU0901-5678", + "supplier_code" => "SU0901-5678", "customer_code_accountancy" => "", "supplier_code_accountancy" => "", "date_creation" => "", // dateTime @@ -197,7 +197,7 @@ class WebservicesThirdpartyTest extends PHPUnit_Framework_TestCase "vat_used" => "", "vat_number" => "" ); - + // Test URL $result=''; $parameters = array('authentication'=>$authentication, 'thirdparty'=>$body); @@ -217,20 +217,20 @@ class WebservicesThirdpartyTest extends PHPUnit_Framework_TestCase print $this->soapclient->response; print "\n"; } - + print __METHOD__." result=".$result['result']['result_code']."\n"; $this->assertEquals('OK',$result['result']['result_code']); - $this->assertEquals('name',$result['ref']); - + $this->assertEquals('name',$result['ref']); + return $result; } /** * testWSThirdpartygetThirdPartyById - * + * * Use id to retrieve thirdparty * @depends testWSThirdpartycreateThirdParty - * + * * @param array $result thirdparty created by create method * @return array thirpdarty updated */ @@ -280,18 +280,18 @@ class WebservicesThirdpartyTest extends PHPUnit_Framework_TestCase $this->assertEquals('0', $result['thirdparty']['status']); $this->assertEquals('1', $result['thirdparty']['client']); $this->assertEquals('0', $result['thirdparty']['supplier']); - - + + return $result; } - + /** * testWSThirdpartygetThirdPartyByRefExt * * Use ref_ext to retrieve thirdparty * * @depends testWSThirdpartycreateThirdParty - * + * * @param array $result thirdparty created by create method * @return array thirdparty */ @@ -303,9 +303,9 @@ class WebservicesThirdpartyTest extends PHPUnit_Framework_TestCase $langs=$this->savlangs; $db=$this->savdb; $id = $result['id']; - + $WS_METHOD = 'getThirdParty'; - + // Call the WebService method and store its result in $result. $authentication=array( 'dolibarrkey'=>$conf->global->WEBSERVICES_KEY, @@ -313,7 +313,7 @@ class WebservicesThirdpartyTest extends PHPUnit_Framework_TestCase 'login'=>'admin', 'password'=>'admin', 'entity'=>''); - + // Test URL $result=''; $parameters = array('authentication'=>$authentication, 'id'=>'', 'ref'=>'', 'ref_ext'=>'12'); @@ -334,7 +334,7 @@ class WebservicesThirdpartyTest extends PHPUnit_Framework_TestCase print $this->soapclient->response; print "\n"; } - + print __METHOD__." result=".$result['result']['result_code']."\n"; $this->assertEquals('OK',$result['result']['result_code']); $this->assertEquals($id, $result['thirdparty']['id']); @@ -343,11 +343,11 @@ class WebservicesThirdpartyTest extends PHPUnit_Framework_TestCase $this->assertEquals('0', $result['thirdparty']['status']); $this->assertEquals('1', $result['thirdparty']['client']); $this->assertEquals('0', $result['thirdparty']['supplier']); - - + + return $result; } - + /** * testWSThirdpartydeleteThirdParty * @@ -364,9 +364,9 @@ class WebservicesThirdpartyTest extends PHPUnit_Framework_TestCase $langs=$this->savlangs; $db=$this->savdb; $id = $result['id']; - + $WS_METHOD = 'deleteThirdParty'; - + // Call the WebService method and store its result in $result. $authentication=array( 'dolibarrkey'=>$conf->global->WEBSERVICES_KEY, @@ -374,7 +374,7 @@ class WebservicesThirdpartyTest extends PHPUnit_Framework_TestCase 'login'=>'admin', 'password'=>'admin', 'entity'=>''); - + $result=''; $parameters = array('authentication'=>$authentication, 'id'=>$id, 'ref'=>'', 'ref_ext'=>''); print __METHOD__." call method ".$WS_METHOD."\n"; @@ -395,7 +395,7 @@ class WebservicesThirdpartyTest extends PHPUnit_Framework_TestCase print __METHOD__." result=".$result['result']['result_code']."\n"; $this->assertEquals('OK',$result['result']['result_code']); - + return $result; }