diff --git a/code/horizon/AUTHORS b/code/horizon/AUTHORS deleted file mode 100644 index 94b5324c..00000000 --- a/code/horizon/AUTHORS +++ /dev/null @@ -1,484 +0,0 @@ -Aaron Rosen -Aaron Sahlin -Abhijeet Malawade -Abishek Subramanian -Adam Gandelman -Adrien Cunin -Adrien Vergé -Akihiro MOTOKI -Akihiro MOTOKI -Akihiro Motoki -Ala Rezmerita -Alan Fung -Alejandro Emanuel Paredes -Alessandro Pilotti -Alessio Ababilov -Alex Chan -Alex Gaynor -Alexey Izbyshev -Ambroise Christea -Ami Jeain -Ana Krivokapic -Ana Malagon -Anastasia Karpinska -Andreas Jaeger -Andres Buraschi -Andrew Bramley -Andrew Lazarev -Andrews Medina -Andy Chong -Anita Kuno -Annapoornima Koppad -Anne Gentle -Anthony Young -Anton V. Yanchenko -Anya Marshall -Artem Osadchiy -Artem Osadchyi -Arvind Somya -Ashish Chandra -Assaf Muller -Attila Fazekas -Avishay Balderman -Babitha Donepudi -Bartosz Fic -Behdad Fariba -Bernhard M. Wiedemann -Bhavanishankar Ravindra -Bradley Jones -Brant Knudson -Brian DeHamer -Brian Fischer -Brian Tully -Brian Waldon -Brianna Poulos -Brooklyn Chen -CHARDON Gerome -Carlo Truijllo -Cedric Brandily -Cedric Soulas -Chad Lung -Chad Roberts -Chaitanya Challa -Charles V Bock -ChenZheng -Chris Johnson -Chris St. Pierre -Christian Berendt -Christian Berendt -Chuck Short -Cindy Lu -Claire Delcourt -Clark Boylan -Clayton O'Neill -Cody A.W. Somerville -Cole Robinson -Cristian A Sanchez -Cristian Tomoiaga -CristianFiorentino -Cyril Roelandt -Dan Reif -Dan Wendlandt -Daniel Gauthier -Daniel Korn -Daniel P. Berrange -David Caudill -David Lapsley -David Lyle -David Lyle -Davide Guerri -Dean Troyer -Denise Hale -Devin Carlen -Diana Whitten -Diego Garcia del Rio -Dimitri Mazmanov -Dirk Mueller -Dmitry Tantsur -Doug Doan -Doug Fish -Doug Hellmann -Du Yujie -Duncan McGreggor -Edgar Magana -Ekaterina Chernova -Ekaterina Fedorova -EmilienM -Emma Steimann -Eoghan Glynn -Eric Peterson -Erwan Gallen -Eugene Nikanorov -Ewan Mellor -Fabrizio Fresco -Facundo Farias -Facundo Maldonado -Federico Gimenez Nieto -Felipe Reyes -Fengqian Gao -Flavio Percoco -Floren Llanos -Francois Eleouet -François Magimel -Gabriel Briones -Gabriel Hurley -Gabriel Luong -Gabriel Pettier -Gabriel Wainer -Gary W. Smith -Geetika Batra -George Peristerakis -George Peristerakis -Georges Dubus -Georgi Demirchev -Ghe Rivero -Gloria Gu -Gordon Chung -Greg Althaus -Guilherme Lazzari -Guillermo Cabrera -He Yongli -Heiko Krämer -Hengqing Hu -Hidekazu Nakamura -Ian Cordasco -Ihar Hrachyshka -Ilya Shakhat -Imre Farkas -Ionuț Arțăriși -Ivan A. Melnikov -Ivan Chavero -Ivan Kolodyazhny -J. Daniel Schmidt -Jake Dahn -Jake Zukowski -James E. Blair -James E. Blair -James Nzomo -James Slagle -Jamie Lennox -Jan Provaznik -Janet Yu -Jason Derrett -Jason E. Rist -Jasper Capel -Jay Pipes -Jeff Kramer -Jeffrey Wilcox -Jeremy Moffitt -Jeremy Stanley -Jesse Andrews -Jesse Pretorius -JiaHao Li -Jiang Yong -Jianing YANG -Jim Yeh -Jingjing Ren -Jiri Tomasek -Joanna H. Huang -Joanna Huang -Joe Gordon -Joe Heck -Joe Topjian -John Davidge -John Postlethwait -Johnu George -Jordan OMara -Joris Roovers -Jose Castro Leon -Joseph Heck -Josh Durgin -Joshua McKenty -Juan Manuel Olle -Julie Gravel -Julie Pichon -Julie Pichon -Julien Danjou -Julien Danjou -Justin Pomeroy -Justin Shepherd -KC Wang -KC Wang -Kahou Lei -Kamil Rykowski -Kanagaraj Manickam -Kanchan Gupta -Kannan Manickam -Ke WU -Ke Wu -Kelly Domico -Kelsey Tripp -Ken Pepple -Keshava Bharadwaj -Kev Bittner -Kevin Benton -Kevin Benton -Kevin Kirkpatrick -Kieran Spear -Kirill Izotov -Kui Shi -Kun Huang -Kylin CG -LIU Yulong -LIU-Yulong -LIU-Yulong -Ladislav Smola -Laura Athanasiou -Laura Frank -Laura Frank -Leandro I. Costantino -Lei Zhang -Li Ma -Liang Bo -Lin Hua Cheng -Liz Blanchard -Luigi Toscano -Luis de Bethencourt -Lukas Bezdicka -Malini Bhandaru -Marcin Karkocha -Marcos Fermin Lobo -Marcos Lobo -Marcus Furlong -Mark Gius -Mark McClain -Mark McLoughlin -Martin Hickey -Martin Kletzander -Martin Pavlasek -Masahito Muroi -Masaki Matsushita -Masco Kaliyamoorthy -Matt Borland -Matt Farina -Matt Fischer -Matt Joyce -Matt Wagner -Matthew Wood -Matthias Runge -Maxime Vidori -Michael Still -Michael Szilagyi -Michael Yu -Michal Dulko -Miguel Grinberg -Mike Hagedorn -Mike Moore -Mike Perez -Mike Scherbakov -Mingyan Bao -Monty Taylor -Nachi Ueno -Nachi Ueno -Nathan Beittenmiller -Nathan Reller -Neil Johnston -Nicolas Simonds -Nikhil Manchanda -Nikita Konovalov -Noboru Arai -Noorul Islam K M -Om Prakash Pandey -Omri Gazitt -Paolo Gatti -Paul Belanger -Paul Karikh -Paul McMillan -Pavel Sviderski -Pawel Palucki -Pawel Skowron -Pedro Kostelec -Peng Wu -Peter Belanyi -Prasoon Telang -Pádraig Brady -Qijing Li -Rabi Mishra -Radomir Dopieralski -Rafi Khardalian -Randy Bertram -Ravi Repaka -Ray Chen -Rich Bowen -Rich Hagarty -Richard Jones -Rishabh Jain -Rob -Rob Cresswell -Rob Cresswell -Rob Raymond -Robert C. Barth -Robert Mizielski -Robert Myers -Rodrigo Duarte Sousa -Romain Hardouin -Roman Podolyaka -Roman Rader -Rosario Di Somma -Russell Bryant -Russell Sim -Ryan Hsu -Ryan Petrello -Ryan Petrello -Sahid Orentino Ferdjaoui -Salvo Rapisarda -Sam Betts -Sam Morrison -Sam Stoelinga -Santiago Baldassin -Saro Chandra Bhooshan -Sascha Peilicke -Sascha Peilicke -Sascha Peilicke -Sascha Peilicke -Sayali Lunkad -Sean Dague -Sean Dague -Sergey Lukjanov -Sergey Reshetnyak -Sergio Cazzolato -Shamail Tahir -Shane Wang -Shaoquan Chen -Shuichiro MAKIGAKI -Simon Chung -Solly Ross -Stephane Angot -Stephen Gordon -Steve Baker -Steve Leon -SudheerKall -Sushil Kumar -Swaminathan Vasudevan -Szymon Wroblewski -Tapan Sharma -Tatiana Mazur -Tatiana Ovchinnikova -Thai Tran -Thiago Paiva -Thiago Paiva Brito -Thierry Carrez -Thomas Goirand -Thomas Stenberg -Tianpeng Wang -Tihomir Trifonov -Tim Schnell -Timur Sufiev -Todd Willey -Tom Fifield -Tom Fifield -Tomas Novacik -Tomas Sedovic -Tomasz 'Zen' Napierala -Tomáš Nováčik -Toshi Hayashi -Toshiyuki Hayashi -Travis Tripp -Tres Henry -Trung Trinh -Tyr Johanson -Tzu-Mainn Chen -Vahid Hashemian -Valerii Zhelezniakov -Veronica Musso -Vic Howard -Victor Morales -Victoria Martinez de la Cruz -Victoria Martínez de la Cruz -Vincent Untz -Vishvananda Ishaya -Vishwanath Jayaraman -Visnusaran Murugan -Vlad Okhrimenko -Wlodzimierz Borkowski -Wu Wenxiang -Xiao Hanyu -XinXiaohui -Yangyang Zheng -Yanping Xie -Yash Bathia -Yidan Zhang -Yuanhui Liu -Yuliya Portnova -Yuriy Taraday -Yves-Gwenael Bourhis -ZHU ZHU -Zhang Chun -Zhang Hua -Zhang John -Zhenguo Niu -Zhenguo Niu -ZhiQiang Fan -Zhigang Wang -Zhongyue Luo -Ziad Sawalha -aababilov -absubram -amcrn -amitpp -ankitagrawal -armando-migliaccio -avpra -chenhaiq -daisy-ycguo -daniel-a-nguyen -dkorn -dominik dobruchowski -eric -eric -ericpeterson-l -facundo Farias -heather -hyphon-zh -imran -imran -jackychen -jakedahn -jakedahn -jaypipes -jeffjapan -jing.liuqing -jmatayoshi -johndavidge -keshy -kstev -lawrancejing -lawrancejing -lin-hua-cheng -lin-hua-cheng -liuqing -liyingjun -liyingjun -lrqrun -mariamj@us.ibm.com -marianitadn -masco -mavinagi -meena -nanhai liao -nikunj2512 -nyechiel -qiaojian -ravikumar-venkatesan -root -sagardmni -sayalilunkad -simon -sleepsonthefloor -swati -tanlin -termie -tianliang -tintmy -tinytmy -utsav dusad -veena -whg -woodm1979 -yamini sardana -yuanke wei -zhang-hare -zhang-jinnan -zhu.rong -Łukasz Jernaś -Łukasz Jernaś diff --git a/code/horizon/CONTRIBUTING.rst b/code/horizon/CONTRIBUTING.rst deleted file mode 100644 index 7095b253..00000000 --- a/code/horizon/CONTRIBUTING.rst +++ /dev/null @@ -1,18 +0,0 @@ -If you would like to contribute to the development of OpenStack, -you must follow the steps documented at: - - http://docs.openstack.org/developer/horizon/contributing.html - - or http://docs.openstack.org/infra/manual/developers.html#development-workflow - -Once those steps have been completed, changes to OpenStack -should be submitted for review via the Gerrit tool, following -the workflow documented at: - - http://docs.openstack.org/infra/manual/developers.html#development-workflow - -Pull requests submitted through GitHub will be ignored. - -Bugs should be filed on Launchpad, not GitHub: - - https://bugs.launchpad.net/horizon diff --git a/code/horizon/ChangeLog b/code/horizon/ChangeLog deleted file mode 100644 index 3e4d6a1f..00000000 --- a/code/horizon/ChangeLog +++ /dev/null @@ -1,4368 +0,0 @@ -CHANGES -======= - -2015.1.0 --------- - -* Import translations from Transifex for Juno -* Format numbers in a locale sensitive manner -* update .tx/config to match Kilo Transifex resources -* Updated from global requirements -* Initialize variable 'networks' before referencing -* Fix addition of plugin panel to panel group -* Updated from global requirements -* Hide Cancel button if no cancel_url is provided -* Make status column on admin network table translatable -* [Launch Instance Fix] Security Group Nova Net -* update .gitreview for stable/kilo -* Updated from global requirements - -2015.1.0rc1 ------------ - -* Imported Translations from Transifex -* Add Russian to settings.py -* [Heat] Resource url mapping improvement -* Imported Translations from Transifex -* Fixing typo in OPENSTACK_NEUTRON_NETWORK section -* Imported Translations from Transifex -* Fixing typo in AVAILABLE_REGIONS section -* Fixing typo in CONSOLE_TYPE documentation -* Silently drop access to non-existent flavours -* [Launch Instance Fix] Show volume device name -* Imported Translations from Transifex -* [Launch Instance Fix] Settings for volume name -* Remove unnecessary class -* Launch Instance Step - Key Pair Import -* added network id field in update network model -* Imported Translations from Transifex -* Removing scope digest from login directive -* [Launch Instance Fix] Add Configuration Step Unit Tests -* Adding horizon to jshint -* Fixing the running of jobs without data sources -* Update customizing docs to include themes -* [Launch Instance Fix] Add Network Step Unit Tests -* Imported Translations from Transifex -* Minor Jasmine test cleanup -* Updated from global requirements -* Make "RAW" in image table translatable -* Make Image Type translatable -* Imported Translations from Transifex -* [Launch Instance Fix] Nested search box in flavor step -* Revert "Refactoring the exceptions lists" -* Removed unused injections in launch-instance-config step -* Fix logic in modal to accept cancel param -* [Launch Instance Fix] Add better coverage for widgets -* Imported Translations from Transifex -* Imported Translations from Transifex -* Replace '-' in Port Range column to 'Any' in secgroup rule table -* Remove meaningless "(CIDR)" suffix in Security Group Rules table -* Imported Translations from Transifex -* Fixing selenium tests to work with Django 1.7 -* [Launch Instance Fix] Conditionally enable UI -* [Launch Instance Fix] Remove a step if it is not ready -* [Launch Instance Fix] Fix detail rows not expanding on source and flavor -* Default to old Launch Instance workflow -* [Launch Instance Fix] Enabling loading script from local file -* [Launch Instance Fix] Launch Instance from Various Screens -* Rename utilsSpec.js to utils.spec.js -* Metadata widget multivalue selection support -* Updated from global requirements -* Detect apache version -* Imported Translations from Transifex -* Adding transclude to search-bar for batch actions -* [Launch Instance Fix] Flavor Metadata Details -* [Launch Instance Fix] Source Details - Metadata -* [Launch Instance Fix] Add Keypair Step Unit Tests -* [Launch Instance Fix] Glance rest API fix -* Add hzSelect directive to Angular table -* [Sahara] fix sahara client calls -* Imported Translations from Transifex -* Pass SSL parameters to sahara client -* [Launch Instance Fix] Fix css for transfer table -* Sort the panel's variable in the dashboards.py -* [Launch Instance Fix] Making table expand faster -* Launch Instance - MultiRegion Support / Networks -* Refactoring the exceptions lists -* Fetch user's projects from request.user -* Add help text to DeleteVolumeTransfer action -* [Launch Instance Fix] Cleanup $scope injection in help controllers -* Fix sort order for User IDs in identity table -* Warn if boot volume AZ differs from instance AZ -* Imported Translations from Transifex -* [Launch Instance Fix] Enhancing wizard widget -* [Launch Instance Fix] Update Local Settings Sample -* [Launch Instance Fix] Adding unit tests to hz.dashboard -* [Launch Instance Fix] Adding validation -* Improve instance source form field valignment -* Fix web-server memory overrun when downloading objects from Swift -* Enable login via openID and SAML -* Fix unlikely XSS in attachment rendering -* Updated keystone api for roles and edit -* Refactor/remove obsolete page_header blocks -* Update instruction for publishing xstatic packages -* Fix bad performance on project update panel -* Updated incorrect name for angular lrdragndrop -* passing wrong dict in lbaas -* Add 7 missed meters in Resource Usage Panel -* Modified hzSelectAll to select all visible checkboxes in table -* Modify form for Volume Transfer Details -* Add subtitle text for Launch Instance source step -* Modified hzSelectAll to watch changes in row length -* Add --location option to image create -* Use WEBROOT setting for the 500 page home button -* [Heat] Fix default values displaying for "Launch Stack" -* Remove duplicated __init__ from api/fwaas.py -* Imported Translations from Transifex -* Adds configuration support to associate firewall to routers -* Imported Translations from Transifex -* [Launch Instance fix] Show header for Source Allocated table -* Correct the identity groups create url -* [Launch Instance Fix] Add details to Select Flavor step -* Removing HA interfaces from port list -* [Launch Instance Fix] Split Security & Access in 2 -* [Sahara] Added indirect access support -* [Launch Instance fix] Fix decimal point -* Removing unnecessary and annoying error message -* Add help panel text - Launch Instance source step -* [Launch Instance Fix] Wizard should have max-width of 1440px -* Adding styling for disabled and danger action items -* run compilemessages with runtime deps -* Correct "Uptime" field in csv report file -* Makes Launch/ Edit buttons in Images explicit -* change the floating_ips tables.py argument -* Imported Translations from Transifex -* Change preset for resource usage to 'last day' -* Imported Translations from Transifex -* [Launch Instance Fix] Add step help content -* Adding spyOn and jasmine to global jshint -* Fixing changing WEBROOT from / -* Fix horizon login autocomplete control issues -* Next/Create button loses state in create network -* Fix common misspellings -* [Data_processing] fix job_executions table -* Fixes inconsistent Edit between tables & details -* Fixes inconsistent Router Details page -* Use novaclient v2 instead v1_1 -* Imported Translations from Transifex -* Imported Translations from Transifex -* I18N: Allow to control word order in create_pseudo_folder -* Imported Translations from Transifex -* Updated from global requirements -* Removing apiPromise -* [Launch Instance fix] Refactor translation for Angular filter -* Removing absolute URLs from data processing templates -* Improve Launch Instance step subtitle styling -* [Launch Instance Fix] Remove outline from basic search bar -* Translated count filter for table footer -* Add html source code on test failure for debugging -* Admin state column added in firewall table -* Fix security group checking action permissions raise error -* Imported Translations from Transifex -* Replace 'raise AssertionError' with 'self.assertIn' -* Custom Horizon Theme -* Add placeholder text to transfer table search bar -* [Launch Instance Fix] Launch instance refreshes instance tables -* Magic Search Enablement -* Source step - fix dynamic column headers and data - -2015.1.0b3 ----------- - -* Changing the order of panels for data processing -* [Launch Instance Fix] Cleaning up unused injected dependencies -* Add column sorting to Access & Security tables -* Make "cluster type chosen" translatable -* Adds initial SRIOV creation/config support -* Change of path of wrap_delimiter function -* Global error HTTP handler -* Make guided job success message translatable -* Fix small typo in error in data processing wizard -* Make sahara permission check backward compatible -* Changing terminology for jobs and job executions in data processing -* Imported Translations from Transifex -* Add fallback on sahara endpoint lookup -* Improve styling for key pair detail table -* Fixing typo in Cinder API -* Fixing typo in Glance API -* Metadata display widget -* [Launch Instance fix] Flavor table should be sorted by RAM -* Improve styling for security group detail table -* Source step - fix donut chart label color -* Add Django-1.7 support -* Imported Translations from Transifex -* [Launch Instance fix] Removing step number in Wizard widget -* Add missing telemetry policy example file -* Allow specifying authentication URLs from settings -* [Launch Instance Fix] Add Sorting To Table in Select Source -* [Launch Instance Fix] Removing period from selecting tips -* [Launch Instance Fix] Network Step HTML cleanup -* Metadata widget support for readonly flag -* Imported Translations from Transifex -* hypervisor list and details page reports invalid data -* Source step - fix instance count limit and donut chart -* Correct ngdoc in Neutron AngularJS service -* Launch Instance Step - Network -* Fixed transcluded content not updating in action list -* Replace usage of urllib in nova rest api -* Refactor, customization and fixes of Metadata Widget -* Updated overview graph when usage exceeds quota -* Show ports from shared nets in floating IP assoc -* Heat resource url mapping improvement -* made all status values translatable in port table -* Imported Translations from Transifex -* Fix transfer tables example -* Imported Translations from Transifex -* Launch Instance Step - Configuration -* Launch Instance Step - Access and Security -* Launch Instance Step - Select Flavor -* Launch Instance Step - Select Source -* Launch Instance Model -* Launch instance - common style -* Clean modal forms in Orchestration Stacks -* Add "Preview Stack" action to Stacks table -* made network status value translatable -* Imported Translations from Transifex -* Redirect initial hit to login page -* Updated transfer tables -* Fix CSS, remove bad semicolon in _variables.scss -* add the package 'which' to fedora -* Fixes alignment of pencil icon in Users Table -* Guided job execution page for Sahara -* Guided cluster creation mode for Sahara -* Imported Translations from Transifex -* Follow-up patch to fix a descrition in docs -* Imported Translations from Transifex -* Angular-based Modal Wait Spinner Widget -* [Launch Instance Fix] Filter AKI and ARI Images -* Modified "remote" column in the secgroup table -* added check for delay >= timeout in LB add monitor -* Support to move the horizon relative to web root -* Imported Translations from Transifex -* 'External Gateway Information' TO 'External Gateway' -* Double check admin password when update user password -* Refactor multiple references to $(document) -* Action List with Angular directives -* Fixing permissions for data processing panels -* Updated parsing of catalog to handle bad format -* Remove unviewable data from dashboard images (gif/png) -* Updating sahara image registry form for dynamic adds -* Always show stack status reason in topology -* Add job create test -* Imported Translations from Transifex -* Add missing "plus" symbol to the firwall Add Policy button -* Imported Translations from Transifex -* Narrow selector to eliminate JavaScript keydown perf hit -* Floating IP table should support sorting -* Angular Form Password Validation -* Allow to hide tab title bar when only one tab is available -* Set OS_PROJECT_NAME -* Replacing data_processing with data-processing -* Imported Translations from Transifex -* Base dashboard Jasmine framework -* Updated Wizard Help Panel Design -* Fixing up job binary creation in data processing -* Angular Filter files -* Add test_sahara_create_delete_job_binary test method -* Add test_sahara_image_registry -* Imported Translations from Transifex -* admin state column added in router table -* Updated from global requirements -* Fix tutorial to correctly display custom dashboard/panel -* Move variables from accordion nav to _variables.scss -* Use _wait_for_spinner() -* Clean up whitespace in settings files -* REST API to support create instance angular (Neutron) -* Refactor modal forms for Volumes -* Imported Translations from Transifex -* Permit using latest python-cinderclient -* Remove extra jQuery object creation in horizon.modals.js -* Allow Jasmine failures to fail test -* Fix Jasmine unit tests failing -* Avoid failure when spinner is already gone -* Fix inappropriate error message for network table -* edit option hided when firewall in pending status -* Imported Translations from Transifex -* Keystone REST API single project GET -* context['view'] not available in Serial Console -* Rest API for Users list filter -* Fixing job binary creation from existing file -* fixed row update for loadbalancer tables -* Refactor of Metadata Widget -* Missing commas in one-element tuples -* cancel next previous buttons are aligned properly -* Imported Translations from Transifex -* Creating a new volume_type's extra_specs returns a relative path -* Imported Translations from Transifex -* REST Angular for Cinder Fix -* Imported Translations from Transifex -* Pie and donut chart directive -* Load "url" in Serial Console html -* Fix router details's name empty and change inheritance project table -* Adding policy rest endpoint for angular -* Generate a drop down field for custom heat parameters -* Replaced hard coded values with oslo_utils.units constants -* Making Resource panel visible where appropriate -* New generic _wait_until method which wraps selenium waiting -* Fix typo, replace ass with as, not ass:( -* Add help text to BatchAction -* made action value translatable in firewall rules table -* Imported Translations from Transifex -* Prevent flash of left nav panels when loading page -* Fix skip decorator in integration tests -* Add django url tag to network create template -* Nova Flavor Server Extensions Rest APIs - Angular -* Refactor REST API tests for common code patterns -* Fix Jasmine unit tests failing -* Fix typo errors in comments for api modules -* Imported Translations from Transifex -* spelling mistakes on display outputs and docsstrings -* Transfer tables -* Add orchestration service status reporting -* Adding Angular IrDragNDrop to requirements.txt -* Updated from global requirements -* Fix N1K Profile creation -* Updates tab bar styling -* Refactor modal forms for Access & Security -* Imported Translations from Transifex -* Read access to config via REST -* Go button on the Instance Log page should be enable all the time -* Skip also test fixtures when the entire class is skipped -* MapR FS datasource -* Reduce page title duplication in Data Processing -* Add string for verbose name -* Error handling patterns are consistent in volumes forms -* Change Edit volume button to save -* Make the values of Stack Resource status be translatable -* Refactor modal forms for Settings dashboard -* Add log lines change to settings page and test -* Imported Translations from Transifex -* Default sort added to hzTable -* Remove unused import -* Imported Translations from Transifex -* Update to horizon tutorial.rst -* Network Rest API for Angular Front End -* makes router id visible in update router modal -* Migrate all instances from host marked for maintenance -* improved the create router form -* Cinder REST API for angular front end -* Add service catalog get for keystone REST API -* Fixing CSS namespace collision over wizard -* Updated from global requirements -* Show MTU in Network details page -* Imported Translations from Transifex -* Make "enabled" colume values display-friendly and consistent -* Updated from global requirements -* Replace unittest2 with testtools -* Base launch instance wizard -* Wait till spinner disappears -* Refactor modal forms for Ports -* Refactor modal forms for Load Balancers -* Make Default value for Groups column translatable -* Remove Heat from example local.conf -* [Sahara] Fix Node Group Templates copy -* Incorrect error message when VM deletion failed -* Remove useless deepcopy to avoid Maximum Recursion Error -* Imported Translations from Transifex -* Serial Console -* Nova REST API for angular front end -* Net name field is not required when creating port -* move Users Edit Password into separate form -* Glance Rest API for Angular Front End -* Refactor modal forms for VPN -* Reduce page title duplication in Admin networking -* [Sahara] Add status description for clusters -* Reduce page title duplication in Adv net services -* made firewall status value translatable -* Make values for IPSec&VPN status be translatable -* Imported Translations from Transifex -* Updated from global requirements -* Help text clarification for data processing data sources -* Refactor modal forms for Routers -* Reduce title duplication in project networking -* Remove test skipping since #1396954 was fixed -* Allow adding to INSTALLED_APPS from local_settings.py -* Imported Translations from Transifex -* [Data processing] Fixing data source create form to be switchable -* Refactor modal forms for Firewalls -* Fixes error message during volume snapshot creation -* Refactor modal forms for Nexus1000v -* Refactor modal forms for Subnets -* Fixing Ceilometer measurements descriptions and comment typos -* Add horizon.cookies.getRaw to access raw cookie values -* Fix inconsistent sidebar toggle icon -* Fix missing icon of `Terminate instance` -* Fixes inconsistent Admin > Instances table header -* List shared firewall policies/rules in Project panel -* Refactor modal forms for Networks -* Applies ImageFormCtrl to Admin > Images -* Revert "Fix shared firewall policy can not be displayed in horizon" -* Adding constants to tables -* Add help text for vcpu hours -* Fixing Bug 1421818 - Jasmine tesing failed on FF -* Improving jshint -* Extending Horizon's plug-in architecture to Jasmine -* Remove unused import NoReverseMatch -* Adds default for resource_type_names in metadata -* Imported Translations from Transifex -* Angular Confirmation Modal -* Updated from global requirements -* remove duplicate line from users/views.py -* Make auto console type in network topology work -* Use IDs in locators instead of CSS when it is possible -* Reduce page title duplication in settings and test -* Reduce page title duplication in Images & Instance -* Reduce page title duplication in Identity views -* unite the property of usage test -* Imported Translations from Transifex -* Add missing comma in Create Network help string -* Add virtual size to image detail -* [Data Processing] Fixing job binary form label text -* Set the password_autocomplete default to "off" -* Reduce page title duplication in Nexus1000v views -* Reduce page title duplication in Stacks -* Reduce page title duplication in databases -* Reduce page title duplication in Containers -* Reduce page title duplication in A and S views -* Reduce page title duplication in Admin volumes -* Reduce page title duplication in Admin views -* Reduce page title duplication in Admin Images -* Reduce page title duplication in Admin Hypervisors -* Reduce page title duplication in Admin Flavors -* Reduce page title duplication in Admin Defaults -* Reduce page title duplication in Admin Aggregates -* Re-designed and Angularized tables -* Document and improve PageTitleMixin readability -* Add missing stubs to project stacks tests -* Add missing percent-format character -* Reduced code duplication in creating page headers -* made interface status value translatable -* Use less permissive chmod in secret key test -* Imported Translations from Transifex -* made router status value translatable -* [Data Processing] Changing node group form to be switchable -* Enabling jsi18n in Jasmine spec runner -* Fixing service name typo -* Stack resources table improvement -* Make values for Database&Backup status be translatable -* Imported Translations from Transifex -* Translatable system information panel state/status -* Fix documentation for setting password_autocomplete -* Fixes inline edit icon size/placement -* added filter for keypair and security and access tables -* Change N/A to id in the message -* Imported Translations from Transifex -* made stack status value is translatable -* change the network page's layout when launch instance -* Integration test - Create and delete user -* Add support for Trove Replication -* Imported Translations from Transifex -* Imported Translations from Transifex -* Adding policy support for ceilometer -* Data Processing: changing labels of submit buttons -* Making modify usage report params modal -* Correcting JavaScript files order -* Improves Launch Cluster model in Data Processing panel -* Adds styling of "Confirm Password" Field in user forms -* Imported Translations from Transifex -* Fix import order in utils/metering.py -* add angular-bootstrap to jasmine spec runner page - -2015.1.0b2 ----------- - -* Added a migrate_settings command -* Imported Translations from Transifex -* Changes Identity->Projects Forms into Horizontal Forms -* Create a reusable angular-based wizard -* Move to hacking 0.10 -* [Sahara] Fixed copy nodegroup template when sec groups missing -* Make values for name&status about job_executions be translatable -* Fix typo in calling _is_element_visible method -* Make port status and state translatable -* Make params order fixed in stack forms -* Make the values of Cluster status be translatable -* Fixes Error message during image upload due to long name -* Remove unused import urlencode -* added detail page for keypair -* Remove not required parentheses for tables.Column(link=..) -* Required fields' asterisk missing in 'Launch Instance' Dialog -* Make test helpers properly inheritable/extendable -* Fixes Resource id mapping with Heat Resources -* [Sahara] Support Cinder availability zones -* Add "btn-create" Class to Create Volume Button -* Imported Translations from Transifex -* Alter verb usage for keystone REST and add Angular service -* Clean unused code for `supports_tenants` -* New admin volume panel to manage/unmanage volumes -* Remove extra code in memoized method in Volumes -* Remove extra indention in Firewall views.py -* Add wait till element methods for selenium Integration tests -* Fix replacement of exception category list -* Message appear N/A in the tab compute host of hypervisors page -* Make size columns be text wrapped in admin dashboard -* Make values for volume status be translatable -* fix bug - failed loading external angular templates -* Fix shared firewall policy can not be displayed in horizon -* added filter for stacks table -* Add missing OS::Cinder::Volume resource url map -* Imported Translations from Transifex -* Make values for image status be translatable -* Removing reference to deleted template -* Metadata widget support for default values -* Add support for OVA images in Horizon -* Add ram-hours in overview page -* Updating stack resource urls mapping -* angular-based help-panel widget -* Imported Translations from Transifex -* Imported Translations from Transifex -* Quality of life improvements to APIVersionManager -* Correct the policy check call in keystone -* Alert user on JavaScript requirement if it's disabled -* 403 page displays trans template tag -* Create a "Identity Projects details" page -* Enables the editing of Allocation pools in edit subnet -* Heat stack status column improvement -* Imported Translations from Transifex -* Updated from global requirements -* Make Enabled column values translated -* Updates contribution guidelines for JS object performance -* added flavor id in instance detail page -* Imported Translations from Transifex -* Display loading status when database is building -* Makes create time in Job Binary Details more readable -* Fixes checkbox alignment in multi-select column -* Adding filtering to data_processing tables -* Add *.lock to .gitignore file -* Pulled CSS logic from inline-editing -* Fix editing current project -* Imported Translations from Transifex -* Handle RequestURITooLong error in large instance table -* Clean modal forms in Identity Users -* Improving data processing create job form -* Correcting heat resource page title -* Adding review clean up script -* Improving data processing job binaries form -* Refactor metering utility and view functions -* Add general function for generating random names -* Throw a warning message when failed to get pool detail -* Imported Translations from Transifex -* Updated from global requirements -* Add Unit column to Usage Report table -* Replace lockfile by oslo_concurrency -* Imported Translations from Transifex -* Fixes spacing in Containers details modal -* Remove unused wait_for_title method -* Imported Translations from Transifex -* Fix help message in "Manage Floating IP Associations" dialog -* Add "Suspend" and "Resume" actions to Stacks table -* Misspell in comments in settings.py -* Resource types table improvement -* Imported Translations from Transifex -* when launch instance image size changed, device_size not change -* Keystone REST API for angular front end -* Moving policy engine implementation -* Removing dead css -* Fix spelling and description in IPv6 subnet modes -* Remove extra jQuery object creation in horizon.instances.js -* added filter for networks and router -* equal(=) added in project filter option -* password visibility icon not shown for first page -* Fix cell(User Name) inline edit with a link in user table -* Imported Translations from Transifex -* Fix incorrect mocking in quota tests -* Wrap the main block of detail.html with col-sm-12 class -* Add "Check Stack" action to Stacks table -* List port for distributed router interface -* Fix sorting by size for Project->Images table -* Update Horizon to Jasmine 2.1.x -* Disable the IPv6 components in Subnet form -* Orchestration Resource types panel -* Change uptime to time since created -* adopt namespace-less oslo imports -* Imported Translations from Transifex -* revise settings doc with Font Awesome reference -* Pseudo translation tool -* Adding -ac and -noreset arguments to Xvfb -* Fix grammatical mistake in contributing.rst doc -* Updated from global requirements -* Fix PEP8 issues in the panel template -* filter added for snapshots and types -* Imported Translations from Transifex -* Change mbformat to mb_float_format -* Fix broken network topology css -* Unify the syntax used for the {% ... %} delimter in Jinja2 templates -* Update AngularJS best practices for translatable string -* Unify the syntax used for the {{ ... }} delimter in Jinja2 templates -* Imported Translations from Transifex -* Switch from oslo.utils to oslo_utils -* Imported Translations from Transifex -* Add page forward and refresh wrapper functions -* Imported Translations from Transifex -* Fix setting Primary Project for new user once the project was created -* Better description for Floating IPs quota usage diagram -* Imported Translations from Transifex -* Cleanup copyright from static_settings -* Update Metadata Widget to angular 1.3.7 -* Integration tests - Imagespage and test -* Separate static_settings.py from settings.py -* Updating startpanel for pluggables -* Makes User Details page consistent with others -* Tests pass in languages other than English -* Flavors page and basic create flavor test -* Modified teardown method to handle login and logout failure -* Updating Horizon contributing docs -* Make table BatchAction help text configurable -* Make ipmi meters be visible in Horizon -* Imported Translations from Transifex -* Update description for 'Create Snapshot' -* we don't need to allow insecure any more -* Remove unused method get_stats -* Decorator for skipping tests hitting known bugs -* Fixed the inconsistent VCPU-Hours summary -* REST API for angular front end -* Change "Add..." to "Add Users" in Group Management -* Updated from global requirements -* [Sahara] Moved security options to separate tab of ng template -* some FilterAction attributes don't show in docs -* [Sahara] Added links to security groups -* Refactoring main_content css -* Implementation inline table editing for Users table -* Do not show progress bar for shelved instance -* Imported Translations from Transifex -* Imported Translations from Transifex -* Fix disappearing Sahara workflow navbar in 'Jobs' panel -* Fixes 2 password visibility icons -* Add new angular dependencies to requirements.txt -* Updated from global requirements -* Replace use of
tag in RouterRules Grid template -* Imported Translations from Transifex -* Changing term 'name' to 'slug' -* View encryption metadata for encrypted volumes -* Password reveal feature should be configurable -* Updated from global requirements -* Cleanup angular 1.2.1.1 dependencies -* Fixes Error message during image upload due to file filtering -* Fixes resource name problem in "Resources Usage" tab -* Reorganized scss imports -* security group not mandatory to create instance -* Updated from global requirements -* Fix multi-nic issue with nexus plugin -* Imported Translations from Transifex -* Integration test for showing logout message (password change) -* Imported Translations from Transifex -* Fixed display issues on Details Page caused by bootstrap 3 update -* Clean modal forms in Identity Roles -* Clean modal forms in Identity Groups -* Added tests for Data Image Registry -* Imported Translations from Transifex -* Add support for volume transfers -* Removing Moscow's timezone check -* Imported Translations from Transifex -* Filter current flavor in resize instance/database -* Spelling fixes in images tests -* Adding back scroll on Project members list style -* Prevent user from disabling her current project -* Removes reference to compute api v1.1 in openrc -* Potential 500 pages on allowed methods removed -* Allow all printable ASCII characters in security group names -* Fix UncompressableFileError for latest horizon code -* Using get_url_current_page wrapper method -* Imported Translations from Transifex -* Automatically expand the current panel group on dashboard expansion -* Add TabbedFormRegion to Integration tests -* Imported Translations from Transifex -* Display the vip name in the floating IP association dialog -* Add missing nova meters for metering -* Imported Translations from Transifex -* Add a graphical distinction for external networks at Topology page -* Fix method passed to selenium way it suggests -* Imported Translations from Transifex -* Fix wrong calling of selenium driver function -* Add navigation among pages -* Creating a new user with an existing user name -* Imported Translations from Transifex -* Adds the security group id besides the name in Manage Rules -* Create a "user details" page -* Imported Translations from Transifex -* Add collectstatic commands to install doc - -2015.1.0b1 ----------- - -* Updated from global requirements -* Fix Firewalls panel to override the right method -* Imported Translations from Transifex -* Base Glance Metadata Definitions Admin UI -* Integration tests - 3 new form fields -* Imported Translations from Transifex -* Updated description of update user form -* Nav submenu font size smaller -* Test's random name gen now uses uuid4 -* Make admin_state translatable -* Set topology container to scroll -* Add bootable flag to edit volume panel -* Check input for Log length -* Added tests for Node Group Templates' create and copy workflows -* Imported Translations from Transifex -* Add volume type encryption delete -* Updated from global requirements -* Documenting create_stubs decorator for tests -* Clean '/tmp' after image upload from horizon -* Imported Translations from Transifex -* Small performance improvement -* Wrong success url for instance floatingip related actions -* add missing icons for Project > Images filter -* Update project list in the header bar -* Fixes Inconsistent usage of Detail / Details -* Updated from global requirements -* Imported Translations from Transifex -* No delete volume action for volume with snapshots -* Updated from global requirements -* Fixes the Order of "launch" buttons on jobs panel -* removing mandatory mark for post_creation tab -* Ability to change modal form backdrop element behavior -* Add "login as admin" for integration tests -* Imported Translations from Transifex -* Fixed issue of progress bars in resize instance -* [Sahara] Fixed display of nodegroup template service parameters -* With angular hz module, use strict & avoid globals -* Provide tenant_id in Neutron create requests -* Imported Translations from Transifex -* Replace set_id_as_name_if_empty with name_or_id -* Horizon login page contains DOS attack mechanism -* Improving more projects link in context selection -* Fixed row deletion for deleted stack -* Modal fixes - 2 columns, padding, header, membership -* Imported Translations from Transifex -* Add _wait_till_text_present_in_element method -* Imported Translations from Transifex -* Refactor horizon/common/_modal_form.html template -* POST instantiation for Django-Angular -* Updated from global requirements -* Fix Terminate Instance on network topology page -* Imported Translations from Transifex -* Split large methods into submethods to reduce max-complexity -* Workflow documentation is now in infra-manual -* Fix dropdown menu does not open with firefox 34 -* Updated from global requirements -* Cell empty value defaults to - removing redundancy -* Imported Translations from Transifex -* update/cleanup bootstrap 3 icon usage -* Standardizing translation of "-" -* Add plus icon on AddDHCPAgent button -* Imported Translations from Transifex -* Add pencil icon on Update Defaults button -* Adding Host Server to instance detail page -* Changing icons for floating IP association -* Create titles without concatenation -* Change "Modify Users" to "Manage Members" -* Add 'Start/Stop Instance' to Instances table actions -* Replace the glyphicons with font awesome icons -* @import font-awesome styles, instead of including -* Change arrow transparent borders to inset borders -* Add volume type encryption to horizon -* Prevent leaking `target` info into subsequent `policy.check()` calls -* KeyError on getting PanelGroup -* Handle situation when endpoint deleted -* Remove port_id from floating ip disassociate -* Imported Translations from Transifex -* Quotas for users with admin role do not work -* Fix the expression to be python3 compatible -* Imported Translations from Transifex -* Enable tables inline-editing in lazy-loaded tabs -* [Data_processing] auto security group -* Imported Translations from Transifex -* Fix popup error when volume service disabled -* Add menu regions to integration tests -* Add form regions to integration tests -* Add new directory structure for page objects -* Restyled sidebar to resemble UX guidelines -* Integration tests - switch_window method -* Temporarily disable the Jasmine unit tests -* Show up to 1 decimal place for instance detail RAM -* Add fix for incorrect display email in inline editing input -* Include instance name in errors on Instance Details -* Remove Python 2.6 classifier -* Imported Translations from Transifex -* Stack update call needs password -* Fix dashboard nav, when panelgroup empty -* Imported Translations from Transifex -* [Sahara] Fixed job execution update for deleted row -* [Sahara] Do not request for nodegroup template if not present -* Support for resizing a trove instance -* Renaming a user name with an existing user name -* Imported Translations from Transifex -* Imported Translations from Transifex -* Add regions module to integration tests -* Gracefully handle failures to retrieve a flavor -* Make 'IP address' field optional for LBaaS VIP creation -* Imported Translations from Transifex -* place the word "Info" with "Information" -* Update project limits when using input selector -* Adds ability to set default log length -* Corrected IPv6 Address Configuration Mode tooltip -* Updated from global requirements -* Integration test for fix the logout issue in basepage -* Delete duplicated code from router tests -* Imported Translations from Transifex -* Update metering unit selection to use smaller units for time -* Make Task state translatable -* Disable "Associate floating IP" when instance error -* Imported Translations from Transifex -* Support nova service-disable/enable for Hypervisor -* Automatically remove interfaces on router delete -* Modal form cleanup -* Add values for empty sahara dropdown boxes -* Add unit conversion for metering views -* Remove 'action_*' for tables.LinkAction -* Set row action dropdown to right-align -* Updated from global requirements -* Change CSV file date format to Horizon standard -* Fix Instance Details error when using Cinder V2 -* Imported Translations from Transifex -* Adding missing table headers -* Defining missing failure_url -* Add delete tests for Data Processing panels -* Data Processing - capitalize some delete action buttons -* Data Processing delete buttons missing icon -* Adds a dynamic subheading to delimit floating IPs -* Updated from global requirements -* Imported Translations from Transifex -* Escape help text for Remote field in Rule panel -* Make Power State column on admin instances translatable -* Update project limits when flavor changes -* Documentation error in base tables link_classes -* Fix TemplateSyntaxError at hypervisors view -* Added a modal dialog with the user credentials details -* Remove duplicated headings from horizon tables -* Update integration tests password -* Error messages for failing floating IP association -* Fixes group by none defect in resource usage stats: -* Fixes ceilometer test data spelling error: -* Add support for locking and unlocking servers -* Only enable one images filter button -* Imported Translations from Transifex -* add tooltip to cells if 'truncate' variable is set -* Change ComputeHost table to filter on host field -* Reorganize variables to enable overriding -* Change network status cell values to Title case -* 'Stack Template' tab for Heat Stack Details page -* 'Session timed out' error on 'Login' sceen doesn't have proper css -* Imported Translations from Transifex -* Field "Volume name" on Horizon no longer mandatory -* Imported Translations from Transifex -* Fix misaligned actions on table toolbar -* Honor keystone policy file when creating client -* Imported Translations from Transifex -* Updated from global requirements -* Imported Translations from Transifex -* Fix incorrect ca arguments for calling ceilometer client -* Fix Horizon crash when parsing volume list -* Updated from global requirements -* Typo in "Tutorial: Building a Dashboard using Horizon" -* Integration tests - BaseWebObject class -* Imported Translations from Transifex -* wrong message while deleting non empty pseudo folder -* Add 'Device Name' in Launch Instance Dialog when 'Boot from Volume' -* Imported Translations from Transifex -* Display action column buttons on single line -* Make update metadata segments translatable -* Create Subnet button should respect quotas -* Guard against `None` value of User.email attribute -* Imported Translations from Transifex -* Clarify meaning of "Disk GB Hours" column -* Invalid instance_snapshot causes KeyError -* Missing a closing semicolon in _configure_general_help.html -* Return eye-icon to its place when validation message is shown -* Handle negative values in total*Used for Cinder absolute limits -* Modal forms have extra borders -* Update state of table batch actions based on row selection -* Imported Translations from Transifex -* Imported Translations from Transifex -* Fixes double slash problem in Swift Container pseudo folder -* Imported Translations from Transifex -* Better color arrangement in distribution pie charts -* Move the panel mocks to a separate method on TestCase -* Fixes nothing is displayed if volume metadata is empty problem -* Imported Translations from Transifex -* Determine environment version based requirement files -* Use cinder API v2, remove support for v1 -* Imported Translations from Transifex -* Hide the "Host Aggregates" admin panel if not enabled -* Fix borders for "Actions" column in Firefox -* Changed Project members list style, added scrolls -* Imported Translations from Transifex -* fix wrong background color on workflow tabs -* Make status in instance details screen translatable -* Resource Usage Overview - reduce dropdown menu width -* Add init methods to javascript -* Fix dynamic select layout when help block is displayed -* Make modal dialogs draggable -* Fix misleading message in Update Metadata Form -* Refactor metering dashboard -* Disallow Resize Volume If Status Is Shutdown -* Fixing typo -* Replaces always disabled context selection link -* Juno Release Notes -* Change "System Info" to "System Information" -* Update JavaScript best practices -* Create buttons in network topology respect quotas -* Imported Translations from Transifex -* Remove string concatenation related to volume attachment -* Dropdown Actions For Database Details Page -* Imported Translations from Transifex -* Add max-complexity to pep8 for Horizon -* add missing semicolon in networktopology -* Imported Translations from Transifex -* Make labels in Network Topology translatable -* Pass correct project ID to get tenant_usages -* Disable router HA attribute due to Neutron bug -* Removes term inconsistency in the dashboard -* Do not log keystone token -* Imported Translations from Transifex -* Fixing template syntax -* add Column attribute for help tooltip in heading -* Update WSGI app creation to be compatible with Django 1.7 -* Fix E128 errors in remaining openstack_dashboard/ -* Fix E128 errors in openstack_dashboard/dashboards/project/ -* Imported Translations from Transifex -* Restyled topbar to resemble UX guidelines -* Restrict the length of user name input -* Make "VLAN", "VXLAN" and "GRE" translatable -* Update Horizon terminology relating to storage -* Improve sub-navigation styling -* _formset_table_row.html missing i18n tag -* Ensure DataTableView applies filter after redirect -* Hiding device name field when unhandled -* Imported Translations from Transifex -* Fix E127 errors in remaining openstack_dashboard/ -* Fix E128 errors in openstack_dashboard/dashboards/admin/ -* Fix E128 errors in horizon/ -* Fixes KeyError in floating ip unit test -* Add floating ip status to table -* [Sahara] Support Nova availability zones -* Imported Translations from Transifex -* Fixes poor error message when deleting networks -* [Sahara] style the template parameter configuration filter -* Improve list groups roles performance -* Breakdown CSS: split styling for table inline edits -* Remove unused openstack.common.importutils -* Do not override user-defined Device Size -* Update doc/source/conf.py -* Use timeutils from oslo.utils -* Updated from global requirements -* Updates to horizon settings.rst -* Fix sidebar background color -* Imported Translations from Transifex -* Imported Translations from Transifex -* Updated from global requirements -* Use strutils from oslo.utils -* Migrate jsonutils to oslo.serializer.jsonutils -* Sync oslo-incubator for fileutils, log and policy -* Imported Translations from Transifex -* Avoid shutting off a paused VM instance -* Fix E127 errors in other openstack_dashboard/dashboards/ -* Fix E127 errors in openstack_dashboard/dashboards/project/ -* Add graduated oslo code to requirements -* Stubout cinder.tenant_absolute_limits in cinder test -* Remove selenium dependency when not using selenium tests -* No longer stripping dots from downloaded filenames -* Add ':' inside translatable (Part 1 of 2) -* Clean up test output -* Imported Translations from Transifex -* Fixed sahara cluster details page -* Change django message storage backends default -* 'Delete Volume Types' button typo -* Hide right border for the active tab in nav bar -* Add check for makemessages in tox.ini PEP8 -* Remove compiled message catalogs -* fixed errors when run_tests.sh --makemessages -* Revert file permissions -* Fix for "No existing metadata" in Horizon metadata selector -* Removed references to hadoop data_processing -* Fix an encoding exception when creating a public_url -* Revert file permissions changed unexpectedly -* display boolean and json parameters in stack launch form -* Add install guide for users and clean up README -* allow empty device name when launching an instance -* Fix jshint failure in horizon.d3piechart.js -* Updated tenant_id to project_id in policy.py -* Add workaround for StaleElementReferenceException -* Imported Translations from Transifex -* Updated from global requirements -* Remove @author tags from copyright statements -* fix tiny gap in navigation sidebar -* Add ':' inside translatable (Part 2 of 2) -* Add support for row actions to detail pages -* Add dropdown actions to all details pages -* Add dropdown actions to detail page -* Change labels in QOS Specs panels -* Improve tabs styling -* Imported Translations from Transifex -* Reduce height for "Description" text areas -* Show domain name in the change project dropdown -* Make timezones translatable -* Fix inconsistent behaviour exceeding quota limit -* Imported Translations from Transifex -* Warn OPENSTACK_QUANTUM_NETWORK setting as deprecated -* Use action_present/past methods in BatchAction -* Support BS3 events in Retrieve Instance Pw -* Hide gateway ip input field if gateway ip disabled -* Style network address for subnet as required field -* Imported Translations from Transifex - -2014.2.rc1 ----------- - -* Add a session cache of can_access call results -* Enable launching instance from zero-size image snapshot -* Fix E127 errors in openstack_dashboard/dashboards/admin/ -* Imported Translations from Transifex -* fix redirect for admin user password relogin -* Amending the quickstart guide -* Add "cancel" button -* Change column uptime -* Use shades of blue for distribution pie charts -* Move translator notes just before translatable strings -* Sort networks and projects by name instead of UUID -* Fix E127 errors in horizon/ -* Override Error Message in Create Subnet Workflow -* Remove and deprecate dashboards config from settings file -* Imported Translations from Transifex -* Display only reachable IP as Floating IP association target -* Make Image Description an input field instead of a textarea -* Unbundle bootstrap and use xstatic version -* Open Kilo development -* remove read-only network ID field from Edit Network form -* Workaround for 'File exists' test failure -* Revert "Remove the update default quotas feature" -* Imported Translations from Transifex -* Updated from global requirements -* Use identity operator in horizon.modals.js -* Remove #noqa from django.conf.urls.include -* Imported Translations from Transifex -* Redefine instance.security_groups as list -* Imported Translations from Transifex -* Remove glyphicon-eye-open icon from Description -* Add HA mode support for Neutron router -* Imported Translations from Transifex -* Updated from global requirements -* Persist usage start and end dates in the session -* Fix concatenation in more misc actions -* Fix concatenation in Network and Router actions -* Fixing issue with editing N1K network profiles -* Fix concatenation in identity related actions -* Fix concatenation in Database actions -* Checking session timeout before authentication -* Fix concatenation in data processing actions -* Fix for Data Processing Templates copy -* Disable buttons opening the modal forms on page unload -* Job Execuiton form improvement -* Upgrade and unbundle jquery-ui -* Fix concatenation in Volume related actions -* Fix concatenation is misc delete actions -* Fix concatenation in firewall related actions -* [Sahara] Added ability to specify security groups for node group -* Rename Extra Specs with Metadata in Flavors table -* Move datepicker language js inclusion outside compress -* Updated from global requirements -* Fixes session timeout string in horizon -* XMLHttpRequest header instantiation for Django-Angular -* Datepicker locale support -* Instance customization script can now be uploaded as file -* Fix policy check for subnet operation -* Fixes double evaluation of AngularJS in modal box -* Fixes downloading a keypair -* Add mixin to replace replicated get_policy_target -* Always split template names on forward slash -* Preserve dashboard order configured from settings -* Fixed missing Launch as Instance for snapshot -* Fixed typos in the QOS Spec forms in Volume Types -* Add additional attributes to choices in ChoiceField -* Fixing template compatibility -* Device Size field now pre-fills with appropriate value -* Replace Ceilometer ClientException with HTTPException -* Imported Translations from Transifex -* Document token hash algorithm option -* Put units in paranthesis in Create Flavor form -* Revert "Style network address for subnet as required field" -* Correct protocol/action initial values provided to UpdateRule -* Imported Translations from Transifex -* Sahara small UI fixes -* Updated from global requirements -* Handle correctly protocol 'ANY' in firewall rule -* Only show type field on specific volume sources -* Aggregates metadata cleanup -* Imported Translations from Transifex -* Images metadata cleanup -* Updated from global requirements -* Flavors metadata cleanup -* Give size field default value (Create Volume) -* Workaround for negative vals in total*Used in nova absolute_limits -* Imported Translations from Transifex -* Removing obsolete reference to lesscpy -* horizon ignores region for identity service -* Made Admin State choice more human readable -* Uniquify horizon messages returned in a single response -* Capitalise 'router' in create router templates -* Imported Translations from Transifex -* Reuse API client object in a request -* Replace pgettext with pgettext_lazy to display translated string -* rephrase action_past text in Access & Security panel -* Fix concatenation in Delete Rule action -* set max_length on volume/snapshot description text area -* Fix concatenation in network tables -* Added links to other pages instead of just ID's -* Fix concatenation in Delete Image action -* Translation feedback - Add contextual marker for short strings -* Dismiss flavor detail pop-over on users next click -* Update Usage Comments for DeleteAction -* Remove concatenation from Delete Flavors -* Update Users Table to Avoid Concatenation -* Added no_autocomplete attribute to password form -* Ability to add form confirm/cancel button labels -* Remove #noqa from two common imports and add them to import_exceptions -* swift: Respect the OPENSTACK_SSL_NO_VERIFY setting -* Bringing HACKING.rst in correspondence with tox.ini -* Add columns to the job executions page -* Unit test for floating ip quota exceeded -* Update border-radius css and remove mixin -* Fix cancel button size in modal dialogs -* Enable flavors metadata update -* Style network address for subnet as required field -* Show floating IP associated with Load Balancer VIP -* Imported Translations from Transifex -* Fix locator typo in go_to_accesssecurity_page -* Use integer instead of string for form max_length -* Imported Translations from Transifex -* Stop using intersphinx -* Permit 'exceptions' to be omitted from HORIZON_CONFIG -* Corrected dash.can_access call to take context -* Enable QOS Specs to be associated with volume type -* Order tenants in tenant switch list -* Order regions in region list -* Fix AttributeError in VolumeSnapshot -* Filter does not work when table name has spaces -* Set the correct min_disk size when creating volume from image -* Enable host aggregate metadata update -* Switch to xstatic-bootstrap-datepicker -* Updated from global requirements -* Widget to expose the metadata catalog from glance -* QOS edit, create, and delete functionality -* QOS Specs - added edit feature -* fix the logic of api.lbaas._pool_list -* Change page header heading to H1 -* Imported Translations from Transifex -* Translation feedback - Correction/update of help texts -* Modified docs to list supported browsers -* [Sahara] Replaced several IDs with names and names with links -* Fix auto-fill on filename input -* Show floating IPs from other projects of admin instance table -* Replace "tenant" with "project" in visible strings -* Fix host listing in live migration -* render stack parameters in the correct order -* Fixed the nagging 404 errors in the unit test -* Making credentials optional for data sources -* Fixed add_bootstrap_class template filter -* Refactor test code to reduce duplication -* Allow setting config drive option when launching instance -* Allow some translations to be made -* Allow translators to translate BatchActions -* Hiding "Launch as Instance" if volume is not bootable -* Fixes broken rendering of dashboard for IE -* Added missing floating IP pool section -* Updated from global requirements -* Index.html fix for startpanel command -* Validation check if exceeding vol snapshot quota -* Fix password reveal icon for Bootstrap 3 -* Add templates for bootstrap's horizontal forms -* Avoid string concatenation in Volume Type Extra Spec Edit -* Add attributes to cell in a table depending on data -* Description clean-up for volume actions -* Fix auto-filled object names enabling upload button -* Remove the urlquote to arguments passed to reverse -* Fix timezones in line chart -* Imported Translations from Transifex -* Fix missing trailing commas for modal dialogs -* Updated from global requirements -* Support new IPv6 subnet modes in Neutron - -2014.2.b3 ---------- - -* Added new filter class for sub-service tables -* Ensure duplicates are removed from image list -* [Sahara] Fixed cluster template creation -* Fix Cancel button styling -* Work toward Python 3.4 support and testing -* Updating the environment version -* Fixed incorrect position of modal container -* Made storage location help text more descriptive -* Volume Types tab with QOS Specs -* Need ability to evacuate host in syspanel -* Fix Cancel buttons in Custom Property dialogs -* Render hidden stack parameters with a password field -* Context selection for project and region -* Allow forms to disable autofill in all browsers -* Add Font Awesome icons -* Updated from global requirements -* Allow adding or changing the CSS classes of a data table -* Remove NotImplementedErrors from "virtual" methods -* Fix border colors for Firefox -* Imported Translations from Transifex -* Display Network panels based on neutron ext-list -* Fix LinkAction class name for Domain and Project -* Corrected AZ FilterAction and table filter -* Add a None option to the CONSOLE_TYPE setting -* Imported Translations from Transifex -* Fix order of arguments in assertEqual -* Updating case on requirement to satisfy pip -* Allow auto device name for attach volume -* Port details template missing some translation -* Instance Action Dashboard Blueprint -* Disable Floating IP features if Neutron router is disabled -* Add a config option to disable Router panel -* Add "Edit Router" to allow to change router type -* Add missing mock to test_set_external_network_empty -* Updates the OpenStack Settings Description for API_RESULT_PAGE_SIZE -* Fix alert styling using "error" instead of "danger" -* Imported Translations from Transifex -* Add quota validation to volume extending size -* Upload volume to image service -* Not compressing a specific js bloc -* Improve help messages on modals -* Fix for adding panel to panel group via plugin -* sort Create Node Group Template's Flavor List -* Show validation errors in modal forms -* Imported Translations from Transifex -* sort Database Launch Instance Flavor list -* Fix handling of missing external network -* Enable changing volume type of a volume -* Navigation causes undefined error when clicked on twice -* Barchart popup window position is broken -* Small SCSS fixes of overview charts -* Allow to hide Y axis label -* Imported Translations from Transifex -* Horizon changes for DVR -* Importing with_statement from __future__ is useless -* Use string.ascii_letters to be python 3 compatible -* Refactor network topology JSONView class -* Provide a quick way to run flake8 -* Domain Role assignment to Users -* Imported Translations from Transifex -* Updated from global requirements -* Exclude .ropeproject from flake8 checks -* Correct return values of mocked methods in LBaaS API test -* Add Data Processing missing translations -* Data Processing Adding support for Spark jobs -* Add instructions for packaging JS libs -* Fix Data Processing image registry -* show correct link to compute instances in stack resource overview tab -* Fix improper HTML in base template -* Suppress expected exception messages in unit test -* Remove hard coded URLs from metering view -* Ensure document ready before auto download -* Fix wrong config values displaying -* Data Processing post-bootstrap 3 UI fixes -* Fix bootstrap issues on Volume Backups dialogs -* Imported Translations from Transifex -* Validate cores and ram when booting instance -* Fixed issue of 'terminate instance' with fresh login -* Fixed jshint gating errors -* Fix odd row last cell border colors on Firefox -* Fix IE spacing for pie charts -* Use a singly created set while copying cookies -* Imported Translations from Transifex -* reduce the height of the textarea to 4 -* Fix bootstrap issue on Volume Backup Details page -* Made Availability Zone mandatory for Aggregates -* Fix backup details with missing volumes -* Min Disk and RAM fields not allow negatives -* Fix XSS issue with the unordered_list filter -* Set self.kwargs in horizon.tables.actions.LinkAction -* Fix background highlight for dropdown -* Unbundle all JavaScript libraries from Horizon -* Fix action_class typo and exception message -* Imported Translations from Transifex -* Fix typo error in the comment -* Separating Identity Dashboard and using RBAC -* Stop preloading Admin Volumes tabs -* Edit image - made format field as editable -* "Device size" field only allow positive values -* Imported Translations from Transifex -* Remove "builtins = _" from tox.ini -* Removed edit icon hover effect -* Remove the word 'More' in the row actions split button -* Data processing templates tables refactoring -* Updated the documentation of the OPENSTACK_NEUTRON_NETWORK settings -* Imported Translations from Transifex -* Change message from Warning to Error message -* rename pagination 'More' link to 'Next' -* Remove redundant template from data_processing/data_plugins -* Imported Translations from Transifex -* Updated from global requirements -* Fix styling for dynamic select widget add item button -* Fix list of possible trove instnace status choices -* Stop preloading the Volumes tabs -* Handle TypeError from table column summation code -* Imported Translations from Transifex -* Fix ok-icon in membership widget -* Fix instance table IP column indentation -* Change value of None in encrypted volume field from "Maybe" to "-" -* Not display loading image for shelved instances -* Imported Translations from Transifex -* Add Volume Snapshots table to Admin Volumes -* Exception handling is captured correctly when deleting a container -* Allow access to HTML final class string -* Change unit string translation in volume limit templates -* Initialize table action buttons for lazy-loaded tabs -* Run the integration tests headlessly -* Imported Translations from Transifex -* Remove the "Currently Not Supported" field from "Add VIP" -* Redefine instance.security_groups as list -* Enable updating the status of a volume -* [Sahara] Added error handling for cluster template list -* Rename Trove create database dialog -* Add API filtering to paged tables -* Remove hard-coded static prefix from JS and CSS files -* Cleans up the translation -* Imported Translations from Transifex -* Map quota keys to translatable strings -* Fix policy check for LoadBalancer panels -* Quota error message should be more descriptive -* Make some new strings translator friendly -* Ability to create data sources from job launch -* User keystone policy to check if user password can be updated -* Fix 'Associate' and 'Disassociate Monitor' actions -* Removing border from overview charts -* Allowing to have static x-axes in line chart -* Automatically discover "Image Format" based on file extension -* Rename add_error methods: Django 1.7 conflict -* Imported Translations from Transifex -* Remove extra loop in populate_network_choices -* Fix network select widget for launching instances -* Rename selenium.py -> selenium_tests.py -* Allow table actions to be displayed in a menu -* Fix tab show/shown handlers for bootstrap v3 -* Add test skip decorator when service not available -* Replace force_unicode with force_text -* Fix wrong redirect url after instance resizing -* Fix instance flavor popover table -* Provide docstrings for horizon tables DeleteAction -* Redirect to the current page after edited instance -* Imported Translations from Transifex -* Fix unexpected return from Step::__init__() -* Updated from global requirements -* add Previous link to Project > Stacks table -* Manually disable IP version when creating network subnets -* Spelling correction in exception -* Add missing inline edit save and cancel icon -* Support provider network extension when creating network -* Adds keypair create,delete integration tests -* template to rely on the the "id" attribute -* Fixed cannot delete router port because of permission denied -* Fix Volume DeleteBackup success message -* Add missing Disk unit to Overview Usage -* Re-raise exception using six -* Delete Stacks button doesn't work -* Fix broken Subnet Wizard by updating to latest library -* Upgrade django-pyscss to version 1.0.2 -* Set python hash seed to 0 in tox.ini -* Honor dashboard DISABLED over horizon settings -* TEMPLATE_DIRS must be a tuple -* Imported Translations from Transifex -* Translatable value for Status column for Services -* Imported Translations from Transifex -* Fix and enable H701 check "Empty localization string" -* Fix and enable H702 _() method check -* membership widget styling -* Fix Sahara cluster templates details -* Proper port for LBaaS members -* Support assignment for network to DHCP agent -* Fixing display order of data processing panels -* Fixup trove screens for Bootstrap 3 changes -* Remove Filter button from query-type filters -* Fixed TypeError in database launch error handle -* Properly inline help icon for form checkboxes -* Verify Help button redirects to the right URL -* Make source fields required for 'Create Volume' form -* Make project optional during User creation -* Fixed error message for recoverable exceptions -* Fix wide input fields on Resource Usage > Daily Report tab -* Lint-based cleanup of 2 scss files -* Re-enable flake8 check -* Fixed styling of ajax-animated bar -* Updated from global requirements -* Add ".copy" before extension when copying a Swift object -* Fix Flake8 style warnings in openstack_dashboard/ -* Allow form to stay modal after uploading file -* Imported Translations from Transifex -* restyle pencil icon for table inline edit -* Fix Flake8 style warnings in horizon/ -* Terminate Instance button doesn't work -* Use default_project_id as user project for keystone v3 -* Updated the steps of the tutorial -* Add some missing '+' icons -* Fixed wrong quota check for instance launch -* Remove use of "quota_tenant_usages" in Volumes page -* Imported Translations from Transifex -* Change Admin Volumes to a tabgroup -* Some 'Create' buttons missing '+' icon -* Change note about the removal of variable SESSION_SERIALIZER -* preserving dashboard order for update_dashboards call -* Update Twitter Bootstrap to version 3 -* Add mismatch arguments in inherited dashboard classes -* Reveal icon for password field -* Imported Translations from Transifex -* Add metadata option to Nova Create API Wrapper -* Replace mimetype argument name with content_type -* Remove Cinder traces from test output -* Cleanup for Horizon fields -* Cleanup for Sahara fields -* Updated description of create volume type dialog -* Adding start/end time to data processing-job execution details -* Remove per-feature extension check method in api/neutron -* Data Processing: Fixing UI refresh for deleted clusters -* Data Processing: Adding keypair import from launch cluster dialog -* Data Processing: Making cluster template field required -* Fixed text on create cluster dialog -* Data Processing: Allowing for HDFS data sources without hdfs:// -* Data Processing: Fixing update of execution status -* Imported Translations from Transifex -* change spelling Ram to RAM for consistency - -2014.2.b2 ---------- - -* Imported Translations from Transifex -* Sync keystone policy file -* Replace UserManager with None in tests -* Adding Jobs and Job Executions panels for Sahara -* Fixing data processing image registry -* Display host address on row update -* Updated from global requirements -* Update exception map based on neutronclient exception rearrange -* Imported Translations from Transifex -* Add knobs for setting MAC learning on ports -* Add support for trove incremental backups -* Add a proper IPv4 sorter for jquery-tablesort -* Change trove instance table name -* Tolerate service catalog and endpoint connection errors -* Imported Translations from Transifex -* Settings page ChangePassword page and their tests -* Made import key pair examples more specific -* Rename Host to Allowed Host -* Add create and update times for trove components -* Initial support for datastore in Horizon -* Add string translation -* Add scss logger configuration -* Imported Translations from Transifex -* Volume Type Extra Specs support -* fix Instance table's Flavor Detail popover not showing up -* Add ability to manage image custom properties -* Adding Job Binaries panel for Sahara -* Data Sources panel for Sahara -* Fix typo in select methods definition -* Display flavor details in instance listing in a popover -* Imported Translations from Transifex -* Fix security group modal header overflow -* Adding cluster_template and cluster panels for Sahara -* Run router dashboard unit tests by default -* Imported Translations from Transifex -* Remove Cinder traces from test output (add missing mock) -* Make distinction for disabled text field in membership step -* AttributeError at attaching a non-existent volume -* Trove backup should have link to instance -* Improve display of flavor information for trove -* Adding nodegroup_template panel for Sahara -* Move _datepicker.scss to a correct place -* Cleaned up dict.update(single elem dict) code -* Add datastore and version information for backups -* Breakdown CSS: split out the resource browser -* Updated from global requirements -* Display volume size for trove instances -* Consistent handling of choiceField for backups -* Fixing subproject test runs -* adapt to python-novaclient-2.18.0 -* Adds option to select a different subnet when adding 'vip' -* Add IMAGE related settings to documentation -* Add support for resize of Trove volume -* Fix the requirements for a django library -* Trove Details pages should be plural -* Trove navigation panel should not be plural -* Rename Trove panels to remove redundant information -* Move the HTML-escaping JavaScript code to a separate function -* Adding the data_image_registry panel for Sahara -* Add CONTRIBUTING.rst -* Imported Translations from Transifex -* Remove docutils pin -* Remove requirements style check -* Don't recommend setting SESSION_COOKIE_HTTPONLY -* Fix multiple Cross-Site Scripting (XSS) vulnerabilities -* Imported Translations from Transifex -* Hide "Download EC2 Credentials" if EC2 is missing -* Run integration tests full screen -* horizon_workflow.scss could be more scss-like -* Fix adding members to a group -* Updated from global requirements -* Add max-width and ellipsis to project names in the tenant switch -* Raise NotImplementedError instead of NotImplemented -* Adding support for volume backups -* Imported Translations from Transifex -* Implement missing mocks to remove error noise during test run -* Network topology crashes with timing issue -* Long container names no longer break the page -* Log Trove API errors on databases tabs -* Users can now be deleted within trove -* LBaaS member creation enhancement -* Imported Translations from Transifex -* Updated from global requirements -* cannot add users to groups -* Updated from global requirements -* Use SCSS instead of LESS -* Imported Translations from Transifex -* Allow panel plugins to use ADD_EXCEPTIONS and UPDATE_HORIZON_CONFIG -* Fixes bad performance when editing project members -* Correct styles for workflow update members step -* Adding plugins panel for Sahara -* Unbundle jquery from horizon using xstatic -* Reinstate highlighting of selected container in Containers view -* Imported Translations from Transifex -* Making compute services status fields consistent -* Container:improve 'Copy Object' help description -* Updated from global requirements -* Imported Translations from Transifex -* add Previous link to Admin > Images table -* Make xvfbwrapper import dependent on the selenium imports -* Add OS_REGION_NAME to openrc -* Add extra_context to SetInstanceDetailsAction.get_help_text -* Adding link_attrs to column -* Updated from global requirements -* Add vCPU topology related extra flavor keys -* add httplib2 explicitly to requirements.txt -* Make the More link translatable -* Add heading property to BasePage class -* Raise sane error when failing to modify security group -* Add jshint for javascript linting -* Fix typo in calling is_the_current_page method -* Specify a Network During Database Instance Create -* Imported Translations from Transifex -* Check neutron agent extension support in Info page -* Removing decimal place when it's 0 -* Imported Translations from Transifex -* Make security rules with All translatable -* Fix inconsistent inline help text in forms -* Add a table customisation example to the docs -* Allow running a subset of the integration tests -* Fixing the instance boot source -* Updated from global requirements -* Imported Translations from Transifex -* Fix Updated At label -* Disable broken unit test (related to "Change Password") -* Exclude security group related quotas when the extension disabled -* Add missing "load url from future" in a container template -* Fix issues with importing the Login form -* Imported Translations from Transifex -* Remove the unused success_url and return -* hyperlink from hypervisor page to instance details -* Exception traces in the test output -* Upgrade jquery to version 1.10.2 with jquery-migrate -* Imported Translations from Transifex -* Delete debug statement in js file -* Fix version display position on system info page -* sort snapshots in drop-down when launching instance -* Fix keystone warnings while building docs -* Remove warnings when generating docs -* Update customizing docs, css was replaced by .less -* Display Horizon version number in System Info page -* Add text to the Create Volume dialog's Type menu -* Adding sahara client api code -* Database Launch Form shouldn't autocomplete -* Ensuring environment data is passed to heat template validate -* Sort security group rules by protocol and port -* Fix for UPDATE_HORIZON_CONFIG listed as part of Icehouse in the docs -* Removed the link to the outdated horizon demo - -2014.2.b1 ---------- - -* Use import from six.moves to import the HTMLParser module -* Accept translated exceptions in exceptions.handle -* Admin Hypervisor table - change order of columns -* Imported Translations from Transifex -* Friendlier information for lbaas members creation -* Add encryption indicator for volumes -* Remove unused load of sizeformat -* Handle error from neutron extension check in Overview page -* Country names in capital letters -* Update 'Create Volume' button with ajax -* Fix issue when Nova does not support DiskConfig -* Display cinder services in System Info -* Add CLI option for running Selenium tests headless -* Not able to delete a pseudo-folder via horizon -* Introduce safer access to resource meters -* APIDictWrapper getitem lookups fail for non str -* Images table/detail view term consistency -* Image uploads should always happen in the background -* Improve extend volume form -* Do not delete properties when create image from URL -* volume details page does not show source image details -* Change Column name from Enabled to Status -* Add "Size" column to Image Table -* Fix testing fails on specific platforms -* Use six.add_metaclass instead of __metaclass__ -* Fix Instance Image Name cell value -* Prevent error message when creating a user -* Incorrect config item in local_settings.py.example -* UX improvements for Launch Instance dialog -* Sort project list by openstack_auth -* Remove extra div -* Remove "Panel" from navigation elements -* Imported Translations from Transifex -* Allow extensions to add Angular modules -* Imported Translations from Transifex -* Inactive calendar widget should be closed -* added disabled reason to column status in listing of compute services -* Synced jsonutils from oslo-incubator -* replace dict.iteritems() with six.iteritems(dict) -* Make selenium tests more robust -* Remove extra whitespace -* Add user and password parameters to _do_login -* Fixed several typos in comments -* Fix the default text for Instance Boot Source -* Volume Snapshots tab - more button dropdown fix text -* Show default text for image format -* Document how to add panel with no panel group -* Copy the selected file name in the object name field -* Fixed status on Cell class -* updated description of the create image screen -* Do not render port template if device has no port -* Add a column to show if Extra Specs are defined on a Flavor -* Fix missing translations in Firewall views -* Updated from global requirements -* Adding bootable as a column in volumes table -* Make selenium tests pass in WebKit -* Fix delete button interface in network topology view -* update language list in openstack_dashboard settings.py -* Removing non-bootable volumes from boot source -* Add unit tests to instance Retrieve Password action -* Refactor code around Console support -* Fix hide drop_arrow.png if only one tenant -* Exception handling should not use exc.message -* Add "new in" tags for pre-Icehouse settings -* CSV Download button from Daily Usage Report -* not display loading image for rescued instances -* Icehouse release notes -* Change mbformat to mb_float_format in hypervisor table -* Add "new in" tags to docs for new Icehouse settings -* 'Create Volume Snapshot' form should show the quota for snapshot -* More clear message when detaching volume -* Fix build instructions and formatting in README -* Fix row updates for tables without quicksearch filtering -* Fix max_length value for flavor's name -* policy checks for nova access/security actions -* adding policy check for neutron -* ValueError when cookie pagesize is empty string -* wrap_list is not honored for not-editable cells -* Add update method of snapshot name and description -* Fix pseudo-folder content listing -* Integration tests - base class for all tests -* Remove extraneous vim configuration comments -* added field 'delete on terminate' (launch/volume) -* To allow keypair name could contain spaces -* add missing references to policy files -* Fix fake_init_exception() to better handle Neutron exceptions -* Fix unicode error when assertMessageCount() fails -* Updated from global requirements -* fixed typos found by topy -* Patch Django 1.4 on Python 2.7.4 or greater -* Fix the dot overlaps with the table border in Availability Zones table -* Enable passing additional parameter to metering query -* Preventing __builtins__ from being in HORIZON_CONFIG -* Update documentation to clarify Image Upload setting -* Added the field label to the field arguments -* Added tabindex value to links in the sidebar -* Use floats instead of integer in memory calculation of admin dashboard -* Fixing Neutron Subnet Details help text -* Hide disk config option if the extension is not supported -* Fix endpoint error when running keystone on apache -* Changes in assert message and select dropdown -* Avoid attr error on database backup page -* Avoid AttributeError: SecurityGroup error handle -* Fixes wrong logic for clean method in SetInstanceDetailsAction -* Add sort indicator to table headers -* Flavor access list titles consistent capitalization -* Added button Add Interface on Network Topology tab -* Add semi-colons in Less files -* Move `Forbidden` exceptions to `RECOVERABLE` group -* Use escapejs filter on JavaScript strings -* Allow changing any horizon settings from the plugin config files -* Updated from global requirements -* Allow static files to be exposed for any plugin -* Fix start date should after end date in calendar -* Add a launch instance action to volume & snapshots screens -* Use the latest Django 1.4 release to test Horizon -* Remove trailing commas in JS files -* Textarea field can be extended over other fields -* Propagate logout_reason messages -* Add missing comma in Volume ResourceWrapper class -* Clear barchart before rendering it -* Return False if instance is None in TogglePause and ToggleSuspend -* Support for django csrf token -* Perform natural sorts on "Hostname" column on the Hypervisors panel -* Replace Horizon cookies by the angular one -* Correct default usage filtering on overview page -* Fix translatable string for "Injected File Path Bytes" -* Refer local_settings in doc to customize settings -* Centre piecharts properly -* Fix formatting of heat exceptions -* Fix default get_user_home with dynamic dashboards -* Do not auto resize line charts by default -* Add a centralized palette to Horizon -* Use the domain filter provided by keystoneclient -* Updated from global requirements -* Fix tox does not pass arguments to nose -* Adding python-saharaclient to requirements -* Just fix some minor coding styles inconsistency in local_settings.py -* Fix timestampSorter parser -* Use "python -m coverage" rather than use "coverage" explicitly -* TypeError in database view error handle -* Daily Usage report format value column -* Fix KeyError in router:AddInterface error handle -* Introduces escaping in Horizon/Orchestration -* Check host is not none in host aggregate page -* Fix DynamicSelectWidget.get_add_item_url() method -* Better tab name on Hosts Aggregate modal -* Add go_to_home_page method and two more properties -* Changed message when there are no IP available addresses -* Sync latest Oslo -* Add tox env to build docs -* Add pagination to stack list -* Add logging handler for openstack_auth in the tests -* Add a timestamp parser for jquery tablesorter -* Created a make_web_conf command -* Improve Host Aggregates handle method -* Don't ignore the HORIZON_CONFIG['user_home'] setting -* Fix settings titles and underlines -* Fix documentation about adding a new dashboard -* Remove unused openstack.common modules -* use ec2-user instead of ec2_user -* 1284884 Overlogging of failed container delete -* Cardinal interpolation error -* Add missing mock for cinder.default_quota_get - -2014.1.rc1 ----------- - -* Open Juno development -* Added network's api mocking for the servers_update_addresses method -* Make "Gigabytes" quotas description more meaningful -* Fix excessive ajax session thrash -* Plugin-based panel group configuration -* Remove duplicate colon from Size string -* Fix Exceptions doc page generation -* Updated from global requirements -* Adding missing system dependencies to quickstart -* Enable settings/change password on keystone v3 -* Make wizard workflow work when non-modal -* Remove non dev dependency on mox -* Remove the update default quotas feature -* Handle "null" time values for Stacks -* Fix create instance workflow help typo -* Create links in LBaaS detail pages -* Clarify description string for image metric -* Remove English compiled catalogs after compilemessages -* Integration tests - page objects pattern -* Use built-in print() instead of print statement -* Sync default OPENSTACK_KEYSTONE_DEFAULT_ROLE with keystone -* Fix wrong links to volume detail -* Increase the datepicker input width -* Make makemessage ignore option work with Django 1.6 -* Add missing trunk segment type option for profile create -* Update .tx/config with type of files -* Switch over to oslosphinx -* Pre-select the network when there's only one -* Ensure TabGroup to handle bad GET parameter -* Fix project name in the table for Cisco N1K profiles -* Disables the clear text password UI by default -* I18N: Fix untranslatable strings in LBaaS workflow -* Remove get_resource_or_fake method in VPN panel -* Make project left-side menu titles consistent -* Stop altering the glance API URL -* Update "dashboard" setting documentation -* Error message in create vol with a vol source -* Selected instances are not deleted with pagination -* Changed the label from Edit Rules to Manage Rules -* Hidden checkboxes in Availability Zones table -* Remove I18N strings from test/settings.py -* Handle failures on column filters more gracefully -* Fix unbound local error in instance DetailView -* Host aggregates missing the metadata column -* Clarified success message for instance resize -* Improve help message in Retrieve Password form -* Remove verbose_name from hidden fields -* Fix username's maximum length to match the backend -* Mark string in routerrule template translatable -* Allow translator to control the word order (update extra spec) -* No need to mark strings in test_plugin translatable -* Redirect to the proper tab on creating vol/snap -* enable plugins to override templates -* Fix selenium imports on tests -* Fixing potential attribute access on None -* Updated from global requirements -* Fix unbound locals in IPAssociationWorkflow -* Hide column on multi_select tables if no actions available -* Adding django 1.6 support -* Enforce length checking for instance name field -* Fix Membership list loading bug -* Updated outdated docstring, fixed typo/space -* Tell users when there is no data available in Daily Report -* Updated from global requirements -* Raise an error when no slug on tab group -* Fixes description field extension -* Adding resource link to resource detail page in Heat view -* Additional optional Environment data to heat template selection -* On flavors menu, the _update.html file was deleted -* Fix distribution pie chart -* Allow 'Manage Host' to show membership action -* Fix middleware to not access session fields without user auth -* filter always returns the last created item -* Updated from global requirements -* Fixing heat stack status column - -2014.1.b3 ---------- - -* Decrypt and display VM generated password -* Remove copyright in empty __init__ file -* Live Migration should not contain current host in the new host list -* update test to hit default page instead of login -* Heat Stack update view/form -* Remove gettext_noop from language list -* Host aggregates panel -* Group specific fields in horizon.form module -* Use unminified javascript files -* Remove volume source option on some dialogs -* Add flavor extra spec key templates -* Enhanced error message when router creation failed -* Plugin-based panel configuration -* Refactor CSV generation code to utils -* Basic support for Cinder v2 -* Fix typo -* Add indent to make code more pleasure -* Sort requirement files in alphabetical order -* Add disk config option support -* Adds support for Nova RDP console -* Fix animation on pie charts -* Enhance pie chart capabilities -* Remove apps from settings -* Fixes some column translations -* Updated from global requirements -* Implementing accordion navigation -* Clean up Cinder client traces in the test output -* Rename UpdateDefaultQuotas to UpdateDefaultQuotasStep -* Add missing mocked calls to the Volumes tests -* Integration tests - running the tests -* Use six.StringIO/BytesIO instead of StringIO.StringIO -* update test to handle IntegerField html change -* Reduce number of novaclient calls -* Allow redisplay of the workflow from its handle() -* Fixing filesizeformat test issue with Django 1.6 -* sort flavors on Resize Instance modal -* Updated from global requirements -* List all tenant images/snapshots on admin images view -* Keep py3.X compatibility for urllib -* Use six.moves.urllib.parse instead of urlparse -* Using '0' instead of '-' in overview page -* Fix wrong key for 'usage.summary.instances' in CSV summary -* Enforce FlavorExtraSpecs Key format -* Fix a code indentation error -* Add Daily Usage tab to Resource Usage panel -* Change redirect of details on admin instance table -* Use the min_disk property for volume size -* Documented Flavor Sorting Options -* Action required status shows proper icon -* Typo corrections in run_tests.sh comments -* Fixing issue with VXLAN network profile create -* Always pass 'modal' context variable to workflow template -* fix project quota showing error and success message -* Don't lose AttributeError in API Wrappers -* typos in workflows/views.py -* Move volume snapshots table to volumes panel -* Exclude local directory from flake8 tests -* Add jasmine testing and helpers -* Replace horizon.utils with an angular one -* Replace horizon.conf with an angular one -* Fix submit button in overview -* Rename Openstack to OpenStack -* Replace assertEqual(None, *) with assertIsNone in tests -* Adding policy checks for heat -* Clear date picker fields every time 'Other' Period is selected -* 1279979 Neutron TypeError when token invalid -* Fixing tests to work with keystoneclient 0.6.0 -* Fix form error access for django 1.6 -* Restrict the length of the Security Group name input -* Bug fix on neutron's API to return the correct target ID -* fix templatetag for no fractional bytes -* get_user_home test fix for django 1.6 -* Fix table rendering for iterable objects -* Make two identical LBaaS tests different -* Allows the user to modify an object -* VPNaaS tests refactoring -* Refactor large method into 4 methods -* Add month to date option for Resource Usage -* Fixes instance double delete via row_action -* Fix missing option in the test settings.py file -* Fix typo in ceilometer.py -* Translating entity types in client side templates -* Test coverage improvement for FWaaS screens -* Make object upload success message translatable -* Updating tutorial doc for dashboard loading -* Display trove instance hostname if available -* Volume status must be available to extend -* Remove delete action and bar when stack is DELETE_COMPLETE -* Fix misspellings in horizon -* Adds meta and head-js partials to head in base.html -* Updated from global requirements -* Restrict the length of the project name input -* Policy check needs to check for None in target -* Don't copy the flavorid when updating flavors -* Add a Row check to enable/disable checkbox on ajax updates -* Move Network topology init call to template -* The order of fields have changed for update default quota form -* Fix regression on auto-fade of success message -* Warn user when no meters in metrics panel -* Revert "CSS to fix content appearing below side pane" -* Fix Typo in loadbalancers/workflow.py -* Checks min requirements before trying to launch an instance -* Change 'update default quotas' success and failure messages -* Adding policy checks for glance -* Add dependencies on Quick Start page -* Add create volume from volume -* Javascript prohibits the use of bitwise operators -* Javascript force filtering object items -* External interface shows as up fake -* Remove leftovers of "# noqa" -* Fix small pep8 issue -* Update Launch Instance button with ajax -* Change internationalizable string -* Give no background color to the pie charts -* Document the IMAGE_LIST_FILTER_TENANTS setting -* Speed up unit tests without coverage -* Get instance networking information from Neutron -* Updated from global requirements -* Adding table search framework and use in admin instances -* Replace mimetype with content_type argument of HttpResponse -* 'Update' options for VPNaaS UI - -2014.1.b2 ---------- - -* Make hardcoded fields translatable -* adding policy checks for nova instance actions -* Translating entity types in network topology -* Remove grey line when pie chart is at 100% -* Revert "JSHint integration" -* disable volume creation, when cinder is disabled -* Remove Restore Backup Action For Non-Completed -* LBaaS tests refactoring -* Upgrade bootstrap-datepicker.js to latest version -* Make table_actions style work with buttons -* Removing duplicated classes from lbaas.py and vpn.py -* Make values display in Flavor Table consistent -* Sync OPENSTACK_KEYSTONE_DEFAULT_ROLE with keystone -* Fix inappropriate display for inf value of RAM and Storage -* Change assertTrue(isinstance()) by optimal assert -* Restrict flavor fields input on creation/update -* Remove leftovers of django.conf.urls.defaults -* Add volume extend functionality support -* Fixes create flavor extras success_url -* give a fullscreen attribute to workflow, for modal view -* CSS to fix content appearing below side pane -* Make text in Project Overview - Limit Summary section consistent -* Test coverage improvement for LBaaS screens -* Add asterisk to required field in user edit box -* Remove Create Backup Action For Non-Active -* Remove unused arg `instances` -* New message added informing how to exit fullscreen mode -* Empty email for users gets saved as an empty string -* Infinite volumes quota shows as 'inf' -* Fixes some typos spotted in a few Horizon files -* Make download an action rather than a column -* Handle summary information for deleted project -* Adding management_url to test mock client -* Consolidate user visible spelling of keypair vs Key Pair -* Add update method of volume name and description -* Passing stack_id argument to get_data view -* Remove "Delete" buttons when VPN objects are in use -* Empty files shouldn't contain copyright nor license -* adding policy checks for cinder -* Don't reset LOCAL_PATH if it's already set -* Wrong marker sent to keystone -* Replace asserts in __init__ files with __all__ -* Improve docs about horizon settings -* Inconsistent filesizeformat return value -* Change "peer_cidrs" field to MultiIpField -* Fix charts display in Resource Usage -* Remove leftovers of django.conf.urls.defaults -* Remove #noqa from most common imports and add them to import_exceptions -* Wizard UI for Workflow -* Rewrite pieces of code deprecated by Django 1.7 -* Whitelist external netaddr requirement -* Fixed sphinx ERRORs -* Allowing snapshoting attached volume -* Make running of unit tests more robust -* Do not close modal if escape is pressed on select -* Fix typo error -* unify keypair name handling -* add support for Django-1.6 -* Update to the latest version of the jquery tablesorter plugin -* Fix typo in class name -* Refactoring the loadbalancing view classes -* Javascript force use of the curly braces -* Javascript force use of the identity operator -* Javascript coding style indent 2 -* Adding missing files in JSHint -* Access & security, floating IPs tab cleanup -* Add init value None to port -* Visual improvement on Launch Instance workflow -* Same styling for "Limit Summary" and "Usage Summary" -* Removal of underscorejs library -* Replace xrange in for loop with range -* Fix pie chart rendering -* Delete periods from select options -* DataTables: disable action buttons even if there are no checkboxes -* Updated from global requirements -* Indicate pseudo-folders in containers panel -* Add missing __contains__() and get() methods to QuotaUsage -* Attach volume eventhough the instance is shutoff -* Clean up the hypervisor DataTable members columns -* Set "remove rule" field to be required in dialog -* Use memoized_method decorator in views -* Fix parse_isotime filter into horizon -* Wrap call to extension_supported with try/except -* User email is optional and can be absent -* Object Upload validated on client side -* Modified images list to be sorted alphabetically -* Cannot view detailed image with empty name -* Add member to LBaaS when no servers available always succeed -* Make Neutron API name consistent -* Set Keypair create button disabled when quota exceeded -* Allows the user to create an object without file -* Add breadcrumb to containers panel -* Logging error if cookie size is > 4KB -* Support warning messages in SelfHandlingForm -* Bad workflow-steps check: has_required_fields -* Gracefully handle Users with no email attribute -* Updates tox.ini to use new features -* Quoting attachment filename -* Centralizing page size code, reading cookie -* Change how scrollShift is calculated -* Fix behavior of select all checkbox -* Added help note in attach volume dialog -* Extend options for custom flavor sorting when launching instances -* Add UpdateRow method and status_columns to AdminImagesTable -* Enable update image description to blank -* Show all custom properties on image detail page -* Do not filter image list from glance api -* Updated from global requirements -* Allow translators to control word order of BatchAction message -* JavaScript use policy -* Common keystone version fallback -* Django Formset support in DataTable -* Configurable cell_class in DataTable -* Run selenium tests only when requested -* Specify tenant_id when retrieving LBaaS/VPNaaS resource -* Fix URLs of panels grouped into packages -* Add architecture field in image properties -* Adds Cinder client mock to tests -* Adds Trove mock to tests in database_backups -* Initialize the table after data load in TableTab -* Hide AZ when creating Volume from snapshot -* Add a loadAngular function -* Hide key field in edit Flavor Extra Specs dialog -* CSV Summary not working inside Admin panel -* Corrected incorrect message when deleting port -* Removal of json2.js -* Fix display of images in Rebuild Instance -* Fix VPNaaS success messages translation -* Increase Horizon base unit test suite -* Limit coverage report to horizon modules -* Set can_set_mount_point default to False -* Plugin-based dashboard configuration -* Add a warning to @memoized when caching is impossible - -2014.1.b1 ---------- - -* Improve contributor documentation -* Use HEAD on Container panel ajax update -* Inline Table editing -* Increase Keypair name size to 255 -* Show volume quota graphs if totalVolumesUsed >= 0 -* Add more Horizon unit tests -* Bumping up max_length of flavor extra spec -* Fix bad line breaking and radix in JavaScript -* Add ability to configure read access of container -* Allow snapshots of paused and suspended instances -* Role name should not be translated in Domain Groups dialog -* The use of the class variables -* Use === and !== instead of == and != in JavaScript -* Add parse_isotime filter to Image created and updated date strings -* Updated can_set_mount_point default in docs -* Set can_set_mount_point to False by default -* Add volume limits to project overview -* Fix duplicate definition and scope in JavaScript -* Use dot notation in JavaScript -* Fix duplicate keys in JavaScript -* Abstraction of Ceilometer meters information -* Better @memoized decorator -* Fix confusing use of ! and = in JavaScript -* Don't use extra leading zeros in JavaScript -* Use [] for new arrays in JavaScript -* Updates .gitignore -* Remove returns of user_update api -* Show success msg when container deletion succeeds -* unify the text: change "Update Subnet" to "Edit Subnet" -* Add check for BlockDeviceMappingV2 nova extension -* Fix semicolons in JavaScript -* JSHint integration -* Deleting statistics tables from resource usage page -* Display error message in instance detials page -* pre-select if theres just one project -* Logging user out after self password change -* Allow "Working" in spinner to be translatable -* Add missing egress sec group for all tcp/udp/icmp -* Disable selection of undersized flavors for image -* Removed "NT_" prefix in network topology tables -* Rename method get_hosts in admin/info/tables.py -* Update troveclient to 1.0.0 -* Heat Stack name is missing form validation -* Gate on H4xx docstrings for pep8 -* translate text: "subnet"/"subnet details" -* Fix translatable string for "Injected File Path Bytes" -* Live migration support -* Change Network Topology panel so it stops polling ajax on error -* Fix bug so that escaped html is not shown in volume detach dialog -* Remove confusing text from description form -* Update 'action_not_allowed' message to be more generic -* AngularJS + base horizon module -* fix help message of "create flavor" -* Add contextual markers to BatchAction messages -* VIP creation fails if ip address is not specified -* Fix "it's vs. its" typos -* Gate on H102 Apache 2.0 license header not found for pep8 -* Give HealthMonitor a proper display name -* Adding bar chart -* lbaas/horizon - adds tcp protocol choice when create lb -* Filter snapshots with status 'available' -* added Neutron incompatiility note for simple IP management -* Updated from global requirements -* Remove asserts for optional imports -* fix help text in "Create An image" window -* Importing from trove-client compat first -* Transform Quotas 'inf' to 'No Limit' -* Remove 'file' source type when HORIZON_IMAGES_ALLOW_UPLOAD is False -* Change "Tenant" to "Project" -* Handle '%' in Swift container names -* Documenting OPENSTACK_SSL_CACERT -* Enhancements of line-chart -* Ensure all compute meters are listed in dropdown -* Add option to disable server password fields -* Remove docs for removed can_encrypt_volumes setting -* Add logging configuration for iso8601 module -* Import install_venv from oslo -* Importing from trove-client compat -* Make HACKING.rst formatting sync with other repos -* Fix default port of MS SQL in security group template -* Enabled django-compressor for javascript sanity test -* Make the alert type in horizon.alert translatable -* Show AZ for instances -* Fix bug by escaping strings from Nova before displaying them -* changed default values of OPENSTACK_ENDPOINT_TYPE to publicURL -* Fix django.conf.urls.defaults imports -* Make cookie_name field in LBaaS VIP creation switchable -* Do not release FIP on disassociate action -* Presents color contrast in resource usage charts -* RST typo for tutorial documentation -* Allow customization of logo link -* Remove "Delete Pool" button when a pool is connected to a VIP -* Use a @cached_property decorator -* Fix LBaaS "Edit" forms displaying -* Add the missing _ -* Rename the action lable of LBaaS monitor disassociation -* Broken charting for non compute resources -* Update my mailmap -* Updating readme with grammar correction -* Removed extraneous period -* Changed "panels.py" to "panel.py" -* Fix warning in run_tests.sh --makemessages -* Updated from global requirements -* change assertEquals to assertEqual -* Fix a bug some optional field in LBaaS are mandatory -* Add Port ID to VIP details page -* Make instance DISPLAY_CHOICES translatable -* Fix horizon.tables.Column __init__ method -* Provide missing hover hints for instance: meters -* Fix AttributeError on Ajax calls with expired session -* Sortable instances -* Fixing possible exception on tables in tabs -* Display LBaaS pool/member status in the tables -* Updated from global requirements -* Do not concatenate localized strings -* Avoid discarding precision of metering data -* Fix untranslated project title text -* Validate volume size is larger than image minDisk -* Updated from global requirements -* Updated from global requirements -* Adds router rules support to router details -* Improve display of instance image information -* Revert patch causing Instance Image Perf Issue -* Adds pseudo-folder creation -* Updates OpenStack Style Commandments link -* Display instances with no image information -* Add filtering parameters to list requests -* Standardize display name on detail pages -* Fix incomplete translation of "Update members" widget -* Add extra extension file to makemessage command line -* Hide settings/change password on keystone v3 -* Ignore irrelevant secgroup form field errors -* Add Availability Zone to Volume screens -* Updated from global requirements -* capping python-troveclient version -* Run flake8 tests automatically on ./run_tests.sh -* Add keystoneclient CredentialsManager if missing -* Use "flavor details" rather than "flavor data" -* Fix import keypair help text -* Use HEAD when retrieving Container details -* LUKS quotas names easier to understand -* Handle the case no SimpleTenantUsage Nova extension -* Use HEAD when viewing Object details -* Improve default logging configuration -* Refactor horizon TemplateLoader -* Fix rendering of Localized string on cell links -* Disable H803 check -* Sort tenants in tenant dropdown, per #1234993 -* emit warning while running flake8 without virtual env -* Show an error message on instance launch error -* Fix a issue on retrieving default quota in Create Project -* Quota/limit graphs now work in IE -* Update DataTables only after previous call is done - -2013.2.rc1 ----------- - -* Open Icehouse development -* Release notes for the Havana release -* Fix typos: "gruop" and "remove from" -* Limit the odds of making N calls to Glance for image names -* Translating entity types in network topology -* Updated from global requirements -* Allow to specify custom horizon.tables.DataTable template -* Fix add policy missing rule issue -* Correcting help text for database launch -* Create links between FWaaS resources -* Retrieve security group quotas from Neutron if enabled -* Remove extra blank line -* Remove unused LOG -* Import translations from Transifex for Havana RC1 -* Convert generator to list in Heat list API call -* Code quality improvements in heat topology -* Code more defensively in image views/forms -* Cleaning up policy documentation -* Handle case without session_persistence attr in LBaaS VIP -* Only send gateway_ip on neutron subnet update when it's changed -* Add support for loadbalancer providers -* Ensure to return empty when no secgroup is associated to VM -* VPNaaS: Sync field names in IPSecSiteConn detail with creation form -* Update English PO files (source lang of translations) -* Allow region override for url_for -* Fixing database instance launch workflow -* Remove gettext_lazy of log message in nexus/profile impl -* Handled ajax request crash after session timeout -* Remove colon in item names in LBaaS detail page -* Fix excessive volume_get requests in snaps table -* Make some PEP8 understandable in run_tests.sh -p -* Fix editing of nameless images -* Don't insert "Any Availaibility Zone" on single-AZ configurations -* Don't generate the secret_key until after loading local settings -* Update English PO files -* Fix a bug firewall rule creation fails with ANY protocol -* Optimization of ceilometer API -* Fix help string for peer_address and peer_id -* show limit summary in GB -* Reduce image_list_detailed calls -* Allow Django unknown language in LANGUAGES settings -* Determine security group API dynamically -* Fixes inconsistent console problem -* Update English PO files (source lang of translations) -* Fix Instance secgroup update error with Nova secgroup -* Typo fix rangein -> range in -* enabling trove to work in multi-region deployment -* replace hard coded url for vnc view -* Chart css small fixes -* Hide the View Details for swift pseudo-folder -* Update English PO files (source lang of translations) -* replace nova flavor_list call with trove call -* Replace OpenStack LLC with OpenStack Foundation -* Update error messeages in Launch Instance -* Fix volume snapshot creation -* Adding Y value unit into linechart popup -* Update English PO files (source lang of translations) -* Enable two verbose_names in AttachmentsTable translatable -* Role name should not be translated in Project Member Edit Tab -* PEP8 E126 has been resolved -* Regenerate POT (English PO) files -* Make troveclient optional -* divides "import" statement in a url.py -* Fixes incomplete translation support of "Defaults" table -* replace "ugettext" method with "ugettext_lazy" -* Don't display non-tenant Floating IP in Floating IP project tab -* assertEquals is deprecated, use assertEqual -* Restore icons on buttons -* Make show_roles language independent -* Fix several login template translation issues -* The word "IP" is a proper name -* Use substitutions in the messages of delete confirm form -* Enable some table actions translatable -* Fixed a PyPy compatibility issue in the test fixtures -* Update English PO files (source lang of translations) -* Store user settings in persistent cookies as well as the session -* Fixing typo: use -> user -* Update English PO files (source lang of translations) -* Display the 'Settings Saved' confirmation in the new language -* Fixes openrc to properly manage '\' characters in the user password -* added tab showing all servers assigned to a hypervisor -* Minor cleanups on FWaaS message strings -* Fix bug on missing success message for delete actions -* Redirecting user back to previous screen -* modifies error message in adding security rule -* Adding documentation to Tables and Workflows -* ./run_tests.sh --makemessages update English PO files only -* Add tests for VPNaaS screens -* Fix three spelling errors -* Add success message after successful deletion of VPNaaS resources -* Fix UpdateProjectMembersAction excess keystone calls -* Internationalise a couple of forgotten strings -* Added button to Reboot multiple instances -* Provide a default for OPENSTACK_IMAGE_BACKEND -* Remove general 'unauthorized' message from middleware -* Move Network Topology to the top of "Manage Network" group -* Update the source languange PO files with FWaaS/VPNaaS support -* FWaaS Horizon panel -* Create links between VPN resources -* Show IPSec Site Connection in VPN service detail -* Improves VPNaaS detail page templates -* Sync the defaults of VPNaaS forms with the server-side defaults -* storage.object.container ceilometer stat incorrectly set -* Enclose command args in with_venv.sh -* Enable F403 and F999 check -* VPNaaS UI implementation -* Correct amount of samples in the chart -* Remove test string from translation files -* Sync English PO files with the latest code for Havana-3 -* Create Router on network topology fails - -2013.2.b3 ---------- - -* PEP8 E121 has been resolved -* Add Cisco N1K plugin support in Horizon -* Adds support for passing extra tenant attributes to keystoneclient -* Remove spaces from translatable strings -* Do not run preemptive actions twice -* Fixing typos for Resource Usage page -* update neutronclient to 2.3.0 minimum -* Moves SECRET_KEY generation to base settings.py file -* Make Image Service image formats configurable -* Implement required field indicator -* Fixes missed localization in network agents -* Custom CA certificate for verifying SSL connections -* added Network Agents to System Info panel -* Add metering panel to admin console -* "# noqa" cleanup -* Improved boot from volume -* Fix help string for Host routes -* Define flavor for each project -* Adding panels for trove -* Display a message on the login page -* Remove encryption option for volumes -* Sync Transifex config with the source lang change in Transifex -* Fix row striping when sorting table data -* Use the horizon_pagesize value in the session cookie -* Allow admins to update default quotas -* Adding reusable Line Chart -* Delete and launch devices on the topology view -* Fix the Domain Context for Users panel -* Fix the Domain context for Projects panel -* Add ceilometer api and the tests for it -* Use proper method name for assembling the aggregate_list -* Update Horizon English message files for translation -* Add update method of security group name and description -* View and update Neutron project quotas -* Import is_service_enabled from module -* Adding Rickshaw as dependency -* Rename heat logical_resource_id to resource_name -* Adding RBAC policy system and checks for identity -* Show Neutron floating IPs quotas on Overview -* Don't fidget with the image/snapshot name/size if it's set -* Apply a tempate filter to output for openrc.sh -* Small cleanup in "test_data" -* Small "H302 check" cleanup -* Fix for openrc download on Firefox if the project contains blanks -* Implement assignment of Domain Roles to Group -* Corrected misspelled method in horizon documentation -* Enable H302 check -* Hide form tooltip when form closes on escape key -* Custom css and js docs -* Implement assignment of Project Roles to Group -* Display the container and object metadata -* Adds availability zone info to System Info panel -* Clean-up code issues related to reboot -* Fix "Add Association" and "Delete Association" displaying -* Drop NodeJS dependency in favor of pure-python lesscpy -* Adding rebuild action under Project/Instances -* Set row_count value on datatable update method -* Revert "Fix middleware to not access session fields without user auth" -* Always display the Domains panel for Keystone V3 -* Remove 'Status' field from healthmonitors details -* Hide default Floating IPs quotas with Neutron -* Adds hypervisor statistics to admin dashboard -* Fix middleware to not access session fields without user auth -* Enable H201: do not write "except:" -* Fix minor bugs in the "Resize Instance" workflow -* Customization: Add an explicit example of disabling Floating IPs -* Improve consistency of quota checking in forms -* Fix stack status displaying -* fix gettext calls to work on uninterpolated strings -* Updated from global requirements -* Sync install_venv_common from oslo -* Updates Topology to correctly handle resources in the INIT state -* Ensure the user monkey patching is done for the API tests -* Revert "Fix selector syntax" -* Allow translators to control the word order -* Refactoring of user assignment workflow -* added new exception cinderclient.ConnectionError -* Update implementation and remove TODO comment -* Add support for parsing jsonfied heat error -* Fix typo -* Better sorting of flavors in the "Launch Instance" view -* Fixed keystone test data to match openstack_auth -* Fixing missed translation -* Minor typo corrections -* Replaces term tenant with project -* Fix selector syntax -* calling nova extensions api to enable certain nova features -* remove 'import *' usage (or mark is #noqa) -* Update heat and ceilometer clients requirements -* Make row actions menu visible for the lower row -* Correct error messages -* Flavor ID added to Flavor creation form -* Query a period of time for usage summary -* Ignore non-existing attr in APIResourceWrapper __repr__ -* Add column "Uptime" to instances overview -* adding aggregates panel to admin dashboard -* Add Image Source Field to choose Location or File -* added Compute Services to System Info panel -* removing horizon exceptions adding colors to log messages -* Unpinning upper bound on python-*clients -* Removed a comment from tox.ini that no longer applied -* Remove all_tenants from server_list of Floating IPs tab -* Enable pep8 F841 checking -* fix r'home/$' in url partten -* Fixing the AJAX function location -* Prevent an array index exception if server does not have an image -* Email field is made not mandatory in user creation and editing -* rename "enable" action to "toggle" - -2013.2.b2 ---------- - -* Adding Heat Resource Topology to Horizon -* Enable H304 check -* Sync pytz from requirements.txt -* Pinning minimum pbr and d2to1 versions -* Neutron Security Group native support -* Prompt for password on stack create -* Add openstack-common -* added column "Image Name" to instances overview -* Adding the ability to set/use domain context -* Adding configuring hints in Horizon documentation -* Temporary change the django_openstack_auth requirement -* update Quantum references to Neutron -* Custom javascript files -* Fix a few visual issues on the network topology diagram -* Add ceilometerclient and bootstrap-datepicker as dependency -* Added btn-create loadbalancer dashboard -* Use oslo.sphinx and remove local copy of doc theme -* Avoid ImportError when selenium is missing -* adding hypervisors panel to admin dashboard -* Implementation of a Heat stacks UI -* Show ID for None display name in boot from volume -* Enable H306 check -* Mock some more keystoneclient.Client properties for mox -* Always load CSS files first -* Doc added for Running selenium tests in VM -* Revised a few confusing quota legends on the overview page -* Fix Further Pyflakes warnings -* Enable hacking H101 test -* Add Filter Action to Volume Views -* Make get_object_by_id() work for most Django objects -* Clean-up some of the workflows-related javascript -* python3: Introduce py33 to tox.ini -* Updates term tenant to project in error messages -* Implement Browser session timeout -* Improvements in csv export for usage data -* Add general description field in image properties -* Fixing scoping of instances in admin volume view -* Region selector enabling multi-region support -* Fixing unmocked call errors -* Disable stop action when instance is deleting -* Ensure flake8 runs with a valid settings file -* Fix quota charts on the Resize Instance form -* Remove pool selection from "Add Monitor" page -* Only display tenant resources in network topology when admin -* Manually mock service_catalog in stub_keystoneclient -* Use Python 3.x compatible except construct -* Sort imports alphabetically -* Update my mailmap -* remove unused imports -* Enable "Start Instance" and "Shut Off Instance" buttons -* List only projects accessible by user -* Remove explicit distribute depend -* Add HACKING.rst -* Edit some load balancers titles -* Quota summary graphs, added styling to indicate percentage full -* Mix snapshots and images tables together -* Make the multi-select button on the "Floating IPs" page work again -* Fix bug in port creation form -* Remove "Edit VIP" button when there is no VIP -* Make 'Router created' message translatable -* switching to use limits instead of quotas -* Enable most of the pyflakes checks -* Adding pagination to the tenant views -* Refactoring url_for to remove admin parameter -* Add RAM/disk requirements to image details -* Add edit buttons for vip, member and monitor -* Resizing a server by means of changing its flavor -* Make 'Creating volume' message translatable -* Add availability zone choice to launch instance -* When launching instances, clarifies quota text to "X of Y Used" -* Fix spelling errors -* Pop 'password' in user_update v3 if it is left blank -* Adds methods for [] & len into LazyURLPattern -* Add settings for console type (vnc vs spice) -* Add security group rule templates -* Fixing get_panel_groups uncaught exception -* Specify the django-compressor version to be 1.3 and higher -* New tox environment for testing with Django 1.4 -* Renames tools/pip-requires to requirements.txt - -2013.2.b1 ---------- - -* Correct exception msg in ClearGateway::action -* Improve test stability -* Use default cidr to avoid exception when editing quantum security rules -* Group CRUD and Management in Admin Dashboard -* Enable snapshot quota setting -* Fixes max recursion warning -* Fixes boot from volume without image -* Adding CRUD for roles -* Make the Settings form fully translatable -* Orchestration endpoints for keystone test data -* Revert "Improvements in csv export for usage data" -* Added insecure SSL support to quantum api -* Adding Domain CRUD in Admin Dashboard -* Add "Edit Pool" button -* Improvements in csv export for usage data -* Preparing for Heat tests -* Access to heat API via python-heatclient -* parse_isotime filter to parse a date string -* Allow users to change their passwords -* Add a logging handler for the cinderclient to the local_settings.py.example -* Display table actions BatchActions buttons in the correct locale -* Fix run_tests documentation on skip-selenium flag -* Always return a list from VolumeTableMixIn._get* -* Refactored the templates code -* register replace_underscores filter for templates -* Allow workflows to support multipart POST -* Shows a warning message when deleting a container that contains data -* Use ugettext_lazy instead of ugettext -* Mark additional strings as translatable -* Make discovery of version for KS catalog smarter -* Allow "Create Snapshot" for SHUTOFF state -* Correct a wonky translation from commit b7e3624 -* Add ability to create a volume from an image -* Ensure an error message in LBaaS is displayed once -* Changes generic error message in horizon.modals.js -* Enable parsing of Identity Service V3 catalog -* Add unit tests for customization module -* Adds d3.js library and reworked quota infographics -* Fixing Floating IP capitalization bug -* Make pagination tunable through the settings panel -* Ensure to use keyword parameters in format string in create_instance.py -* Fix cosmetic bug when displaying unnamed volumes -* Updated translations from Transifex -* Fix translation error for missing default role -* Don't duplicate networks list on keypair import -* Enable using multiple API versions for Identity Service -* Move to flake8 -* Shortens displayed action names in Floating IPs table -* Update Horizon for Django 1.5 compatibility -* Adding extensibility to table actions template -* Remove workaround for keystone -* Migrate to PBR for build tooling -* Quotas names fixed Cores->VCPUs, Floating Ips->Floating IPs -* Remove the term 'syspanel' from docs -* Add help text for some fields of Load Balancer forms -* Remove deprecated features -* Add a logout when admin user update his own password -* Expose "protected" attribute of images -* Fix regression on running manage command -* Fixes sorting on IP Address columns in tables -* Add Filter Action to Instance Views -* Fix the "Updated" field in the Image Detail page -* Adding pagination to the instance views -* Fix floating IP management from instance panel -* Enhancement on prompts to list selected objects -* Add tests for LBaaS screens -* CharFields replaced by IntegerFields in LBaaS forms -* Refactor the quotas tests -* Increase socket timeout for selenium tests -* Return an empty string rather than None when calling repr() -* Update "Getting Started" Contributing docs -* Release notes on Quantum Brocade plugin incompatibility -* Allow admin to edit project quotas for fixed IPs -* Remove unused tools/rfc.sh -* Allow users to create a rich network topology -* Add flavor name regex validation to match nova -* Remove inheritance of More action on first action -* Made default values in templates translatable -* Tiny Mistake in Document -* Fix adding security groups to an existing instance -* Fix some not-consistent titles for virtual routers management - -2013.1.rc1 ----------- - -* Remove note on theming from release notes -* Bump version to 2013.2 -* Adds Grizzly release notes -* Updated translations from transifex for Grizzly RC -* Handle None protocol in security group rule table -* Check if volume service is enabled in quota update -* Pin the cinderclient version -* Disable LB panel by default; allow UUID for Sec Group ID -* Improve UX around "unauthorized" API exceptions -* Reduce duplicate definitions about quota sets -* Hide unnecessary fields based on Loadbalancer Monitor type -* Adds docs for settings/configuration -* rm invalid args when updating quotas with nova api -* Correct the related tenant_id when getting quotas -* Adding extensibility to workflow template file -* Implement configurable auto-fade for alerts messages -* Fix device name for example. Fixes bug 1152975 -* Fix circular dependencies in dashboard settings -* Display port link between router and extra network -* Pass-in the initial value when performing a POST on Workflow Action. This fixes the call to self.changed_data, it allows django forms to be able to compare initial value with current value -* Fixes uncaught exception on Add Pool when unable to retrieve networks -* Updating .po files for translation -* Fixes error message formatting in Load Balancers panel -* Remove router actions from Admin panel -* Fixes uncaught exception on Add Monitor when unable to retrieve pools -* Update to Quantum Client 2.2.0 -* Update CACHE_ to CACHES settings -* Add some more customization help and examples -* Increase maxlength of Snapshot Name to 255 -* Prevents flavors to be deleted when reusing a name -* Allow non-admin users to clear router gateway properly -* blueprint quantum-lbaas -* Don't change dashboard on admin tenant switch -* Improve style of network topology -* Bump python-quantumclient version to 2.1.2 -* Support multiple role selection in projects -* Allow for terminating paused/suspended instances -* Fix errant XHR request happening on every page -* pin django to 1.4.x stream -* Escape the region name before passing as value in URL -* Correctly mock keystoneclient.Client.auto_token property with Mox -* Ensure "Add Interface" form in Admin Panel works -* Fix row striping when datatables are filtered -* Fix footer count update for multi-table pages -* Fix uninitialized variable in launch instance - -2013.1.g3 ---------- - -* Fix hogan js templates in IE8 -* Fix images/snapshots table pagination -* Allow admin to edit project quotas for security groups and rules -* Fix a TypeError when working in a Folsom env -* Add support for both soft and hard reboot options -* Adding network-topology view for quantum -* Added encryption support for volumes -* Resolve API import issues (quantum) -* Support adding/removing instance security groups -* Improved security group rule editing -* Update (some) table actions to use icons together with text -* Allow users to specify the order of VNICs of an instance -* Replaces ugettext with ugettext_lazy in the dashboard-related files -* Implements ability to upload local image to glance -* Remove placeholder objects for subfolders -* If a user only has 1 keypair, this keypair should be selected by default -* Allow image filtering based on image ownership -* Add X-FRAME_OPTIONS header to protect against Clickjacking -* Add recommendations for secure deployments -* Adds API Access information to Access & Security panel -* Some text in html are not translatable, this cleans-up some of those files -* Fixes support for User filtering without JavaScript -* Added openstack_dashboard/local/.secret_key_store to .gitignore -* Improve error message when the default role doesn't exist -* Properly enable/disable project/user edit via setting -* Fixes the width of the error box on the login form -* Change the first letter of routers tab header and html title from lowercase to uppercase -* Fixing sidebar layout in IE -* Timezones can change - display the current tz offset -* Fix on async messaging to don't escape message string marked as safe -* Allow password-field autocomplete to be configured in settings -* Re-enable client logging -* Implements the autocomplete attribute on the login form -* Fix footer count update -* Update to latest oslo-version -* Confirmation dialogs lists selected objects name -* Disable allocate IP button if the current number of floating IP is equal or larger than the amount allowed by the quota -* Change "select all" checkbox behaviour while checkboxes is checked/unchecked -* Remove image_type column from images/snaps tables -* Enhances consistency in 'Create Project' modal -* Quantum Floating IP support -* Default recoverable error to WARN log level -* Invoke the has_more_data function of tables when loading TableTab. This allows classes extending TableTab to support pagination -* Prevent the user from creating a single IP address sized network -* Add support for SPICE consoles -* save the original requestor's IP so it doesn't get overwritten -* Split the logo.png into two files to enable splash page branding -* Add UTC offset information to the timezone -* Added "create image" capabiltiy to the admin dashboard -* Ensure to use api.. -* Don't show the EC2 Credentials panel if there is no EC2 service -* Clean-up deprecated diablo code in index.html -* Fix attributes processing in ActionMetaclass -* Remove |safe from openrc.template -* Improves some UX details -* Extend offline-compression context -* Adding extensibility to data_table template file -* Use default_if_none rather than default filter -* Prevent column summation if no non-None cells -* Absolute limits of -1 should be treated as unlimited -* Allow insecure authentication -* make long tenant names look better -* Clarify the ambiguity of the "more actions" dropdown -* Horizon escapes special characters in openrc.sh -* Don't update count on tables without a summary row -* Allow setting nova quotas to unlimited -* Catch another breakage, when cinder is unavailable -* Check the display name for volumes on AJAX polls - -grizzly-2 ---------- - -* Migrate an instance from the admin dashboard -* Support Quantum L3 function -* Improve Quantum panels to Folsom advanced features -* Don't redirect when clicking instance detail page in admin panel -* Disable Launch Button based on quotas -* Fixed unicode for object copy -* Really, really, honestly adjust the size of the noVNC iframe -* Fixes PEP8 errors as reported by pep8 1.3.4 -* Pin docutils to 0.9.1 -* Store timezone as string. Fixes bug 1091021 -* Avoid cinder calls, when cinder is unavailable -* Fixes bug 1086290 https://bugs.launchpad.net/horizon/+bug/1086290, edit-flavor broken when flavor has extra specs. Includes unittest for the same, and modified mock data to to include extra-specs Change-Id: I286d97568daff26bbd03418b2ea0b808caceadba -* Adds a "simplified" floating IP management option -* Removes unused imports -* Allow permissions to be set on tables -* Add a check for unlimited quotas -* show swap disk in listing and forms in flavors syspanel -* Return a better error message(security_groups) -* Specify floating ips table action cloumn's width -* Fix handling of UUID-typed flavor ids -* Make sure vCPU and RAM quotas are initialised when no instances are running -* Ignore the socket timeout error in Selenium test -* Add an optional link_classes to tables.Column, this is used as the class of the displayed link in the cell -* For long tenant name, display an ellipsis using CSS3 -* refactor UserFilterAction code -* Accepts UUID as an ID of Floating IP - -grizzly-1 ---------- - -* Return a friendly error at flavor creation -* Adds transitional deprecation code for old dashboard names -* Don't inherit from base.html in 500 error page -* Fixes for missing files in MANIFEST -* Unifies Horizon conf -* Client-side validation of password/confirmation match -* Honour LOGIN_URL when redirecting to login page -* Reworks quotas and services panels into System Info panel -* use addHorizonLoadEvent() method instead of $(document).ready() -* Allow running tests individually -* Move netaddr to pip-requires -* Added a check for volume service in quota functions -* Remove superfluous slash from admin usage.csv template -* When editing an image, correctly set the 'is_public' checkbox -* Changed "Delete volume" success message text -* Flavor Extra Specs support -* Wrap a project list call with exception handler -* Enforce use of latest django_openstack_auth for PKI compat -* Dynamically size the noVNC iframe, fix typos in copy -* Remove unused usage.csv template -* Update all usage.csv templates to use 2 decimal places -* Add newline between rows of Admin usage.csv -* Adding volume owner (project) to admin table -* Report correct return value from pep8 check -* Adding volume host to admin table -* Added support for volume types -* Use UUIDs for flavor create/edit -* Enable quota data from multiple sources -* Fixed url pattern for project:instances:detail page -* Add OpenStack trove classifier for PyPI -* Update common -* Fixes JavaScript count bug in tables -* Show message when user has no permissions -* User shouldn't remove their own roles on project -* Readding bin dir which was mistakenly deleted -* Fix bug 1055929 - Can not display usage data for Quota Summary -* Adding ephemeral disk to instance details -* Splits OpenStack Dashboard bits from framework app code -* Corrects an error in the EC2 form choices -* Renames legacy dashboards -* Final translations for Folsom -* Fixes error when clicking OpenStack logo -* Allow any python-swiftclient v1.1 through v1.X -* Open Grizzly (2013.1) -* Document limitations of quantum/nova/floating ip integration -* Remove template comments from compressed blocks -* Admin panel: Don't poll shutoff instances -* Adds release notes for 2012.2 "Folsom" -* Fixes workflows to work without javascript -* Adds a docs example for a customization module -* Preserve add-to-field after form error -* Don't poll on instances in a shutoff state -* Adds a method for overriding specific API messages -* Use device name from nova for attach message -* Fix BatchAction class incongruence between documentation and code Fixes launchpad bug #1044424 -* Make sure quota error message is displayed in overview page -* Fix PEP8 issues -* Add Quantum public network support -* PEP8 issues fixed -* grammar fixes and other minutia -* Makes Launch Instance only show images that are "active" Fixes launchpad Bug #1040231 -* Add nosehtmloutput as a test dependency -* Creates volume snapshot detail page and links to it via the Name column in the Volume Snapshots table -* Syspanel volume list once again shows all volumes -* * Removes instance ID from create volume snapshot Fixes launchpad bug #1039080 * Changes volume id to name in volume snapshot Fixes launchpad bug #1039082 -* Adds instance UUID to associate floating ip dialog Fixes launchpad Bug #1039092 -* Removes instance UUID from floating ip table Fixes launchpad bug #1039090 -* Only blur project membership inputs -* Fixes some table footer bugs -* High-light selected container in browser Fixed bug #1038264 Change-Id: I46c1d2faf58872d9ed72ee9f6f0f9c4d61d20756 -* Adds breadcrumb to resource browser. Fixes bug #1037012 -* Don't change tabs based on cookie if GET param is set -* Fix slight grammar error -* Makes "Instance Name" consistent across dashboard instead of "Server Name" -* Makes the usage of "RAM" consistent across dashboard instead of "Memory" -* Catch an exception of API call when retrieving quota usage - -folsom-3 --------- - -* Bug #1018560 Adding quota display to Overview template -* Fixes form error box width -* Fixes inline object creation button styling -* Removes the jquery.example plugin -* Fixes a js error when tables loaded on the page are empty -* Restores the warning message to the Project dashboard -* Clean up instance state checking for actions -* Clarifying Quickstart Documentation -* Adding missing files to MANIFEST.in -* Resolves i18n problem on batch actions -* Adds javascript console logging for debug mode -* Removes the admin launch instance function -* Table filtering fixes -* Update python-quantumclient dep to require >=2.0 -* Switch to using cinderclient -* "Select all" checkboxes now don't select hidden items -* Update tablesorter cache after ajax updates -* Fix floating notifications so they scroll with window -* Corrects the CSV download link for overview pages -* Specify tenant_id when retrieving network list from Quantum -* Removed inline object creation. Added project membership tab to 'Add Project' workflow -* Switch to use python-swiftclient instead of cloudfiles -* Fetch "deleted" flavors for quota tabulation -* Adds faux "edit" UI for Flavors -* Adds i18n support for Javascript -* Initial support of Quantum V2 -* Update python-glanceclient to allow anything < v2 -* Set env version to 25 for python-glanceclient dep -* Update python-glanceclient dep to 0.3.X -* Don't call a method that doesn't exist for unauth'd requests -* Allow empty device name -* Adds ResourceBrowser and ResourceBrowserView class -* Replace spin.js with animated gif for updating table rows -* project workflow: project membership UI -* Don't show attachment UI if volume is already attached -* Added a check for None value in get_object_display -* Separate "modal" behavior from "self-handling" in forms -* Separate OpenStack exceptions from Horizon exceptions -* Added breadcrumb selector for swift subfolders -* Adds an option for linking to external help docs -* Allow control of whether a user can specify a volume mount point -* Update glanceclient imports and version req -* Fixed name of snaphot button -* Emails in the user list now urlized -* Warn user if no role assigned in default Project -* Cleans up instance log page, form, HTML/styles.. -* Guarantee that data is not undefined in quota index view -* Makes the instance detail tabs sticky -* Adds dynamic project creation to Create User -* Temp fix for api/keystone.py -* Moves bootstrap LESS back to openstack_dashboard -* Add run_tests flag to run only selenium tests -* Fixed/enabled selenium tests -* Fix for quota initialization scripts -* Display form with initial input and error after failure to import keypair -* Makes data table accept mixed data types -* admin workflow to add/edit project info and quotas -* Fixed the bug with images returned as generator -* Added action for creating a volume from snapshot -* Added custom parser for tablesorter.js -* Allow to use SSL with self-signed certificates -* Inline object creation -* Fix the "more" link on the images table -* Partial sync of jsonutils from openstack-common -* Allow security group rules to have their own group as a source -* Fixed logic for disabling form button -* Added 'always-enabled' submit button selector -* Smarter table form rendering and controls -* Allow arbitrarily setting the entry point in a workflow -* Fixing documentation style -* Remove glanceclient.AuthorizationFailure exception -* Auth refactor -* A description is not required for a Project creation -* Allowed empty file for upload -* Adding Better Error for Launching Instance -* Fix run_tests.sh --pep8 jenkins interaction -* Provide user-selectable timezone support -* Makes API endpoints discoverable for an end user -* Allows filtering form field to be selected -* Fixes behavior of the 'check-all' checkbox - -folsom-2 --------- - -* Includes LESS files in bdist packages -* Volumes Redux -* Summation rows handle None correctly -* Provide utilities to automate secure secret key generation -* Use client libs from PyPI (what?) -* Ensure that launching from image/snapshot selects proper default -* Check for quota data before trying to use it in JS -* Fixing the scrollbars on the VNC window -* Fix for openrc.sh to support tenant names with blanks -* Adding Associated Keypair as Column 'Keypair' to Instances table view -* Adding flavor name to instances table view under column 'Size' -* Add flavor name to Detailed Instance Overview -* Volume Progress Bar & Fixes For Quota -* Changing 'Associate / Disassociate IP' to 'Associate / Disassociate Floating IP' and adding Portuguese translation -* Pin client versions until verioinfo bug is fixed -* 'Edit' image disabled if image in 'Queued' state -* Updated wording for instance termination -* Update the sensitive data exception filter bugfix -* Fixing the project dropdown -* Fixes Nonetype error of flavor info in intances index view -* Make TIME_ZONE a local settings with a sane default -* Removed new lines when importing a keypair -* Fixing Amazon Image Creation -* Fix Project Overview link to use instance_id -* JavaScript Refactor -* Tweaking admin warning dialog HTML -* Corrections for stricter pep8 checking -* Forcing Horizon to use PEP8 1.1 -* Use horizon's panel template loader -* Reduced height of modal dialog textareas in dashboard -* Login/Logout redirects with Django variables -* Make Horizon timezone-aware -* Updated status messages after launching multiple instances -* Cleans up the settings files -* Adding the bin dir and lessc binary to the manifest file -* When laxy loading tabs don't overwrite query params -* Removes Horizon's "time" module -* Adds warning banner for admin users in project dash -* Swift Object filter improve and fix bug#1013409 bug#1013412 -* Ensure existing image properties are not deleted -* Return the correct ec2 access/secret when generating ec2rc.sh -* Fix async messages w/ translated strings -* Fixing Nameless Volume Display -* Support revisions in version numbers -* compiled i18n file "django.po" for chinese -* Improved message handling -* Fixed validation check for ICMP rules -* Move docs to doc -* New .tmpl files are not included in build -* Clarifying user roles in various places -* Rollup of volume fixes -* Dependency Reconcilliation -* UUID Cleanup -* Horizon should use openstack.common.jsonutils -* Common table functions are now run on modal.show -* Generate two different nosetests.xml files -* Updating Horizon to use LESS -* Adding block links in table cells -* Only sort on sortable columns -* Some tablesort style tweaks -* Prevent erroneous log message when accessing security rules -* Add Swift pseudo-folder support to Horizon -* Re-enabling client-side table sorting on a basic level -* Glance remote image creation -* Added some identifying classes to detail page sections -* Improved floating ip assocation via workflows -* Added a check for attachment['instance'] -* Changed project uuid to project name -* Added metadata for server -* Adds a summation row option to the datatables -* Adding an AJAX indication to modal loading -* Bootstrapifying quota bars in launch modal window -* Added help text in local.settings.example how to setup Horizon to use SSL-offloading proxy to properly handle page redirects to SSL -* Add ProjectTestingInterface to horizon -* Prevent switching from syspanel to nova dash for image detail -* Removing the current project from the drop-down -* Restored functionality of the region switcher dropdown -* PEP8/style cleanup -* Make sure Horizon is treating passwords securely -* Lowering zindex for spinners, so they don't appear above modal windows -* Removing an unused template -* Ordering the attached volumes for an instance by device name instead of order by id -* Translation fixes/updates -* Adds pagination to Glance API and tables -* Adds initial workflow support to Horizon -* update quickstart doc to fix minor typos -* Allow setup.py bdist to complete happily -* bug #1001313, using dict(list) method to support python2.6 -* bug #974599, rename the cookie 'delete' function to 'remove' to avoid reserve word usage -* Change tenant to project in python code to match templates -* Fixing security group create success message -* Adding css files from horizon dir to manifest file -* bug 999371, add a simple test case to test the tag -* Added a new attribute - display_choices to Column class, for substituting the display value of the statuses provided by Nova to some more meaningful ones in the instance table -* Isolates base_tests.py from "real" dashboards -* bug/997665 Po file has been created under locale directory for French, but it has not been translated, all message strings are empty -* Fixed template loader bug. Fixes bug 999360 -* Panel scaffolding fixes -* Make empty_value accept a callable -* set the admin_pass when creating the server -* Implementation of blueprint ip-validation -* Allow proper log output during test runs -* Fixes to the user form, UI behaviors, and tests -* Unit test corrections. Fixes bug 996255 -* Added instance names to floating ip table -* Fixes lp978896 -- Session fixation security fix -* makes api return default endpoint types. fixes bug 994151 -* Use publicURLs for generated endpoints for ec2rc.sh -* Dismissing alerts when a new modal is opened -* Added instance name for volume attachment -* Adds dash/panel app templates, mgmt commands, template loader -* Replacing the gif AJAX spinner with spin.js -* Move to python-glanceclient -* Complete Simplified Chinese translation for po file -* Improvements to flavor details in the launch instance dialog. The relevant pieces of the flavor are now shown in a table above the auota usage and update dynamically when a flavor is selected -* Added tutorial docs for "Building on Horizon" -* Added english translation files and updated all strings -* Quota usage infographics now update dynamically when flavor or instance count are changed -* Make it easy to have VNC without scrollbars -* Adds S3_URL to generated ec2rc.sh template -* Revamp of testing machinery -* Adding a closing tag to DT -* Change Instance to Image for image detail page -* Add distribute to test-requires -* html escape the console log in refresh -* Remove instance from 'Attach volume' form if the instance is already attached to that volume -* Instance table minor fixes -* Made quota names prettier. Fixed bug 979417 -* Fix it's in the doc's. :P -* Added release notes for 2012.1 -* Corrects the ImportError handling for the override mechanism -* Adding a user configurable log length -* Don't choke on unlimited quotas. Fixes bug 971937 -* Prevent table data elements from wrapping text -* Can now specify endpoint type via setting -* fix cidr help text -* Adds an error message for an outright failure on an ajax modal -* Prevent confirmation password data from being sent to keystone -* Instance log and console actions now go to detail tabs -* Don't try to make an admin call in a user-level dashboard -* Prevent multiple modals/multiple form submissions via ajax -* Ensure that table action ids are unique again. Fixes bug 971328 -* Improved keystone error handling in syspanel -* volume.volumeId property used wrongly as .volume_id -* Using internalURL for Keystone endpoint -* Replacing the ULs with DLs on the instance detail page -* Makes OS_TENANT_ID and OS_TENANT_NAME separate in RC file -* Added "network" to the list of required nova services -* Add preference towards single id for action handling -* Fix issue with not loading and showing tenant name in syspanel/instance view -* Added a min-width to the header bar -* Fix display of volumes and snapshots -* show proper error message in VNC tab if instance not ready -* Dropdown arrow button inherits the same style as main button -* Adds configurable ajax connection queueing -* Adds an option for "sticky" tabs -* Adds PanelGroup class and site customization hook -* User needs to log in messages -* Replacing the caption tag in data tables -* Replaces "_" with " " for instance status and task messages -* Add link to instance for its id in floating ip list -* ".modal" style only applied to modals now -* updating image should redirect back to original page -* fix ajax row update polling decay, -* Copies column instances to be unique per table instance -* Ensures tab data is preloaded. With tests! Fixes bug 964317 -* Removed max_length from username/password fields in login page -* Fix ephemeral field name in quota computing -* Prevent AJAX POST for multipart forms (e.g. file uploads) -* Adds support for tabs + tables -* skip adding spinner animation to row cell if no polling needed -* Additional translations for Traditional Chinese -* Added check to verify email exists when filtering users -* fix label name for add rule in security group to be consistent -* remove console.log from javascript -* Use ugettext_lazy for verbose_texts instead of unicode -* Rework translation for panel and dashboard names. Marked more strings -* Fixing an issue where a unique id was not being returned for the overview table, causing the same information to be rendered for instances with the same name but differing stats. Fixes bug #959489 -* Translate the sidebar -* Fix instance row updates polling and actions name -* fix ajax-modal to work with updated row -* make setup.py execute with python by default -* fix IndexError when trying to create the first flavor (bug 959232) -* LaunchAction button enabled only if image is in 'active' state -* Allow image name up to 255 characters -* Block launching more than one instance if volume is specified -* Fix AJAX form posting that work incorrectly if get() in base views is overridden by subclass, e.g. EditRulesView and EditAttachmentsView if they don't add X-Horizon-Location custom headers if redirect is used. This mucking is probably the cleanest way to fix this in the meantime -* fix horizontal form error field layout break -* Implements AJAX form posting -* Fixing an issue with overlapping content in FireFox using the caption tag. Fixes bug #960823 -* set kernel and ramdisk id not as required field as it's not editable -* Show the modal exactly where it's invoked -* Handle custom column classes; inherit from HTMLElement -* Open Folsom -* Corrects glance image action permissions -* Load tab context data during init for "preload" tabs. Fixes bug 959800 -* Changing name of project settings page to Download OpenStack RC File -* Making download ec2 credentials submit button blue -* Allow message assertions to check response context as well -* Fixed a variable being clobbered in the auth_forms handler -* Adds service name to services table -* Fix EC2 endpoint when downloading credentials -* don't use zipfile's context manager as it won't work on py2.6 -* Add a select all checkbox at table header dynamically -* Filter action respects HTTP method. Fixes bug 931272 -* Paring down the syspanel instances table -* Security Group Rule enhancements -* Added AJAX updating error handling -* Instantiate novaclient managers for test data -* Using the tag for table captions. Fixes bug #953741 -* reset table to empty look if row becomes empty during updates -* Improves the BaseAdminView TestCase -* Adding a string for the create volume form. Fixes Bug #957139 -* Set usage to 0 if attribute not present -* fix syspanel overview missing messages if future date selected -* allow backdrop for modal inside modal, and rearrange the z-indexes -* Port validation should include 65535 -* Clears session if login fails unexepctedly. Fixes bug 956493 -* Updates Image Details page to match other details pages. Fixes bug 955625 -* Remove OPENSTACK_KEYSTONE_ADMIN_URL -* auth_forms: remove dead code -* allow errored volume to be deleted since nova api allows it now -* adds default text for empty instance list in form select widget -* Corrects available actions for syspanel images table -* Updating ec2 credentials verbiage -* Changes 'project settings' to a more fitting 'OpenStack Credentials' -* Added IDs and identifiable classes to all action buttons -* Add missing docs files in tarball -* set minimum instance launch count to 1 -* Created a new detail view for volumes (like instance details) -* Moved ajax updating from Action to Row -* Adding a cancel CSS class to confirmation modals so they can be styled individualls. Fixes Bug #954515 -* User.authorized_tenants is now a cached property -* Updated docs to reflect current required services for Horizon -* Show security groups for instance in overview detail -* Adds default text for keypair select widget on launch form -* force actions_column min-width:140px to prevent dropdown collapse -* add progressive interval delay, extra checks in ajax row update polling -* fix filter form for container objects list -* use tables.DeleteAction for DeleteContainer and DeleteObject -* add source group rule interface in security groups edit -* Removes duplicate error messages from being displayed during batch action error -* Volume delete action cleanup -* Improved contributing docs -* Ensuring the exception handler for the image detail page works -* When the glance client throws an Exception at Horizon, catch it and determine if it is an HTTP exception. If it is, recast it as a glance_client.ClientConnectionError so that Horizon can deal with it in a better manner. Fixes 951200 -* Allows row status to be determined as the aggregate of multiple columns -* Changed CharField to IntegerField in forms where the actual value is expected to be integer -* hide tooltip after select field is selected -* Adding the ability to configure password strength in the local_settings. Fixes bug 948317 -* Update openrc.sh to work with latest novaclient * fixes bug 951919 -* Don't show stack trace when unknown exception happens during login -* Fix the translation of transform string -* Removed id sanitizers now that cinder client does the right thing -* User crud no longer available in syspanel when Keystone is using something other than the native auth backend -* Translate names for some tables -* Restores volume attachment list to instance details -* Fix changing locale if using WSGIScriptAlias -* add table column verbose_name to make it into translation -* Show quotas in Allocate IP form and block if quota limit reached -* load Edit Attachments for volume in modal window -* Fix quicksearch filter for tables, thr row class odd/even has been missing -* Minor extensibility tweaks (sidebar context and div wrapper) -* Moves the branding back out of the main nav template -* Makes sure ajax-updated rows still get correct actions allowed -* Refactorize JS codes for action button check to reduce duplication -* Minor extensibility improvements -* Making initial stride to improve openstack-esq design in sphinx -* Removed "networks" panel from Horizon -* Update for AUTHORS file to remove duplicate entries Multiple emails per person are mapped in .mailmap file Fixes bug 945268 -* Translation for Chinese Traditional -* Fix typo vnc to VNC -* Fix typo Snaphots to Snapshots -* Fix typo termiante to terminate -* fix chinese i18n code name from zh-TW/zh-CN to zh_TW/zh_CN -* Remove old Glance variables from openrc template -* Updated translation files; added sphinx template placeholder to manifest -* Form errors should be very apparent -* Fixed a couple of places where tenant was still being shown to the user -* Show proper warning message if security group rule is incomplete -* Return proper error message when adding security group with no params -* Disable submit action button until any of list item is selected -* set image attributes not modifiable as read-only -* Remove trailing whitespaces in regular file -* Made readme a little more clear on where to put local_settings.py -* add git commit date / sha1 to sphinx html docs -* One last redux for setup.py requirement parsing -* Prevents fade-in of modal forms in case of existing previous modal form. Note: This is just a quick fix for the problem specified in the bug. In general there are problems with using overlaying modals. Each subsequent modal form doesn't 'backdrop' the previous one, and the first modal could be closed without closing the last one -* Appending [Instance_ID] in instance name for Floating IP association form in case the instance name is not unique. Screenshot can be seen at: https://pzt.me/8ud1 -* Made Create Snapshot load in modal -* Fixed MANIFEST.in so the setup.py sdist command works properly -* Added a default SECRET_KEY -* Require django >= 1.3.1 and rework __init__ to make installing easier -* Added package_data to horizon -* Changed alert message to show actual IP instead of obj_id for 'Disassociate IP' action -* Removed subheading from Overview pages -* Made Release Floating IPs buttons red -* Give a project name instead of tenant id when allocating an ip -* Removed period from login status -* Removed unwanted handling for the -e and -f flags in install_requires -* Added floatformat:2 filter to Overview usage for Hours/GBs -* Removed '/' symbol in csv report -* Makes setup.py actually list it's dependencies for pip/easy_install -* Volumes page should not show inactive instances -* Added detail view for images -* Small fix for forms with alert messages -* Updated the django.wsgi file for devstack -* Unifies the project packaging into one set of modules -* Implements reusable tab components -* Prevents unauth'd view calls from popping up login in modal window -* Adds usage vs quota data to the launch instance dialog. Adds a reusable progress bar indicator -* Implementing EC2 credentials download -* Added beginnings of a deployment guide w/ info on sessions -* Validates port range and displayed non-field errors -* Fixing Volume call used in image launch modal -* Validates CIDR for security group rule input -* Remove an unused template -* Makes the background color default to white -* Floating ip attachment needed ip instead of id -* Changing default volume attachment interface -* Use the volume endpoint for volume actions -* Swift name usage cleanup. Unicode support and slash prohibition -* don't show batch actions if no table data is available -* Adds test (copied from Glance/Keystone) to verify authors file is up-to-date -* Adding new ephemeral disk attribute to flavors -* Allow login post without region in POST data -* Removed a *really* outdated setting -* Improve usability of syspanel instance list -* Added an authors file generated from the git log (and de-duplicated) -* Adds new explicit interstitial page to download keypair -* Cleanup of quantum dependencies and imports -* Help texts and dynamic label change for entering security group rules. ICMP rules have different meanings for the from_port and to_port fields -* Updated for Django 1.4 -* Updated to Bootstrap 2.0 Final, and removed unused media -* Adding iso8601 to pip-requires for Glance -* allow rebooting instance in shutoff state -* Fixed #934459. Remove outdated -E arg for pip -* Close button added for alert messages -* Keystone-related improvements -* Adds tests for pause/unpause instances -* Adds tests for instance console exception -* Fixes for volume attachments view and modal behavior -* Ignoring .venv dir -* Adds tests for suspend/resume instances -* Bugfixes for modify project users -* Sets default values for month/year at Usage Form in overview page -* Adds client-side templating capabilities -* Refactored test suite -* Coloring errors in forms red -* Fixes a style bug when a button is the first element in a button group -* Improved AJAX polling -* Rename venvs to match everyone else -* Full support for dashboard and panel configuration via service catalog -* Fixes logic for toggle Pause/Suspend actions Fixes bug 925395. Added functionality in BatchAction to support multiple actions. The verbose_names are accordingly changed in update method. It is only required that the current action index is set in the control -* Adds support for volume snapshots (volume snapshots table and ability to boot from a volume snapshot) -* Cleanup on syspanel.images code, and unuset template removal -* Improved region switcher -* Added readme for changing branding -* Updated Copyright dates to 2012 -* Auto-updating for data in data tables! -* Making attach volume detach action work again -* Renamed all user-facing cases of "tenant" to "project" -* Syspanel instance display corrections -* Use unscoped token to fetch authorized projects. Fixes bug 927939 -* Re-fixing the horizontal layout of the usage range form -* Fixes delete of a flavor in syspanel. Fixes bug 924110. novaclient API is changed - purge param is removed. Patch 2: removed duplicate line Patch 3: removed repeated test call of the same method -* Slightly imrpoved usability of noVNC console -* Cleans up leftover coverage files after test run -* Added spacing in sidebar for nab elements -* fixed whitespace and alignment of elements to be consistent -* Making checkbox padding more flexible (vs. static pixel amounts) Making width of checkbox column consistent, even when no rows are shown -* Make space consistent between tables -* Added vertical padding in tenant switcher -* Converted Quantum to Datatables -* Reworked all the usage implementations into one standard set -* Fixing scroll overflow of table actions -* Coverage stats no longer incorrect -* Adjusting placement of alert action buttons -* Center all multi-select checkboxes -* Trades out a one-off style tweak for a reusable one from bootstrap -* Window now goes as low as 1024px wide without breaking -* Fixed a tupo in Floating IP table header Fixes bug 923281 -* Import cleanups, removing unused vars, exception handling, one test fix -* Tenant user administration upgrades -* Makes failing mox test output 10x easier to decipher -* Cleans up imports and error handling for syspanel.tenants. Fixes bug 922406 -* Improves error handling for missing table values (less confusing) -* Adds title to tenant edit modal. Fixes bug 922350 -* Tenant description no longer raises an exception if missing. Fixes bug 922301 -* Novaclient for usage features. Kill openstackx -* Separate time overrides from test machinery -* Removes unmainted requirements from setup.py - -essex-3 -------- - -* Implements action colors as per style guide. Fixes bug 921741 -* Corrects spacing for dropdown menu items. Fixes bug 921747 -* Removes max-height from modals. Fixes bug 921733 -* Corrects cross-browser height issues for .btn-group + .small -* Bootstrap 2! -* switching to use python-quantumclient intead of quantum repo directly -* horizon: Use novaclient for flavor create/delete -* Port quantum vif servers call to novaclient -* Remove another quota-related openstackx dep -* Fixing default for boot from volume (from /dev/vda to vda) -* Hide boot from volume UI when no volumes are available -* Converts syspanel.images to use datatables, new modals, etc -* Made cancel button more visible -* Tenant description now required on create and edit -* Deleting a directory that should not have been there -* Implementing multi-region support -* Swift exception handling improvements -* Pylint cleanup (mostly unused or missing imports) -* Remove services openstackx dependency -* VNC no longer loads by default on instance detail page -* Update Actions to require class-level name -* Port servers calls to novaclient -* Port quotas to novaclient -* Tooltip implementation cleanup -* Added a contributing guide to the Horizon docs -* Auto-remove auto-generated .rst files for deleted .py files -* Added specific style for error box. * fixes bug 900432 -* Adds ID to flavors list -* Adds support for boot from volume -* Implementing instance count field in launch form. * fixes bug 905061 * Allows for launching multiple instances at once -* Fix reference to vnc console.url -* Use novaclient to get a vnc console -* Fixes a syntax error when updating tenants -* Converts images and snapshots to new tables, modals, error handling, etc -* Fix volume deletion by adding object id sanitization and object display names -* Prevents rendered data from being cached across table instantiations -* Converts instances and volumes to new tables, modals, etc -* Implementing Floating IP Pools for Horizon -* Fix flavor creation template -* Makes all dashboards (and all views under them) login_required by default -* Moved authorized_tenants retrieval to middleware -* adding suspend/resume and pause/unpause instances to horizon added to both user and sys view for blueprint suspend-instance -* pip-requires: Document dep list -* Converted Syspanel Flavors table -* Centralized error handling -* Docs fixes -* Batch actions (including Delete) for DataTables -* Tenant quota API cleanup and tests. Fixed bug 913020 -* Adds first inklings of metadata support for swift and adds extensions for files with no extension when downloading if available -* Silences logging output during test runs -* Converts nova.containers to use new tables, modals, etc -* Ensure the test runner uses the same settings for both sets of tests -* * Fix instance console log output for log tab * Add some css to make things a bit more pretty -* Implement tooltips using twipsy and field help_text property -* Converts all of Access & Security to use new panels, modals, views, etc -* Converts nova.access_and_security.keypairs to new tables and modals -* Fixed some questionable grammar in an error message -* Converts syspanel.services to new tables -* Unified horizon and openstack-dashboard environments -* Converts syspanel.quotas to new tables -* Cleanup on syspanel.users to use new CBV's -* Float ALL form checkboxes left -* Remove last chzn ref -* PEP8 cleanup -* Fix inconsistencies between overview and index -* Converts syspanel.tenants to use DataTables and modal forms -* Bug #910494: Horizon still tries to load quantum.client when QUANTUM_ENABLED=False -* Don't override PIP_DOWNLOAD_CACHE if it has already been set externally -* Fix another reference to python-keystoneclient, now that it's moved -* Wraps all cancel button in trans tag -* python-keystoneclient has moved from 4P to openstack. Update the reference -* Prevent disabling/deleting yourself. Fixes bug 909940 -* Intelligent programmatic table generation! -* Changing sidebar tab titles -* Refactoring the JS to clean things up and pull stuff out into separate files -* Added IP addresses by network group to instance detail page -* Remove problematic .pyc file for local_settings after test run completion -* Improve runserver command to accept arguments -* Fix Translation auto generation -* Updated template loaders to the current class-based versions -* PEP8 fixes -* Fix for pep8 output so Jenkins will recognize the violations -* Hide instance launch modal window on images page by default -* Bug #906105: run_tests.sh ignores -V option -* Removing Chosen js plugin call -* Fix for a non-fatal error in the bash script due to an uninitialized variable -* Fixed failure caused by non-interactive pip installs erroring out on github repo changes -* Making changes for new keystoneclient changes -* updating python-novaclient -* Bumping Django version to 1.3.1 for security fixes -* update horizon generation of openrc to reflect cliauth -* Fixing GIB and MIB on system overview -* Loading settings page while logged out now redirects -* Converting security groups to check boxes -* readding ip to main list table for usability -* Stop using api_key as a keyword -* Fixing cancel button on create flavor page -* Fixing incorrect formatting of django tags -* Fixes deprecated attribute access -* Adding page titles to all pages - -essex-2 -------- - -* Fixing floating ip allocation -* Fixing the edit security group rules form -* Fixing the logic for hiding server actions when they're building -* blueprint UX Improvement -* Hiding unusable actions for instances that are not in the active state -* Restored instance details to instance index and detail pages -* blueprint Improve Dashboard UX -* Adds a named view for sending users to the appropriate home page -* OpenRC file download settings panel w/ tenant selector -* Merging Images and Snapshots into a single panel -* Volume name is passed to novaclient properly. Fixed bug 890908 -* Fixes the syspanel instances page after instances_and_volumes merge -* Merging Floating Ips, Keypairs, and Security Groups into a single panel -* Testing improvements -* fixing url error which occurs when you attach a volume -* Merging Instances and Volumes into a single panel -* Cleans up error handling for index view api calls. Prevents 500 errors -* Keypair bugfixes -* CSS layout fix to make sure title elements are properly cleared -* Corrected a broken trans tag. Fixed 900527 -* Adds the ability to specify the URL pattern name for Panel.get_absolute_url -* PEP8 fixes -* Reworks messages so they display if they have multiple tags applied -* Cleanup of splash page error messages and keystone error handling -* Updated docs for the Dashboard.panels attribute to be clearer -* Updated quantum API -* Changing the wording for disk quota -* Fixes LP Bug#862664 - Improper calls to get_image -* Fix templates installation -* Remove openstack.compute usage -* Moving login error messages into the login dialog -* Converts keypairs to use the new ajax modal dialogs -* Fixed nova dashboard image update view (was returning 500 error) -* Fix for a misnamed attribute -* Implementing new table features -* Improved error message for attempt to access an unregistered dashboard -* Updated the other half of the quantum dependency and bumped env version -* Added bugfix for Django URL reverse bug -* Gave the README an extension that github would recognize and then render -* Fix sys.path in WSGI file -* Added urlquote call around keypair name in delete form. Fixed bug 898803 -* Adding comment to local_settings.py.example -* Remove dependency on django-mailer -* adding danger class to keypair delete button -* Quantum was removed from pypi, this fixes the pip-requires -* Remove execute bit on static files -* AJAX modal for associate floating IP. Fixes bug 884495 -* Adds tabindex to nav elements for better accessibility -* Clears session on splash page to prevent old user ids from being cached -* Fixing login message when bad credentials are supplied -* Dashboards can now add an attribute that indicates the dashboard has support for tenants/projects -* Fix for launch instance bug and some associated tests -* Various fixes for swift UI -* Unit tests shouldn't override template rendering -* Fix three instances of the same typo -* New template when no instances running shared from overview and instances list -* Adds enctype back to object upload form. Allows for extra attrs on modal forms -* Massive UI fixes + bugfixes -* Accounts for non-standard width of the splash modal for centering -* Adds error messages back into syspanel base template -* meaningless change to drive CI -* login dialog fix -* PEP8 fixes -* fixing swift bugs introduced with ui refactor -* Test fixes for glance index, server novaclient, and auth user changes -* Modal form abstraction and cleanup. Bug fixes -* fixed flash message layout for overview -* Removes multiple selections from security groups in launch form -* Fixes the splash page/login box styling -* fixing splash stylesheet link -* moving stylesheet, clearing up spacing -* The new hotness that is Bootstrap -* Adds function to count tab characters in files to run_test.sh -* Setting force back to 0, cleaning up, driving Jenkins -* Use separate backup environments for each job name -* Use relative paths for buildout and have run_tests.sh regenerate the horizon egg link -* drving CI -* driving the CI engine -* Adds environment backup and restoration to run_tests.sh -* Adds docs about environment versioning and the --quiet flag to run_tests.sh -* Download caching, dependency cleanup, run_tests improvements -* blueprint: improve-user-experience Bug #884453 Ensured branding is contained and can't escape sidebar space/break layout by adding a CSS style #main_nav h1. This bounds the branding area and disables overflow. Additionally padding ot the right is adjuested moving the topbar navigation in line with the sidebars righthand side for asthetics - -essex-1 -------- - -* Added sanity checks and environment versioning to run_tests.sh -* Remove Debian bits and let the debian package take care of it -* Adds selenium and qunit integration into Django test suite -* Four modest bug fixes -* unquieting the pip install, theming the docs to match other openstack dev docs -* Adding setup instructions to the quickstart docs -* Updates for readthedocs.org compatibility in docs building -* Re-architects the OpenStack Dashboard for modularity and extensibility -* bug #873216: Fixing ajax refresh for instance view -* bug #862667 -* Fixing some pep8 issues with volumes -* Fixed a copy-paste error in pip-requires -* Adds quantum and kombu to buildout -* Buildout correctly installs novaclient and keystoneclient -* more pep8 cleanup to reduce to 0 pep8 issues -* pep8 cleanup -* Migrates Horizon to use KeystoneClient -* Add .gitreview and rfc.sh -* Fixes LP bug 875231 -- use tenant name instead of id for dropdown -* fixing NOVA -> Horizon -* Fix name references -* adding version to project, setting up autobuild of docs with ./run_tests.sh --docs -* adding developer docs -* Update django-openstack/README -* Update django-openstack/README -* Fixed RAM quota to use MB instead of KB -* Corrected localized format strings and updated internationalization files -* Updates every usage of the messages framework with ugettext -* Internationalizes all form labels -* Fixes all the places where _ was used as a throwaway that might conflict with ugettext -* Fixes LP bug 882245 -- removes js libraries which are completely unused -* Fixes LP bug 882189 -- Adds paging support to swift API calls -* Fix localization string error and updated internationalization files -* Fixes for LP bugs 879626, 879633, and 879641 -* Fix image details -* killing missed semicolons -* killing semicolons in js -* adding todo to cleanup the tailing code once it is supported via the api -* adding ugettext stuff to instances view -* fixing issue with internationalization merge -* Update README -* merging master -* Fixed broken settings CSS sprite in topbar; Relocated dashboard settings bits -* Fixes all failing unit tests post localization merge. :-/ -* refixed console log -* Protect against premature "AuthorizationFailure" error when no service catalog is returned (a la an unscoped token) -* adding instance names to instance detail page headers -* adding link to dashboard instance list -* adding instance detail to syspanel -* Fixed LP bug 877001 -- Disabling a tenant doesn't cause a form validation error -* adding view full log link to logs tab -* fixing issue where overview would hide after switching away -* adding vnc tab -* don't need fancy tail method anymore -* added prototype for basic instance detail page, includes overview and log view -* clean up some errors introduced by rebase -* scaled settings image -* update internationalization files for openstack-dashboard -* Localization of openstack-dashboard templates -* update and recompile internationalization string files for django-openstack -* Localized Syspanel templates -* Localize django_openstack dashboard templates -* Clean up PEP8 errors -* localized syspanel views -* localized django-openstack views -* added Polish to language dropdown since there are localizations -* add settings page to choose UI language -* Initial test of new localization (on Images page) -* Updated style nits, and cleaned up some imports in django_openstack.api -* Reworked to support exchanging unscoped token for scoped token via tenant and unscoped token (no user/pass) -* Converts auth/token/service catalog mechanisms to use novaclient. Refs (if not fixes) LP bug 848396 -* Reworked to support exchanging unscoped token for scoped token via tenant and unscoped token (no user/pass) -* Fixes LP bug 872684 -- Use service catalog instead of settings.SWIFT_ENABLED -* Converts auth/token/service catalog mechanisms to use novaclient. Refs (if not fixes) LP bug 848396 -* Fixes LP bug 872684 -- Use service catalog instead of settings.SWIFT_ENABLED -* this gives the possibility to have an image launchable :) previous release removed it -* Fix identifier for PyPi -* Bumped version -* fixing tenant update test -* Fix w/ tests for LP 844442 -- dash sidebar module loading respects different 'type' params for duplicate names -* fixed other nits -* Fix for issue 863694 on launchpad -- use 'object-store' instead of 'swift' in service catalog lookups -* Fixes the glance API tests that were reverted by 61c9a75201a89af530db3eeb281a39ba19a60676 -* updating api -* update admin port for keystone -* fixing style nits -* adding a notice for when there are no images, so the page isnt just blank -* merging master -* adding delete form to index, so images owned by a user can be deleted by them -* adding edit/delete capability for owner of an image through the user dashboard -* fixing pep8 spacing -* removing useless variable assignment -* creating a separate api method for keypair import, and adding a test -* adding the ability to import an existing public key as a keypair -* removing slash -* renaming js file to follow standard convention, re-adding js file to be included in the head -* moving chosen assets to the newer location in the static dir -* Remove the keystone admin auth hack. Handle condition when no valid tenants returned gracefully -* Make dashboard look for a service of type 'image' rather than specifically 'glance' -* adding normalize_newline to userdata box on launch instances form -* adding test for role_add_for_tenant_user -* fixing error which would cause setting of user role to fail -* ids aren't useful here either -* no need to show ids here -* fix redirects based on Gabriel's feedback -* add/remove user from tenant improvements -* add name to user listing -* Fixed Bug 849488 -- use log.exception instead of log.error -* use type='compute' instead of type='nova' in serviceCatalog -* Fixed issue 858649 on Launchpad -- Distinguishes between tenant name and tenant id -* Completed polish translation -* initial polish l10n setup -* some cleanup -* remove extraneous line -* s/OPENSTACK_KEYSTONE_DEFAULT_ROLE_ID/OPENSTACK_KEYSTONE_DEFAULT_ROLE/ and related fallout -* remove keystone_manage context processor - unused -* make roles case insensitive -* tweaks to account for a bug in keystone where all tenants are returned for admin user, even if adminURL is not used -* changes to let dashboard work with diablo and the latest keystone -* finally fixed the annoying over-sized error box on login splash page -* make server_create use novaclient -* Fixed bug 838257 on Launchpad -- glance Client instances now pass along the token -* fixing flashing issue which occurs when you would click edit image -* Fixed license headers -* Fixed bug 853461 on Launchpad -- Refactors API tests to excercise as much real code as possible in instances where novaclient mocks were being tested previously -* updating requires and dependencies for Glance and Quantum to git from LP -* Converts flavors to use novaclient (where novaclient support is implemented). Reworks unit test mechanism for testing api calls that involve novaclient -* fixing image tests -* fixing keypair list in image launch page -* Removed a duplicate function definition for api.novaclient -* Edited openstack-dashboard/tools/pip-requires via GitHub -* fix osapi 404 message to hint towards keystone service catalog as a possible error source -* Renamed templates within their new directory structures to remove unnecessary duplication of information. Updated views and tests. Removed duplicate copy of _messages.html. All tests pass, click-through successful -* updating snapshots with create test, and hooking up to novaclient -* Fixes bug #846771 on LaunchPad -- moves django_openstack templates out of openstack_dashboard and into directories in the django_openstack app grouped logically according to modules. Site-specific templates (not referenced by the django_openstack app) remain in the openstack_dashboard project -* fixing up keypair tests -* merging with up to date floating ips / master -* fixed tests, tweaked the way api call is made for adding/removing floating ips to instance -* chanigng name of unused variable -* adding python-novaclient to buildout -* adding novaclient to buildout -* cleaning up spacing in css -* cleaning up a pep8 nit -* updating keypair tests -* switching exceptions handling over to novaclient and doing a pylint/pep8 cleanup -* porting keypair functionality over to novaclient -* pep8 cleanup -* remove admin-novaclient as it is only used in broken clients -* remove old references to project_id -* pep8 and pyflakes cleanup on floating ips view -* oops, forgot to save file before commit -* merging -* switched over to novaclient exceptions -* Adding disassociate view tests -* adding first few view tests -* remove extra spaces -* use novaclient exceptions -* switching over to novaclient exceptions instead of openstackx -* add in tests -* some style tweaks -* fix typo in runtests -* trying to get pep8 output to parse in pylint @ jenkins -* returning 0 intentionally from pep8 to show pep8 charts on dash -* adjusting client, adding api tests -* pep8 fixes for quantum integration files -* fixing the allocate floating ip method -* Modified quantum view tests to use Mox -* disassociate from floating ips page now works -* got the floating ip list mostly working now -* Refitting to new Quantum API spec -* updating README to explain project/repo structure -* fixing run_tests - typo, missing requires -* updating run_tests.sh to mimic other openstack projects, pep8, pylint, coverage -* Fix issue #838054: Search form submit causes Forbidden (403) page -* merging with updated pip-requires -* adding novaclient wrapper to api.py, and fixing issue for security groups rules cidr display -* updating api.py to point to novaclient for security groups -* merging api.py -* merging style.css -* Refactored openstack-dashboard to use Django 1.3's contrib.staticfiles app as per current best-practices. This bumps the minimum required version of Django to 1.3 and introduces a backwards-incompatible change for any third-party code that relied on hard-coded paths to the media directory -* hooking up associate floating ip actions -* updating the api to reflect changes in the floating ips api, and removing the admin bits as they will be added later with a admin api extension/client -* Refactored openstack-dashboard to use Django 1.3's contrib.staticfiles app as per current best-practices. This bumps the minimum required version of Django to 1.3 and introduces a backwards-incompatible change for any third-party code that relied on hard-coded paths to the media directory -* adding python-novaclient to the piprequires -* fix inverse project id & container format -* Adding unit tests for network and port views -* cleaning up a few things, and making template tag not error out when there are no modules -* cleaning up recurring calls in sidebar template tag -* Removing duplicate kuombu dependency -* Changes suggested in merge discussion -* Add missing kombu dependency -* Removed all Jquery UI dependencies -* adding ajax toggler to dash instance list -* adding a simple checkbox to toggle ajax refreshing -* syspanel instances will now show globally launched instances after ajax refresh -* adding httpresponse to update image view, without it dashboard will crash on update of image -* Updated pip requires and new client library -* Modified git requires to include https -* Adding kombu to the pip requirements -* Made quantum networking configurable -* Updated local settings file for quantum settings -* Merged quantum code into django-openstack module -* lines added to be compliant with standards -* enforcing admin ( syspanel ) urls -* adding a bit of documentation -* making things a little more pep8 friendly -* rephrasing method name as a verb instead of statement -* fixing typo, consolidating down code -* parsable csv format -* date and iteration formatting fixed -* missing a mock that allows tests to pass -* dry some messages -* when an image gets deleted, existing instances should be able to display without the interface throwing an exception -* Italian Localization Added -* make tests pass again - no need to get_server if recent data is available -* now using add/remove class to prevent state weirdness from toggleclass -* in production, I've seen that vcpus can sometimes be null for compute hosts that do not initialize properly. this prevents /syspanel/ from croaking in that case -* Remove unneeded installed app -* Enable Disable buttons need appropriate messages -* remove debug message -* display tenant on admin server list -* use a separate admin_server_list call to retrieve instances in syspanel. In syspanel, all instances should display, while in dash only the current tenant's instances should display -* instance update status message now refers to instance name instead of id -* clearing .dash_block for style -* fix instance updating -* link hover artifact is now hidden when you hover over tenant info dropdown in header -* refresh button in page header now shows ajax spinner when items are being updated -* removing huge gap on syspanel overview page -* clearing .dash_block for style purposes -* fixing the sizing of capacity info on flavor create form -* making the snapshot create info message display name instead of id -* fixing ip list labels -* associating now works with instances instead of fixed_ips -* adding ip groups instead of public/private ips to instance lists -* fixed a swishy issue with status box width -* reformatting information about instances in floating ips list -* added more information about instance in the associate floating ip form -* making floating ips associate form play nicely with new ip config -* fixing association form -* adding ip allocation to user floating ips stuff -* adding admin interface for listing of floating ips -* floating ip association, allocation, and disassociation now work -* adding pretty sketchy floating ip support for users -* fix more cosmetic issues -* fix spacing issues -* add in tests for snapshot functionality -* remove extra space -* add test to make sure csv gets rendered in dash_usage -* add in user-facing csv download link -* add download links -* initial commit of csv download for dash usage -* making active links work properly in sidebar for modules -* sidebars now only display in their given type area -* hashing out more general modules -* make tests pass with change from imageRef to image obj -* in nova trunk, server.imageRef has been replaced by a server.image object -* adding urls -* Adding new glance dependency to dashboard -* a few small fixes to the way modules work -* adding necessary code to allow for modules in syspanel -* starting to make things modular -* initial impl of instance snapshots -* Adds new glance dependency to buildout -* don't preventDefault - we want the click action to complete the form submit -* Add the fourth date format -* Better codestyle for resource avail/usage information -* Fix keypair creation -* Found a few more errors in api.py's GlobalSummary class -* Correct missing import, used in services -* Cleans up test code a bit -* Clean up settings.py -* Better error reporting for keystone errors -* Gracefully handle keystone token expiration -* remove debian directory - OS projects generally exclude this directory from the main source -* Fix resource avail/usage information -* Typo in info message -* Put edit back in now that keystone has been updated -* Unit tests for user enable/disable -* Support for user enable/disable -* readding object filter form -* Fixes behavior for prefixs that matches no objects -* finishing up styling of swift interface -* tests for auth views -* adjusting styles for table action links -* adding back in the testing of both subcomponents of this project -* address final review comments by mgius: uncomment needed code in run_tests.sh, remove comments from api_tests -* style tweaks for swift ui -* address mgius review comments -* fix instances/refresh action -* re-add LazyUser, fix tests so that they pass -* Remove LazyUser, which causes complications with testing and isn't much of a perf improvement -* Implement api.Server.reboot() -* merging style changes with work in master -* add default OPENSTACK_KEYSTONE_DEFAULT_ROLE='Member'. You must also make sure that this role exists in keystone: ./keystone-manage $* role add Member -* fixing services view -* remove this exception handler - there may be a condition that will have to be handled on token expiration - if that is the case this is not the way it should be handled -* key_name instead of name in keypair templates -* remove tenant create button from quotas index -* making swift use keystone -* remove image name hacks -* in most recent keystone, 'identity' is used as a service name, rather than 'keystone' -* fix log-in -* make tests pass again -* Added support for debug_toolbar -* two minor style fixes -* converting tabs to spaces, removing cssedit crud, my masterpiece is complete! -* adding login and remaining little bits -* getting forms styled -* styled usage blocks for users and tenants usage pages -* styling the status and message boxes, as well as tweaking some of the html class names -* adding styles for most of content area, general tables and content have been added -* beginning css refactor and cleanup from the ground up, header done -* intermediate commit -* big ugly merge -* lots of changes to style -* teaking type in tenants dropdown -* header is now swishy -* header styling, still broken but making progress -* fixing usage pages -* moving to a new way of setting page titles in syspanel -* moving to a new way of setting page titles in dash -* removing another typo -* fixing typo -* removing unneeded commented bits -* small tweaks to templates -* cleaning up all dash templates -* Better error messages on suspected openstackx missing errors -* cleaning up all systempanel templates -* Hide password characters on the login screen -* Change 'keystone' to 'identity' according to changes in keystone -* Can now filter objects in the dashboard -* changing refresh link -* killing debug message -* added quotas to syspanel -* 100% coverage for object views -* fixing conflict -* renaming method endpoint for quotas -* removing debug message -* modifying quotas now works -* tenant_id now pulls from quotas.id -* adding autorefresh to syspanel instance list and fixing spinner styles -* adding auto refresh for dashboard instances -* adding relevant quota information to the image launch page -* attempting to get quota info on image launch page for user -* quotas update form mostly working -* Container creation now checks for existance of a container of the same name -* keypair tests 100% coverage -* enable tenant switching -* Fix for api test: keystone->identity -* Fixed problem with swift copy object trying to instantiate swift api when imported. Moved to __init__ to only make the call when necessary -* Adding convenient upload object link -* Sidebar cleanup -* Unit tests for dash/views/instances.py -* support updating of instance name and description -* Update readme for testing prerequisites and update setup.py to include django_nose -* Fix keystone name change to identity -* Full unit test coverage of dash/views/images.py -* Fixed container access to use swift objects -* cleaner messaging when token expires -* fix ram unit in tenant usage -* Added missing modules to pip-requires -* Unit tests for dashboard container views. Includes support code for future view tests -* improve error handling when keystone and other services are down -* Added copy support for swift objects. Can now copy an object within a container or to a new container -* adding users to tenants -* tenant adding -* adding confirmations to terminate instance, and commenting out permissions toggle for images -* removing all things related to uploading server images -* made create links green and prettyish -* adding availability information to create flavor page to help keep users from making bad decisions -* Typo in readme and api -* PEP8 fixes -* Last function tested. Unused function dropped -* Everything but the keystone api hit and the unused function tested -* Everything but swift and a couple of odd functions done -* Many more tests -* More api tests -* More tests. Removed one API call because it was a duplicate -* Add another test for the compute api -* Unit tests for admin and auth api getters -* Full test coverage for API wrapper classes -* Support options for running coverage tests -* Tests for APIResource and APIDict wrappers -* Updated license headers -* Updated license headers -* display cpu/disk/ram info on service list -* increase number of characters for image names -* Edited django-openstack/buildout.cfg via GitHub -* Glance now deploys through buildout, and copious comments added -* Turn a bad hack into a better one -* Add cloudfiles to buildout -* That ought to do it -* Wrapped Swift api calls -* glance juggled around some exception definitions -* Fix bug in __getattr__ for api object, and PEP8 fixes -* Quick fix to api to make glance api work right -* Glance api wraps -* Fixed problems with incorrect import/usage for glance_exception.ClientConnectionerror -* Fixed problem with ClientConnectionError import failing -* All api calls except for glance now wrapped -* don't purge flavor by default!!! -* allow flavor names to be longer -* pull in build changes from server -* also allow underscores and dashes -* allow periods in group names -* Support for VERY basic Swift container and object management -* So clever I messed it up myself -* This is clever. Perhaps too clever -* Console and Server wrappers -* Bunch of API functions wrapped, tested by hitting dashboard -* Fix flavors delete and keypair list attribute access -* Interface objects added to api, api_tests and api adjusted to use them -* Tests for every api call that uses auth_api -* First test implemented, and buildout changes to allow unit test to run -* Totally out of band diff of improve_logging_again -* fix paramater ordering in server_create -* fixing hide bug for instance list -* make name a bit smaller -* oopsy left in debuggery -* fix host name wrapping -* making long instance names truncate -* add an empty span to correct spacing on syspanel dash -* fix dash usage display -* some visual and ergonomic tweaks -* fixing issue with getting max ram usage -* clean up instances display -* all update links now say edit -* making a text pass on everything -* fix gbformatting -* diskgbformat -* fix formatting of ram sizes -* display correct headers in services tab -* fix ram display to show gb -* list terminated instances last -* capitalize status -* fix text console -* no-wrap table headers -* display instance host -* display key name -* adding a proper description to keypairs -* redirect to image list after image edit -* removing debug info message -* fixing dashboard instances -* merging small changes -* some tweaks - fix image editing as well -* moving position of keypair link -* changing units on dash usage overview -* password field on login form is no longer plaintxt -* changing unit to gb-hr -* fix uptime for tenant drilldown -* hisde password on login form -* fix uptime on user dashboard -* use actual instance name in page title -* add title to vnc console -* allow branding of title -* specify ram on a per-host basis -* fix #190 -* make length requirement more lax -* wrong order -* display secgroups -* order fields -* UI to add security groups -* make service name first -* remove haskey hack -* no need to display empty message -* tweaks in wording, and better empty displays -* some progress on user editing -* empty keypair message -* fix display of instance uptime -* fix compute usage computation on syspanel -* keep dash_usage from puking when there is no instance data -* assorted cosmetic and ergonomic changes: Group terminated instances on user dash. Don't require keypair -* some display fixes for user usage dash -* show MB for ram usage -* parse more date formats -* syspanel overview needs this setting to compile -* Fix to api to allow images to launch -* minor pep8 fixes for api and gitignore fix for new layout -* deprecated form should be Login -* we don't use boto anymore -* remove nose deps -* adding units -* adding instance size details to user instance list -* formatting uptime, and changing text on tenant overview page from inside of syspanel -* adding refresh buttons -* adding refresh to dash instances, fixing syspanel flavors refresh button -* fixing extra quote on refresh links -* making dates consistent through the dashboard, also adding units to flavor table -* deleting flavors now works, as well as displays a proper flash message -* adding title to refresh links, and fixing image table width -* if user gives keypair name a space, it is now hyphenated to prevent breakage -* Updated Keystone port to 5000 - new default -* stub out build files -* remove registration dep -* fixing width of keypair list -* Add comment ot openstack test -* Update the settings -* made success message after deleting a user an info message -* fixing and styling the create user form -* removing error message -* actually committing the right stylesheet this time -* made the status message box less wide -* fix redirect on image launch -* Fix test runner to allow pdb -* login page is now standalone, and error messages have been styled -* Switching to nosetests runner, moving broken tests to a non-module dir, adding dependency_tests -* show empty usage info on /dash -* handle token expiration -* Adds django_mailer and a presence check for it -* fix image launching -* factor out api calls -* image uploading now works -* image editing now works -* image editing now mostly working -* move django_openstack out of src -* Removed some dead code from base and updated testsettings -* use image_ref not image_id -* add in tenant crap -* stash -* Added empty stub for models to avoid django bug. Zero tests now run -* Working to get tests working -* update pip requires to point to openstackx -* add files for debian packaging -* merge trunk -* make user editing work -* first take at auto-logout -* adding confirmation for all actions -* work improving authentication -* Removing tests that depend on CLC_IP -* Manager tests -* remove duplicate code -* we don't really need toggle if there is update -* sidebar ordering changes -* work on tenants -* add fake user management -* make state displays consistent -* move datetime parsing into filter -* need to handle more time formats apparently -* humanize uptime -* remove some xtra spaces -* more overview page fixes -* fix admin dashboard overview display -* s/networking/\- in instance_list's private ip -* more work on instance lists -* fix up admin instance list -* fix file size formatting in admin/images -* use td#actions instead for css selection + form elements -* make form links in tables consistent -* add messages to splash -* fix enabled/disabled logic for services -* fix instance launching, and add keypair/user_data -* Updated README -* removing tenant field from login form, when user signs in it sends them to their default tenant -* pull in code from trunk to only show amis -* brought back the standalone login splash page -* making suggested fixes from termie -* fixing services functionality, cleaning templates, generalizing a few things -* move tests related stuff out of the way for now, it is currently all broken and needs to be ported -* add missing template for create_flavor -* remove unused templatetags -* add missing template for create_flavor -* remove a bunch of unnecessary files -* re-add get_tenant -* merge changes from trunk -* changing page title to compute -* fixing sidebar active state -* finishing port for keypairs -* porting most of keypairs -* some small fixes -* add in services tab -* add in user views -* highlight correct sidebar -* partially working user management -* add features/fixes from trunk to the overview panel -* syspanel existing screens working again -* update local_settings.py.example to reflect keystone-ness -* make compute api work -* use service catalog -* Moved run_instance request logic to ProjectManager class -* Some small issues we encountered trying to create distribution package for Dashboard installing it as subdir of appache's root -* add flavors support -* delete and toggle images -* syspanel images -* syspanel overviews, instances -* move launch to self-handling -* add self-handling-form concept -* squash me -* add switch tenants -* upload... but in wrong place -* launch, console log, vnc -* cleanup + login page -* More url fixes -* Merged with trunk -* Merged with trunk -* theme + images + instances index pages -* skeletal framework for non-admin dashboard -* console and vnc -* terminate instance -* instnace detail page -* instance launching -* remove template region loading -* add context processor for tenants -* overview page and tenant detail -* get auth working -* add local login form -* get login page loading -* remove references to auth and reg -* stripping out user/project stuff, step 1 -* Unit tests for django-openstack.models -* Fix final nit -* Remove hacky post_save short-circuit. Post_save tests to follow later -* Address review comments -* Internationalized the dashboard so that users who have nova running in other languages can select a dashboard UI language to match. Translated all the strings (Localized) into Japanese & tested in English and Japanese. Created empty translation files for other languages but did not perform translation -* updated buildout configuration to work with new version of buildout -* Better formatting and some comments on a couple of the less obvious tests -* Recompiled all message files to catch pep8 string reformatting -* Cleaned up pep8 violations -* Updated translation (po) file headers -* Better way of mocking out get_admin_connection -* Added Japanese localization for django-nova-syspanel -* Japanese Localization of django-openstack -* Finished openstack-dashboard/dashboard localization into Japanese -* CredentialsAuthorization fully tested -* Corrected a merge bug in the localization -* updated localization files to reflect yesterday's merge -* One test failing. Need to become a Mox Guru to make it pass -* Tests for credentials authorization model. Also change testsettings to not rely on a magic string, instead rely on None object -* Corrected bugs introduced in merge -* merge -* Add logging throughout django-openstack, mostly informational code-tracing and logging of error conditions. Add middleware to openstack-dashboard to log uncaught exceptions along with tracebacks for them. Updated local_settings.py to give basic idea of how to silence logging for various modules if not desired -* Format is discouraged, so this is probably the next best thing -* Missed addition -* Still new to bzr, missed middleware -* One trailing whitespace line and adapting LOG to openstack convention -* corrected positional string formats in localizable text and generated localization files -* Fixed language selection box -* Corrected bugs introduced in internationalization -* Update local_settings.py to show example of how to control logging output -* added translation tags to django nova syspanel templates -* Overzealous auto-indent -* Revert changes to createnovausers, CLI interface should print status to stdout -* PEP8 fixes for lines I touched -* added translation tags to django_openstack templates -* Missed debug line and typo -* Should be done now -* Added translation tags to openstack-dashboard/dashboard templates -* added {% load i18n %} to base templates -* marked static strings in python code for Internationalization -* instances logged. Some trivial whitespace changes -* Fix import order. Add logging to images. Some todos and notes in exceptions and shortcuts that need to be addressed -* Slight change to location/naming of logger. Remove some unnecessary debug logs. Finish nova/views/admin.py -* Lots of minor pep8 fixes -* pep8 fixes -* Added logging to a number of methods -* Commented out logging directives to reduce debug output introduced by improved logging in django 1.3 -* Fix setup.py package_data after django_nova rename -* Another fix after nova->openstack rename -* Rename get_nova_connection to get_openstack_connection in nova.views -* Add template files autodiscovery -* Bump django version numbers to 1.3, fix one trivial deprecation warning and fix settings file to allow project to run under 1.3 -* address merge review nitpicks -* Update value of TIME_ZONE and replace some deprecated views with new class based views -* Bump version for django to 1.3 -* Fix run_tests.sh to return non-zero exit status when test cases fail. run_tests.sh currently only returns the exit status of the openstack-dashboard tests, ignoring the exit status of the django-openstack tests -* Fix setup.py package_data after django_nova rename -* merge unit test fixes -* modify run_tests.sh to return nonzero on failed tests -* Add two lines to testsettings that were missed during refactor -* Renamed django_nova to django_openstack in package_data in setup.py -* Add missing settings directives to fix unit test failures -* Name as primary for column, id in brackets -* Added Name field in Launch dialog -* Updates check_dependencies to properly report error messages when easy_install and virtualenv are both missing, and add in an attempt to install virtualenv using easy_install before giving up. Better error messages and error typos fixed -* Makes existing messages for check_dependencies more clear. output for later steps already clear -* Whitespace changes only -* check dependencies now attempts to install dependencies and gives better error messages -* Clearer output on check_dependencies -* install_venv -> PEP8 compliance -* Refactored django-nova into django-openstack. This will allow additional OpenStack modules to be supported -* Merged trunk -* Completed refactor -* Added a flag in settings.py to enable/disable the vnc button from the instances detail page -* adding a settings flag for the vnc button -* removing vnc button on instances -* Fixed run_tests.sh -* Refactored templates -* Refactored connection.py -* Refactored exceptions -* Refactored shortcuts -* Refactored manager.py -* Refactored forms -* Refactored tests -* Refactored tests structure -* Some small issues we encountered trying to create distribution package for Dashboard installing it as subdir of appache's root -* Split up templatetags -* Added package_data attributes to django-nova and django-nova-syspanel to install templates with this packages. Fixed url displayed as "Sign In" (made it use url template tag). Little hack to login.html to make it redirect to index page even when Dashboard is accessed not from server's root. Removed ancient hack from django.wsgi. It was needed only for very old Django versions -* Made tests pass -* Began refactoring django_nova into django_openstack and submodules - -2011.2 ------- - -* This branch adds the instance 'display name' (nickname -* adding the forgotten parentheses -* This branch adds the instance 'display name' (nickname) to attach the attache volume to instance form -* changing string formatting -* adding instance display name to attach volume to instances form -* Fix user table styling bug #741109 -* Remove some print statements that shouldn't have been there -* Remove default "admin"/"admin" user/project credentials and replace with what is configured in settings.py -* Use proper credentials when getting per-project connections -* Remove print statements -* fixed user table styling -* This branch prevents openstack-dashboard from erroring out when a netadmin tries to modify instance details. It also adds a proper error message for when users who try to terminate instances without permission -* permission denied errors now show proper error for instance actions -* When netadmin tries to edit instance details, they are now given a permissions denied error -* This branch adds styling to the permission denied page -* removing redirect from images view, as it is handled by the @handle_nova_error decorator -* Added button in instance details to open VNC session. Requires nova-vncproxy to work -* Selectively show a detach or destroy link on volume list, based on the volume's current attach status -* Show volume id and attachment point on instances list on syspanel -* Add django-nova-syspanel, a holistic operations view of the cloud -* Detach volumes so they can be destroyed -* removing redundant error message -* List volumes on instances -* Added button in instance details to open VNC session -* Fix for Bug #761913. I made the python version string in the install script dynamically set to the version that was used to create the virtualenv. Tested with Python 2.6.6. and Python 2.7.6 on Ubuntu 10.10 -* detect python version in install script -* styling permission denied page -* Ignore egg info directory -* Added close link to the image detail ui, so users do not have to go to the main navigation to return to the standard image list -* Add missing setup.py file -* added a close button for the image detail interface -* Add systempanel -* Update pip-requires to use django 1.2.4 to address security vulnerability -* Made dashboard require Django 1.2.4 -* The jquery ui popup alert that the user may be having connection issues when ajax requests fail now waits until it fails twice (30 seconds) before notifying the user -* instances page now waits until it fails to connect to the server for at least 30 seconds before it alerts the user that there may be a vpn or connection error -* Now references the nova-adminclient project instead of maintaining a copy of the adminclient -* Fixed nova-adminclient reference in setup.py -* Fixed pip-requires -* Merged trunk -* This branch fixes inconsistencies which were causing errors and breaking section 508 compatibility -* fixing 508 errors on user management page -* fixing section 508 error where launch form had an extra label with no form field -* Fixed overlap of register h3 with button on Firefox 3.6, and adjusted height of login box to match -* fixed overlap of register button and h3 text bug 741106 -* change message when attach message sent to compute host. change the default, as ephemeral disks (depending on instance since, like m1.medium) may be available at /dev/vdb -* Change message for shorter wait if volume attach fails -* Fixed an issue that preventing images from being made public -* Fixed an issue where images couldnt be made public -* Update default device & success message for attaching a disk -* Simplified the logic around whether a user can modify images. It needs to be refactored again but it was very broken in its current state -* Patched image list to not show edit links for all images -* The manage user roles UI on the project tab wasn't showing the correct roles when editing a user -* Fixed modify user roles UI -* Fixed the project role admin UI -* Fixed project role admin ui -* Fixed an issue where some auth drivers would cause get_user to fail -* Patch to make get_user work with all auth drivers -* Patch to make get_user work with all auth drivers -* Fixed DescribeUser in adminclient -* Refactored django-nova to pull nova adminclient from pypi -* This branch adds the ability to modify the project manager of any given project from the django-admin interface -* fixing typo in the form, and adding modify_project to adminclient.py -* adding modify_project to adminclient and fixing typo which caused error on form post -* stubbed out the ability to modify project manager -* Removed a 'read more' link which was a text artifact from the nebula dashboard -* Fixed a problem that caused Send Credentials from the admin UI to fail if the email subject template contained a newline -* Fixed credentials email subject parsing -* removing text artifact from nebula dashboard -* The django-nova project has been moved into the openstack-dashboard repo to simplify development efforts -* Combined django-nova and openstack-dashboard -* Ignore sqlite database, venv directory, and local settings -* Add sample configuration and explanatory comments to the local/local_settings.py.example to show how to configure your outgoing mail server, which is used by django-registration -* Change text of the submit button on the registration form to say "Register" instead of "Reset Password" -* Change the name of the default sqlite database to have a .sqlite3 extension -* Added django-nova to openstack-dashboard repo -* Fix text on button for registration form -* Ignore sqlite database, venv directory, and local settings -* Change the name of the default sqlite database to have a .sqlite3 extension -* Add dummy SMTP settings in local settings exmple -* Added site branding tags to reduce number of templates that must be overridden in containing projects -* Merged trunk -* Merged lp:~jakedahn/openstack-dashboard/homepage-additions -* Merged trunk -* Merged lp:~jakedahn/openstack-dashboard/ie-fixes -* Simplified site branding tag -* finishing up first pass on homepage design -* updating links for openstack resources section -* first design pass on homepage when logged out -* Filling in some preliminary content for styling -* Fixed broken template tag reference -* Modified templates to use site branding template tags -* killing new sidebar background image for now -* refactoring some of the main css, and fixing display issues in IE7 -* chmox +x run_tests.sh -* Merged lp:~mordred/openstack-dashboard/add-test-script -* Added simple test runner -* Merged lp:~devcamcar/openstack-dashboard/lp710868 -* Merged lp:~ken-pepple/openstack-dashboard/lp710890 -* Removed all Nebula references -* added NOVA_ADMIN_USER and NOVA_PROJECT to local_settings to prompt users that these are needed -* Merged lp:~devcamcar/openstack-dashboard/fix_unavailable_template -* Cleaned up unavailable template -* Merged lp:~jakedahn/openstack-dashboard/templates-cleanup -* adding forgotten text update to template -* adding 'service unavailable' template and adjusting urls to point to it -* removed the extra 'or' text on the signin form -* removing references to nebula forum and wiki -* Merged lp:~jakedashn/openstack-dashboard/newcss -* refactoring css -* Merged lp:~devcamcar/openstack-dashboard/maintenance_mode -* Added handle_nova_error to home page view -* Support django-nova maintenance mode -* Added README -* Made with_venv.sh executable -* Initial commit diff --git a/code/horizon/HACKING.rst b/code/horizon/HACKING.rst deleted file mode 100644 index 7ac9b75b..00000000 --- a/code/horizon/HACKING.rst +++ /dev/null @@ -1,14 +0,0 @@ -Horizon Style Commandments -========================== - -- Step 1: Read the OpenStack Style Commandments - http://docs.openstack.org/developer/hacking/ -- Step 2: Read [hacking] section in tox.ini to find the list of names which - can be imported directly without triggering the "H302: import only modules" - flake8 warning -- Step 3: Read on - -Horizon Specific Commandments ------------------------------ - -- Read the Horizon contributing documentation at http://docs.openstack.org/developer/horizon/contributing.html diff --git a/code/horizon/LICENSE b/code/horizon/LICENSE deleted file mode 100644 index 68c771a0..00000000 --- a/code/horizon/LICENSE +++ /dev/null @@ -1,176 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - diff --git a/code/horizon/MANIFEST.in b/code/horizon/MANIFEST.in deleted file mode 100644 index 5f296274..00000000 --- a/code/horizon/MANIFEST.in +++ /dev/null @@ -1,19 +0,0 @@ -recursive-include doc *.py *.rst *.css *.js *.html *.conf *.jpg *.gif *.png *.css_t -recursive-include horizon *.html *.css *.js *.csv *.template *.tmpl *.mo *.po -recursive-include openstack_dashboard *.html *.js *.less *.mo *.po *.example *.eot *.svg *.ttf *.woff *.png *.ico *.wsgi *.gif *.csv *.template -recursive-include tools *.py *.sh - -include AUTHORS -include ChangeLog -include LICENSE -include Makefile -include manage.py -include README.rst -include run_tests.sh -include tox.ini -include doc/Makefile -include doc/source/_templates/.placeholder -include requirements.txt -include test-requirements.txt - -exclude openstack_dashboard/local/local_settings.py diff --git a/code/horizon/Makefile b/code/horizon/Makefile deleted file mode 100644 index 49e4f728..00000000 --- a/code/horizon/Makefile +++ /dev/null @@ -1,24 +0,0 @@ -PYTHON=`which python` -DESTDIR=/ -PROJECT=horizon - -all: - @echo "make test - Run tests" - @echo "make source - Create source package" - @echo "make install - Install on local system" - @echo "make buildrpm - Generate a rpm package" - @echo "make clean - Get rid of scratch and byte files" - -source: - $(PYTHON) setup.py sdist $(COMPILE) - -install: - $(PYTHON) setup.py install --root $(DESTDIR) $(COMPILE) - -buildrpm: - $(PYTHON) setup.py bdist_rpm --post-install=rpm/postinstall --pre-uninstall=rpm/preuninstall - -clean: - $(PYTHON) setup.py clean - rm -rf build/ MANIFEST - find . -name '*.pyc' -delete diff --git a/code/horizon/README.rst b/code/horizon/README.rst deleted file mode 100644 index 382ddb2c..00000000 --- a/code/horizon/README.rst +++ /dev/null @@ -1,51 +0,0 @@ -============================= -Horizon (OpenStack Dashboard) -============================= - -Horizon is a Django-based project aimed at providing a complete OpenStack -Dashboard along with an extensible framework for building new dashboards -from reusable components. The ``openstack_dashboard`` module is a reference -implementation of a Django site that uses the ``horizon`` app to provide -web-based interactions with the various OpenStack projects. - -* Release management: https://launchpad.net/horizon -* Blueprints and feature specifications: https://blueprints.launchpad.net/horizon -* Issue tracking: https://bugs.launchpad.net/horizon - - -Using Horizon -============= - -See ``doc/source/topics/install.rst`` about how to install Horizon -in your OpenStack setup. It describes the example steps and -has pointers for more detailed settings and configurations. - -It is also available at http://docs.openstack.org/developer/horizon/topics/install.html. - -Getting Started for Developers -============================== - -``doc/source/quickstart.rst`` or -http://docs.openstack.org/developer/horizon/quickstart.html -describes how to setup Horizon development environment and start development. - -Building Contributor Documentation -================================== - -This documentation is written by contributors, for contributors. - -The source is maintained in the ``doc/source`` directory using -`reStructuredText`_ and built by `Sphinx`_ - -.. _reStructuredText: http://docutils.sourceforge.net/rst.html -.. _Sphinx: http://sphinx-doc.org/ - -* Building Automatically:: - - $ ./run_tests.sh --docs - -* Building Manually:: - - $ tools/with_venv.sh sphinx-build doc/source doc/build/html - -Results are in the ``doc/build/html`` directory diff --git a/code/horizon/horizon/__init__.py b/code/horizon/horizon/__init__.py deleted file mode 100644 index b45e3da8..00000000 --- a/code/horizon/horizon/__init__.py +++ /dev/null @@ -1,66 +0,0 @@ -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" The Horizon interface. - -Contains the core Horizon classes--:class:`~horizon.Dashboard` and -:class:`horizon.Panel`--the dynamic URLconf for Horizon, and common interface -methods like :func:`~horizon.register` and :func:`~horizon.unregister`. - -""" -# Because this module is compiled by setup.py before Django may be installed -# in the environment we try importing Django and issue a warning but move on -# should that fail. -Horizon = None -try: - from horizon.base import Dashboard # noqa - from horizon.base import Horizon # noqa - from horizon.base import Panel # noqa - from horizon.base import PanelGroup # noqa -except ImportError: - import warnings - - def simple_warn(message, category, filename, lineno, file=None, line=None): - return '%s: %s' % (category.__name__, message) - - msg = ("Could not import Horizon dependencies. " - "This is normal during installation.\n") - warnings.formatwarning = simple_warn - warnings.warn(msg, Warning) - -if Horizon: - register = Horizon.register - unregister = Horizon.unregister - get_absolute_url = Horizon.get_absolute_url - get_user_home = Horizon.get_user_home - get_dashboard = Horizon.get_dashboard - get_default_dashboard = Horizon.get_default_dashboard - get_dashboards = Horizon.get_dashboards - urls = Horizon._lazy_urls - -# silence flake8 about unused imports here: -__all__ = [ - "Dashboard", - "Horizon", - "Panel", - "PanelGroup", - "register", - "unregister", - "get_absolute_url", - "get_user_home", - "get_dashboard", - "get_default_dashboard", - "get_dashboards", - "urls", -] diff --git a/code/horizon/horizon/base.py b/code/horizon/horizon/base.py deleted file mode 100644 index 61f944f0..00000000 --- a/code/horizon/horizon/base.py +++ /dev/null @@ -1,982 +0,0 @@ -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Contains the core classes and functionality that makes Horizon what it is. -This module is considered internal, and should not be relied on directly. - -Public APIs are made available through the :mod:`horizon` module and -the classes contained therein. -""" - -import collections -import copy -import inspect -import logging -import os - -from django.conf import settings -from django.conf.urls import include -from django.conf.urls import patterns -from django.conf.urls import url -from django.core.exceptions import ImproperlyConfigured # noqa -from django.core.urlresolvers import reverse -from django.utils.datastructures import SortedDict -from django.utils.functional import SimpleLazyObject # noqa -from django.utils.importlib import import_module # noqa -from django.utils.module_loading import module_has_submodule # noqa -from django.utils.translation import ugettext_lazy as _ - -from horizon import conf -from horizon.decorators import _current_component # noqa -from horizon.decorators import require_auth # noqa -from horizon.decorators import require_perms # noqa -from horizon import loaders - - -LOG = logging.getLogger(__name__) - - -def _decorate_urlconf(urlpatterns, decorator, *args, **kwargs): - for pattern in urlpatterns: - if getattr(pattern, 'callback', None): - pattern._callback = decorator(pattern.callback, *args, **kwargs) - if getattr(pattern, 'url_patterns', []): - _decorate_urlconf(pattern.url_patterns, decorator, *args, **kwargs) - - -def access_cached(func): - def inner(self, context): - session = context['request'].session - try: - if session['allowed']['valid_for'] != session.get('token'): - raise KeyError() - except KeyError: - session['allowed'] = {"valid_for": session.get('token')} - - key = "%s.%s" % (self.__class__.__module__, self.__class__.__name__) - if key not in session['allowed']: - session['allowed'][key] = func(self, context) - session.modified = True - return session['allowed'][key] - return inner - - -class NotRegistered(Exception): - pass - - -class HorizonComponent(object): - policy_rules = None - - def __init__(self): - super(HorizonComponent, self).__init__() - if not self.slug: - raise ImproperlyConfigured('Every %s must have a slug.' - % self.__class__) - - def __unicode__(self): - name = getattr(self, 'name', u"Unnamed %s" % self.__class__.__name__) - return unicode(name) - - def _get_default_urlpatterns(self): - package_string = '.'.join(self.__module__.split('.')[:-1]) - if getattr(self, 'urls', None): - try: - mod = import_module('.%s' % self.urls, package_string) - except ImportError: - mod = import_module(self.urls) - urlpatterns = mod.urlpatterns - else: - # Try importing a urls.py from the dashboard package - if module_has_submodule(import_module(package_string), 'urls'): - urls_mod = import_module('.urls', package_string) - urlpatterns = urls_mod.urlpatterns - else: - urlpatterns = patterns('') - return urlpatterns - - @access_cached - def can_access(self, context): - """Return whether the user has role based access to this component. - - This method is not intended to be overridden. - The result of the method is stored in per-session cache. - """ - return self.allowed(context) - - def allowed(self, context): - """Checks if the user is allowed to access this component. - - This method should be overridden to return the result of - any policy checks required for the user to access this component - when more complex checks are required. - """ - return self._can_access(context['request']) - - def _can_access(self, request): - policy_check = getattr(settings, "POLICY_CHECK_FUNCTION", None) - - # this check is an OR check rather than an AND check that is the - # default in the policy engine, so calling each rule individually - if policy_check and self.policy_rules: - for rule in self.policy_rules: - if policy_check((rule,), request): - return True - return False - - # default to allowed - return True - - -class Registry(object): - def __init__(self): - self._registry = {} - if not getattr(self, '_registerable_class', None): - raise ImproperlyConfigured('Subclasses of Registry must set a ' - '"_registerable_class" property.') - - def _register(self, cls): - """Registers the given class. - - If the specified class is already registered then it is ignored. - """ - if not inspect.isclass(cls): - raise ValueError('Only classes may be registered.') - elif not issubclass(cls, self._registerable_class): - raise ValueError('Only %s classes or subclasses may be registered.' - % self._registerable_class.__name__) - - if cls not in self._registry: - cls._registered_with = self - self._registry[cls] = cls() - - return self._registry[cls] - - def _unregister(self, cls): - """Unregisters the given class. - - If the specified class isn't registered, ``NotRegistered`` will - be raised. - """ - if not issubclass(cls, self._registerable_class): - raise ValueError('Only %s classes or subclasses may be ' - 'unregistered.' % self._registerable_class) - - if cls not in self._registry.keys(): - raise NotRegistered('%s is not registered' % cls) - - del self._registry[cls] - - return True - - def _registered(self, cls): - if inspect.isclass(cls) and issubclass(cls, self._registerable_class): - found = self._registry.get(cls, None) - if found: - return found - else: - # Allow for fetching by slugs as well. - for registered in self._registry.values(): - if registered.slug == cls: - return registered - class_name = self._registerable_class.__name__ - if hasattr(self, "_registered_with"): - parent = self._registered_with._registerable_class.__name__ - raise NotRegistered('%(type)s with slug "%(slug)s" is not ' - 'registered with %(parent)s "%(name)s".' - % {"type": class_name, - "slug": cls, - "parent": parent, - "name": self.slug}) - else: - slug = getattr(cls, "slug", cls) - raise NotRegistered('%(type)s with slug "%(slug)s" is not ' - 'registered.' % {"type": class_name, - "slug": slug}) - - -class Panel(HorizonComponent): - """A base class for defining Horizon dashboard panels. - - All Horizon dashboard panels should extend from this class. It provides - the appropriate hooks for automatically constructing URLconfs, and - providing permission-based access control. - - .. attribute:: name - - The name of the panel. This will be displayed in the - auto-generated navigation and various other places. - Default: ``''``. - - .. attribute:: slug - - A unique "short name" for the panel. The slug is used as - a component of the URL path for the panel. Default: ``''``. - - .. attribute:: permissions - - A list of permission names, all of which a user must possess in order - to access any view associated with this panel. This attribute - is combined cumulatively with any permissions required on the - ``Dashboard`` class with which it is registered. - - .. attribute:: urls - - Path to a URLconf of views for this panel using dotted Python - notation. If no value is specified, a file called ``urls.py`` - living in the same package as the ``panel.py`` file is used. - Default: ``None``. - - .. attribute:: nav - .. method:: nav(context) - - The ``nav`` attribute can be either boolean value or a callable - which accepts a ``RequestContext`` object as a single argument - to control whether or not this panel should appear in - automatically-generated navigation. Default: ``True``. - - .. attribute:: index_url_name - - The ``name`` argument for the URL pattern which corresponds to - the index view for this ``Panel``. This is the view that - :meth:`.Panel.get_absolute_url` will attempt to reverse. - """ - name = '' - slug = '' - urls = None - nav = True - index_url_name = "index" - - def __repr__(self): - return "" % self.slug - - def get_absolute_url(self): - """Returns the default URL for this panel. - - The default URL is defined as the URL pattern with ``name="index"`` in - the URLconf for this panel. - """ - try: - return reverse('horizon:%s:%s:%s' % (self._registered_with.slug, - self.slug, - self.index_url_name)) - except Exception as exc: - # Logging here since this will often be called in a template - # where the exception would be hidden. - LOG.info("Error reversing absolute URL for %s: %s" % (self, exc)) - raise - - @property - def _decorated_urls(self): - urlpatterns = self._get_default_urlpatterns() - - # Apply access controls to all views in the patterns - permissions = getattr(self, 'permissions', []) - _decorate_urlconf(urlpatterns, require_perms, permissions) - _decorate_urlconf(urlpatterns, _current_component, panel=self) - - # Return the three arguments to django.conf.urls.include - return urlpatterns, self.slug, self.slug - - -class PanelGroup(object): - """A container for a set of :class:`~horizon.Panel` classes. - - When iterated, it will yield each of the ``Panel`` instances it - contains. - - .. attribute:: slug - - A unique string to identify this panel group. Required. - - .. attribute:: name - - A user-friendly name which will be used as the group heading in - places such as the navigation. Default: ``None``. - - .. attribute:: panels - - A list of panel module names which should be contained within this - grouping. - """ - def __init__(self, dashboard, slug=None, name=None, panels=None): - self.dashboard = dashboard - self.slug = slug or getattr(self, "slug", "default") - self.name = name or getattr(self, "name", None) - # Our panels must be mutable so it can be extended by others. - self.panels = list(panels or getattr(self, "panels", [])) - - def __repr__(self): - return "<%s: %s>" % (self.__class__.__name__, self.slug) - - def __unicode__(self): - return self.name - - def __iter__(self): - panel_instances = [] - for name in self.panels: - try: - panel_instances.append(self.dashboard.get_panel(name)) - except NotRegistered as e: - LOG.debug(e) - return iter(panel_instances) - - -class Dashboard(Registry, HorizonComponent): - """A base class for defining Horizon dashboards. - - All Horizon dashboards should extend from this base class. It provides the - appropriate hooks for automatic discovery of :class:`~horizon.Panel` - modules, automatically constructing URLconfs, and providing - permission-based access control. - - .. attribute:: name - - The name of the dashboard. This will be displayed in the - auto-generated navigation and various other places. - Default: ``''``. - - .. attribute:: slug - - A unique "short name" for the dashboard. The slug is used as - a component of the URL path for the dashboard. Default: ``''``. - - .. attribute:: panels - - The ``panels`` attribute can be either a flat list containing the name - of each panel **module** which should be loaded as part of this - dashboard, or a list of :class:`~horizon.PanelGroup` classes which - define groups of panels as in the following example:: - - class SystemPanels(horizon.PanelGroup): - slug = "syspanel" - name = _("System") - panels = ('overview', 'instances', ...) - - class Syspanel(horizon.Dashboard): - panels = (SystemPanels,) - - Automatically generated navigation will use the order of the - modules in this attribute. - - Default: ``[]``. - - .. warning:: - - The values for this attribute should not correspond to the - :attr:`~.Panel.name` attributes of the ``Panel`` classes. - They should be the names of the Python modules in which the - ``panel.py`` files live. This is used for the automatic - loading and registration of ``Panel`` classes much like - Django's ``ModelAdmin`` machinery. - - Panel modules must be listed in ``panels`` in order to be - discovered by the automatic registration mechanism. - - .. attribute:: default_panel - - The name of the panel which should be treated as the default - panel for the dashboard, i.e. when you visit the root URL - for this dashboard, that's the panel that is displayed. - Default: ``None``. - - .. attribute:: permissions - - A list of permission names, all of which a user must possess in order - to access any panel registered with this dashboard. This attribute - is combined cumulatively with any permissions required on individual - :class:`~horizon.Panel` classes. - - .. attribute:: urls - - Optional path to a URLconf of additional views for this dashboard - which are not connected to specific panels. Default: ``None``. - - .. attribute:: nav - .. method:: nav(context) - - The ``nav`` attribute can be either boolean value or a callable - which accepts a ``RequestContext`` object as a single argument - to control whether or not this dashboard should appear in - automatically-generated navigation. Default: ``True``. - - .. attribute:: public - - Boolean value to determine whether this dashboard can be viewed - without being logged in. Defaults to ``False``. - - """ - _registerable_class = Panel - name = '' - slug = '' - urls = None - panels = [] - default_panel = None - nav = True - public = False - - def __repr__(self): - return "" % self.slug - - def __init__(self, *args, **kwargs): - super(Dashboard, self).__init__(*args, **kwargs) - self._panel_groups = None - - def get_panel(self, panel): - """Returns the specified :class:`~horizon.Panel` instance registered - with this dashboard. - """ - return self._registered(panel) - - def get_panels(self): - """Returns the :class:`~horizon.Panel` instances registered with this - dashboard in order, without any panel groupings. - """ - all_panels = [] - panel_groups = self.get_panel_groups() - for panel_group in panel_groups.values(): - all_panels.extend(panel_group) - return all_panels - - def get_panel_group(self, slug): - """Returns the specified :class:~horizon.PanelGroup - or None if not registered - """ - return self._panel_groups.get(slug) - - def get_panel_groups(self): - registered = copy.copy(self._registry) - panel_groups = [] - - # Gather our known panels - if self._panel_groups is not None: - for panel_group in self._panel_groups.values(): - for panel in panel_group: - registered.pop(panel.__class__) - panel_groups.append((panel_group.slug, panel_group)) - - # Deal with leftovers (such as add-on registrations) - if len(registered): - slugs = [panel.slug for panel in registered.values()] - new_group = PanelGroup(self, - slug="other", - name=_("Other"), - panels=slugs) - panel_groups.append((new_group.slug, new_group)) - return SortedDict(panel_groups) - - def get_absolute_url(self): - """Returns the default URL for this dashboard. - - The default URL is defined as the URL pattern with ``name="index"`` - in the URLconf for the :class:`~horizon.Panel` specified by - :attr:`~horizon.Dashboard.default_panel`. - """ - try: - return self._registered(self.default_panel).get_absolute_url() - except Exception: - # Logging here since this will often be called in a template - # where the exception would be hidden. - LOG.exception("Error reversing absolute URL for %s." % self) - raise - - @property - def _decorated_urls(self): - urlpatterns = self._get_default_urlpatterns() - - default_panel = None - - # Add in each panel's views except for the default view. - for panel in self._registry.values(): - if panel.slug == self.default_panel: - default_panel = panel - continue - url_slug = panel.slug.replace('.', '/') - urlpatterns += patterns('', - url(r'^%s/' % url_slug, - include(panel._decorated_urls))) - # Now the default view, which should come last - if not default_panel: - raise NotRegistered('The default panel "%s" is not registered.' - % self.default_panel) - urlpatterns += patterns('', - url(r'', - include(default_panel._decorated_urls))) - - # Require login if not public. - if not self.public: - _decorate_urlconf(urlpatterns, require_auth) - # Apply access controls to all views in the patterns - permissions = getattr(self, 'permissions', []) - _decorate_urlconf(urlpatterns, require_perms, permissions) - _decorate_urlconf(urlpatterns, _current_component, dashboard=self) - - # Return the three arguments to django.conf.urls.include - return urlpatterns, self.slug, self.slug - - def _autodiscover(self): - """Discovers panels to register from the current dashboard module.""" - if getattr(self, "_autodiscover_complete", False): - return - - panels_to_discover = [] - panel_groups = [] - # If we have a flat iterable of panel names, wrap it again so - # we have a consistent structure for the next step. - if all([isinstance(i, basestring) for i in self.panels]): - self.panels = [self.panels] - - # Now iterate our panel sets. - for panel_set in self.panels: - # Instantiate PanelGroup classes. - if not isinstance(panel_set, collections.Iterable) and \ - issubclass(panel_set, PanelGroup): - panel_group = panel_set(self) - # Check for nested tuples, and convert them to PanelGroups - elif not isinstance(panel_set, PanelGroup): - panel_group = PanelGroup(self, panels=panel_set) - - # Put our results into their appropriate places - panels_to_discover.extend(panel_group.panels) - panel_groups.append((panel_group.slug, panel_group)) - - self._panel_groups = SortedDict(panel_groups) - - # Do the actual discovery - package = '.'.join(self.__module__.split('.')[:-1]) - mod = import_module(package) - for panel in panels_to_discover: - try: - before_import_registry = copy.copy(self._registry) - import_module('.%s.panel' % panel, package) - except Exception: - self._registry = before_import_registry - if module_has_submodule(mod, panel): - raise - self._autodiscover_complete = True - - @classmethod - def register(cls, panel): - """Registers a :class:`~horizon.Panel` with this dashboard.""" - panel_class = Horizon.register_panel(cls, panel) - # Support template loading from panel template directories. - panel_mod = import_module(panel.__module__) - panel_dir = os.path.dirname(panel_mod.__file__) - template_dir = os.path.join(panel_dir, "templates") - if os.path.exists(template_dir): - key = os.path.join(cls.slug, panel.slug) - loaders.panel_template_dirs[key] = template_dir - return panel_class - - @classmethod - def unregister(cls, panel): - """Unregisters a :class:`~horizon.Panel` from this dashboard.""" - success = Horizon.unregister_panel(cls, panel) - if success: - # Remove the panel's template directory. - key = os.path.join(cls.slug, panel.slug) - if key in loaders.panel_template_dirs: - del loaders.panel_template_dirs[key] - return success - - def allowed(self, context): - """Checks for role based access for this dashboard. - - Checks for access to any panels in the dashboard and of the the - dashboard itself. - - This method should be overridden to return the result of - any policy checks required for the user to access this dashboard - when more complex checks are required. - """ - - # if the dashboard has policy rules, honor those above individual - # panels - if not self._can_access(context['request']): - return False - - # check if access is allowed to a single panel, - # the default for each panel is True - for panel in self.get_panels(): - if panel.can_access(context): - return True - - return False - - -class Workflow(object): - pass - -try: - from django.utils.functional import empty # noqa -except ImportError: - # Django 1.3 fallback - empty = None - - -class LazyURLPattern(SimpleLazyObject): - def __iter__(self): - if self._wrapped is empty: - self._setup() - return iter(self._wrapped) - - def __reversed__(self): - if self._wrapped is empty: - self._setup() - return reversed(self._wrapped) - - def __len__(self): - if self._wrapped is empty: - self._setup() - return len(self._wrapped) - - def __getitem__(self, idx): - if self._wrapped is empty: - self._setup() - return self._wrapped[idx] - - -class Site(Registry, HorizonComponent): - """The overarching class which encompasses all dashboards and panels.""" - - # Required for registry - _registerable_class = Dashboard - - name = "Horizon" - namespace = 'horizon' - slug = 'horizon' - urls = 'horizon.site_urls' - - def __repr__(self): - return u"" % self.slug - - @property - def _conf(self): - return conf.HORIZON_CONFIG - - @property - def dashboards(self): - return self._conf['dashboards'] - - @property - def default_dashboard(self): - return self._conf['default_dashboard'] - - def register(self, dashboard): - """Registers a :class:`~horizon.Dashboard` with Horizon.""" - return self._register(dashboard) - - def unregister(self, dashboard): - """Unregisters a :class:`~horizon.Dashboard` from Horizon.""" - return self._unregister(dashboard) - - def registered(self, dashboard): - return self._registered(dashboard) - - def register_panel(self, dashboard, panel): - dash_instance = self.registered(dashboard) - return dash_instance._register(panel) - - def unregister_panel(self, dashboard, panel): - dash_instance = self.registered(dashboard) - if not dash_instance: - raise NotRegistered("The dashboard %s is not registered." - % dashboard) - return dash_instance._unregister(panel) - - def get_dashboard(self, dashboard): - """Returns the specified :class:`~horizon.Dashboard` instance.""" - return self._registered(dashboard) - - def get_dashboards(self): - """Returns an ordered tuple of :class:`~horizon.Dashboard` modules. - - Orders dashboards according to the ``"dashboards"`` key in - ``HORIZON_CONFIG`` or else returns all registered dashboards - in alphabetical order. - - Any remaining :class:`~horizon.Dashboard` classes registered with - Horizon but not listed in ``HORIZON_CONFIG['dashboards']`` - will be appended to the end of the list alphabetically. - """ - if self.dashboards: - registered = copy.copy(self._registry) - dashboards = [] - for item in self.dashboards: - dashboard = self._registered(item) - dashboards.append(dashboard) - registered.pop(dashboard.__class__) - if len(registered): - extra = registered.values() - extra.sort() - dashboards.extend(extra) - return dashboards - else: - dashboards = self._registry.values() - dashboards.sort() - return dashboards - - def get_default_dashboard(self): - """Returns the default :class:`~horizon.Dashboard` instance. - - If ``"default_dashboard"`` is specified in ``HORIZON_CONFIG`` - then that dashboard will be returned. If not, the first dashboard - returned by :func:`~horizon.get_dashboards` will be returned. - """ - if self.default_dashboard: - return self._registered(self.default_dashboard) - elif len(self._registry): - return self.get_dashboards()[0] - else: - raise NotRegistered("No dashboard modules have been registered.") - - def get_user_home(self, user): - """Returns the default URL for a particular user. - - This method can be used to customize where a user is sent when - they log in, etc. By default it returns the value of - :meth:`get_absolute_url`. - - An alternative function can be supplied to customize this behavior - by specifying a either a URL or a function which returns a URL via - the ``"user_home"`` key in ``HORIZON_CONFIG``. Each of these - would be valid:: - - {"user_home": "/home",} # A URL - {"user_home": "my_module.get_user_home",} # Path to a function - {"user_home": lambda user: "/" + user.name,} # A function - {"user_home": None,} # Will always return the default dashboard - - This can be useful if the default dashboard may not be accessible - to all users. When user_home is missing from HORIZON_CONFIG, - it will default to the settings.LOGIN_REDIRECT_URL value. - """ - user_home = self._conf['user_home'] - if user_home: - if callable(user_home): - return user_home(user) - elif isinstance(user_home, basestring): - # Assume we've got a URL if there's a slash in it - if '/' in user_home: - return user_home - else: - mod, func = user_home.rsplit(".", 1) - return getattr(import_module(mod), func)(user) - # If it's not callable and not a string, it's wrong. - raise ValueError('The user_home setting must be either a string ' - 'or a callable object (e.g. a function).') - else: - return self.get_absolute_url() - - def get_absolute_url(self): - """Returns the default URL for Horizon's URLconf. - - The default URL is determined by calling - :meth:`~horizon.Dashboard.get_absolute_url` - on the :class:`~horizon.Dashboard` instance returned by - :meth:`~horizon.get_default_dashboard`. - """ - return self.get_default_dashboard().get_absolute_url() - - @property - def _lazy_urls(self): - """Lazy loading for URL patterns. - - This method avoids problems associated with attempting to evaluate - the URLconf before the settings module has been loaded. - """ - def url_patterns(): - return self._urls()[0] - - return LazyURLPattern(url_patterns), self.namespace, self.slug - - def _urls(self): - """Constructs the URLconf for Horizon from registered Dashboards.""" - urlpatterns = self._get_default_urlpatterns() - self._autodiscover() - - # Discover each dashboard's panels. - for dash in self._registry.values(): - dash._autodiscover() - - # Load the plugin-based panel configuration - self._load_panel_customization() - - # Allow for override modules - if self._conf.get("customization_module", None): - customization_module = self._conf["customization_module"] - bits = customization_module.split('.') - mod_name = bits.pop() - package = '.'.join(bits) - mod = import_module(package) - try: - before_import_registry = copy.copy(self._registry) - import_module('%s.%s' % (package, mod_name)) - except Exception: - self._registry = before_import_registry - if module_has_submodule(mod, mod_name): - raise - - # Compile the dynamic urlconf. - for dash in self._registry.values(): - urlpatterns += patterns('', - url(r'^%s/' % dash.slug, - include(dash._decorated_urls))) - - # Return the three arguments to django.conf.urls.include - return urlpatterns, self.namespace, self.slug - - def _autodiscover(self): - """Discovers modules to register from ``settings.INSTALLED_APPS``. - - This makes sure that the appropriate modules get imported to register - themselves with Horizon. - """ - if not getattr(self, '_registerable_class', None): - raise ImproperlyConfigured('You must set a ' - '"_registerable_class" property ' - 'in order to use autodiscovery.') - # Discover both dashboards and panels, in that order - for mod_name in ('dashboard', 'panel'): - for app in settings.INSTALLED_APPS: - mod = import_module(app) - try: - before_import_registry = copy.copy(self._registry) - import_module('%s.%s' % (app, mod_name)) - except Exception: - self._registry = before_import_registry - if module_has_submodule(mod, mod_name): - raise - - def _load_panel_customization(self): - """Applies the plugin-based panel configurations. - - This method parses the panel customization from the ``HORIZON_CONFIG`` - and make changes to the dashboard accordingly. - - It supports adding, removing and setting default panels on the - dashboard. It also support registering a panel group. - """ - panel_customization = self._conf.get("panel_customization", []) - - # Process all the panel groups first so that they exist before panels - # are added to them and Dashboard._autodiscover() doesn't wipe out any - # panels previously added when its panel groups are instantiated. - panel_configs = [] - for config in panel_customization: - if config.get('PANEL'): - panel_configs.append(config) - elif config.get('PANEL_GROUP'): - self._process_panel_group_configuration(config) - else: - LOG.warning("Skipping %s because it doesn't have PANEL or " - "PANEL_GROUP defined.", config.__name__) - # Now process the panels. - for config in panel_configs: - self._process_panel_configuration(config) - - def _process_panel_configuration(self, config): - """Add, remove and set default panels on the dashboard.""" - try: - dashboard = config.get('PANEL_DASHBOARD') - if not dashboard: - LOG.warning("Skipping %s because it doesn't have " - "PANEL_DASHBOARD defined.", config.__name__) - return - panel_slug = config.get('PANEL') - dashboard_cls = self.get_dashboard(dashboard) - panel_group = config.get('PANEL_GROUP') - default_panel = config.get('DEFAULT_PANEL') - - # Set the default panel - if default_panel: - dashboard_cls.default_panel = default_panel - - # Remove the panel - if config.get('REMOVE_PANEL', False): - for panel in dashboard_cls.get_panels(): - if panel_slug == panel.slug: - dashboard_cls.unregister(panel.__class__) - elif config.get('ADD_PANEL', None): - # Add the panel to the dashboard - panel_path = config['ADD_PANEL'] - mod_path, panel_cls = panel_path.rsplit(".", 1) - try: - mod = import_module(mod_path) - except ImportError: - LOG.warning("Could not load panel: %s", mod_path) - return - panel = getattr(mod, panel_cls) - dashboard_cls.register(panel) - if panel_group: - dashboard_cls.get_panel_group(panel_group).\ - panels.append(panel.slug) - else: - panels = list(dashboard_cls.panels) - panels.append(panel) - dashboard_cls.panels = tuple(panels) - except Exception as e: - LOG.warning('Could not process panel %(panel)s: %(exc)s', - {'panel': panel_slug, 'exc': e}) - - def _process_panel_group_configuration(self, config): - """Adds a panel group to the dashboard.""" - panel_group_slug = config.get('PANEL_GROUP') - try: - dashboard = config.get('PANEL_GROUP_DASHBOARD') - if not dashboard: - LOG.warning("Skipping %s because it doesn't have " - "PANEL_GROUP_DASHBOARD defined.", config.__name__) - return - dashboard_cls = self.get_dashboard(dashboard) - - panel_group_name = config.get('PANEL_GROUP_NAME') - if not panel_group_name: - LOG.warning("Skipping %s because it doesn't have " - "PANEL_GROUP_NAME defined.", config.__name__) - return - # Create the panel group class - panel_group = type(panel_group_slug, - (PanelGroup, ), - {'slug': panel_group_slug, - 'name': panel_group_name, - 'panels': []},) - # Add the panel group to dashboard - panels = list(dashboard_cls.panels) - panels.append(panel_group) - dashboard_cls.panels = tuple(panels) - # Trigger the autodiscovery to completely load the new panel group - dashboard_cls._autodiscover_complete = False - dashboard_cls._autodiscover() - except Exception as e: - LOG.warning('Could not process panel group %(panel_group)s: ' - '%(exc)s', - {'panel_group': panel_group_slug, 'exc': e}) - - -class HorizonSite(Site): - """A singleton implementation of Site such that all dealings with horizon - get the same instance no matter what. There can be only one. - """ - _instance = None - - def __new__(cls, *args, **kwargs): - if not cls._instance: - cls._instance = super(Site, cls).__new__(cls, *args, **kwargs) - return cls._instance - - -# The one true Horizon -Horizon = HorizonSite() diff --git a/code/horizon/horizon/browsers/__init__.py b/code/horizon/horizon/browsers/__init__.py deleted file mode 100644 index a36f6285..00000000 --- a/code/horizon/horizon/browsers/__init__.py +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# Importing non-modules that are not used explicitly -from horizon.browsers.base import ResourceBrowser # noqa -from horizon.browsers.views import ResourceBrowserView # noqa diff --git a/code/horizon/horizon/browsers/base.py b/code/horizon/horizon/browsers/base.py deleted file mode 100644 index 4b9193b5..00000000 --- a/code/horizon/horizon/browsers/base.py +++ /dev/null @@ -1,145 +0,0 @@ -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from django import template -from django.utils.translation import ugettext_lazy as _ - -from horizon.browsers.breadcrumb import Breadcrumb # noqa -from horizon.tables import DataTable # noqa -from horizon.utils import html - - -class ResourceBrowser(html.HTMLElement): - """A class which defines a browser for displaying data. - - .. attribute:: name - - A short name or slug for the browser. - - .. attribute:: verbose_name - - A more verbose name for the browser meant for display purposes. - - .. attribute:: navigation_table_class - - This table displays data on the left side of the browser. - Set the ``navigation_table_class`` attribute with - the desired :class:`~horizon.tables.DataTable` class. - This table class must set browser_table attribute in Meta to - ``"navigation"``. - - .. attribute:: content_table_class - - This table displays data on the right side of the browser. - Set the ``content_table_class`` attribute with - the desired :class:`~horizon.tables.DataTable` class. - This table class must set browser_table attribute in Meta to - ``"content"``. - - .. attribute:: navigation_kwarg_name - - This attribute represents the key of the navigatable items in the - kwargs property of this browser's view. - Defaults to ``"navigation_kwarg"``. - - .. attribute:: content_kwarg_name - - This attribute represents the key of the content items in the - kwargs property of this browser's view. - Defaults to ``"content_kwarg"``. - - .. attribute:: template - - String containing the template which should be used to render - the browser. Defaults to ``"horizon/common/_resource_browser.html"``. - - .. attribute:: context_var_name - - The name of the context variable which will contain the browser when - it is rendered. Defaults to ``"browser"``. - - .. attribute:: has_breadcrumb - - Indicates if the content table of the browser would have breadcrumb. - Defaults to false. - - .. attribute:: breadcrumb_template - - This is a template used to render the breadcrumb. - Defaults to ``"horizon/common/_breadcrumb.html"``. - """ - name = None - verbose_name = None - navigation_table_class = None - content_table_class = None - navigation_kwarg_name = "navigation_kwarg" - content_kwarg_name = "content_kwarg" - navigable_item_name = _("Navigation Item") - template = "horizon/common/_resource_browser.html" - context_var_name = "browser" - has_breadcrumb = False - breadcrumb_template = "horizon/common/_breadcrumb.html" - breadcrumb_url = None - - def __init__(self, request, tables_dict=None, attrs=None, **kwargs): - super(ResourceBrowser, self).__init__() - self.name = self.name or self.__class__.__name__ - self.verbose_name = self.verbose_name or self.name.title() - self.request = request - self.kwargs = kwargs - self.has_breadcrumb = getattr(self, "has_breadcrumb") - if self.has_breadcrumb: - self.breadcrumb_template = getattr(self, "breadcrumb_template") - self.breadcrumb_url = getattr(self, "breadcrumb_url") - if not self.breadcrumb_url: - raise ValueError("You must specify a breadcrumb_url " - "if the has_breadcrumb is set to True.") - self.attrs.update(attrs or {}) - self.check_table_class(self.content_table_class, "content_table_class") - self.check_table_class(self.navigation_table_class, - "navigation_table_class") - if tables_dict: - self.set_tables(tables_dict) - - def check_table_class(self, cls, attr_name): - if not cls or not issubclass(cls, DataTable): - raise ValueError("You must specify a DataTable subclass for " - "the %s attribute on %s." - % (attr_name, self.__class__.__name__)) - - def set_tables(self, tables): - """Sets the table instances on the browser from a dictionary mapping - table names to table instances (as constructed by MultiTableView). - """ - self.navigation_table = tables[self.navigation_table_class._meta.name] - self.content_table = tables[self.content_table_class._meta.name] - navigation_item = self.kwargs.get(self.navigation_kwarg_name) - content_path = self.kwargs.get(self.content_kwarg_name) - if self.has_breadcrumb: - self.prepare_breadcrumb(tables, navigation_item, content_path) - - def prepare_breadcrumb(self, tables, navigation_item, content_path): - if self.has_breadcrumb and navigation_item and content_path: - for table in tables.values(): - table.breadcrumb = Breadcrumb(self.request, - self.breadcrumb_template, - navigation_item, - content_path, - self.breadcrumb_url) - - def render(self): - browser_template = template.loader.get_template(self.template) - extra_context = {self.context_var_name: self} - context = template.RequestContext(self.request, extra_context) - return browser_template.render(context) diff --git a/code/horizon/horizon/browsers/breadcrumb.py b/code/horizon/horizon/browsers/breadcrumb.py deleted file mode 100644 index f4e13c55..00000000 --- a/code/horizon/horizon/browsers/breadcrumb.py +++ /dev/null @@ -1,46 +0,0 @@ -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from django import template - -from horizon.utils import html - - -class Breadcrumb(html.HTMLElement): - def __init__(self, request, template, root, - subfolder_path, url, attr=None): - super(Breadcrumb, self).__init__() - self.template = template - self.request = request - self.root = root - self.subfolder_path = subfolder_path - self.url = url - self._subfolders = [] - - def get_subfolders(self): - if self.subfolder_path and not self._subfolders: - (parent, slash, folder) = self.subfolder_path.strip('/') \ - .rpartition('/') - while folder: - path = "%s%s%s/" % (parent, slash, folder) - self._subfolders.insert(0, (folder, path)) - (parent, slash, folder) = parent.rpartition('/') - return self._subfolders - - def render(self): - """Renders the table using the template from the table options.""" - breadcrumb_template = template.loader.get_template(self.template) - extra_context = {"breadcrumb": self} - context = template.RequestContext(self.request, extra_context) - return breadcrumb_template.render(context) diff --git a/code/horizon/horizon/browsers/views.py b/code/horizon/horizon/browsers/views.py deleted file mode 100644 index 351f4833..00000000 --- a/code/horizon/horizon/browsers/views.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from django.utils.translation import ugettext_lazy as _ - -from horizon.tables import MultiTableView # noqa -from horizon.utils import memoized - - -class ResourceBrowserView(MultiTableView): - browser_class = None - - def __init__(self, *args, **kwargs): - if not self.browser_class: - raise ValueError("You must specify a ResourceBrowser subclass " - "for the browser_class attribute on %s." - % self.__class__.__name__) - self.table_classes = (self.browser_class.navigation_table_class, - self.browser_class.content_table_class) - self.navigation_selection = False - super(ResourceBrowserView, self).__init__(*args, **kwargs) - - @memoized.memoized_method - def get_browser(self): - browser = self.browser_class(self.request, **self.kwargs) - browser.set_tables(self.get_tables()) - if not self.navigation_selection: - ct = browser.content_table - item = browser.navigable_item_name.lower() - ct._no_data_message = _("Select a %s to browse.") % item - return browser - - def get_tables(self): - tables = super(ResourceBrowserView, self).get_tables() - # Tells the navigation table what is selected. - navigation_table = tables[ - self.browser_class.navigation_table_class._meta.name] - navigation_item = self.kwargs.get( - self.browser_class.navigation_kwarg_name) - navigation_table.current_item_id = navigation_item - return tables - - def get_context_data(self, **kwargs): - context = super(ResourceBrowserView, self).get_context_data(**kwargs) - browser = self.get_browser() - context["%s_browser" % browser.name] = browser - return context diff --git a/code/horizon/horizon/conf/__init__.py b/code/horizon/horizon/conf/__init__.py deleted file mode 100644 index 73a3af5c..00000000 --- a/code/horizon/horizon/conf/__init__.py +++ /dev/null @@ -1,47 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import copy - -from django.utils.functional import empty # noqa -from django.utils.functional import LazyObject # noqa - - -class LazySettings(LazyObject): - def _setup(self, name=None): - from django.conf import settings - from horizon.conf.default import HORIZON_CONFIG as DEFAULT_CONFIG # noqa - HORIZON_CONFIG = copy.copy(DEFAULT_CONFIG) - HORIZON_CONFIG.update(settings.HORIZON_CONFIG) - - # Ensure we always have our exception configuration... - for exc_category in ['unauthorized', 'not_found', 'recoverable']: - if exc_category not in HORIZON_CONFIG['exceptions']: - default_exc_config = DEFAULT_CONFIG['exceptions'][exc_category] - HORIZON_CONFIG['exceptions'][exc_category] = default_exc_config - - # Ensure our password validator always exists... - if 'regex' not in HORIZON_CONFIG['password_validator']: - default_pw_regex = DEFAULT_CONFIG['password_validator']['regex'] - HORIZON_CONFIG['password_validator']['regex'] = default_pw_regex - if 'help_text' not in HORIZON_CONFIG['password_validator']: - default_pw_help = DEFAULT_CONFIG['password_validator']['help_text'] - HORIZON_CONFIG['password_validator']['help_text'] = default_pw_help - - self._wrapped = HORIZON_CONFIG - - def __getitem__(self, name, fallback=None): - if self._wrapped is empty: - self._setup(name) - return self._wrapped.get(name, fallback) - -HORIZON_CONFIG = LazySettings() diff --git a/code/horizon/horizon/conf/dash_template/__init__.py b/code/horizon/horizon/conf/dash_template/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/code/horizon/horizon/conf/dash_template/dashboard.py.tmpl b/code/horizon/horizon/conf/dash_template/dashboard.py.tmpl deleted file mode 100644 index 9e435bef..00000000 --- a/code/horizon/horizon/conf/dash_template/dashboard.py.tmpl +++ /dev/null @@ -1,13 +0,0 @@ -from django.utils.translation import ugettext_lazy as _ - -import horizon - - -class {{ dash_name|title }}(horizon.Dashboard): - name = _("{{ dash_name|title }}") - slug = "{{ dash_name|slugify }}" - panels = () # Add your panels here. - default_panel = '' # Specify the slug of the dashboard's default panel. - - -horizon.register({{ dash_name|title }}) diff --git a/code/horizon/horizon/conf/dash_template/static/dash_name/css/dash_name.css b/code/horizon/horizon/conf/dash_template/static/dash_name/css/dash_name.css deleted file mode 100644 index ed03b4f6..00000000 --- a/code/horizon/horizon/conf/dash_template/static/dash_name/css/dash_name.css +++ /dev/null @@ -1 +0,0 @@ -/* Additional CSS for {{ dash_name }}. */ diff --git a/code/horizon/horizon/conf/dash_template/static/dash_name/js/dash_name.js b/code/horizon/horizon/conf/dash_template/static/dash_name/js/dash_name.js deleted file mode 100644 index a8088523..00000000 --- a/code/horizon/horizon/conf/dash_template/static/dash_name/js/dash_name.js +++ /dev/null @@ -1 +0,0 @@ -/* Additional JavaScript for {{ dash_name }}. */ diff --git a/code/horizon/horizon/conf/dash_template/templates/dash_name/base.html b/code/horizon/horizon/conf/dash_template/templates/dash_name/base.html deleted file mode 100644 index f07a01ba..00000000 --- a/code/horizon/horizon/conf/dash_template/templates/dash_name/base.html +++ /dev/null @@ -1,11 +0,0 @@ -{% load horizon %}{% jstemplate %}[% extends 'base.html' %] - -[% block sidebar %] - [% include 'horizon/common/_sidebar.html' %] -[% endblock %] - -[% block main %] - [% include "horizon/_messages.html" %] - [% block {{ dash_name }}_main %][% endblock %] -[% endblock %] -{% endjstemplate %} diff --git a/code/horizon/horizon/conf/default.py b/code/horizon/horizon/conf/default.py deleted file mode 100644 index 7ad8da25..00000000 --- a/code/horizon/horizon/conf/default.py +++ /dev/null @@ -1,47 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from django.conf import settings -from django.utils.translation import ugettext_lazy as _ - -# Default configuration dictionary. Do not mutate. -HORIZON_CONFIG = { - # Allow for ordering dashboards; list or tuple if provided. - 'dashboards': None, - - # Name of a default dashboard; defaults to first alphabetically if None - 'default_dashboard': None, - - # Default redirect url for users' home - 'user_home': settings.LOGIN_REDIRECT_URL, - - # AJAX settings for JavaScript - 'ajax_queue_limit': 10, - 'ajax_poll_interval': 2500, - - # URL for additional help with this site. - 'help_url': None, - - # Exception configuration. - 'exceptions': {'unauthorized': [], - 'not_found': [], - 'recoverable': []}, - - # Password configuration. - 'password_validator': {'regex': '.*', - 'help_text': _("Password is not accepted")}, - - 'password_autocomplete': 'off', - - # Enable or disable simplified floating IP address management. - 'simple_ip_management': True -} diff --git a/code/horizon/horizon/conf/panel_template/__init__.py b/code/horizon/horizon/conf/panel_template/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/code/horizon/horizon/conf/panel_template/panel.py.tmpl b/code/horizon/horizon/conf/panel_template/panel.py.tmpl deleted file mode 100644 index 949ac096..00000000 --- a/code/horizon/horizon/conf/panel_template/panel.py.tmpl +++ /dev/null @@ -1,11 +0,0 @@ -from django.utils.translation import ugettext_lazy as _ - -import horizon -{% if dashboard %}from {{ dash_path }} import dashboard{% endif %} - -class {{ panel_name|title }}(horizon.Panel): - name = _("{{ panel_name|title }}") - slug = "{{ panel_name|slugify }}" -{% if dashboard %} - -dashboard.{{ dash_name|title }}.register({{ panel_name|title }}){% endif %} diff --git a/code/horizon/horizon/conf/panel_template/templates/panel_name/index.html b/code/horizon/horizon/conf/panel_template/templates/panel_name/index.html deleted file mode 100644 index 97a0d57b..00000000 --- a/code/horizon/horizon/conf/panel_template/templates/panel_name/index.html +++ /dev/null @@ -1,12 +0,0 @@ -{% load horizon %}{% jstemplate %}[% extends 'base.html' %] -[% load i18n %] -[% block title %][% trans "{{ panel_name|title }}" %][% endblock %] - -[% block page_header %] - [% include "horizon/common/_page_header.html" with title=_("{{ panel_name|title }}") %] -[% endblock page_header %] - -[% block main %] -[% endblock %] - -{% endjstemplate %} diff --git a/code/horizon/horizon/conf/panel_template/tests.py.tmpl b/code/horizon/horizon/conf/panel_template/tests.py.tmpl deleted file mode 100644 index 4663b3b3..00000000 --- a/code/horizon/horizon/conf/panel_template/tests.py.tmpl +++ /dev/null @@ -1,7 +0,0 @@ -from horizon.test import helpers as test - - -class {{ panel_name|title }}Tests(test.TestCase): - # Unit tests for {{ panel_name }}. - def test_me(self): - self.assertTrue(1 + 1 == 2) diff --git a/code/horizon/horizon/conf/panel_template/urls.py.tmpl b/code/horizon/horizon/conf/panel_template/urls.py.tmpl deleted file mode 100644 index 13113211..00000000 --- a/code/horizon/horizon/conf/panel_template/urls.py.tmpl +++ /dev/null @@ -1,11 +0,0 @@ -from django.conf.urls import patterns -from django.conf.urls import url - -from {{ dash_path }}.{{ panel_name }}.views \ - import IndexView - - -urlpatterns = patterns( - '', - url(r'^$', IndexView.as_view(), name='index'), -) diff --git a/code/horizon/horizon/conf/panel_template/views.py b/code/horizon/horizon/conf/panel_template/views.py deleted file mode 100644 index a5116ca4..00000000 --- a/code/horizon/horizon/conf/panel_template/views.py +++ /dev/null @@ -1,10 +0,0 @@ -from horizon import views - - -class IndexView(views.APIView): - # A very simple class-based view... - template_name = '{{ dash_name }}/{{ panel_name }}/index.html' - - def get_data(self, request, context, *args, **kwargs): - # Add data to the context here... - return context diff --git a/code/horizon/horizon/context_processors.py b/code/horizon/horizon/context_processors.py deleted file mode 100644 index 81a71db0..00000000 --- a/code/horizon/horizon/context_processors.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2012 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -""" -Context processors used by Horizon. -""" - -from horizon import conf - - -def horizon(request): - """The main Horizon context processor. Required for Horizon to function. - - It adds the Horizon config to the context as well as setting the names - ``True`` and ``False`` in the context to their boolean equivalents - for convenience. - - .. warning:: - - Don't put API calls in context processors; they will be called once - for each template/template fragment which takes context that is used - to render the complete output. - """ - context = {"HORIZON_CONFIG": conf.HORIZON_CONFIG, - "True": True, - "False": False} - - return context diff --git a/code/horizon/horizon/contrib/__init__.py b/code/horizon/horizon/contrib/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/code/horizon/horizon/contrib/bootstrap_datepicker.py b/code/horizon/horizon/contrib/bootstrap_datepicker.py deleted file mode 100644 index 3741fa68..00000000 --- a/code/horizon/horizon/contrib/bootstrap_datepicker.py +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2014 IBM Corp. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# Map Horizon languages to datepicker locales -LOCALE_MAPPING = { - 'ar': 'ar', - 'az': 'az', - 'bg': 'bg', - 'ca': 'ca', - 'cs': 'cs', - 'cy': 'cy', - 'da': 'da', - 'de': 'de', - 'el': 'el', - 'es': 'es', - 'et': 'et', - 'fa': 'fa', - 'fi': 'fi', - 'fr': 'fr', - 'gl': 'gl', - 'he': 'he', - 'hr': 'hr', - 'hu': 'hu', - 'id': 'id', - 'is': 'is', - 'it': 'it', - 'ja': 'ja', - 'ka': 'ka', - 'kk': 'kk', - 'ko': 'kr', # difference between horizon and datepicker - 'lt': 'lt', - 'lv': 'lv', - 'mk': 'mk', - 'ms': 'ms', - 'nb': 'nb', - 'nl-be': 'nl-BE', - 'nl': 'nl', - 'no': 'no', - 'pl': 'pl', - 'pt-br': 'pt-BR', - 'pt': 'pt', - 'ro': 'ro', - 'rs-latin': 'rs-latin', - 'sr': 'rs', # difference between horizon and datepicker - 'ru': 'ru', - 'sk': 'sk', - 'sl': 'sl', - 'sq': 'sq', - 'sv': 'sv', - 'sw': 'sw', - 'th': 'th', - 'tr': 'tr', - 'ua': 'ua', - 'vi': 'vi', - 'zh-cn': 'zh-CN', - 'zh-tw': 'zh-TW', -} diff --git a/code/horizon/horizon/decorators.py b/code/horizon/horizon/decorators.py deleted file mode 100644 index c95aed61..00000000 --- a/code/horizon/horizon/decorators.py +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright 2012 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Copyright 2012 CRS4 -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -General-purpose decorators for use with Horizon. -""" -import functools - -from django.utils.decorators import available_attrs # noqa -from django.utils.translation import ugettext_lazy as _ - - -def _current_component(view_func, dashboard=None, panel=None): - """Sets the currently-active dashboard and/or panel on the request.""" - @functools.wraps(view_func, assigned=available_attrs(view_func)) - def dec(request, *args, **kwargs): - if dashboard: - request.horizon['dashboard'] = dashboard - if panel: - request.horizon['panel'] = panel - return view_func(request, *args, **kwargs) - return dec - - -def require_auth(view_func): - """Performs user authentication check. - - Similar to Django's `login_required` decorator, except that this throws - :exc:`~horizon.exceptions.NotAuthenticated` exception if the user is not - signed-in. - """ - from horizon.exceptions import NotAuthenticated # noqa - - @functools.wraps(view_func, assigned=available_attrs(view_func)) - def dec(request, *args, **kwargs): - if request.user.is_authenticated(): - return view_func(request, *args, **kwargs) - raise NotAuthenticated(_("Please log in to continue.")) - return dec - - -def require_perms(view_func, required): - """Enforces permission-based access controls. - - :param list required: A tuple of permission names, all of which the request - user must possess in order access the decorated view. - - Example usage:: - - from horizon.decorators import require_perms - - - @require_perms(['foo.admin', 'foo.member']) - def my_view(request): - ... - - Raises a :exc:`~horizon.exceptions.NotAuthorized` exception if the - requirements are not met. - """ - from horizon.exceptions import NotAuthorized # noqa - # We only need to check each permission once for a view, so we'll use a set - current_perms = getattr(view_func, '_required_perms', set([])) - view_func._required_perms = current_perms | set(required) - - @functools.wraps(view_func, assigned=available_attrs(view_func)) - def dec(request, *args, **kwargs): - if request.user.is_authenticated(): - if request.user.has_perms(view_func._required_perms): - return view_func(request, *args, **kwargs) - raise NotAuthorized(_("You are not authorized to access %s") - % request.path) - - # If we don't have any permissions, just return the original view. - if required: - return dec - else: - return view_func diff --git a/code/horizon/horizon/exceptions.py b/code/horizon/horizon/exceptions.py deleted file mode 100755 index 92ea2fb5..00000000 --- a/code/horizon/horizon/exceptions.py +++ /dev/null @@ -1,365 +0,0 @@ -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Exceptions raised by the Horizon code and the machinery for handling them. -""" - -import logging -import os -import sys - -import six - -from django.core.management import color_style # noqa -from django.http import HttpRequest # noqa -from django.utils import encoding -from django.utils.translation import ugettext_lazy as _ -from django.views.debug import CLEANSED_SUBSTITUTE # noqa -from django.views.debug import SafeExceptionReporterFilter # noqa - -from horizon.conf import HORIZON_CONFIG # noqa -from horizon import messages - -LOG = logging.getLogger(__name__) - - -class HorizonReporterFilter(SafeExceptionReporterFilter): - """Error report filter that's always active, even in DEBUG mode.""" - def is_active(self, request): - return True - - # TODO(gabriel): This bugfix is cribbed from Django's code. When 1.4.1 - # is available we can remove this code. - def get_traceback_frame_variables(self, request, tb_frame): - """Replaces the values of variables marked as sensitive with - stars (*********). - """ - # Loop through the frame's callers to see if the sensitive_variables - # decorator was used. - current_frame = tb_frame.f_back - sensitive_variables = None - while current_frame is not None: - if (current_frame.f_code.co_name == - 'sensitive_variables_wrapper' and - 'sensitive_variables_wrapper' - in current_frame.f_locals): - # The sensitive_variables decorator was used, so we take note - # of the sensitive variables' names. - wrapper = current_frame.f_locals['sensitive_variables_wrapper'] - sensitive_variables = getattr(wrapper, - 'sensitive_variables', - None) - break - current_frame = current_frame.f_back - - cleansed = [] - if self.is_active(request) and sensitive_variables: - if sensitive_variables == '__ALL__': - # Cleanse all variables - for name, value in tb_frame.f_locals.items(): - cleansed.append((name, CLEANSED_SUBSTITUTE)) - return cleansed - else: - # Cleanse specified variables - for name, value in tb_frame.f_locals.items(): - if name in sensitive_variables: - value = CLEANSED_SUBSTITUTE - elif isinstance(value, HttpRequest): - # Cleanse the request's POST parameters. - value = self.get_request_repr(value) - cleansed.append((name, value)) - return cleansed - else: - # Potentially cleanse only the request if it's one of the - # frame variables. - for name, value in tb_frame.f_locals.items(): - if isinstance(value, HttpRequest): - # Cleanse the request's POST parameters. - value = self.get_request_repr(value) - cleansed.append((name, value)) - return cleansed - - -class HorizonException(Exception): - """Base exception class for distinguishing our own exception classes.""" - pass - - -class Http302(HorizonException): - """Error class which can be raised from within a handler to cause an - early bailout and redirect at the middleware level. - """ - status_code = 302 - - def __init__(self, location, message=None): - self.location = location - self.message = message - - -class NotAuthorized(HorizonException): - """Raised whenever a user attempts to access a resource which they do not - have permission-based access to (such as when failing the - :func:`~horizon.decorators.require_perms` decorator). - - The included :class:`~horizon.middleware.HorizonMiddleware` catches - ``NotAuthorized`` and handles it gracefully by displaying an error - message and redirecting the user to a login page. - """ - status_code = 401 - - -class NotAuthenticated(HorizonException): - """Raised when a user is trying to make requests and they are not logged - in. - - The included :class:`~horizon.middleware.HorizonMiddleware` catches - ``NotAuthenticated`` and handles it gracefully by displaying an error - message and redirecting the user to a login page. - """ - status_code = 403 - - -class NotFound(HorizonException): - """Generic error to replace all "Not Found"-type API errors.""" - status_code = 404 - - -class Conflict(HorizonException): - """Generic error to replace all "Conflict"-type API errors.""" - status_code = 409 - - -class RecoverableError(HorizonException): - """Generic error to replace any "Recoverable"-type API errors.""" - status_code = 100 # HTTP status code "Continue" - - -class ServiceCatalogException(HorizonException): - """Raised when a requested service is not available in the - ``ServiceCatalog`` returned by Keystone. - """ - def __init__(self, service_name): - message = 'Invalid service catalog service: %s' % service_name - super(ServiceCatalogException, self).__init__(message) - - -class AlreadyExists(HorizonException): - """Exception to be raised when trying to create an API resource which - already exists. - """ - def __init__(self, name, resource_type): - self.attrs = {"name": name, "resource": resource_type} - self.msg = _('A %(resource)s with the name "%(name)s" already exists.') - - def __repr__(self): - return self.msg % self.attrs - - def __str__(self): - return self.msg % self.attrs - - def __unicode__(self): - return self.msg % self.attrs - - -class ConfigurationError(HorizonException): - """Exception to be raised when invalid settings have been provided.""" - pass - - -class NotAvailable(HorizonException): - """Exception to be raised when something is not available.""" - pass - - -class WorkflowError(HorizonException): - """Exception to be raised when something goes wrong in a workflow.""" - pass - - -class WorkflowValidationError(HorizonException): - """Exception raised during workflow validation if required data is missing, - or existing data is not valid. - """ - pass - - -class HandledException(HorizonException): - """Used internally to track exceptions that have gone through - :func:`horizon.exceptions.handle` more than once. - """ - def __init__(self, wrapped): - self.wrapped = wrapped - - -UNAUTHORIZED = tuple(HORIZON_CONFIG['exceptions']['unauthorized']) -NOT_FOUND = tuple(HORIZON_CONFIG['exceptions']['not_found']) -RECOVERABLE = (AlreadyExists, Conflict, NotAvailable, ServiceCatalogException) -RECOVERABLE += tuple(HORIZON_CONFIG['exceptions']['recoverable']) - - -def error_color(msg): - return color_style().ERROR_OUTPUT(msg) - - -def check_message(keywords, message): - """Checks an exception for given keywords and raises a new ``ActionError`` - with the desired message if the keywords are found. This allows selective - control over API error messages. - """ - exc_type, exc_value, exc_traceback = sys.exc_info() - if set(str(exc_value).split(" ")).issuperset(set(keywords)): - exc_value._safe_message = message - raise - - -def handle_unauthorized(request, message, redirect, ignore, escalate, handled, - force_silence, force_log, - log_method, log_entry, log_level): - if ignore: - return NotAuthorized - if not force_silence and not handled: - log_method(error_color("Unauthorized: %s" % log_entry)) - if not handled: - if message: - message = _("Unauthorized: %s") % message - # We get some pretty useless error messages back from - # some clients, so let's define our own fallback. - fallback = _("Unauthorized. Please try logging in again.") - messages.error(request, message or fallback) - # Escalation means logging the user out and raising NotAuthorized - # so the middleware will redirect them appropriately. - if escalate: - # Prevents creation of circular import. django.contrib.auth - # requires openstack_dashboard.settings to be loaded (by trying to - # access settings.CACHES in in django.core.caches) while - # openstack_dashboard.settings requires django.contrib.auth to be - # loaded while importing openstack_auth.utils - from django.contrib.auth import logout # noqa - logout(request) - raise NotAuthorized - # Otherwise continue and present our "unauthorized" error message. - return NotAuthorized - - -def handle_notfound(request, message, redirect, ignore, escalate, handled, - force_silence, force_log, - log_method, log_entry, log_level): - if not force_silence and not handled and (not ignore or force_log): - log_method(error_color("Not Found: %s" % log_entry)) - if not ignore and not handled: - messages.error(request, message or log_entry) - if redirect: - raise Http302(redirect) - if not escalate: - return NotFound # return to normal code flow - - -def handle_recoverable(request, message, redirect, ignore, escalate, handled, - force_silence, force_log, - log_method, log_entry, log_level): - if not force_silence and not handled and (not ignore or force_log): - # Default recoverable error to WARN log level - log_method = getattr(LOG, log_level or "warning") - log_method(error_color("Recoverable error: %s" % log_entry)) - if not ignore and not handled: - messages.error(request, message or log_entry) - if redirect: - raise Http302(redirect) - if not escalate: - return RecoverableError # return to normal code flow - - -HANDLE_EXC_METHODS = [ - {'exc': UNAUTHORIZED, 'handler': handle_unauthorized, 'set_wrap': False}, - {'exc': NOT_FOUND, 'handler': handle_notfound, 'set_wrap': True}, - {'exc': RECOVERABLE, 'handler': handle_recoverable, 'set_wrap': True}, -] - - -def handle(request, message=None, redirect=None, ignore=False, - escalate=False, log_level=None, force_log=None): - """Centralized error handling for Horizon. - - Because Horizon consumes so many different APIs with completely - different ``Exception`` types, it's necessary to have a centralized - place for handling exceptions which may be raised. - - Exceptions are roughly divided into 3 types: - - #. ``UNAUTHORIZED``: Errors resulting from authentication or authorization - problems. These result in being logged out and sent to the login screen. - #. ``NOT_FOUND``: Errors resulting from objects which could not be - located via the API. These generally result in a user-facing error - message, but are otherwise returned to the normal code flow. Optionally - a redirect value may be passed to the error handler so users are - returned to a different view than the one requested in addition to the - error message. - #. RECOVERABLE: Generic API errors which generate a user-facing message - but drop directly back to the regular code flow. - - All other exceptions bubble the stack as normal unless the ``ignore`` - argument is passed in as ``True``, in which case only unrecognized - errors are bubbled. - - If the exception is not re-raised, an appropriate wrapper exception - class indicating the type of exception that was encountered will be - returned. - """ - exc_type, exc_value, exc_traceback = sys.exc_info() - log_method = getattr(LOG, log_level or "exception") - force_log = force_log or os.environ.get("HORIZON_TEST_RUN", False) - force_silence = getattr(exc_value, "silence_logging", False) - - # Because the same exception may travel through this method more than - # once (if it's re-raised) we may want to treat it differently - # the second time (e.g. no user messages/logging). - handled = issubclass(exc_type, HandledException) - wrap = False - - # Restore our original exception information, but re-wrap it at the end - if handled: - exc_type, exc_value, exc_traceback = exc_value.wrapped - wrap = True - - log_entry = encoding.force_text(exc_value) - - # We trust messages from our own exceptions - if issubclass(exc_type, HorizonException): - message = exc_value - # Check for an override message - elif getattr(exc_value, "_safe_message", None): - message = exc_value._safe_message - # If the message has a placeholder for the exception, fill it in - elif message and "%(exc)s" in message: - message = encoding.force_text(message) % {"exc": log_entry} - if message: - message = encoding.force_text(message) - - for exc_handler in HANDLE_EXC_METHODS: - if issubclass(exc_type, exc_handler['exc']): - if exc_handler['set_wrap']: - wrap = True - handler = exc_handler['handler'] - ret = handler(request, message, redirect, ignore, escalate, - handled, force_silence, force_log, - log_method, log_entry, log_level) - if ret: - return ret # return to normal code flow - - # If we've gotten here, time to wrap and/or raise our exception. - if wrap: - raise HandledException([exc_type, exc_value, exc_traceback]) - - six.reraise(exc_type, exc_value, exc_traceback) diff --git a/code/horizon/horizon/forms/__init__.py b/code/horizon/horizon/forms/__init__.py deleted file mode 100644 index fca0ffb3..00000000 --- a/code/horizon/horizon/forms/__init__.py +++ /dev/null @@ -1,76 +0,0 @@ -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -# Importing non-modules that are not used explicitly - -# FIXME(gabriel): Legacy imports for API compatibility. -from django.core.exceptions import ValidationError # noqa -from django.forms.fields import * # noqa -from django.forms.forms import * # noqa -from django.forms import widgets -from django.forms.widgets import * # noqa - - -# Convenience imports for public API components. -from horizon.forms.base import DateForm # noqa -from horizon.forms.base import SelfHandlingForm # noqa -from horizon.forms.base import SelfHandlingMixin # noqa -from horizon.forms.fields import DynamicChoiceField # noqa -from horizon.forms.fields import DynamicTypedChoiceField # noqa -from horizon.forms.fields import IPField # noqa -from horizon.forms.fields import IPv4 # noqa -from horizon.forms.fields import IPv6 # noqa -from horizon.forms.fields import MultiIPField # noqa -from horizon.forms.fields import SelectWidget # noqa -from horizon.forms.views import ModalFormMixin # noqa -from horizon.forms.views import ModalFormView # noqa - - -__all__ = [ - "SelfHandlingMixin", - "SelfHandlingForm", - "DateForm", - "ModalFormView", - "ModalFormMixin", - "DynamicTypedChoiceField", - "DynamicChoiceField", - "IPField", - "IPv4", - "IPv6", - "MultiIPField", - "SelectWidget" - - # From django.forms - "ValidationError", - - # From django.forms.fields - 'Field', 'CharField', 'IntegerField', 'DateField', 'TimeField', - 'DateTimeField', 'TimeField', 'RegexField', 'EmailField', 'FileField', - 'ImageField', 'URLField', 'BooleanField', 'NullBooleanField', - 'ChoiceField', 'MultipleChoiceField', 'ComboField', 'MultiValueField', - 'FloatField', 'DecimalField', 'SplitDateTimeField', 'IPAddressField', - 'GenericIPAddressField', 'FilePathField', 'SlugField', 'TypedChoiceField', - 'TypedMultipleChoiceField', - - # From django.forms.widgets - "widgets", - 'Media', 'MediaDefiningClass', 'Widget', 'TextInput', 'PasswordInput', - 'HiddenInput', 'MultipleHiddenInput', 'ClearableFileInput', 'FileInput', - 'DateInput', 'DateTimeInput', 'TimeInput', 'Textarea', 'CheckboxInput', - 'Select', 'NullBooleanSelect', 'SelectMultiple', 'RadioSelect', - 'CheckboxSelectMultiple', 'MultiWidget', 'SplitDateTimeWidget', - - # From django.forms.forms - 'BaseForm', 'Form', -] diff --git a/code/horizon/horizon/forms/base.py b/code/horizon/horizon/forms/base.py deleted file mode 100644 index 5364d387..00000000 --- a/code/horizon/horizon/forms/base.py +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright 2012 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from django import forms -from django.forms.forms import NON_FIELD_ERRORS # noqa - - -class SelfHandlingMixin(object): - def __init__(self, request, *args, **kwargs): - self.request = request - if not hasattr(self, "handle"): - raise NotImplementedError("%s does not define a handle method." - % self.__class__.__name__) - super(SelfHandlingMixin, self).__init__(*args, **kwargs) - - -class SelfHandlingForm(SelfHandlingMixin, forms.Form): - """A base :class:`Form ` class which includes - processing logic in its subclasses. - """ - required_css_class = 'required' - - def api_error(self, message): - """Adds an error to the form's error dictionary after validation - based on problems reported via the API. This is useful when you - wish for API errors to appear as errors on the form rather than - using the messages framework. - """ - self._errors[NON_FIELD_ERRORS] = self.error_class([message]) - - def set_warning(self, message): - """Sets a warning on the form. - - Unlike NON_FIELD_ERRORS, this doesn't fail form validation. - """ - self.warnings = self.error_class([message]) - - -class DateForm(forms.Form): - """A simple form for selecting a range of time.""" - start = forms.DateField(input_formats=("%Y-%m-%d",)) - end = forms.DateField(input_formats=("%Y-%m-%d",)) - - def __init__(self, *args, **kwargs): - super(DateForm, self).__init__(*args, **kwargs) - self.fields['start'].widget.attrs['data-date-format'] = "yyyy-mm-dd" - self.fields['end'].widget.attrs['data-date-format'] = "yyyy-mm-dd" diff --git a/code/horizon/horizon/forms/fields.py b/code/horizon/horizon/forms/fields.py deleted file mode 100644 index 3ded97b1..00000000 --- a/code/horizon/horizon/forms/fields.py +++ /dev/null @@ -1,253 +0,0 @@ -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import re - -import netaddr - -from django.core.exceptions import ValidationError # noqa -from django.core import urlresolvers -from django.forms import fields -from django.forms.util import flatatt # noqa -from django.forms import widgets -from django.utils.encoding import force_text -from django.utils.functional import Promise # noqa -from django.utils import html -from django.utils.translation import ugettext_lazy as _ - -ip_allowed_symbols_re = re.compile(r'^[a-fA-F0-9:/\.]+$') -IPv4 = 1 -IPv6 = 2 - - -class IPField(fields.Field): - """Form field for entering IP/range values, with validation. - Supports IPv4/IPv6 in the format: - .. xxx.xxx.xxx.xxx - .. xxx.xxx.xxx.xxx/zz - .. ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff - .. ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff/zz - and all compressed forms. Also the short forms - are supported: - xxx/yy - xxx.xxx/yy - - .. attribute:: version - - Specifies which IP version to validate, - valid values are 1 (fields.IPv4), 2 (fields.IPv6) or - both - 3 (fields.IPv4 | fields.IPv6). - Defaults to IPv4 (1) - - .. attribute:: mask - - Boolean flag to validate subnet masks along with IP address. - E.g: 10.0.0.1/32 - - .. attribute:: mask_range_from - Subnet range limitation, e.g. 16 - That means the input mask will be checked to be in the range - 16:max_value. Useful to limit the subnet ranges - to A/B/C-class networks. - """ - invalid_format_message = _("Incorrect format for IP address") - invalid_version_message = _("Invalid version for IP address") - invalid_mask_message = _("Invalid subnet mask") - max_v4_mask = 32 - max_v6_mask = 128 - - def __init__(self, *args, **kwargs): - self.mask = kwargs.pop("mask", None) - self.min_mask = kwargs.pop("mask_range_from", 0) - self.version = kwargs.pop('version', IPv4) - - super(IPField, self).__init__(*args, **kwargs) - - def validate(self, value): - super(IPField, self).validate(value) - if not value and not self.required: - return - - try: - if self.mask: - self.ip = netaddr.IPNetwork(value) - else: - self.ip = netaddr.IPAddress(value) - except Exception: - raise ValidationError(self.invalid_format_message) - - if not any([self.version & IPv4 > 0 and self.ip.version == 4, - self.version & IPv6 > 0 and self.ip.version == 6]): - raise ValidationError(self.invalid_version_message) - - if self.mask: - if self.ip.version == 4 and \ - not self.min_mask <= self.ip.prefixlen <= self.max_v4_mask: - raise ValidationError(self.invalid_mask_message) - - if self.ip.version == 6 and \ - not self.min_mask <= self.ip.prefixlen <= self.max_v6_mask: - raise ValidationError(self.invalid_mask_message) - - def clean(self, value): - super(IPField, self).clean(value) - return str(getattr(self, "ip", "")) - - -class MultiIPField(IPField): - """Extends IPField to allow comma-separated lists of addresses.""" - def validate(self, value): - self.addresses = [] - if value: - addresses = value.split(',') - for ip in addresses: - super(MultiIPField, self).validate(ip) - self.addresses.append(ip) - else: - super(MultiIPField, self).validate(value) - - def clean(self, value): - super(MultiIPField, self).clean(value) - return str(','.join(getattr(self, "addresses", []))) - - -class SelectWidget(widgets.Select): - """Customizable select widget, that allows to render - data-xxx attributes from choices. This widget also - allows user to specify additional html attributes - for choices. - - .. attribute:: data_attrs - - Specifies object properties to serialize as - data-xxx attribute. If passed ('id', ), - this will be rendered as: - - where 123 is the value of choice_value.id - - .. attribute:: transform - - A callable used to render the display value - from the option object. - - .. attribute:: transform_html_attrs - - A callable used to render additional HTML attributes - for the option object. It returns a dictionary - containing the html attributes and their values. - For example, to define a title attribute for the - choices: - - helpText = { 'Apple': 'This is a fruit', - 'Carrot': 'This is a vegetable' } - - def get_title(data): - text = helpText.get(data, None) - if text: - return {'title': text} - else: - return {} - - .... - .... - - widget=forms.SelectWidget( attrs={'class': 'switchable', - 'data-slug': 'source'}, - transform_html_attrs=get_title ) - - self.fields[].choices = - ([ - ('apple','Apple'), - ('carrot','Carrot') - ]) - """ - def __init__(self, attrs=None, choices=(), data_attrs=(), transform=None, - transform_html_attrs=None): - self.data_attrs = data_attrs - self.transform = transform - self.transform_html_attrs = transform_html_attrs - super(SelectWidget, self).__init__(attrs, choices) - - def render_option(self, selected_choices, option_value, option_label): - option_value = force_text(option_value) - other_html = (u' selected="selected"' - if option_value in selected_choices else '') - - if callable(self.transform_html_attrs): - html_attrs = self.transform_html_attrs(option_label) - other_html += flatatt(html_attrs) - - if not isinstance(option_label, (basestring, Promise)): - for data_attr in self.data_attrs: - data_value = html.conditional_escape( - force_text(getattr(option_label, - data_attr, ""))) - other_html += ' data-%s="%s"' % (data_attr, data_value) - - if callable(self.transform): - option_label = self.transform(option_label) - - return u'' % ( - html.escape(option_value), other_html, - html.conditional_escape(force_text(option_label))) - - -class DynamicSelectWidget(widgets.Select): - """A subclass of the ``Select`` widget which renders extra attributes for - use in callbacks to handle dynamic changes to the available choices. - """ - _data_add_url_attr = "data-add-item-url" - - def render(self, *args, **kwargs): - add_item_url = self.get_add_item_url() - if add_item_url is not None: - self.attrs[self._data_add_url_attr] = add_item_url - return super(DynamicSelectWidget, self).render(*args, **kwargs) - - def get_add_item_url(self): - if callable(self.add_item_link): - return self.add_item_link() - try: - if self.add_item_link_args: - return urlresolvers.reverse(self.add_item_link, - args=self.add_item_link_args) - else: - return urlresolvers.reverse(self.add_item_link) - except urlresolvers.NoReverseMatch: - return self.add_item_link - - -class DynamicChoiceField(fields.ChoiceField): - """A subclass of ``ChoiceField`` with additional properties that make - dynamically updating its elements easier. - - Notably, the field declaration takes an extra argument, ``add_item_link`` - which may be a string or callable defining the URL that should be used - for the "add" link associated with the field. - """ - widget = DynamicSelectWidget - - def __init__(self, - add_item_link=None, - add_item_link_args=None, - *args, - **kwargs): - super(DynamicChoiceField, self).__init__(*args, **kwargs) - self.widget.add_item_link = add_item_link - self.widget.add_item_link_args = add_item_link_args - - -class DynamicTypedChoiceField(DynamicChoiceField, fields.TypedChoiceField): - """Simple mix of ``DynamicChoiceField`` and ``TypedChoiceField``.""" - pass diff --git a/code/horizon/horizon/forms/views.py b/code/horizon/horizon/forms/views.py deleted file mode 100644 index f6276e31..00000000 --- a/code/horizon/horizon/forms/views.py +++ /dev/null @@ -1,196 +0,0 @@ -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import json -import os - -from django.conf import settings -from django import http -from django.utils.translation import ugettext_lazy as _ - -from horizon import exceptions -from horizon import views - - -ADD_TO_FIELD_HEADER = "HTTP_X_HORIZON_ADD_TO_FIELD" - - -class ModalBackdropMixin(object): - """This mixin class is to be used for together with ModalFormView and - WorkflowView classes to augment them with modal_backdrop context data. - - .. attribute: modal_backdrop (optional) - - The appearance and behavior of backdrop under the modal element. - Possible options are: - * 'true' - show backdrop element outside the modal, close the modal - after clicking on backdrop (the default one); - * 'false' - do not show backdrop element, do not close the modal after - clicking outside of it; - * 'static' - show backdrop element outside the modal, do not close - the modal after clicking on backdrop. - """ - modal_backdrop = 'static' - - def __init__(self): - super(ModalBackdropMixin, self).__init__() - config = getattr(settings, 'HORIZON_CONFIG', {}) - if 'modal_backdrop' in config: - self.modal_backdrop = config['modal_backdrop'] - - def get_context_data(self, **kwargs): - context = super(ModalBackdropMixin, self).get_context_data(**kwargs) - context['modal_backdrop'] = self.modal_backdrop - return context - - -class ModalFormMixin(object): - def get_template_names(self): - if self.request.is_ajax(): - if not hasattr(self, "ajax_template_name"): - # Transform standard template name to ajax name (leading "_") - bits = list(os.path.split(self.template_name)) - bits[1] = "".join(("_", bits[1])) - self.ajax_template_name = os.path.join(*bits) - template = self.ajax_template_name - else: - template = self.template_name - return template - - def get_context_data(self, **kwargs): - context = super(ModalFormMixin, self).get_context_data(**kwargs) - if self.request.is_ajax(): - context['hide'] = True - if ADD_TO_FIELD_HEADER in self.request.META: - context['add_to_field'] = self.request.META[ADD_TO_FIELD_HEADER] - return context - - -class ModalFormView(ModalBackdropMixin, ModalFormMixin, views.HorizonFormView): - """The main view class from which all views which handle forms in Horizon - should inherit. It takes care of all details with processing - :class:`~horizon.forms.base.SelfHandlingForm` classes, and modal concerns - when the associated template inherits from - `horizon/common/_modal_form.html`. - - Subclasses must define a ``form_class`` and ``template_name`` attribute - at minimum. - - See Django's documentation on the `FormView `_ class for - more details. - - .. attribute: modal_id (recommended) - - The HTML element id of this modal. - - .. attribute: modal_header (recommended) - - The title of this modal. - - .. attribute: form_id (recommended) - - The HTML element id of the form in this modal. - - .. attribute: submit_url (required) - - The url for a submit action. - - .. attribute: submit_label (optional) - - The label for the submit button. This label defaults to ``Submit``. - This button should only be visible if the action_url is defined. - Clicking on this button will post to the action_url. - - .. attribute: cancel_label (optional) - - The label for the cancel button. This label defaults to ``Cancel``. - Clicking on this button will redirect user to the cancel_url. - - .. attribute: cancel_url (optional) - - The url for a cancel action. This url defaults to the success_url - if omitted. Note that the cancel_url redirect is nullified when - shown in a modal dialog. - """ - - modal_id = None - modal_header = "" - form_id = None - submit_url = None - submit_label = _("Submit") - cancel_label = _("Cancel") - cancel_url = None - - def get_context_data(self, **kwargs): - context = super(ModalFormView, self).get_context_data(**kwargs) - context['modal_id'] = self.modal_id - context['modal_header'] = self.modal_header - context['form_id'] = self.form_id - context['submit_url'] = self.submit_url - context['submit_label'] = self.submit_label - context['cancel_label'] = self.cancel_label - context['cancel_url'] = self.get_cancel_url() - return context - - def get_cancel_url(self): - return self.cancel_url or self.success_url - - def get_object_id(self, obj): - """For dynamic insertion of resources created in modals, this method - returns the id of the created object. Defaults to returning the ``id`` - attribute. - """ - return obj.id - - def get_object_display(self, obj): - """For dynamic insertion of resources created in modals, this method - returns the display name of the created object. Defaults to returning - the ``name`` attribute. - """ - return obj.name - - def get_form(self, form_class): - """Returns an instance of the form to be used in this view.""" - return form_class(self.request, **self.get_form_kwargs()) - - def form_valid(self, form): - try: - handled = form.handle(self.request, form.cleaned_data) - except Exception: - handled = None - exceptions.handle(self.request) - - if handled: - if ADD_TO_FIELD_HEADER in self.request.META: - field_id = self.request.META[ADD_TO_FIELD_HEADER] - data = [self.get_object_id(handled), - self.get_object_display(handled)] - response = http.HttpResponse(json.dumps(data)) - response["X-Horizon-Add-To-Field"] = field_id - elif isinstance(handled, http.HttpResponse): - return handled - else: - success_url = self.get_success_url() - response = http.HttpResponseRedirect(success_url) - # TODO(gabriel): This is not a long-term solution to how - # AJAX should be handled, but it's an expedient solution - # until the blueprint for AJAX handling is architected - # and implemented. - response['X-Horizon-Location'] = success_url - return response - else: - # If handled didn't return, we can assume something went - # wrong, and we should send back the form as-is. - return self.form_invalid(form) diff --git a/code/horizon/horizon/loaders.py b/code/horizon/horizon/loaders.py deleted file mode 100644 index 3544f6bc..00000000 --- a/code/horizon/horizon/loaders.py +++ /dev/null @@ -1,68 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Wrapper for loading templates from "templates" directories in panel modules. -""" - -import os - -import django -from django.conf import settings -from django.template.base import TemplateDoesNotExist # noqa - -if django.get_version() >= '1.8': - from django.template.engine import Engine - from django.template.loaders.base import Loader as tLoaderCls -else: - from django.template.loader import BaseLoader as tLoaderCls # noqa - -from django.utils._os import safe_join # noqa - -# Set up a cache of the panel directories to search. -panel_template_dirs = {} - - -class TemplateLoader(tLoaderCls): - is_usable = True - - def get_template_sources(self, template_name): - bits = template_name.split('/', 2) - if len(bits) == 3: - dash_name, panel_name, remainder = bits - key = os.path.join(dash_name, panel_name) - if key in panel_template_dirs: - template_dir = panel_template_dirs[key] - try: - yield safe_join(template_dir, panel_name, remainder) - except UnicodeDecodeError: - # The template dir name wasn't valid UTF-8. - raise - except ValueError: - # The joined path was located outside of template_dir. - pass - - def load_template_source(self, template_name, template_dirs=None): - for path in self.get_template_sources(template_name): - try: - with open(path) as file: - return (file.read().decode(settings.FILE_CHARSET), path) - except IOError: - pass - raise TemplateDoesNotExist(template_name) - - -if django.get_version() >= '1.8': - e = Engine() - _loader = TemplateLoader(e) -else: - _loader = TemplateLoader() diff --git a/code/horizon/horizon/locale/de/LC_MESSAGES/django.po b/code/horizon/horizon/locale/de/LC_MESSAGES/django.po deleted file mode 100644 index 821bcc8a..00000000 --- a/code/horizon/horizon/locale/de/LC_MESSAGES/django.po +++ /dev/null @@ -1,512 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Andreas Jaeger , 2014 -# Robert Simai, 2014-2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-06 21:07-0500\n" -"PO-Revision-Date: 2015-04-01 22:52+0000\n" -"Last-Translator: Robert Simai\n" -"Language-Team: German (http://www.transifex.com/projects/p/horizon/language/de/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: de\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: base.py:475 -msgid "Other" -msgstr "Andere" - -#: browsers/base.py:88 -msgid "Navigation Item" -msgstr "Navigations-Eintrag" - -#: browsers/views.py:41 -#, python-format -msgid "Select a %s to browse." -msgstr "Wähle %s zum Durchsuchen." - -#: conf/default.py:41 -msgid "Password is not accepted" -msgstr "Password wurde nicht akzeptiert" - -#: decorators.py:53 -msgid "Please log in to continue." -msgstr "Bitte melden Sie sich an um fortzufahren." - -#: decorators.py:85 -#, python-format -msgid "You are not authorized to access %s" -msgstr "Sie sind nicht berechtigt für den Zugriff auf %s" - -#: exceptions.py:163 -#, python-format -msgid "A %(resource)s with the name \"%(name)s\" already exists." -msgstr "Ein(e) %(resource)s mit dem Namen \"%(name)s\" existiert bereits." - -#: exceptions.py:235 -#, python-format -msgid "Unauthorized: %s" -msgstr "Nicht berechtigt: %s" - -#: exceptions.py:238 -msgid "Unauthorized. Please try logging in again." -msgstr "Nicht autorisiert. Bitte melden Sie sich erneut an." - -#: forms/fields.py:64 -msgid "Incorrect format for IP address" -msgstr "Ungültiges Format der IP-Adresse" - -#: forms/fields.py:65 -msgid "Invalid version for IP address" -msgstr "Ungültige Version der IP-Adresse" - -#: forms/fields.py:66 -msgid "Invalid subnet mask" -msgstr "Ungültige Subnetzmaske" - -#: forms/views.py:132 templates/horizon/common/_usage_summary.html:16 -msgid "Submit" -msgstr "Abschicken" - -#: forms/views.py:133 -#: templates/horizon/common/_modal_form_update_metadata.html:25 -#: templates/horizon/common/_workflow.html:49 -msgid "Cancel" -msgstr "Abbrechen" - -#: middleware.py:103 -msgid "Session timed out." -msgstr "Die Sitzung ist abgelaufen." - -#: tables/actions.py:460 -#: templates/horizon/common/_data_table_table_actions.html:21 -#: templates/horizon/common/_data_table_table_actions.html:33 -#: templates/horizon/common/_workflow_step_update_members.html:14 -#: templates/horizon/common/_workflow_step_update_members.html:23 -msgid "Filter" -msgstr "Filter" - -#: tables/actions.py:645 -msgid "This action cannot be undone." -msgstr "Diese Aktion kann nicht rückgängig gemacht werden." - -#: tables/actions.py:767 -#, python-format -msgctxt "past" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:769 -#, python-format -msgctxt "present" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:832 -#, python-format -msgid "You are not allowed to %(action)s: %(objs)s" -msgstr "Sie haben keine Berechtigung für %(action)s: %(objs)s" - -#: tables/actions.py:839 -#, python-format -msgid "Unable to %(action)s: %(objs)s" -msgstr "Nicht möglich: %(action)s: %(objs)s" - -#: tables/actions.py:845 -#, python-format -msgid "%(action)s: %(objs)s" -msgstr "%(action)s: %(objs)s" - -#: tables/actions.py:915 -msgid "Delete" -msgstr "Löschen" - -#: tables/actions.py:917 -msgid "Deleted" -msgstr "Gelöscht" - -#: tables/actions.py:948 -msgid "Update" -msgstr "Aktualisieren" - -#: tables/actions.py:949 -msgid "Updated" -msgstr "Aktualisiert" - -#: tables/base.py:305 -msgid "-" -msgstr "-" - -#: tables/base.py:361 -#, python-format -msgid "The attribute %(attr)s doesn't exist on %(obj)s." -msgstr "Das Attribut %(attr)s existiert nicht für %(obj)s." - -#: tables/base.py:990 -msgid "No items to display." -msgstr "Keine Einträge zum anzeigen." - -#: tables/base.py:1099 -#: templates/horizon/common/_data_table_table_actions.html:47 -msgid "Actions" -msgstr "Aktionen" - -#: tables/base.py:1329 -#, python-format -msgid "No match returned for the id \"%s\"." -msgstr "Keine Übereinstimmung für die ID \"%s\"." - -#: tables/base.py:1486 -msgid "Please select a row before taking that action." -msgstr "Bitte wählen Sie vor dem Ausführen dieser Aktion eine Zeile aus." - -#: tables/base.py:1570 -msgid "N/A" -msgstr "Nicht verfügbar" - -#: templates/_header.html:5 -#, python-format -msgid "Logged in as: %(username)s" -msgstr "Angemeldet als: %(username)s" - -#: templates/_header.html:7 -msgid "Help" -msgstr "Hilfe" - -#: templates/_header.html:9 -msgid "Sign Out" -msgstr "Abmelden" - -#: templates/auth/_description.html:9 -msgid "" -"\n" -" If you are not sure which authentication method to use, contact your administrator.\n" -" " -msgstr "\nWenn Sie nicht sicher sind, welche Authentifizierungsmethode zu verwenden ist, kontaktieren Sie Ihren Administrator." - -#: templates/auth/_login.html:5 -msgid "Log In" -msgstr "Anmelden" - -#: templates/auth/_login.html:27 -msgid "You do not have permission to access the resource:" -msgstr "Sie haben keine Zugriffsrechte auf die Ressource:" - -#: templates/auth/_login.html:29 -#, python-format -msgid "" -"Login as different user or go back to home " -"page" -msgstr "Melden Sie sich als anderer Benutzer an oder gehen Sie zurück auf die Startseite" - -#: templates/auth/_login.html:45 -msgid "Sign In" -msgstr "Anmelden" - -#: templates/auth/_login.html:46 -msgid "Connect" -msgstr "Verbinden" - -#: templates/auth/login.html:4 -msgid "Login" -msgstr "Login" - -#: templates/horizon/_messages.html:7 -msgid "Info: " -msgstr "Information:" - -#: templates/horizon/_messages.html:13 -msgid "Warning: " -msgstr "Warnung:" - -#: templates/horizon/_messages.html:19 -msgid "Success: " -msgstr "Erfolg:" - -#: templates/horizon/_messages.html:25 -msgid "Error: " -msgstr "Fehler:" - -#: templates/horizon/common/_data_table.html:63 -msgid "Summary" -msgstr "Zusammenfassung" - -#: templates/horizon/common/_data_table.html:72 -#, python-format -msgid "Displaying %(counter)s item" -msgid_plural "Displaying %(counter)s items" -msgstr[0] "Zeige %(counter)s Eintrag" -msgstr[1] "Zeige %(counter)s Einträge" - -#: templates/horizon/common/_data_table.html:77 -msgid "« Prev" -msgstr "« Zurück" - -#: templates/horizon/common/_data_table.html:80 -msgid "Next »" -msgstr "Weiter »" - -#: templates/horizon/common/_data_table_table_actions.html:45 -msgid "More Actions" -msgstr "Weitere Aktionen" - -#: templates/horizon/common/_domain_page_header.html:6 -#, python-format -msgid "%(context_name)s:" -msgstr "%(context_name)s:" - -#: templates/horizon/common/_formset_table.html:35 -msgid "Add a row" -msgstr "Eine Zeile hinzufügen" - -#: templates/horizon/common/_formset_table_row.html:15 -#, python-format -msgid "%(name)s: %(error)s" -msgstr "%(name)s: %(error)s" - -#: templates/horizon/common/_limit_summary.html:4 -msgid "Limit Summary" -msgstr "Übersicht Begrenzungen" - -#: templates/horizon/common/_limit_summary.html:7 -msgid "Instances" -msgstr "Instanzen" - -#: templates/horizon/common/_limit_summary.html:8 -#: templates/horizon/common/_limit_summary.html:15 -#: templates/horizon/common/_limit_summary.html:22 -#: templates/horizon/common/_limit_summary.html:36 -#: templates/horizon/common/_limit_summary.html:43 -#: templates/horizon/common/_limit_summary.html:50 -#, python-format -msgid "Used %(used)s of %(available)s " -msgstr " %(used)s von %(available)s benutzt" - -#: templates/horizon/common/_limit_summary.html:14 -msgid "VCPUs" -msgstr "VCPUs" - -#: templates/horizon/common/_limit_summary.html:21 -msgid "RAM" -msgstr "RAM" - -#: templates/horizon/common/_limit_summary.html:28 -msgid "Floating IPs" -msgstr "Floating IPs" - -#: templates/horizon/common/_limit_summary.html:29 -#, python-format -msgid "Allocated %(used)s of %(available)s " -msgstr " %(used)s von %(available)s zugewiesen" - -#: templates/horizon/common/_limit_summary.html:35 -msgid "Security Groups" -msgstr "Sicherheitsgruppen" - -#: templates/horizon/common/_limit_summary.html:42 -msgid "Volumes" -msgstr "Datenträger" - -#: templates/horizon/common/_limit_summary.html:49 -msgid "Volume Storage" -msgstr "Datenträger-Speicher" - -#: templates/horizon/common/_modal_form_update_metadata.html:24 -#: workflows/base.py:594 -msgid "Save" -msgstr "Speichern" - -#: templates/horizon/common/_resource_browser.html:10 -#, python-format -msgid "Displaying %(nav_items)s item" -msgid_plural "Displaying %(nav_items)s items" -msgstr[0] "Zeige %(nav_items)s Eintrag" -msgstr[1] "Zeige %(nav_items)s Einträge" - -#: templates/horizon/common/_resource_browser.html:11 -#, python-format -msgid "Displaying %(content_items)s item" -msgid_plural "Displaying %(content_items)s items" -msgstr[0] "Zeige %(content_items)s Eintrag" -msgstr[1] "Zeige %(content_items)s Einträge" - -#: templates/horizon/common/_usage_summary.html:3 -msgid "Usage Summary" -msgstr "Nutzungsübersicht" - -#: templates/horizon/common/_usage_summary.html:7 -msgid "Select a period of time to query its usage:" -msgstr "Wählen Sie einen Zeitbereich, um die Auslastung abzurufen:" - -#: templates/horizon/common/_usage_summary.html:9 -#, python-format -msgid "" -"\n" -" %(start)s" -msgstr "\n %(start)s" - -#: templates/horizon/common/_usage_summary.html:13 -#, python-format -msgid "" -"\n" -" %(end)s" -msgstr "\n %(end)s" - -#: templates/horizon/common/_usage_summary.html:17 -msgid "The date should be in YYYY-mm-dd format." -msgstr "Das Datum sollte im YYYY-mm-dd Format sein." - -#: templates/horizon/common/_usage_summary.html:20 -msgid "Active Instances:" -msgstr "Aktive Instanzen:" - -#: templates/horizon/common/_usage_summary.html:21 -msgid "Active RAM:" -msgstr "Aktiver RAM:" - -#: templates/horizon/common/_usage_summary.html:22 -msgid "This Period's VCPU-Hours:" -msgstr "VCPU-Stunden in diesem Zeitraum:" - -#: templates/horizon/common/_usage_summary.html:23 -msgid "This Period's GB-Hours:" -msgstr "GB-Stunden in diesem Zeitraum:" - -#: templates/horizon/common/_usage_summary.html:24 -msgid "This Period's RAM-Hours:" -msgstr "RAM-Stunden in diesem Zeitraum:" - -#: templates/horizon/common/_workflow.html:40 -msgid "Back" -msgstr "Zurück" - -#: templates/horizon/common/_workflow.html:43 -msgid "Next" -msgstr "Weiter" - -#: templatetags/branding.py:34 -msgid "Horizon" -msgstr "Horizon" - -#: templatetags/horizon.py:137 templatetags/horizon.py:148 -msgid "No Limit" -msgstr "Keine Begrenzung" - -#: templatetags/horizon.py:140 templatetags/horizon.py:142 -msgid "Available" -msgstr "Verfügbar" - -#: templatetags/sizeformat.py:51 templatetags/sizeformat.py:56 -#, python-format -msgid "%(size)d Byte" -msgid_plural "%(size)d Bytes" -msgstr[0] "%(size)d Byte" -msgstr[1] "%(size)d Bytes" - -#: templatetags/sizeformat.py:59 -#, python-format -msgid "%s KB" -msgstr "%s KB" - -#: templatetags/sizeformat.py:61 -#, python-format -msgid "%s MB" -msgstr "%s MB" - -#: templatetags/sizeformat.py:63 -#, python-format -msgid "%s GB" -msgstr "%s GB" - -#: templatetags/sizeformat.py:65 -#, python-format -msgid "%s TB" -msgstr "%s TB" - -#: templatetags/sizeformat.py:66 -#, python-format -msgid "%s PB" -msgstr "%s PB" - -#: templatetags/sizeformat.py:74 -msgid "0 Bytes" -msgstr "0 Bytes" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:31 -msgid "Sell Puppy" -msgid_plural "Sell Puppies" -msgstr[0] "Sell Puppy" -msgstr[1] "Sell Puppies" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:40 -msgid "Sold Puppy" -msgid_plural "Sold Puppies" -msgstr[0] "Sold Puppy" -msgstr[1] "Sold Puppies" - -#: test/tests/views.py:59 -msgid "Fake" -msgstr "Fälschung" - -#: utils/filters.py:49 -msgid "Never" -msgstr "Niemals" - -#: utils/validators.py:26 utils/validators.py:50 -msgid "Not a valid port number" -msgstr "Keine gültige Port-Nummer" - -#: utils/validators.py:31 -msgid "Not a valid IP protocol number" -msgstr "Keine gültige IP-Protokollnummer" - -#: utils/validators.py:45 -msgid "One colon allowed in port range" -msgstr "Im Port-Bereich ist nur ein Doppelpunkt erlaubt" - -#: utils/validators.py:52 -msgid "Port number must be integer" -msgstr "Port-Nummer muss ganzzahlig sein" - -#: utils/validators.py:59 -msgid "The string may only contain ASCII printable characters." -msgstr "Die Zeichenkette darf nur druckbare ASCII-Zeichen enthalten." - -#: workflows/base.py:71 -msgid "Processing..." -msgstr "Verarbeite..." - -#: workflows/base.py:475 -msgid "All available" -msgstr "Alle verfügbaren" - -#: workflows/base.py:476 -msgid "Members" -msgstr "Mitglieder" - -#: workflows/base.py:477 -msgid "None available." -msgstr "Keine verfügbar." - -#: workflows/base.py:478 -msgid "No members." -msgstr "Keine Mitglieder." - -#: workflows/base.py:595 -#, python-format -msgid "%s completed successfully." -msgstr "%s erfolgreich abgeschlossen." - -#: workflows/base.py:596 -#, python-format -msgid "%s did not complete." -msgstr "%s nicht abgeschlossen." diff --git a/code/horizon/horizon/locale/de/LC_MESSAGES/djangojs.po b/code/horizon/horizon/locale/de/LC_MESSAGES/djangojs.po deleted file mode 100644 index e4773302..00000000 --- a/code/horizon/horizon/locale/de/LC_MESSAGES/djangojs.po +++ /dev/null @@ -1,621 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Andreas Jaeger , 2015 -# Ettore Atalan , 2015 -# Robert Simai, 2014-2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-11 11:47-0500\n" -"PO-Revision-Date: 2015-04-12 03:25+0000\n" -"Last-Translator: Ettore Atalan \n" -"Language-Team: German (http://www.transifex.com/projects/p/horizon/language/de/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: de\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: static/angular/action-list/button-tooltip.js:15 -msgid "" -"The action cannot be performed. The contents of this row have errors or are " -"missing information." -msgstr "Die Aktion kann nicht ausgeführt werden. Der Inhalt dieser Spalte enthält Fehler oder es fehlen Informationen." - -#: static/angular/metadata-display/metadata-display.js:33 -msgid "Detail Information" -msgstr "Detail-Informationen" - -#: static/angular/metadata-tree/metadata-tree.js:35 -msgid "" -"You can specify resource metadata by moving items from the left column to " -"the right column. In the left columns there are metadata definitions from " -"the Glance Metadata Catalog. Use the \"Other\" option to add metadata with " -"the key of your choice." -msgstr "Sie können Ressourcen-Metadaten bestimmen, indem Sie Positionen aus der linken Spalte in die rechte bewegen. In der linken Spalte finden Sie Metadaten-Definitionen aus dem Glace Metadaten-Katalog. Verwenden Sie die \"Andere\" Option, um Metadaten mit dem Schlüssel Ihrer Wahl hinzuzufügen." - -#: static/angular/metadata-tree/metadata-tree.js:36 -msgid "Min" -msgstr "Min" - -#: static/angular/metadata-tree/metadata-tree.js:37 -msgid "Max" -msgstr "Max" - -#: static/angular/metadata-tree/metadata-tree.js:38 -msgid "Min length" -msgstr "Minimale Länge" - -#: static/angular/metadata-tree/metadata-tree.js:39 -msgid "Max length" -msgstr "Maximale Länge" - -#: static/angular/metadata-tree/metadata-tree.js:40 -msgid "Pattern mismatch" -msgstr "Muster-Übereinstimmungsfehler" - -#: static/angular/metadata-tree/metadata-tree.js:41 -msgid "Integer required" -msgstr "Ganzzahl erforderlich" - -#: static/angular/metadata-tree/metadata-tree.js:42 -msgid "Decimal required" -msgstr "Dezimalzahl erforderlich" - -#: static/angular/metadata-tree/metadata-tree.js:43 -msgid "Required" -msgstr "Erforderlich" - -#: static/angular/metadata-tree/metadata-tree.js:44 -msgid "Duplicate keys are not allowed" -msgstr "Doppelte Schlüssel sind nicht erlaubt" - -#: static/angular/metadata-tree/metadata-tree.js:45 -#: static/angular/table/basic-table.js:6 -#: static/horizon/js/horizon.forms.js:184 -msgid "Filter" -msgstr "Filter" - -#: static/angular/metadata-tree/metadata-tree.js:46 -msgid "Available Metadata" -msgstr "Verfügbare Metadaten" - -#: static/angular/metadata-tree/metadata-tree.js:47 -msgid "Existing Metadata" -msgstr "Vorhandene Metadaten" - -#: static/angular/metadata-tree/metadata-tree.js:48 -msgid "Custom" -msgstr "Angepasst" - -#: static/angular/metadata-tree/metadata-tree.js:49 -msgid "No available metadata" -msgstr "Keine Metadaten vorhanden" - -#: static/angular/metadata-tree/metadata-tree.js:50 -msgid "No existing metadata" -msgstr "Keine existierenden Metadaten" - -#: static/angular/modal/modal.js:83 -msgid "Submit" -msgstr "Abschicken" - -#: static/angular/modal/modal.js:84 static/angular/wizard/wizard.js:11 -#: static/horizon/js/horizon.modals.js:33 -msgid "Cancel" -msgstr "Abbrechen" - -#: static/angular/transfer-table/transfer-table.js:39 -msgid "Allocated" -msgstr "Zugewiesen" - -#: static/angular/transfer-table/transfer-table.js:40 -msgid "Available" -msgstr "Verfügbar" - -#: static/angular/transfer-table/transfer-table.js:41 -msgid "Select one" -msgstr "Eines auswählen" - -#: static/angular/transfer-table/transfer-table.js:42 -msgid "Select an item from Available items below" -msgstr "Wählen Sie einen Eintrag aus den verfügbaren Positionen aus" - -#: static/angular/transfer-table/transfer-table.js:43 -msgid "No available items" -msgstr "Keine verfügbaren Positionen" - -#: static/angular/transfer-table/transfer-table.js:44 -msgid "Expand to see allocated items" -msgstr "Erweitern, um zugewiesene Positionen zu sehen" - -#: static/angular/transfer-table/transfer-table.js:45 -msgid "Expand to see available items" -msgstr "Erweitern, um verfügbare Positionen zu sehen" - -#: static/angular/transfer-table/transfer-table.js:46 -msgid "Click to show or hide" -msgstr "Klicken zum zeigen oder verbergen" - -#: static/angular/transfer-table/transfer-table.js:47 -msgid "Re-order items using drag and drop" -msgstr "Umsortieren der Positionen durch ziehen und ablegen" - -#: static/angular/transfer-table/transfer-table.js:48 -msgid "Click to see more details" -msgstr "Klicken um mehr Details zu sehen" - -#: static/angular/transfer-table/transfer-table.js:100 -msgid "Found %(found)s of %(total)s" -msgstr "%(found)s von %(total)s gefunden" - -#: static/angular/transfer-table/transfer-table.js:166 -msgid "Click here to expand the row and view the errors." -msgstr "Klicken Sie hier um die Zeile zu erweitern und die Fehler zu sehen." - -#: static/angular/wizard/wizard.js:12 -msgid "Back" -msgstr "Zurück" - -#: static/angular/wizard/wizard.js:13 -msgid "Next" -msgstr "Weiter" - -#: static/angular/wizard/wizard.js:14 -msgid "Finish" -msgstr "Beenden" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Connecting" -msgstr "Verbinde" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Open" -msgstr "Öffnen" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closing" -msgstr "Schließen" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closed" -msgstr "Geschlossen" - -#: static/horizon/js/angular/directives/serialConsole.js:85 -#, c-format -msgid "Status: %s" -msgstr "Status: %s" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "Yes" -msgstr "Ja" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "No" -msgstr "Nein" - -#: static/horizon/js/angular/filters/filters.js:53 -#: static/horizon/js/angular/filters/filters.js:140 -#, c-format -msgid "%s GB" -msgstr "%s GB" - -#: static/horizon/js/angular/filters/filters.js:70 -#: static/horizon/js/angular/filters/filters.js:142 -#, c-format -msgid "%s MB" -msgstr "%s MB" - -#: static/horizon/js/angular/filters/filters.js:138 -#, c-format -msgid "%s TB" -msgstr "%s TB" - -#: static/horizon/js/angular/filters/filters.js:144 -#, c-format -msgid "%s KB" -msgstr "%s KB" - -#: static/horizon/js/angular/filters/filters.js:146 -#, c-format -msgid "%s bytes" -msgstr "%s Bytes" - -#: static/horizon/js/angular/filters/filters.js:163 -#: static/horizon/js/horizon.tables.js:393 -#, c-format -msgid "Displaying %s item" -msgid_plural "Displaying %s items" -msgstr[0] "Zeige %s Eintrag" -msgstr[1] "Zeige %s Einträge" - -#: static/horizon/js/angular/services/hz.api.cinder.js:47 -msgid "Unable to retrieve volumes." -msgstr "Datenträger können nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.cinder.js:74 -msgid "Unable to retrieve volume snapshots." -msgstr "Datenträger-Schattenkopien können nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.config.js:43 -msgid "Unable to retrieve user configuration." -msgstr "Benutzerkonfiguration kann nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.config.js:62 -msgid "Unable to retrieve admin configuration." -msgstr "Admin-Konfiguration kann nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.config.js:105 -msgid "Unable to retrieve settings." -msgstr "Einstellungen können nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.config.js:289 -msgid "Setting is not enabled: %(setting)s" -msgstr "Einstellung ist nicht aktiviert: %(setting)s" - -#: static/horizon/js/angular/services/hz.api.glance.js:38 -msgid "Unable to retrieve image." -msgstr "Abbild kann nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.glance.js:81 -msgid "Unable to retrieve images." -msgstr "Abbilder können nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.glance.js:144 -msgid "Unable to retrieve namespaces." -msgstr "Namensräume können nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:24 -msgid "Unable to retrieve users" -msgstr "Benutzer können nicht abgerufen werden" - -#: static/horizon/js/angular/services/hz.api.keystone.js:31 -msgid "Unable to create the user." -msgstr "Benutzer kann nicht angelegt werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:38 -msgid "Unable to delete the users." -msgstr "Benutzer können nicht gelöscht werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:73 -msgid "Unable to retrieve the current user session." -msgstr "Aktuelle Benutzersitzung kann nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:80 -msgid "Unable to retrieve the user" -msgstr "Benutzer kann nicht abgerufen werden" - -#: static/horizon/js/angular/services/hz.api.keystone.js:88 -msgid "Unable to edit the user." -msgstr "Benutzer kann nicht bearbeitet werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:95 -msgid "Unable to delete the user." -msgstr "Benutzer kann nicht gelöscht werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:103 -msgid "Unable to retrieve role" -msgstr "Rolle kann nicht abgerufen werden" - -#: static/horizon/js/angular/services/hz.api.keystone.js:110 -msgid "Unable to create the role." -msgstr "Die Rolle kann nicht erstellt werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:117 -msgid "Unable to delete the roles." -msgstr "Die Rollen können nicht gelöscht werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:124 -msgid "Unable to retrieve the role" -msgstr "Die Rolle kann nicht abgerufen werden" - -#: static/horizon/js/angular/services/hz.api.keystone.js:132 -msgid "Unable to edit the role." -msgstr "Die Rolle kann nicht bearbeitet werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:139 -msgid "Unable to delete the role." -msgstr "Die Rolle kann nicht gelöscht werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:147 -msgid "Unable to retrieve domains" -msgstr "Domänen können nicht abgerufen werden" - -#: static/horizon/js/angular/services/hz.api.keystone.js:154 -msgid "Unable to create the domain." -msgstr "Die Domäne kann nicht erstellt werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:161 -msgid "Unable to delete the domains." -msgstr "Die Domänen können nicht gelöscht werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:168 -msgid "Unable to retrieve the domain" -msgstr "Die Domäne kann nicht abgerufen werden" - -#: static/horizon/js/angular/services/hz.api.keystone.js:176 -msgid "Unable to edit the domain." -msgstr "Die Domäne kann nicht bearbeitet werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:183 -msgid "Unable to delete the domain." -msgstr "Die Domäne kann nicht gelöscht werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:192 -msgid "Unable to retrieve projects" -msgstr "Projekte können nicht abgerufen werden" - -#: static/horizon/js/angular/services/hz.api.keystone.js:199 -msgid "Unable to create the project." -msgstr "Das Projekt kann nicht erstellt werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:206 -msgid "Unable to delete the projects." -msgstr "Die Projekte können nicht gelöscht werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:213 -msgid "Unable to retrieve the project" -msgstr "Das Projekt kann nicht abgerufen werden" - -#: static/horizon/js/angular/services/hz.api.keystone.js:221 -msgid "Unable to edit the project." -msgstr "Das Projekt kann nicht bearbeitet werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:228 -msgid "Unable to delete the project." -msgstr "Das Projekt kann nicht gelöscht werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:236 -msgid "Unable to grant the role." -msgstr "Die Rolle kann nicht gewährt werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:250 -msgid "Unable to fetch the service catalog." -msgstr "Die Dienstekatalog kann nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.keystone.js:385 -msgid "Service type is not enabled: %(desiredType)s" -msgstr "Dienst-Typ ist nicht aktiviert: %(desiredType)s" - -#: static/horizon/js/angular/services/hz.api.keystone.js:392 -msgid "Cannot get service catalog from keystone." -msgstr "Dienstekatalog kann nicht von Keystone abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.neutron.js:39 -msgid "Unable to retrieve networks." -msgstr "Netzwerke können nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.neutron.js:88 -msgid "Unable to create the network." -msgstr "Netzwerk kann nicht angelegt werden." - -#: static/horizon/js/angular/services/hz.api.neutron.js:108 -msgid "Unable to retrieve subnets." -msgstr "Subnetze können nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.neutron.js:172 -msgid "Unable to create the subnet." -msgstr "Subnetz kann nicht erzeugt werden." - -#: static/horizon/js/angular/services/hz.api.neutron.js:192 -msgid "Unable to retrieve ports." -msgstr "Ports können nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.nova.js:40 -msgid "Unable to retrieve keypairs." -msgstr "Schlüsselpaare können nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.nova.js:62 -msgid "Unable to import the keypair." -msgstr "Das Schlüsselpaar kann nicht importiert werden." - -#: static/horizon/js/angular/services/hz.api.nova.js:64 -msgid "Unable to create the keypair." -msgstr "Das Schlüsselpaar kann nicht erstellt werden." - -#: static/horizon/js/angular/services/hz.api.nova.js:83 -msgid "Unable to retrieve availability zones." -msgstr "Verfügbarkeitszonen können nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.nova.js:121 -msgid "Unable to retrieve limits." -msgstr "Begrenzungen können nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.nova.js:148 -msgid "Unable to create the server." -msgstr "Der Server kann nicht erstellt werden." - -#: static/horizon/js/angular/services/hz.api.nova.js:162 -msgid "Unable to retrieve server." -msgstr "Server kann nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.nova.js:192 -msgid "Unable to retrieve extensions." -msgstr "Erweiterungen können nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.nova.js:237 -msgid "Unable to retrieve flavors." -msgstr "Varianten können nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.nova.js:255 -msgid "Unable to retrieve flavor." -msgstr "Variante kann nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.nova.js:269 -msgid "Unable to retrieve flavor extra specs." -msgstr "Extraspezifikationen zur Variante können nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.nova.js:311 -msgid "Extension is not enabled: %(extension)s" -msgstr "Nicht aktivierte Erweiterung: %(extension)s" - -#: static/horizon/js/angular/services/hz.api.nova.js:318 -msgid "Cannot get nova extension list." -msgstr "Liste der Nova-Erweiterungen kann nicht abgerufen werden." - -#: static/horizon/js/angular/services/hz.api.policy.js:65 -msgid "Policy check failed." -msgstr "Richtlinienüberprüfung fehlgeschlagen." - -#: static/horizon/js/angular/services/hz.api.security-group.js:64 -msgid "Unable to retrieve security groups." -msgstr "Sicherheitsgruppen können nicht abgerufen werden." - -#: static/horizon/js/horizon.accordion_nav.js:78 -#: static/horizon/js/horizon.modals.js:315 -#: static/horizon/js/horizon.tabs.js:21 -msgid "Loading" -msgstr "Lade" - -#: static/horizon/js/horizon.d3linechart.js:394 -#: static/horizon/js/horizon.d3linechart.js:404 -msgid "No data available." -msgstr "Keine Daten verfügbar." - -#: static/horizon/js/horizon.d3linechart.js:410 -#: static/horizon/js/horizon.modals.js:334 -#: static/horizon/js/horizon.tables_inline_edit.js:94 -#: static/horizon/js/horizon.tables_inline_edit.js:157 -msgid "An error occurred. Please try again later." -msgstr "Ein Fehler ist aufgetreten. Bitte versuchen Sie es später noch einmal." - -#: static/horizon/js/horizon.firewalls.js:32 -#: static/horizon/js/horizon.instances.js:31 -msgid "There was a problem communicating with the server, please try again." -msgstr "Es gab ein Problem bei der Kommunikation mit dem Server. Bitte versuchen Sie es noch einmal." - -#: static/horizon/js/horizon.instances.js:273 -msgid "Could not read the file" -msgstr "Die Datei konnte nicht gelesen werden" - -#: static/horizon/js/horizon.instances.js:279 -#: static/horizon/js/horizon.instances.js:308 -msgid "Could not decrypt the password" -msgstr "Das Passwort konnte nicht entschlüsselt werden" - -#: static/horizon/js/horizon.membership.js:190 -msgid "No roles" -msgstr "Keine Rollen" - -#: static/horizon/js/horizon.membership.js:222 -msgid "Roles" -msgstr "Rollen" - -#: static/horizon/js/horizon.messages.js:9 -msgid "Danger: " -msgstr "Gefahr:" - -#: static/horizon/js/horizon.messages.js:10 -msgid "Warning: " -msgstr "Warnung:" - -#: static/horizon/js/horizon.messages.js:11 -msgid "Notice: " -msgstr "Nachricht:" - -#: static/horizon/js/horizon.messages.js:12 -msgid "Success: " -msgstr "Erfolg:" - -#: static/horizon/js/horizon.messages.js:13 -msgid "Error: " -msgstr "Fehler:" - -#: static/horizon/js/horizon.modals.js:229 -#: static/horizon/js/horizon.tables.js:218 -msgid "Working" -msgstr "In Arbeit" - -#: static/horizon/js/horizon.modals.js:263 -msgid "There was an error submitting the form. Please try again." -msgstr "Es gab einen Fehler beim Abschicken des Formulars. Bitte versuchen Sie es noch einmal." - -#: static/horizon/js/horizon.networktopology.js:530 -#: static/horizon/js/horizon.networktopology.js:536 -msgid "None" -msgstr "Keine" - -#: static/horizon/js/horizon.networktopology.js:549 -msgid "Delete" -msgstr "Löschen" - -#: static/horizon/js/horizon.networktopology.js:552 -msgid "STATUS" -msgstr "STATUS" - -#: static/horizon/js/horizon.networktopology.js:553 -msgid "ID" -msgstr "ID" - -#: static/horizon/js/horizon.networktopology.js:554 -msgid "Interfaces" -msgstr "Schnittstellen" - -#: static/horizon/js/horizon.networktopology.js:555 -msgid "Delete Interface" -msgstr "Schnittstelle löschen" - -#: static/horizon/js/horizon.networktopology.js:556 -msgid "Open Console" -msgstr "Konsole öffnen" - -#: static/horizon/js/horizon.networktopology.js:557 -msgid "View Details" -msgstr "Details anzeigen" - -#: static/horizon/js/horizon.networktopology.js:560 -msgid "Delete Router" -msgstr "Router löschen" - -#: static/horizon/js/horizon.networktopology.js:561 -msgid "View Router Details" -msgstr "Router-Details anzeigen" - -#: static/horizon/js/horizon.networktopology.js:564 -msgid "Add Interface" -msgstr "Schnittstelle hinzufügen" - -#: static/horizon/js/horizon.networktopology.js:570 -msgid "Terminate Instance" -msgstr "Instanz terminieren" - -#: static/horizon/js/horizon.networktopology.js:571 -msgid "View Instance Details" -msgstr "Instanz-Details anzeigen" - -#: static/horizon/js/horizon.tables.js:39 -#: static/horizon/js/horizon.tables.js:406 -msgid "No items to display." -msgstr "Kein Eintrag zum anzeigen." - -#: static/horizon/js/horizon.tables.js:52 -#: static/horizon/js/horizon.tables.js:120 -msgid "An error occurred while updating." -msgstr "Ein Fehler ist beim Aktualisieren aufgetreten." - -#: static/horizon/js/horizon.tables.js:201 -#, c-format -msgid "You have selected %s. " -msgstr "Sie haben %s ausgewählt." - -#: static/horizon/js/horizon.tables.js:203 -#, c-format -msgid "Confirm %s" -msgstr "%s bestätigen" - -#: static/horizon/js/horizon.tables.js:204 -msgid "Please confirm your selection. " -msgstr "Bitte bestätigen Sie Ihre Auswahl." - -#: static/horizon/js/horizon.tables_inline_edit.js:88 -#: static/horizon/js/horizon.tables_inline_edit.js:151 -msgid "Not authorized to do this operation." -msgstr "Keine Berechtigung für diese Aktion." - -#: static/horizon/js/horizon.users.js:18 -msgid "Passwords do not match." -msgstr "Die Passwörter stimmen nicht überein." diff --git a/code/horizon/horizon/locale/en/LC_MESSAGES/django.po b/code/horizon/horizon/locale/en/LC_MESSAGES/django.po deleted file mode 100644 index afcc748f..00000000 --- a/code/horizon/horizon/locale/en/LC_MESSAGES/django.po +++ /dev/null @@ -1,510 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-07 01:16-0500\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: base.py:475 -msgid "Other" -msgstr "" - -#: browsers/base.py:88 -msgid "Navigation Item" -msgstr "" - -#: browsers/views.py:41 -#, python-format -msgid "Select a %s to browse." -msgstr "" - -#: conf/default.py:41 -msgid "Password is not accepted" -msgstr "" - -#: decorators.py:53 -msgid "Please log in to continue." -msgstr "" - -#: decorators.py:85 -#, python-format -msgid "You are not authorized to access %s" -msgstr "" - -#: exceptions.py:163 -#, python-format -msgid "A %(resource)s with the name \"%(name)s\" already exists." -msgstr "" - -#: exceptions.py:235 -#, python-format -msgid "Unauthorized: %s" -msgstr "" - -#: exceptions.py:238 -msgid "Unauthorized. Please try logging in again." -msgstr "" - -#: forms/fields.py:64 -msgid "Incorrect format for IP address" -msgstr "" - -#: forms/fields.py:65 -msgid "Invalid version for IP address" -msgstr "" - -#: forms/fields.py:66 -msgid "Invalid subnet mask" -msgstr "" - -#: forms/views.py:132 templates/horizon/common/_usage_summary.html:16 -msgid "Submit" -msgstr "" - -#: forms/views.py:133 -#: templates/horizon/common/_modal_form_update_metadata.html:25 -#: templates/horizon/common/_workflow.html:49 -msgid "Cancel" -msgstr "" - -#: middleware.py:103 -msgid "Session timed out." -msgstr "" - -#: tables/actions.py:460 -#: templates/horizon/common/_data_table_table_actions.html:21 -#: templates/horizon/common/_data_table_table_actions.html:33 -#: templates/horizon/common/_workflow_step_update_members.html:14 -#: templates/horizon/common/_workflow_step_update_members.html:23 -msgid "Filter" -msgstr "" - -#: tables/actions.py:645 -msgid "This action cannot be undone." -msgstr "" - -#: tables/actions.py:767 -#, python-format -msgctxt "past" -msgid "%(action)s %(data_type)s" -msgstr "" - -#: tables/actions.py:769 -#, python-format -msgctxt "present" -msgid "%(action)s %(data_type)s" -msgstr "" - -#: tables/actions.py:832 -#, python-format -msgid "You are not allowed to %(action)s: %(objs)s" -msgstr "" - -#: tables/actions.py:839 -#, python-format -msgid "Unable to %(action)s: %(objs)s" -msgstr "" - -#: tables/actions.py:845 -#, python-format -msgid "%(action)s: %(objs)s" -msgstr "" - -#: tables/actions.py:915 -msgid "Delete" -msgstr "" - -#: tables/actions.py:917 -msgid "Deleted" -msgstr "" - -#: tables/actions.py:948 -msgid "Update" -msgstr "" - -#: tables/actions.py:949 -msgid "Updated" -msgstr "" - -#: tables/base.py:305 -msgid "-" -msgstr "" - -#: tables/base.py:361 -#, python-format -msgid "The attribute %(attr)s doesn't exist on %(obj)s." -msgstr "" - -#: tables/base.py:990 -msgid "No items to display." -msgstr "" - -#: tables/base.py:1099 -#: templates/horizon/common/_data_table_table_actions.html:47 -msgid "Actions" -msgstr "" - -#: tables/base.py:1329 -#, python-format -msgid "No match returned for the id \"%s\"." -msgstr "" - -#: tables/base.py:1486 -msgid "Please select a row before taking that action." -msgstr "" - -#: tables/base.py:1570 -msgid "N/A" -msgstr "" - -#: templates/_header.html:5 -#, python-format -msgid "Logged in as: %(username)s" -msgstr "" - -#: templates/_header.html:7 -msgid "Help" -msgstr "" - -#: templates/_header.html:9 -msgid "Sign Out" -msgstr "" - -#: templates/auth/_description.html:9 -msgid "" -"\n" -" If you are not sure which authentication method to use, contact your " -"administrator.\n" -" " -msgstr "" - -#: templates/auth/_login.html:5 -msgid "Log In" -msgstr "" - -#: templates/auth/_login.html:27 -msgid "You do not have permission to access the resource:" -msgstr "" - -#: templates/auth/_login.html:29 -#, python-format -msgid "" -"Login as different user or go back to home page" -msgstr "" - -#: templates/auth/_login.html:45 -msgid "Sign In" -msgstr "" - -#: templates/auth/_login.html:46 -msgid "Connect" -msgstr "" - -#: templates/auth/login.html:4 -msgid "Login" -msgstr "" - -#: templates/horizon/_messages.html:7 -msgid "Info: " -msgstr "" - -#: templates/horizon/_messages.html:13 -msgid "Warning: " -msgstr "" - -#: templates/horizon/_messages.html:19 -msgid "Success: " -msgstr "" - -#: templates/horizon/_messages.html:25 -msgid "Error: " -msgstr "" - -#: templates/horizon/common/_data_table.html:63 -msgid "Summary" -msgstr "" - -#: templates/horizon/common/_data_table.html:72 -#, python-format -msgid "Displaying %(counter)s item" -msgid_plural "Displaying %(counter)s items" -msgstr[0] "" -msgstr[1] "" - -#: templates/horizon/common/_data_table.html:77 -msgid "« Prev" -msgstr "" - -#: templates/horizon/common/_data_table.html:80 -msgid "Next »" -msgstr "" - -#: templates/horizon/common/_data_table_table_actions.html:45 -msgid "More Actions" -msgstr "" - -#: templates/horizon/common/_domain_page_header.html:6 -#, python-format -msgid "%(context_name)s:" -msgstr "" - -#: templates/horizon/common/_formset_table.html:35 -msgid "Add a row" -msgstr "" - -#: templates/horizon/common/_formset_table_row.html:15 -#, python-format -msgid "%(name)s: %(error)s" -msgstr "" - -#: templates/horizon/common/_limit_summary.html:4 -msgid "Limit Summary" -msgstr "" - -#: templates/horizon/common/_limit_summary.html:7 -msgid "Instances" -msgstr "" - -#: templates/horizon/common/_limit_summary.html:8 -#: templates/horizon/common/_limit_summary.html:15 -#: templates/horizon/common/_limit_summary.html:22 -#: templates/horizon/common/_limit_summary.html:36 -#: templates/horizon/common/_limit_summary.html:43 -#: templates/horizon/common/_limit_summary.html:50 -#, python-format -msgid "Used %(used)s of %(available)s " -msgstr "" - -#: templates/horizon/common/_limit_summary.html:14 -msgid "VCPUs" -msgstr "" - -#: templates/horizon/common/_limit_summary.html:21 -msgid "RAM" -msgstr "" - -#: templates/horizon/common/_limit_summary.html:28 -msgid "Floating IPs" -msgstr "" - -#: templates/horizon/common/_limit_summary.html:29 -#, python-format -msgid "Allocated %(used)s of %(available)s " -msgstr "" - -#: templates/horizon/common/_limit_summary.html:35 -msgid "Security Groups" -msgstr "" - -#: templates/horizon/common/_limit_summary.html:42 -msgid "Volumes" -msgstr "" - -#: templates/horizon/common/_limit_summary.html:49 -msgid "Volume Storage" -msgstr "" - -#: templates/horizon/common/_modal_form_update_metadata.html:24 -#: workflows/base.py:594 -msgid "Save" -msgstr "" - -#: templates/horizon/common/_resource_browser.html:10 -#, python-format -msgid "Displaying %(nav_items)s item" -msgid_plural "Displaying %(nav_items)s items" -msgstr[0] "" -msgstr[1] "" - -#: templates/horizon/common/_resource_browser.html:11 -#, python-format -msgid "Displaying %(content_items)s item" -msgid_plural "Displaying %(content_items)s items" -msgstr[0] "" -msgstr[1] "" - -#: templates/horizon/common/_usage_summary.html:3 -msgid "Usage Summary" -msgstr "" - -#: templates/horizon/common/_usage_summary.html:7 -msgid "Select a period of time to query its usage:" -msgstr "" - -#: templates/horizon/common/_usage_summary.html:9 -#, python-format -msgid "" -"\n" -" %(start)s" -msgstr "" - -#: templates/horizon/common/_usage_summary.html:13 -#, python-format -msgid "" -"\n" -" %(end)s" -msgstr "" - -#: templates/horizon/common/_usage_summary.html:17 -msgid "The date should be in YYYY-mm-dd format." -msgstr "" - -#: templates/horizon/common/_usage_summary.html:20 -msgid "Active Instances:" -msgstr "" - -#: templates/horizon/common/_usage_summary.html:21 -msgid "Active RAM:" -msgstr "" - -#: templates/horizon/common/_usage_summary.html:22 -msgid "This Period's VCPU-Hours:" -msgstr "" - -#: templates/horizon/common/_usage_summary.html:23 -msgid "This Period's GB-Hours:" -msgstr "" - -#: templates/horizon/common/_usage_summary.html:24 -msgid "This Period's RAM-Hours:" -msgstr "" - -#: templates/horizon/common/_workflow.html:40 -msgid "Back" -msgstr "" - -#: templates/horizon/common/_workflow.html:43 -msgid "Next" -msgstr "" - -#: templatetags/branding.py:34 -msgid "Horizon" -msgstr "" - -#: templatetags/horizon.py:137 templatetags/horizon.py:148 -msgid "No Limit" -msgstr "" - -#: templatetags/horizon.py:140 templatetags/horizon.py:142 -msgid "Available" -msgstr "" - -#: templatetags/sizeformat.py:51 templatetags/sizeformat.py:56 -#, python-format -msgid "%(size)d Byte" -msgid_plural "%(size)d Bytes" -msgstr[0] "" -msgstr[1] "" - -#: templatetags/sizeformat.py:59 -#, python-format -msgid "%s KB" -msgstr "" - -#: templatetags/sizeformat.py:61 -#, python-format -msgid "%s MB" -msgstr "" - -#: templatetags/sizeformat.py:63 -#, python-format -msgid "%s GB" -msgstr "" - -#: templatetags/sizeformat.py:65 -#, python-format -msgid "%s TB" -msgstr "" - -#: templatetags/sizeformat.py:66 -#, python-format -msgid "%s PB" -msgstr "" - -#: templatetags/sizeformat.py:74 -msgid "0 Bytes" -msgstr "" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:31 -msgid "Sell Puppy" -msgid_plural "Sell Puppies" -msgstr[0] "" -msgstr[1] "" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:40 -msgid "Sold Puppy" -msgid_plural "Sold Puppies" -msgstr[0] "" -msgstr[1] "" - -#: test/tests/views.py:59 -msgid "Fake" -msgstr "" - -#: utils/filters.py:49 -msgid "Never" -msgstr "" - -#: utils/validators.py:26 utils/validators.py:50 -msgid "Not a valid port number" -msgstr "" - -#: utils/validators.py:31 -msgid "Not a valid IP protocol number" -msgstr "" - -#: utils/validators.py:45 -msgid "One colon allowed in port range" -msgstr "" - -#: utils/validators.py:52 -msgid "Port number must be integer" -msgstr "" - -#: utils/validators.py:59 -msgid "The string may only contain ASCII printable characters." -msgstr "" - -#: workflows/base.py:71 -msgid "Processing..." -msgstr "" - -#: workflows/base.py:475 -msgid "All available" -msgstr "" - -#: workflows/base.py:476 -msgid "Members" -msgstr "" - -#: workflows/base.py:477 -msgid "None available." -msgstr "" - -#: workflows/base.py:478 -msgid "No members." -msgstr "" - -#: workflows/base.py:595 -#, python-format -msgid "%s completed successfully." -msgstr "" - -#: workflows/base.py:596 -#, python-format -msgid "%s did not complete." -msgstr "" diff --git a/code/horizon/horizon/locale/en/LC_MESSAGES/djangojs.po b/code/horizon/horizon/locale/en/LC_MESSAGES/djangojs.po deleted file mode 100644 index 5d8b68b7..00000000 --- a/code/horizon/horizon/locale/en/LC_MESSAGES/djangojs.po +++ /dev/null @@ -1,618 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# FIRST AUTHOR , YEAR. -# -#, fuzzy -msgid "" -msgstr "" -"Project-Id-Version: PACKAGE VERSION\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-12 01:16-0500\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: FULL NAME \n" -"Language-Team: LANGUAGE \n" -"Language: \n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" - -#: static/angular/action-list/button-tooltip.js:15 -msgid "" -"The action cannot be performed. The contents of this row have errors or are " -"missing information." -msgstr "" - -#: static/angular/metadata-display/metadata-display.js:33 -msgid "Detail Information" -msgstr "" - -#: static/angular/metadata-tree/metadata-tree.js:35 -msgid "" -"You can specify resource metadata by moving items from the left column to " -"the right column. In the left columns there are metadata definitions from " -"the Glance Metadata Catalog. Use the \"Other\" option to add metadata with " -"the key of your choice." -msgstr "" - -#: static/angular/metadata-tree/metadata-tree.js:36 -msgid "Min" -msgstr "" - -#: static/angular/metadata-tree/metadata-tree.js:37 -msgid "Max" -msgstr "" - -#: static/angular/metadata-tree/metadata-tree.js:38 -msgid "Min length" -msgstr "" - -#: static/angular/metadata-tree/metadata-tree.js:39 -msgid "Max length" -msgstr "" - -#: static/angular/metadata-tree/metadata-tree.js:40 -msgid "Pattern mismatch" -msgstr "" - -#: static/angular/metadata-tree/metadata-tree.js:41 -msgid "Integer required" -msgstr "" - -#: static/angular/metadata-tree/metadata-tree.js:42 -msgid "Decimal required" -msgstr "" - -#: static/angular/metadata-tree/metadata-tree.js:43 -msgid "Required" -msgstr "" - -#: static/angular/metadata-tree/metadata-tree.js:44 -msgid "Duplicate keys are not allowed" -msgstr "" - -#: static/angular/metadata-tree/metadata-tree.js:45 -#: static/angular/table/basic-table.js:6 -#: static/horizon/js/horizon.forms.js:184 -msgid "Filter" -msgstr "" - -#: static/angular/metadata-tree/metadata-tree.js:46 -msgid "Available Metadata" -msgstr "" - -#: static/angular/metadata-tree/metadata-tree.js:47 -msgid "Existing Metadata" -msgstr "" - -#: static/angular/metadata-tree/metadata-tree.js:48 -msgid "Custom" -msgstr "" - -#: static/angular/metadata-tree/metadata-tree.js:49 -msgid "No available metadata" -msgstr "" - -#: static/angular/metadata-tree/metadata-tree.js:50 -msgid "No existing metadata" -msgstr "" - -#: static/angular/modal/modal.js:83 -msgid "Submit" -msgstr "" - -#: static/angular/modal/modal.js:84 static/angular/wizard/wizard.js:11 -#: static/horizon/js/horizon.modals.js:33 -msgid "Cancel" -msgstr "" - -#: static/angular/transfer-table/transfer-table.js:39 -msgid "Allocated" -msgstr "" - -#: static/angular/transfer-table/transfer-table.js:40 -msgid "Available" -msgstr "" - -#: static/angular/transfer-table/transfer-table.js:41 -msgid "Select one" -msgstr "" - -#: static/angular/transfer-table/transfer-table.js:42 -msgid "Select an item from Available items below" -msgstr "" - -#: static/angular/transfer-table/transfer-table.js:43 -msgid "No available items" -msgstr "" - -#: static/angular/transfer-table/transfer-table.js:44 -msgid "Expand to see allocated items" -msgstr "" - -#: static/angular/transfer-table/transfer-table.js:45 -msgid "Expand to see available items" -msgstr "" - -#: static/angular/transfer-table/transfer-table.js:46 -msgid "Click to show or hide" -msgstr "" - -#: static/angular/transfer-table/transfer-table.js:47 -msgid "Re-order items using drag and drop" -msgstr "" - -#: static/angular/transfer-table/transfer-table.js:48 -msgid "Click to see more details" -msgstr "" - -#: static/angular/transfer-table/transfer-table.js:100 -msgid "Found %(found)s of %(total)s" -msgstr "" - -#: static/angular/transfer-table/transfer-table.js:166 -msgid "Click here to expand the row and view the errors." -msgstr "" - -#: static/angular/wizard/wizard.js:12 -msgid "Back" -msgstr "" - -#: static/angular/wizard/wizard.js:13 -msgid "Next" -msgstr "" - -#: static/angular/wizard/wizard.js:14 -msgid "Finish" -msgstr "" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Connecting" -msgstr "" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Open" -msgstr "" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closing" -msgstr "" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closed" -msgstr "" - -#: static/horizon/js/angular/directives/serialConsole.js:85 -#, c-format -msgid "Status: %s" -msgstr "" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "Yes" -msgstr "" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "No" -msgstr "" - -#: static/horizon/js/angular/filters/filters.js:53 -#: static/horizon/js/angular/filters/filters.js:140 -#, c-format -msgid "%s GB" -msgstr "" - -#: static/horizon/js/angular/filters/filters.js:70 -#: static/horizon/js/angular/filters/filters.js:142 -#, c-format -msgid "%s MB" -msgstr "" - -#: static/horizon/js/angular/filters/filters.js:138 -#, c-format -msgid "%s TB" -msgstr "" - -#: static/horizon/js/angular/filters/filters.js:144 -#, c-format -msgid "%s KB" -msgstr "" - -#: static/horizon/js/angular/filters/filters.js:146 -#, c-format -msgid "%s bytes" -msgstr "" - -#: static/horizon/js/angular/filters/filters.js:163 -#: static/horizon/js/horizon.tables.js:393 -#, c-format -msgid "Displaying %s item" -msgid_plural "Displaying %s items" -msgstr[0] "" -msgstr[1] "" - -#: static/horizon/js/angular/services/hz.api.cinder.js:47 -msgid "Unable to retrieve volumes." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.cinder.js:74 -msgid "Unable to retrieve volume snapshots." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.config.js:43 -msgid "Unable to retrieve user configuration." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.config.js:62 -msgid "Unable to retrieve admin configuration." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.config.js:105 -msgid "Unable to retrieve settings." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.config.js:289 -msgid "Setting is not enabled: %(setting)s" -msgstr "" - -#: static/horizon/js/angular/services/hz.api.glance.js:38 -msgid "Unable to retrieve image." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.glance.js:81 -msgid "Unable to retrieve images." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.glance.js:144 -msgid "Unable to retrieve namespaces." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:24 -msgid "Unable to retrieve users" -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:31 -msgid "Unable to create the user." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:38 -msgid "Unable to delete the users." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:73 -msgid "Unable to retrieve the current user session." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:80 -msgid "Unable to retrieve the user" -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:88 -msgid "Unable to edit the user." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:95 -msgid "Unable to delete the user." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:103 -msgid "Unable to retrieve role" -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:110 -msgid "Unable to create the role." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:117 -msgid "Unable to delete the roles." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:124 -msgid "Unable to retrieve the role" -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:132 -msgid "Unable to edit the role." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:139 -msgid "Unable to delete the role." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:147 -msgid "Unable to retrieve domains" -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:154 -msgid "Unable to create the domain." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:161 -msgid "Unable to delete the domains." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:168 -msgid "Unable to retrieve the domain" -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:176 -msgid "Unable to edit the domain." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:183 -msgid "Unable to delete the domain." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:192 -msgid "Unable to retrieve projects" -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:199 -msgid "Unable to create the project." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:206 -msgid "Unable to delete the projects." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:213 -msgid "Unable to retrieve the project" -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:221 -msgid "Unable to edit the project." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:228 -msgid "Unable to delete the project." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:236 -msgid "Unable to grant the role." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:250 -msgid "Unable to fetch the service catalog." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:385 -msgid "Service type is not enabled: %(desiredType)s" -msgstr "" - -#: static/horizon/js/angular/services/hz.api.keystone.js:392 -msgid "Cannot get service catalog from keystone." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.neutron.js:39 -msgid "Unable to retrieve networks." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.neutron.js:88 -msgid "Unable to create the network." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.neutron.js:108 -msgid "Unable to retrieve subnets." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.neutron.js:172 -msgid "Unable to create the subnet." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.neutron.js:192 -msgid "Unable to retrieve ports." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.nova.js:40 -msgid "Unable to retrieve keypairs." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.nova.js:62 -msgid "Unable to import the keypair." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.nova.js:64 -msgid "Unable to create the keypair." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.nova.js:83 -msgid "Unable to retrieve availability zones." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.nova.js:121 -msgid "Unable to retrieve limits." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.nova.js:148 -msgid "Unable to create the server." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.nova.js:162 -msgid "Unable to retrieve server." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.nova.js:192 -msgid "Unable to retrieve extensions." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.nova.js:237 -msgid "Unable to retrieve flavors." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.nova.js:255 -msgid "Unable to retrieve flavor." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.nova.js:269 -msgid "Unable to retrieve flavor extra specs." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.nova.js:311 -msgid "Extension is not enabled: %(extension)s" -msgstr "" - -#: static/horizon/js/angular/services/hz.api.nova.js:318 -msgid "Cannot get nova extension list." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.policy.js:65 -msgid "Policy check failed." -msgstr "" - -#: static/horizon/js/angular/services/hz.api.security-group.js:64 -msgid "Unable to retrieve security groups." -msgstr "" - -#: static/horizon/js/horizon.accordion_nav.js:78 -#: static/horizon/js/horizon.modals.js:315 -#: static/horizon/js/horizon.tabs.js:21 -msgid "Loading" -msgstr "" - -#: static/horizon/js/horizon.d3linechart.js:394 -#: static/horizon/js/horizon.d3linechart.js:404 -msgid "No data available." -msgstr "" - -#: static/horizon/js/horizon.d3linechart.js:410 -#: static/horizon/js/horizon.modals.js:334 -#: static/horizon/js/horizon.tables_inline_edit.js:94 -#: static/horizon/js/horizon.tables_inline_edit.js:157 -msgid "An error occurred. Please try again later." -msgstr "" - -#: static/horizon/js/horizon.firewalls.js:32 -#: static/horizon/js/horizon.instances.js:31 -msgid "There was a problem communicating with the server, please try again." -msgstr "" - -#: static/horizon/js/horizon.instances.js:273 -msgid "Could not read the file" -msgstr "" - -#: static/horizon/js/horizon.instances.js:279 -#: static/horizon/js/horizon.instances.js:308 -msgid "Could not decrypt the password" -msgstr "" - -#: static/horizon/js/horizon.membership.js:190 -msgid "No roles" -msgstr "" - -#: static/horizon/js/horizon.membership.js:222 -msgid "Roles" -msgstr "" - -#: static/horizon/js/horizon.messages.js:9 -msgid "Danger: " -msgstr "" - -#: static/horizon/js/horizon.messages.js:10 -msgid "Warning: " -msgstr "" - -#: static/horizon/js/horizon.messages.js:11 -msgid "Notice: " -msgstr "" - -#: static/horizon/js/horizon.messages.js:12 -msgid "Success: " -msgstr "" - -#: static/horizon/js/horizon.messages.js:13 -msgid "Error: " -msgstr "" - -#: static/horizon/js/horizon.modals.js:229 -#: static/horizon/js/horizon.tables.js:218 -msgid "Working" -msgstr "" - -#: static/horizon/js/horizon.modals.js:263 -msgid "There was an error submitting the form. Please try again." -msgstr "" - -#: static/horizon/js/horizon.networktopology.js:530 -#: static/horizon/js/horizon.networktopology.js:536 -msgid "None" -msgstr "" - -#: static/horizon/js/horizon.networktopology.js:549 -msgid "Delete" -msgstr "" - -#: static/horizon/js/horizon.networktopology.js:552 -msgid "STATUS" -msgstr "" - -#: static/horizon/js/horizon.networktopology.js:553 -msgid "ID" -msgstr "" - -#: static/horizon/js/horizon.networktopology.js:554 -msgid "Interfaces" -msgstr "" - -#: static/horizon/js/horizon.networktopology.js:555 -msgid "Delete Interface" -msgstr "" - -#: static/horizon/js/horizon.networktopology.js:556 -msgid "Open Console" -msgstr "" - -#: static/horizon/js/horizon.networktopology.js:557 -msgid "View Details" -msgstr "" - -#: static/horizon/js/horizon.networktopology.js:560 -msgid "Delete Router" -msgstr "" - -#: static/horizon/js/horizon.networktopology.js:561 -msgid "View Router Details" -msgstr "" - -#: static/horizon/js/horizon.networktopology.js:564 -msgid "Add Interface" -msgstr "" - -#: static/horizon/js/horizon.networktopology.js:570 -msgid "Terminate Instance" -msgstr "" - -#: static/horizon/js/horizon.networktopology.js:571 -msgid "View Instance Details" -msgstr "" - -#: static/horizon/js/horizon.tables.js:39 -#: static/horizon/js/horizon.tables.js:406 -msgid "No items to display." -msgstr "" - -#: static/horizon/js/horizon.tables.js:52 -#: static/horizon/js/horizon.tables.js:120 -msgid "An error occurred while updating." -msgstr "" - -#: static/horizon/js/horizon.tables.js:201 -#, c-format -msgid "You have selected %s. " -msgstr "" - -#: static/horizon/js/horizon.tables.js:203 -#, c-format -msgid "Confirm %s" -msgstr "" - -#: static/horizon/js/horizon.tables.js:204 -msgid "Please confirm your selection. " -msgstr "" - -#: static/horizon/js/horizon.tables_inline_edit.js:88 -#: static/horizon/js/horizon.tables_inline_edit.js:151 -msgid "Not authorized to do this operation." -msgstr "" - -#: static/horizon/js/horizon.users.js:18 -msgid "Passwords do not match." -msgstr "" diff --git a/code/horizon/horizon/locale/en_AU/LC_MESSAGES/django.po b/code/horizon/horizon/locale/en_AU/LC_MESSAGES/django.po deleted file mode 100644 index 308a1391..00000000 --- a/code/horizon/horizon/locale/en_AU/LC_MESSAGES/django.po +++ /dev/null @@ -1,511 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Tom Fifield , 2014-2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-07 01:16-0500\n" -"PO-Revision-Date: 2015-04-20 07:07+0000\n" -"Last-Translator: Tom Fifield \n" -"Language-Team: English (Australia) (http://www.transifex.com/projects/p/horizon/language/en_AU/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: en_AU\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: base.py:475 -msgid "Other" -msgstr "Other" - -#: browsers/base.py:88 -msgid "Navigation Item" -msgstr "Navigation Item" - -#: browsers/views.py:41 -#, python-format -msgid "Select a %s to browse." -msgstr "Select a %s to browse." - -#: conf/default.py:41 -msgid "Password is not accepted" -msgstr "Password is not accepted" - -#: decorators.py:53 -msgid "Please log in to continue." -msgstr "Please log in to continue." - -#: decorators.py:85 -#, python-format -msgid "You are not authorized to access %s" -msgstr "You are not authorised to access %s" - -#: exceptions.py:163 -#, python-format -msgid "A %(resource)s with the name \"%(name)s\" already exists." -msgstr "A %(resource)s with the name \"%(name)s\" already exists." - -#: exceptions.py:235 -#, python-format -msgid "Unauthorized: %s" -msgstr "Unauthorised: %s" - -#: exceptions.py:238 -msgid "Unauthorized. Please try logging in again." -msgstr "Unauthorised. Please try logging in again." - -#: forms/fields.py:64 -msgid "Incorrect format for IP address" -msgstr "Incorrect format for IP address" - -#: forms/fields.py:65 -msgid "Invalid version for IP address" -msgstr "Invalid version for IP address" - -#: forms/fields.py:66 -msgid "Invalid subnet mask" -msgstr "Invalid subnet mask" - -#: forms/views.py:132 templates/horizon/common/_usage_summary.html:16 -msgid "Submit" -msgstr "Submit" - -#: forms/views.py:133 -#: templates/horizon/common/_modal_form_update_metadata.html:25 -#: templates/horizon/common/_workflow.html:49 -msgid "Cancel" -msgstr "Cancel" - -#: middleware.py:103 -msgid "Session timed out." -msgstr "Session timed out." - -#: tables/actions.py:460 -#: templates/horizon/common/_data_table_table_actions.html:21 -#: templates/horizon/common/_data_table_table_actions.html:33 -#: templates/horizon/common/_workflow_step_update_members.html:14 -#: templates/horizon/common/_workflow_step_update_members.html:23 -msgid "Filter" -msgstr "Filter" - -#: tables/actions.py:645 -msgid "This action cannot be undone." -msgstr "This action cannot be undone." - -#: tables/actions.py:767 -#, python-format -msgctxt "past" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:769 -#, python-format -msgctxt "present" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:832 -#, python-format -msgid "You are not allowed to %(action)s: %(objs)s" -msgstr "You are not allowed to %(action)s: %(objs)s" - -#: tables/actions.py:839 -#, python-format -msgid "Unable to %(action)s: %(objs)s" -msgstr "Unable to %(action)s: %(objs)s" - -#: tables/actions.py:845 -#, python-format -msgid "%(action)s: %(objs)s" -msgstr "%(action)s: %(objs)s" - -#: tables/actions.py:915 -msgid "Delete" -msgstr "Delete" - -#: tables/actions.py:917 -msgid "Deleted" -msgstr "Deleted" - -#: tables/actions.py:948 -msgid "Update" -msgstr "Update" - -#: tables/actions.py:949 -msgid "Updated" -msgstr "Updated" - -#: tables/base.py:305 -msgid "-" -msgstr "-" - -#: tables/base.py:361 -#, python-format -msgid "The attribute %(attr)s doesn't exist on %(obj)s." -msgstr "The attribute %(attr)s doesn't exist on %(obj)s." - -#: tables/base.py:990 -msgid "No items to display." -msgstr "No items to display." - -#: tables/base.py:1099 -#: templates/horizon/common/_data_table_table_actions.html:47 -msgid "Actions" -msgstr "Actions" - -#: tables/base.py:1329 -#, python-format -msgid "No match returned for the id \"%s\"." -msgstr "No match returned for the id \"%s\"." - -#: tables/base.py:1486 -msgid "Please select a row before taking that action." -msgstr "Please select a row before taking that action." - -#: tables/base.py:1570 -msgid "N/A" -msgstr "N/A" - -#: templates/_header.html:5 -#, python-format -msgid "Logged in as: %(username)s" -msgstr "Logged in as: %(username)s" - -#: templates/_header.html:7 -msgid "Help" -msgstr "Help" - -#: templates/_header.html:9 -msgid "Sign Out" -msgstr "Sign Out" - -#: templates/auth/_description.html:9 -msgid "" -"\n" -" If you are not sure which authentication method to use, contact your administrator.\n" -" " -msgstr "\n If you are not sure which authentication method to use, contact your administrator.\n " - -#: templates/auth/_login.html:5 -msgid "Log In" -msgstr "Log In" - -#: templates/auth/_login.html:27 -msgid "You do not have permission to access the resource:" -msgstr "You do not have permission to access the resource:" - -#: templates/auth/_login.html:29 -#, python-format -msgid "" -"Login as different user or go back to home " -"page" -msgstr "Login as different user or go back to home page" - -#: templates/auth/_login.html:45 -msgid "Sign In" -msgstr "Sign In" - -#: templates/auth/_login.html:46 -msgid "Connect" -msgstr "Connect" - -#: templates/auth/login.html:4 -msgid "Login" -msgstr "Login" - -#: templates/horizon/_messages.html:7 -msgid "Info: " -msgstr "Info: " - -#: templates/horizon/_messages.html:13 -msgid "Warning: " -msgstr "Warning: " - -#: templates/horizon/_messages.html:19 -msgid "Success: " -msgstr "Success: " - -#: templates/horizon/_messages.html:25 -msgid "Error: " -msgstr "Error: " - -#: templates/horizon/common/_data_table.html:63 -msgid "Summary" -msgstr "Summary" - -#: templates/horizon/common/_data_table.html:72 -#, python-format -msgid "Displaying %(counter)s item" -msgid_plural "Displaying %(counter)s items" -msgstr[0] "Displaying %(counter)s item" -msgstr[1] "Displaying %(counter)s items" - -#: templates/horizon/common/_data_table.html:77 -msgid "« Prev" -msgstr "« Prev" - -#: templates/horizon/common/_data_table.html:80 -msgid "Next »" -msgstr "Next »" - -#: templates/horizon/common/_data_table_table_actions.html:45 -msgid "More Actions" -msgstr "More Actions" - -#: templates/horizon/common/_domain_page_header.html:6 -#, python-format -msgid "%(context_name)s:" -msgstr "%(context_name)s:" - -#: templates/horizon/common/_formset_table.html:35 -msgid "Add a row" -msgstr "Add a row" - -#: templates/horizon/common/_formset_table_row.html:15 -#, python-format -msgid "%(name)s: %(error)s" -msgstr "%(name)s: %(error)s" - -#: templates/horizon/common/_limit_summary.html:4 -msgid "Limit Summary" -msgstr "Limit Summary" - -#: templates/horizon/common/_limit_summary.html:7 -msgid "Instances" -msgstr "Instances" - -#: templates/horizon/common/_limit_summary.html:8 -#: templates/horizon/common/_limit_summary.html:15 -#: templates/horizon/common/_limit_summary.html:22 -#: templates/horizon/common/_limit_summary.html:36 -#: templates/horizon/common/_limit_summary.html:43 -#: templates/horizon/common/_limit_summary.html:50 -#, python-format -msgid "Used %(used)s of %(available)s " -msgstr "Used %(used)s of %(available)s " - -#: templates/horizon/common/_limit_summary.html:14 -msgid "VCPUs" -msgstr "VCPUs" - -#: templates/horizon/common/_limit_summary.html:21 -msgid "RAM" -msgstr "RAM" - -#: templates/horizon/common/_limit_summary.html:28 -msgid "Floating IPs" -msgstr "Floating IPs" - -#: templates/horizon/common/_limit_summary.html:29 -#, python-format -msgid "Allocated %(used)s of %(available)s " -msgstr "Allocated %(used)s of %(available)s " - -#: templates/horizon/common/_limit_summary.html:35 -msgid "Security Groups" -msgstr "Security Groups" - -#: templates/horizon/common/_limit_summary.html:42 -msgid "Volumes" -msgstr "Volumes" - -#: templates/horizon/common/_limit_summary.html:49 -msgid "Volume Storage" -msgstr "Volume Storage" - -#: templates/horizon/common/_modal_form_update_metadata.html:24 -#: workflows/base.py:594 -msgid "Save" -msgstr "Save" - -#: templates/horizon/common/_resource_browser.html:10 -#, python-format -msgid "Displaying %(nav_items)s item" -msgid_plural "Displaying %(nav_items)s items" -msgstr[0] "Displaying %(nav_items)s item" -msgstr[1] "Displaying %(nav_items)s items" - -#: templates/horizon/common/_resource_browser.html:11 -#, python-format -msgid "Displaying %(content_items)s item" -msgid_plural "Displaying %(content_items)s items" -msgstr[0] "Displaying %(content_items)s item" -msgstr[1] "Displaying %(content_items)s items" - -#: templates/horizon/common/_usage_summary.html:3 -msgid "Usage Summary" -msgstr "Usage Summary" - -#: templates/horizon/common/_usage_summary.html:7 -msgid "Select a period of time to query its usage:" -msgstr "Select a period of time to query its usage:" - -#: templates/horizon/common/_usage_summary.html:9 -#, python-format -msgid "" -"\n" -" %(start)s" -msgstr "\n %(start)s" - -#: templates/horizon/common/_usage_summary.html:13 -#, python-format -msgid "" -"\n" -" %(end)s" -msgstr "\n %(end)s" - -#: templates/horizon/common/_usage_summary.html:17 -msgid "The date should be in YYYY-mm-dd format." -msgstr "The date should be in YYYY-mm-dd format." - -#: templates/horizon/common/_usage_summary.html:20 -msgid "Active Instances:" -msgstr "Active Instances:" - -#: templates/horizon/common/_usage_summary.html:21 -msgid "Active RAM:" -msgstr "Active RAM:" - -#: templates/horizon/common/_usage_summary.html:22 -msgid "This Period's VCPU-Hours:" -msgstr "This Period's VCPU-Hours:" - -#: templates/horizon/common/_usage_summary.html:23 -msgid "This Period's GB-Hours:" -msgstr "This Period's GB-Hours:" - -#: templates/horizon/common/_usage_summary.html:24 -msgid "This Period's RAM-Hours:" -msgstr "This Period's RAM-Hours:" - -#: templates/horizon/common/_workflow.html:40 -msgid "Back" -msgstr "Back" - -#: templates/horizon/common/_workflow.html:43 -msgid "Next" -msgstr "Next" - -#: templatetags/branding.py:34 -msgid "Horizon" -msgstr "Horizon" - -#: templatetags/horizon.py:137 templatetags/horizon.py:148 -msgid "No Limit" -msgstr "No Limit" - -#: templatetags/horizon.py:140 templatetags/horizon.py:142 -msgid "Available" -msgstr "Available" - -#: templatetags/sizeformat.py:51 templatetags/sizeformat.py:56 -#, python-format -msgid "%(size)d Byte" -msgid_plural "%(size)d Bytes" -msgstr[0] "%(size)d Byte" -msgstr[1] "%(size)d Bytes" - -#: templatetags/sizeformat.py:59 -#, python-format -msgid "%s KB" -msgstr "%s KB" - -#: templatetags/sizeformat.py:61 -#, python-format -msgid "%s MB" -msgstr "%s MB" - -#: templatetags/sizeformat.py:63 -#, python-format -msgid "%s GB" -msgstr "%s GB" - -#: templatetags/sizeformat.py:65 -#, python-format -msgid "%s TB" -msgstr "%s TB" - -#: templatetags/sizeformat.py:66 -#, python-format -msgid "%s PB" -msgstr "%s PB" - -#: templatetags/sizeformat.py:74 -msgid "0 Bytes" -msgstr "0 Bytes" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:31 -msgid "Sell Puppy" -msgid_plural "Sell Puppies" -msgstr[0] "Sell Puppy" -msgstr[1] "Sell Puppies" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:40 -msgid "Sold Puppy" -msgid_plural "Sold Puppies" -msgstr[0] "Sold Puppy" -msgstr[1] "Sold Puppies" - -#: test/tests/views.py:59 -msgid "Fake" -msgstr "Fake" - -#: utils/filters.py:49 -msgid "Never" -msgstr "Never" - -#: utils/validators.py:26 utils/validators.py:50 -msgid "Not a valid port number" -msgstr "Not a valid port number" - -#: utils/validators.py:31 -msgid "Not a valid IP protocol number" -msgstr "Not a valid IP protocol number" - -#: utils/validators.py:45 -msgid "One colon allowed in port range" -msgstr "One colon allowed in port range" - -#: utils/validators.py:52 -msgid "Port number must be integer" -msgstr "Port number must be integer" - -#: utils/validators.py:59 -msgid "The string may only contain ASCII printable characters." -msgstr "The string may only contain ASCII printable characters." - -#: workflows/base.py:71 -msgid "Processing..." -msgstr "Processing..." - -#: workflows/base.py:475 -msgid "All available" -msgstr "All available" - -#: workflows/base.py:476 -msgid "Members" -msgstr "Members" - -#: workflows/base.py:477 -msgid "None available." -msgstr "None available." - -#: workflows/base.py:478 -msgid "No members." -msgstr "No members." - -#: workflows/base.py:595 -#, python-format -msgid "%s completed successfully." -msgstr "%s completed successfully." - -#: workflows/base.py:596 -#, python-format -msgid "%s did not complete." -msgstr "%s did not complete." diff --git a/code/horizon/horizon/locale/en_AU/LC_MESSAGES/djangojs.po b/code/horizon/horizon/locale/en_AU/LC_MESSAGES/djangojs.po deleted file mode 100644 index 37c0513f..00000000 --- a/code/horizon/horizon/locale/en_AU/LC_MESSAGES/djangojs.po +++ /dev/null @@ -1,619 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Tom Fifield , 2014-2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-12 01:16-0500\n" -"PO-Revision-Date: 2015-04-20 07:06+0000\n" -"Last-Translator: Tom Fifield \n" -"Language-Team: English (Australia) (http://www.transifex.com/projects/p/horizon/language/en_AU/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: en_AU\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: static/angular/action-list/button-tooltip.js:15 -msgid "" -"The action cannot be performed. The contents of this row have errors or are " -"missing information." -msgstr "The action cannot be performed. The contents of this row have errors or are missing information." - -#: static/angular/metadata-display/metadata-display.js:33 -msgid "Detail Information" -msgstr "Detail Information" - -#: static/angular/metadata-tree/metadata-tree.js:35 -msgid "" -"You can specify resource metadata by moving items from the left column to " -"the right column. In the left columns there are metadata definitions from " -"the Glance Metadata Catalog. Use the \"Other\" option to add metadata with " -"the key of your choice." -msgstr "You can specify resource metadata by moving items from the left column to the right column. In the left columns there are metadata definitions from the Glance Metadata Catalog. Use the \"Other\" option to add metadata with the key of your choice." - -#: static/angular/metadata-tree/metadata-tree.js:36 -msgid "Min" -msgstr "Min" - -#: static/angular/metadata-tree/metadata-tree.js:37 -msgid "Max" -msgstr "Max" - -#: static/angular/metadata-tree/metadata-tree.js:38 -msgid "Min length" -msgstr "Min length" - -#: static/angular/metadata-tree/metadata-tree.js:39 -msgid "Max length" -msgstr "Max length" - -#: static/angular/metadata-tree/metadata-tree.js:40 -msgid "Pattern mismatch" -msgstr "Pattern mismatch" - -#: static/angular/metadata-tree/metadata-tree.js:41 -msgid "Integer required" -msgstr "Integer required" - -#: static/angular/metadata-tree/metadata-tree.js:42 -msgid "Decimal required" -msgstr "Decimal required" - -#: static/angular/metadata-tree/metadata-tree.js:43 -msgid "Required" -msgstr "Required" - -#: static/angular/metadata-tree/metadata-tree.js:44 -msgid "Duplicate keys are not allowed" -msgstr "Duplicate keys are not allowed" - -#: static/angular/metadata-tree/metadata-tree.js:45 -#: static/angular/table/basic-table.js:6 -#: static/horizon/js/horizon.forms.js:184 -msgid "Filter" -msgstr "Filter" - -#: static/angular/metadata-tree/metadata-tree.js:46 -msgid "Available Metadata" -msgstr "Available Metadata" - -#: static/angular/metadata-tree/metadata-tree.js:47 -msgid "Existing Metadata" -msgstr "Existing Metadata" - -#: static/angular/metadata-tree/metadata-tree.js:48 -msgid "Custom" -msgstr "Custom" - -#: static/angular/metadata-tree/metadata-tree.js:49 -msgid "No available metadata" -msgstr "No available metadata" - -#: static/angular/metadata-tree/metadata-tree.js:50 -msgid "No existing metadata" -msgstr "No existing metadata" - -#: static/angular/modal/modal.js:83 -msgid "Submit" -msgstr "Submit" - -#: static/angular/modal/modal.js:84 static/angular/wizard/wizard.js:11 -#: static/horizon/js/horizon.modals.js:33 -msgid "Cancel" -msgstr "Cancel" - -#: static/angular/transfer-table/transfer-table.js:39 -msgid "Allocated" -msgstr "Allocated" - -#: static/angular/transfer-table/transfer-table.js:40 -msgid "Available" -msgstr "Available" - -#: static/angular/transfer-table/transfer-table.js:41 -msgid "Select one" -msgstr "Select one" - -#: static/angular/transfer-table/transfer-table.js:42 -msgid "Select an item from Available items below" -msgstr "Select an item from Available items below" - -#: static/angular/transfer-table/transfer-table.js:43 -msgid "No available items" -msgstr "No available items" - -#: static/angular/transfer-table/transfer-table.js:44 -msgid "Expand to see allocated items" -msgstr "Expand to see allocated items" - -#: static/angular/transfer-table/transfer-table.js:45 -msgid "Expand to see available items" -msgstr "Expand to see available items" - -#: static/angular/transfer-table/transfer-table.js:46 -msgid "Click to show or hide" -msgstr "Click to show or hide" - -#: static/angular/transfer-table/transfer-table.js:47 -msgid "Re-order items using drag and drop" -msgstr "Re-order items using drag and drop" - -#: static/angular/transfer-table/transfer-table.js:48 -msgid "Click to see more details" -msgstr "Click to see more details" - -#: static/angular/transfer-table/transfer-table.js:100 -msgid "Found %(found)s of %(total)s" -msgstr "Found %(found)s of %(total)s" - -#: static/angular/transfer-table/transfer-table.js:166 -msgid "Click here to expand the row and view the errors." -msgstr "Click here to expand the row and view the errors." - -#: static/angular/wizard/wizard.js:12 -msgid "Back" -msgstr "Back" - -#: static/angular/wizard/wizard.js:13 -msgid "Next" -msgstr "Next" - -#: static/angular/wizard/wizard.js:14 -msgid "Finish" -msgstr "Finish" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Connecting" -msgstr "Connecting" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Open" -msgstr "Open" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closing" -msgstr "Closing" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closed" -msgstr "Closed" - -#: static/horizon/js/angular/directives/serialConsole.js:85 -#, c-format -msgid "Status: %s" -msgstr "Status: %s" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "Yes" -msgstr "Yes" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "No" -msgstr "No" - -#: static/horizon/js/angular/filters/filters.js:53 -#: static/horizon/js/angular/filters/filters.js:140 -#, c-format -msgid "%s GB" -msgstr "%s GB" - -#: static/horizon/js/angular/filters/filters.js:70 -#: static/horizon/js/angular/filters/filters.js:142 -#, c-format -msgid "%s MB" -msgstr "%s MB" - -#: static/horizon/js/angular/filters/filters.js:138 -#, c-format -msgid "%s TB" -msgstr "%s TB" - -#: static/horizon/js/angular/filters/filters.js:144 -#, c-format -msgid "%s KB" -msgstr "%s KB" - -#: static/horizon/js/angular/filters/filters.js:146 -#, c-format -msgid "%s bytes" -msgstr "%s bytes" - -#: static/horizon/js/angular/filters/filters.js:163 -#: static/horizon/js/horizon.tables.js:393 -#, c-format -msgid "Displaying %s item" -msgid_plural "Displaying %s items" -msgstr[0] "Displaying %s item" -msgstr[1] "Displaying %s items" - -#: static/horizon/js/angular/services/hz.api.cinder.js:47 -msgid "Unable to retrieve volumes." -msgstr "Unable to retrieve volumes." - -#: static/horizon/js/angular/services/hz.api.cinder.js:74 -msgid "Unable to retrieve volume snapshots." -msgstr "Unable to retrieve volume snapshots." - -#: static/horizon/js/angular/services/hz.api.config.js:43 -msgid "Unable to retrieve user configuration." -msgstr "Unable to retrieve user configuration." - -#: static/horizon/js/angular/services/hz.api.config.js:62 -msgid "Unable to retrieve admin configuration." -msgstr "Unable to retrieve admin configuration." - -#: static/horizon/js/angular/services/hz.api.config.js:105 -msgid "Unable to retrieve settings." -msgstr "Unable to retrieve settings." - -#: static/horizon/js/angular/services/hz.api.config.js:289 -msgid "Setting is not enabled: %(setting)s" -msgstr "Setting is not enabled: %(setting)s" - -#: static/horizon/js/angular/services/hz.api.glance.js:38 -msgid "Unable to retrieve image." -msgstr "Unable to retrieve image." - -#: static/horizon/js/angular/services/hz.api.glance.js:81 -msgid "Unable to retrieve images." -msgstr "Unable to retrieve images." - -#: static/horizon/js/angular/services/hz.api.glance.js:144 -msgid "Unable to retrieve namespaces." -msgstr "Unable to retrieve namespaces." - -#: static/horizon/js/angular/services/hz.api.keystone.js:24 -msgid "Unable to retrieve users" -msgstr "Unable to retrieve users" - -#: static/horizon/js/angular/services/hz.api.keystone.js:31 -msgid "Unable to create the user." -msgstr "Unable to create the user." - -#: static/horizon/js/angular/services/hz.api.keystone.js:38 -msgid "Unable to delete the users." -msgstr "Unable to delete the users." - -#: static/horizon/js/angular/services/hz.api.keystone.js:73 -msgid "Unable to retrieve the current user session." -msgstr "Unable to retrieve the current user session." - -#: static/horizon/js/angular/services/hz.api.keystone.js:80 -msgid "Unable to retrieve the user" -msgstr "Unable to retrieve the user" - -#: static/horizon/js/angular/services/hz.api.keystone.js:88 -msgid "Unable to edit the user." -msgstr "Unable to edit the user." - -#: static/horizon/js/angular/services/hz.api.keystone.js:95 -msgid "Unable to delete the user." -msgstr "Unable to delete the user." - -#: static/horizon/js/angular/services/hz.api.keystone.js:103 -msgid "Unable to retrieve role" -msgstr "Unable to retrieve role" - -#: static/horizon/js/angular/services/hz.api.keystone.js:110 -msgid "Unable to create the role." -msgstr "Unable to create the role." - -#: static/horizon/js/angular/services/hz.api.keystone.js:117 -msgid "Unable to delete the roles." -msgstr "Unable to delete the roles." - -#: static/horizon/js/angular/services/hz.api.keystone.js:124 -msgid "Unable to retrieve the role" -msgstr "Unable to retrieve the role" - -#: static/horizon/js/angular/services/hz.api.keystone.js:132 -msgid "Unable to edit the role." -msgstr "Unable to edit the role." - -#: static/horizon/js/angular/services/hz.api.keystone.js:139 -msgid "Unable to delete the role." -msgstr "Unable to delete the role." - -#: static/horizon/js/angular/services/hz.api.keystone.js:147 -msgid "Unable to retrieve domains" -msgstr "Unable to retrieve domains" - -#: static/horizon/js/angular/services/hz.api.keystone.js:154 -msgid "Unable to create the domain." -msgstr "Unable to create the domain." - -#: static/horizon/js/angular/services/hz.api.keystone.js:161 -msgid "Unable to delete the domains." -msgstr "Unable to delete the domains." - -#: static/horizon/js/angular/services/hz.api.keystone.js:168 -msgid "Unable to retrieve the domain" -msgstr "Unable to retrieve the domain" - -#: static/horizon/js/angular/services/hz.api.keystone.js:176 -msgid "Unable to edit the domain." -msgstr "Unable to edit the domain." - -#: static/horizon/js/angular/services/hz.api.keystone.js:183 -msgid "Unable to delete the domain." -msgstr "Unable to delete the domain." - -#: static/horizon/js/angular/services/hz.api.keystone.js:192 -msgid "Unable to retrieve projects" -msgstr "Unable to retrieve projects" - -#: static/horizon/js/angular/services/hz.api.keystone.js:199 -msgid "Unable to create the project." -msgstr "Unable to create the project." - -#: static/horizon/js/angular/services/hz.api.keystone.js:206 -msgid "Unable to delete the projects." -msgstr "Unable to delete the projects." - -#: static/horizon/js/angular/services/hz.api.keystone.js:213 -msgid "Unable to retrieve the project" -msgstr "Unable to retrieve the project" - -#: static/horizon/js/angular/services/hz.api.keystone.js:221 -msgid "Unable to edit the project." -msgstr "Unable to edit the project." - -#: static/horizon/js/angular/services/hz.api.keystone.js:228 -msgid "Unable to delete the project." -msgstr "Unable to delete the project." - -#: static/horizon/js/angular/services/hz.api.keystone.js:236 -msgid "Unable to grant the role." -msgstr "Unable to grant the role." - -#: static/horizon/js/angular/services/hz.api.keystone.js:250 -msgid "Unable to fetch the service catalog." -msgstr "Unable to fetch the service catalog." - -#: static/horizon/js/angular/services/hz.api.keystone.js:385 -msgid "Service type is not enabled: %(desiredType)s" -msgstr "Service type is not enabled: %(desiredType)s" - -#: static/horizon/js/angular/services/hz.api.keystone.js:392 -msgid "Cannot get service catalog from keystone." -msgstr "Cannot get service catalog from keystone." - -#: static/horizon/js/angular/services/hz.api.neutron.js:39 -msgid "Unable to retrieve networks." -msgstr "Unable to retrieve networks." - -#: static/horizon/js/angular/services/hz.api.neutron.js:88 -msgid "Unable to create the network." -msgstr "Unable to create the network." - -#: static/horizon/js/angular/services/hz.api.neutron.js:108 -msgid "Unable to retrieve subnets." -msgstr "Unable to retrieve subnets." - -#: static/horizon/js/angular/services/hz.api.neutron.js:172 -msgid "Unable to create the subnet." -msgstr "Unable to create the subnet." - -#: static/horizon/js/angular/services/hz.api.neutron.js:192 -msgid "Unable to retrieve ports." -msgstr "Unable to retrieve ports." - -#: static/horizon/js/angular/services/hz.api.nova.js:40 -msgid "Unable to retrieve keypairs." -msgstr "Unable to retrieve keypairs." - -#: static/horizon/js/angular/services/hz.api.nova.js:62 -msgid "Unable to import the keypair." -msgstr "Unable to import the keypair." - -#: static/horizon/js/angular/services/hz.api.nova.js:64 -msgid "Unable to create the keypair." -msgstr "Unable to create the keypair." - -#: static/horizon/js/angular/services/hz.api.nova.js:83 -msgid "Unable to retrieve availability zones." -msgstr "Unable to retrieve availability zones." - -#: static/horizon/js/angular/services/hz.api.nova.js:121 -msgid "Unable to retrieve limits." -msgstr "Unable to retrieve limits." - -#: static/horizon/js/angular/services/hz.api.nova.js:148 -msgid "Unable to create the server." -msgstr "Unable to create the server." - -#: static/horizon/js/angular/services/hz.api.nova.js:162 -msgid "Unable to retrieve server." -msgstr "Unable to retrieve server." - -#: static/horizon/js/angular/services/hz.api.nova.js:192 -msgid "Unable to retrieve extensions." -msgstr "Unable to retrieve extensions." - -#: static/horizon/js/angular/services/hz.api.nova.js:237 -msgid "Unable to retrieve flavors." -msgstr "Unable to retrieve flavors." - -#: static/horizon/js/angular/services/hz.api.nova.js:255 -msgid "Unable to retrieve flavor." -msgstr "Unable to retrieve flavor." - -#: static/horizon/js/angular/services/hz.api.nova.js:269 -msgid "Unable to retrieve flavor extra specs." -msgstr "Unable to retrieve flavor extra specs." - -#: static/horizon/js/angular/services/hz.api.nova.js:311 -msgid "Extension is not enabled: %(extension)s" -msgstr "Extension is not enabled: %(extension)s" - -#: static/horizon/js/angular/services/hz.api.nova.js:318 -msgid "Cannot get nova extension list." -msgstr "Cannot get nova extension list." - -#: static/horizon/js/angular/services/hz.api.policy.js:65 -msgid "Policy check failed." -msgstr "Policy check failed." - -#: static/horizon/js/angular/services/hz.api.security-group.js:64 -msgid "Unable to retrieve security groups." -msgstr "Unable to retrieve security groups." - -#: static/horizon/js/horizon.accordion_nav.js:78 -#: static/horizon/js/horizon.modals.js:315 -#: static/horizon/js/horizon.tabs.js:21 -msgid "Loading" -msgstr "Loading" - -#: static/horizon/js/horizon.d3linechart.js:394 -#: static/horizon/js/horizon.d3linechart.js:404 -msgid "No data available." -msgstr "No data available." - -#: static/horizon/js/horizon.d3linechart.js:410 -#: static/horizon/js/horizon.modals.js:334 -#: static/horizon/js/horizon.tables_inline_edit.js:94 -#: static/horizon/js/horizon.tables_inline_edit.js:157 -msgid "An error occurred. Please try again later." -msgstr "An error occurred. Please try again later." - -#: static/horizon/js/horizon.firewalls.js:32 -#: static/horizon/js/horizon.instances.js:31 -msgid "There was a problem communicating with the server, please try again." -msgstr "There was a problem communicating with the server, please try again." - -#: static/horizon/js/horizon.instances.js:273 -msgid "Could not read the file" -msgstr "Could not read the file" - -#: static/horizon/js/horizon.instances.js:279 -#: static/horizon/js/horizon.instances.js:308 -msgid "Could not decrypt the password" -msgstr "Could not decrypt the password" - -#: static/horizon/js/horizon.membership.js:190 -msgid "No roles" -msgstr "No roles" - -#: static/horizon/js/horizon.membership.js:222 -msgid "Roles" -msgstr "Roles" - -#: static/horizon/js/horizon.messages.js:9 -msgid "Danger: " -msgstr "Danger: " - -#: static/horizon/js/horizon.messages.js:10 -msgid "Warning: " -msgstr "Warning: " - -#: static/horizon/js/horizon.messages.js:11 -msgid "Notice: " -msgstr "Notice: " - -#: static/horizon/js/horizon.messages.js:12 -msgid "Success: " -msgstr "Success: " - -#: static/horizon/js/horizon.messages.js:13 -msgid "Error: " -msgstr "Error: " - -#: static/horizon/js/horizon.modals.js:229 -#: static/horizon/js/horizon.tables.js:218 -msgid "Working" -msgstr "Working" - -#: static/horizon/js/horizon.modals.js:263 -msgid "There was an error submitting the form. Please try again." -msgstr "There was an error submitting the form. Please try again." - -#: static/horizon/js/horizon.networktopology.js:530 -#: static/horizon/js/horizon.networktopology.js:536 -msgid "None" -msgstr "None" - -#: static/horizon/js/horizon.networktopology.js:549 -msgid "Delete" -msgstr "Delete" - -#: static/horizon/js/horizon.networktopology.js:552 -msgid "STATUS" -msgstr "STATUS" - -#: static/horizon/js/horizon.networktopology.js:553 -msgid "ID" -msgstr "ID" - -#: static/horizon/js/horizon.networktopology.js:554 -msgid "Interfaces" -msgstr "Interfaces" - -#: static/horizon/js/horizon.networktopology.js:555 -msgid "Delete Interface" -msgstr "Delete Interface" - -#: static/horizon/js/horizon.networktopology.js:556 -msgid "Open Console" -msgstr "Open Console" - -#: static/horizon/js/horizon.networktopology.js:557 -msgid "View Details" -msgstr "View Details" - -#: static/horizon/js/horizon.networktopology.js:560 -msgid "Delete Router" -msgstr "Delete Router" - -#: static/horizon/js/horizon.networktopology.js:561 -msgid "View Router Details" -msgstr "View Router Details" - -#: static/horizon/js/horizon.networktopology.js:564 -msgid "Add Interface" -msgstr "Add Interface" - -#: static/horizon/js/horizon.networktopology.js:570 -msgid "Terminate Instance" -msgstr "Terminate Instance" - -#: static/horizon/js/horizon.networktopology.js:571 -msgid "View Instance Details" -msgstr "View Instance Details" - -#: static/horizon/js/horizon.tables.js:39 -#: static/horizon/js/horizon.tables.js:406 -msgid "No items to display." -msgstr "No items to display." - -#: static/horizon/js/horizon.tables.js:52 -#: static/horizon/js/horizon.tables.js:120 -msgid "An error occurred while updating." -msgstr "An error occurred while updating." - -#: static/horizon/js/horizon.tables.js:201 -#, c-format -msgid "You have selected %s. " -msgstr "You have selected %s. " - -#: static/horizon/js/horizon.tables.js:203 -#, c-format -msgid "Confirm %s" -msgstr "Confirm %s" - -#: static/horizon/js/horizon.tables.js:204 -msgid "Please confirm your selection. " -msgstr "Please confirm your selection. " - -#: static/horizon/js/horizon.tables_inline_edit.js:88 -#: static/horizon/js/horizon.tables_inline_edit.js:151 -msgid "Not authorized to do this operation." -msgstr "Not authorised to do this operation." - -#: static/horizon/js/horizon.users.js:18 -msgid "Passwords do not match." -msgstr "Passwords do not match." diff --git a/code/horizon/horizon/locale/en_GB/LC_MESSAGES/django.po b/code/horizon/horizon/locale/en_GB/LC_MESSAGES/django.po deleted file mode 100644 index 6b50f5f8..00000000 --- a/code/horizon/horizon/locale/en_GB/LC_MESSAGES/django.po +++ /dev/null @@ -1,512 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Andi Chandler , 2014 -# Rob Cresswell , 2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-06 21:07-0500\n" -"PO-Revision-Date: 2015-04-05 15:01+0000\n" -"Last-Translator: Rob Cresswell \n" -"Language-Team: English (United Kingdom) (http://www.transifex.com/projects/p/horizon/language/en_GB/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: en_GB\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: base.py:475 -msgid "Other" -msgstr "Other" - -#: browsers/base.py:88 -msgid "Navigation Item" -msgstr "Navigation Item" - -#: browsers/views.py:41 -#, python-format -msgid "Select a %s to browse." -msgstr "Select a %s to browse." - -#: conf/default.py:41 -msgid "Password is not accepted" -msgstr "Password is not accepted" - -#: decorators.py:53 -msgid "Please log in to continue." -msgstr "Please log in to continue." - -#: decorators.py:85 -#, python-format -msgid "You are not authorized to access %s" -msgstr "You are not authorised to access %s" - -#: exceptions.py:163 -#, python-format -msgid "A %(resource)s with the name \"%(name)s\" already exists." -msgstr "A %(resource)s with the name \"%(name)s\" already exists." - -#: exceptions.py:235 -#, python-format -msgid "Unauthorized: %s" -msgstr "Unauthorised: %s" - -#: exceptions.py:238 -msgid "Unauthorized. Please try logging in again." -msgstr "Unauthorised. Please try logging in again." - -#: forms/fields.py:64 -msgid "Incorrect format for IP address" -msgstr "Incorrect format for IP address" - -#: forms/fields.py:65 -msgid "Invalid version for IP address" -msgstr "Invalid version for IP address" - -#: forms/fields.py:66 -msgid "Invalid subnet mask" -msgstr "Invalid subnet mask" - -#: forms/views.py:132 templates/horizon/common/_usage_summary.html:16 -msgid "Submit" -msgstr "Submit" - -#: forms/views.py:133 -#: templates/horizon/common/_modal_form_update_metadata.html:25 -#: templates/horizon/common/_workflow.html:49 -msgid "Cancel" -msgstr "Cancel" - -#: middleware.py:103 -msgid "Session timed out." -msgstr "Session timed out." - -#: tables/actions.py:460 -#: templates/horizon/common/_data_table_table_actions.html:21 -#: templates/horizon/common/_data_table_table_actions.html:33 -#: templates/horizon/common/_workflow_step_update_members.html:14 -#: templates/horizon/common/_workflow_step_update_members.html:23 -msgid "Filter" -msgstr "Filter" - -#: tables/actions.py:645 -msgid "This action cannot be undone." -msgstr "This action cannot be undone." - -#: tables/actions.py:767 -#, python-format -msgctxt "past" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:769 -#, python-format -msgctxt "present" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:832 -#, python-format -msgid "You are not allowed to %(action)s: %(objs)s" -msgstr "You are not allowed to %(action)s: %(objs)s" - -#: tables/actions.py:839 -#, python-format -msgid "Unable to %(action)s: %(objs)s" -msgstr "Unable to %(action)s: %(objs)s" - -#: tables/actions.py:845 -#, python-format -msgid "%(action)s: %(objs)s" -msgstr "%(action)s: %(objs)s" - -#: tables/actions.py:915 -msgid "Delete" -msgstr "Delete" - -#: tables/actions.py:917 -msgid "Deleted" -msgstr "Deleted" - -#: tables/actions.py:948 -msgid "Update" -msgstr "Update" - -#: tables/actions.py:949 -msgid "Updated" -msgstr "Updated" - -#: tables/base.py:305 -msgid "-" -msgstr "-" - -#: tables/base.py:361 -#, python-format -msgid "The attribute %(attr)s doesn't exist on %(obj)s." -msgstr "The attribute %(attr)s does not exist on %(obj)s." - -#: tables/base.py:990 -msgid "No items to display." -msgstr "No items to display." - -#: tables/base.py:1099 -#: templates/horizon/common/_data_table_table_actions.html:47 -msgid "Actions" -msgstr "Actions" - -#: tables/base.py:1329 -#, python-format -msgid "No match returned for the id \"%s\"." -msgstr "No match returned for the id \"%s\"." - -#: tables/base.py:1486 -msgid "Please select a row before taking that action." -msgstr "Please select a row before taking that action." - -#: tables/base.py:1570 -msgid "N/A" -msgstr "N/A" - -#: templates/_header.html:5 -#, python-format -msgid "Logged in as: %(username)s" -msgstr "Logged in as: %(username)s" - -#: templates/_header.html:7 -msgid "Help" -msgstr "Help" - -#: templates/_header.html:9 -msgid "Sign Out" -msgstr "Sign Out" - -#: templates/auth/_description.html:9 -msgid "" -"\n" -" If you are not sure which authentication method to use, contact your administrator.\n" -" " -msgstr "\n If you are not sure which authentication method to use, contact your administrator.\n " - -#: templates/auth/_login.html:5 -msgid "Log In" -msgstr "Log In" - -#: templates/auth/_login.html:27 -msgid "You do not have permission to access the resource:" -msgstr "You do not have permission to access the resource:" - -#: templates/auth/_login.html:29 -#, python-format -msgid "" -"Login as different user or go back to home " -"page" -msgstr "Login as different user or go back to home page" - -#: templates/auth/_login.html:45 -msgid "Sign In" -msgstr "Sign In" - -#: templates/auth/_login.html:46 -msgid "Connect" -msgstr "Connect" - -#: templates/auth/login.html:4 -msgid "Login" -msgstr "Login" - -#: templates/horizon/_messages.html:7 -msgid "Info: " -msgstr "Info: " - -#: templates/horizon/_messages.html:13 -msgid "Warning: " -msgstr "Warning: " - -#: templates/horizon/_messages.html:19 -msgid "Success: " -msgstr "Success: " - -#: templates/horizon/_messages.html:25 -msgid "Error: " -msgstr "Error: " - -#: templates/horizon/common/_data_table.html:63 -msgid "Summary" -msgstr "Summary" - -#: templates/horizon/common/_data_table.html:72 -#, python-format -msgid "Displaying %(counter)s item" -msgid_plural "Displaying %(counter)s items" -msgstr[0] "Displaying %(counter)s item" -msgstr[1] "Displaying %(counter)s items" - -#: templates/horizon/common/_data_table.html:77 -msgid "« Prev" -msgstr "« Prev" - -#: templates/horizon/common/_data_table.html:80 -msgid "Next »" -msgstr "Next »" - -#: templates/horizon/common/_data_table_table_actions.html:45 -msgid "More Actions" -msgstr "More Actions" - -#: templates/horizon/common/_domain_page_header.html:6 -#, python-format -msgid "%(context_name)s:" -msgstr "%(context_name)s:" - -#: templates/horizon/common/_formset_table.html:35 -msgid "Add a row" -msgstr "Add a row" - -#: templates/horizon/common/_formset_table_row.html:15 -#, python-format -msgid "%(name)s: %(error)s" -msgstr "%(name)s: %(error)s" - -#: templates/horizon/common/_limit_summary.html:4 -msgid "Limit Summary" -msgstr "Limit Summary" - -#: templates/horizon/common/_limit_summary.html:7 -msgid "Instances" -msgstr "Instances" - -#: templates/horizon/common/_limit_summary.html:8 -#: templates/horizon/common/_limit_summary.html:15 -#: templates/horizon/common/_limit_summary.html:22 -#: templates/horizon/common/_limit_summary.html:36 -#: templates/horizon/common/_limit_summary.html:43 -#: templates/horizon/common/_limit_summary.html:50 -#, python-format -msgid "Used %(used)s of %(available)s " -msgstr "Used %(used)s of %(available)s " - -#: templates/horizon/common/_limit_summary.html:14 -msgid "VCPUs" -msgstr "VCPUs" - -#: templates/horizon/common/_limit_summary.html:21 -msgid "RAM" -msgstr "RAM" - -#: templates/horizon/common/_limit_summary.html:28 -msgid "Floating IPs" -msgstr "Floating IPs" - -#: templates/horizon/common/_limit_summary.html:29 -#, python-format -msgid "Allocated %(used)s of %(available)s " -msgstr "Allocated %(used)s of %(available)s " - -#: templates/horizon/common/_limit_summary.html:35 -msgid "Security Groups" -msgstr "Security Groups" - -#: templates/horizon/common/_limit_summary.html:42 -msgid "Volumes" -msgstr "Volumes" - -#: templates/horizon/common/_limit_summary.html:49 -msgid "Volume Storage" -msgstr "Volume Storage" - -#: templates/horizon/common/_modal_form_update_metadata.html:24 -#: workflows/base.py:594 -msgid "Save" -msgstr "Save" - -#: templates/horizon/common/_resource_browser.html:10 -#, python-format -msgid "Displaying %(nav_items)s item" -msgid_plural "Displaying %(nav_items)s items" -msgstr[0] "Displaying %(nav_items)s item" -msgstr[1] "Displaying %(nav_items)s items" - -#: templates/horizon/common/_resource_browser.html:11 -#, python-format -msgid "Displaying %(content_items)s item" -msgid_plural "Displaying %(content_items)s items" -msgstr[0] "Displaying %(content_items)s item" -msgstr[1] "Displaying %(content_items)s items" - -#: templates/horizon/common/_usage_summary.html:3 -msgid "Usage Summary" -msgstr "Usage Summary" - -#: templates/horizon/common/_usage_summary.html:7 -msgid "Select a period of time to query its usage:" -msgstr "Select a period of time to query its usage:" - -#: templates/horizon/common/_usage_summary.html:9 -#, python-format -msgid "" -"\n" -" %(start)s" -msgstr "\n %(start)s" - -#: templates/horizon/common/_usage_summary.html:13 -#, python-format -msgid "" -"\n" -" %(end)s" -msgstr "\n %(end)s" - -#: templates/horizon/common/_usage_summary.html:17 -msgid "The date should be in YYYY-mm-dd format." -msgstr "The date should be in YYYY-mm-dd format." - -#: templates/horizon/common/_usage_summary.html:20 -msgid "Active Instances:" -msgstr "Active Instances:" - -#: templates/horizon/common/_usage_summary.html:21 -msgid "Active RAM:" -msgstr "Active RAM:" - -#: templates/horizon/common/_usage_summary.html:22 -msgid "This Period's VCPU-Hours:" -msgstr "This Period's VCPU-Hours:" - -#: templates/horizon/common/_usage_summary.html:23 -msgid "This Period's GB-Hours:" -msgstr "This Period's GB-Hours:" - -#: templates/horizon/common/_usage_summary.html:24 -msgid "This Period's RAM-Hours:" -msgstr "This Period's RAM-Hours:" - -#: templates/horizon/common/_workflow.html:40 -msgid "Back" -msgstr "Back" - -#: templates/horizon/common/_workflow.html:43 -msgid "Next" -msgstr "Next" - -#: templatetags/branding.py:34 -msgid "Horizon" -msgstr "Horizon" - -#: templatetags/horizon.py:137 templatetags/horizon.py:148 -msgid "No Limit" -msgstr "No Limit" - -#: templatetags/horizon.py:140 templatetags/horizon.py:142 -msgid "Available" -msgstr "Available" - -#: templatetags/sizeformat.py:51 templatetags/sizeformat.py:56 -#, python-format -msgid "%(size)d Byte" -msgid_plural "%(size)d Bytes" -msgstr[0] "%(size)d Byte" -msgstr[1] "%(size)d Bytes" - -#: templatetags/sizeformat.py:59 -#, python-format -msgid "%s KB" -msgstr "%s KB" - -#: templatetags/sizeformat.py:61 -#, python-format -msgid "%s MB" -msgstr "%s MB" - -#: templatetags/sizeformat.py:63 -#, python-format -msgid "%s GB" -msgstr "%s GB" - -#: templatetags/sizeformat.py:65 -#, python-format -msgid "%s TB" -msgstr "%s TB" - -#: templatetags/sizeformat.py:66 -#, python-format -msgid "%s PB" -msgstr "%s PB" - -#: templatetags/sizeformat.py:74 -msgid "0 Bytes" -msgstr "0 Bytes" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:31 -msgid "Sell Puppy" -msgid_plural "Sell Puppies" -msgstr[0] "" -msgstr[1] "Sell Puppies" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:40 -msgid "Sold Puppy" -msgid_plural "Sold Puppies" -msgstr[0] "" -msgstr[1] "Sold Puppies" - -#: test/tests/views.py:59 -msgid "Fake" -msgstr "Fake" - -#: utils/filters.py:49 -msgid "Never" -msgstr "Never" - -#: utils/validators.py:26 utils/validators.py:50 -msgid "Not a valid port number" -msgstr "Not a valid port number" - -#: utils/validators.py:31 -msgid "Not a valid IP protocol number" -msgstr "Not a valid IP protocol number" - -#: utils/validators.py:45 -msgid "One colon allowed in port range" -msgstr "One colon allowed in port range" - -#: utils/validators.py:52 -msgid "Port number must be integer" -msgstr "Port number must be integer" - -#: utils/validators.py:59 -msgid "The string may only contain ASCII printable characters." -msgstr "The string may only contain ASCII printable characters." - -#: workflows/base.py:71 -msgid "Processing..." -msgstr "Processing..." - -#: workflows/base.py:475 -msgid "All available" -msgstr "All available" - -#: workflows/base.py:476 -msgid "Members" -msgstr "Members" - -#: workflows/base.py:477 -msgid "None available." -msgstr "None available." - -#: workflows/base.py:478 -msgid "No members." -msgstr "No members." - -#: workflows/base.py:595 -#, python-format -msgid "%s completed successfully." -msgstr "%s completed successfully." - -#: workflows/base.py:596 -#, python-format -msgid "%s did not complete." -msgstr "%s did not complete." diff --git a/code/horizon/horizon/locale/en_GB/LC_MESSAGES/djangojs.po b/code/horizon/horizon/locale/en_GB/LC_MESSAGES/djangojs.po deleted file mode 100644 index cb78049f..00000000 --- a/code/horizon/horizon/locale/en_GB/LC_MESSAGES/djangojs.po +++ /dev/null @@ -1,620 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Andi Chandler , 2014 -# Rob Cresswell , 2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-12 16:36-0500\n" -"PO-Revision-Date: 2015-04-13 07:52+0000\n" -"Last-Translator: Rob Cresswell \n" -"Language-Team: English (United Kingdom) (http://www.transifex.com/projects/p/horizon/language/en_GB/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: en_GB\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: static/angular/action-list/button-tooltip.js:15 -msgid "" -"The action cannot be performed. The contents of this row have errors or are " -"missing information." -msgstr "The action cannot be performed. The contents of this row have errors or are missing information." - -#: static/angular/metadata-display/metadata-display.js:33 -msgid "Detail Information" -msgstr "Detail Information" - -#: static/angular/metadata-tree/metadata-tree.js:35 -msgid "" -"You can specify resource metadata by moving items from the left column to " -"the right column. In the left columns there are metadata definitions from " -"the Glance Metadata Catalog. Use the \"Other\" option to add metadata with " -"the key of your choice." -msgstr "You can specify resource metadata by moving items from the left column to the right column. In the left columns there are metadata definitions from the Glance Metadata Catalog. Use the \"Other\" option to add metadata with the key of your choice." - -#: static/angular/metadata-tree/metadata-tree.js:36 -msgid "Min" -msgstr "Min" - -#: static/angular/metadata-tree/metadata-tree.js:37 -msgid "Max" -msgstr "Max" - -#: static/angular/metadata-tree/metadata-tree.js:38 -msgid "Min length" -msgstr "Min length" - -#: static/angular/metadata-tree/metadata-tree.js:39 -msgid "Max length" -msgstr "Max length" - -#: static/angular/metadata-tree/metadata-tree.js:40 -msgid "Pattern mismatch" -msgstr "Pattern mismatch" - -#: static/angular/metadata-tree/metadata-tree.js:41 -msgid "Integer required" -msgstr "Integer required" - -#: static/angular/metadata-tree/metadata-tree.js:42 -msgid "Decimal required" -msgstr "Decimal required" - -#: static/angular/metadata-tree/metadata-tree.js:43 -msgid "Required" -msgstr "Required" - -#: static/angular/metadata-tree/metadata-tree.js:44 -msgid "Duplicate keys are not allowed" -msgstr "Duplicate keys are not allowed" - -#: static/angular/metadata-tree/metadata-tree.js:45 -#: static/angular/table/basic-table.js:6 -#: static/horizon/js/horizon.forms.js:184 -msgid "Filter" -msgstr "Filter" - -#: static/angular/metadata-tree/metadata-tree.js:46 -msgid "Available Metadata" -msgstr "Available Metadata" - -#: static/angular/metadata-tree/metadata-tree.js:47 -msgid "Existing Metadata" -msgstr "Existing Metadata" - -#: static/angular/metadata-tree/metadata-tree.js:48 -msgid "Custom" -msgstr "Custom" - -#: static/angular/metadata-tree/metadata-tree.js:49 -msgid "No available metadata" -msgstr "No available metadata" - -#: static/angular/metadata-tree/metadata-tree.js:50 -msgid "No existing metadata" -msgstr "No existing metadata" - -#: static/angular/modal/modal.js:83 -msgid "Submit" -msgstr "Submit" - -#: static/angular/modal/modal.js:84 static/angular/wizard/wizard.js:11 -#: static/horizon/js/horizon.modals.js:33 -msgid "Cancel" -msgstr "Cancel" - -#: static/angular/transfer-table/transfer-table.js:39 -msgid "Allocated" -msgstr "Allocated" - -#: static/angular/transfer-table/transfer-table.js:40 -msgid "Available" -msgstr "Available" - -#: static/angular/transfer-table/transfer-table.js:41 -msgid "Select one" -msgstr "Select one" - -#: static/angular/transfer-table/transfer-table.js:42 -msgid "Select an item from Available items below" -msgstr "Select an item from Available items below" - -#: static/angular/transfer-table/transfer-table.js:43 -msgid "No available items" -msgstr "No available items" - -#: static/angular/transfer-table/transfer-table.js:44 -msgid "Expand to see allocated items" -msgstr "Expand to see allocated items" - -#: static/angular/transfer-table/transfer-table.js:45 -msgid "Expand to see available items" -msgstr "Expand to see available items" - -#: static/angular/transfer-table/transfer-table.js:46 -msgid "Click to show or hide" -msgstr "Click to show or hide" - -#: static/angular/transfer-table/transfer-table.js:47 -msgid "Re-order items using drag and drop" -msgstr "Re-order items using drag and drop" - -#: static/angular/transfer-table/transfer-table.js:48 -msgid "Click to see more details" -msgstr "Click to see more details" - -#: static/angular/transfer-table/transfer-table.js:100 -msgid "Found %(found)s of %(total)s" -msgstr "Found %(found)s of %(total)s" - -#: static/angular/transfer-table/transfer-table.js:166 -msgid "Click here to expand the row and view the errors." -msgstr "Click here to expand the row and view the errors." - -#: static/angular/wizard/wizard.js:12 -msgid "Back" -msgstr "Back" - -#: static/angular/wizard/wizard.js:13 -msgid "Next" -msgstr "Next" - -#: static/angular/wizard/wizard.js:14 -msgid "Finish" -msgstr "Finish" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Connecting" -msgstr "Connecting" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Open" -msgstr "Open" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closing" -msgstr "Closing" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closed" -msgstr "Closed" - -#: static/horizon/js/angular/directives/serialConsole.js:85 -#, c-format -msgid "Status: %s" -msgstr "Status: %s" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "Yes" -msgstr "Yes" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "No" -msgstr "No" - -#: static/horizon/js/angular/filters/filters.js:53 -#: static/horizon/js/angular/filters/filters.js:140 -#, c-format -msgid "%s GB" -msgstr "%s GB" - -#: static/horizon/js/angular/filters/filters.js:70 -#: static/horizon/js/angular/filters/filters.js:142 -#, c-format -msgid "%s MB" -msgstr "%s MB" - -#: static/horizon/js/angular/filters/filters.js:138 -#, c-format -msgid "%s TB" -msgstr "%s TB" - -#: static/horizon/js/angular/filters/filters.js:144 -#, c-format -msgid "%s KB" -msgstr "%s KB" - -#: static/horizon/js/angular/filters/filters.js:146 -#, c-format -msgid "%s bytes" -msgstr "%s bytes" - -#: static/horizon/js/angular/filters/filters.js:163 -#: static/horizon/js/horizon.tables.js:393 -#, c-format -msgid "Displaying %s item" -msgid_plural "Displaying %s items" -msgstr[0] "Displaying %s item" -msgstr[1] "Displaying %s items" - -#: static/horizon/js/angular/services/hz.api.cinder.js:47 -msgid "Unable to retrieve volumes." -msgstr "Unable to retrieve volumes." - -#: static/horizon/js/angular/services/hz.api.cinder.js:74 -msgid "Unable to retrieve volume snapshots." -msgstr "Unable to retrieve volume snapshots." - -#: static/horizon/js/angular/services/hz.api.config.js:43 -msgid "Unable to retrieve user configuration." -msgstr "Unable to retrieve user configuration." - -#: static/horizon/js/angular/services/hz.api.config.js:62 -msgid "Unable to retrieve admin configuration." -msgstr "Unable to retrieve admin configuration." - -#: static/horizon/js/angular/services/hz.api.config.js:105 -msgid "Unable to retrieve settings." -msgstr "Unable to retrieve settings." - -#: static/horizon/js/angular/services/hz.api.config.js:289 -msgid "Setting is not enabled: %(setting)s" -msgstr "Setting is not enabled: %(setting)s" - -#: static/horizon/js/angular/services/hz.api.glance.js:38 -msgid "Unable to retrieve image." -msgstr "Unable to retrieve image." - -#: static/horizon/js/angular/services/hz.api.glance.js:81 -msgid "Unable to retrieve images." -msgstr "Unable to retrieve images." - -#: static/horizon/js/angular/services/hz.api.glance.js:144 -msgid "Unable to retrieve namespaces." -msgstr "Unable to retrieve namespaces." - -#: static/horizon/js/angular/services/hz.api.keystone.js:24 -msgid "Unable to retrieve users" -msgstr "Unable to retrieve users" - -#: static/horizon/js/angular/services/hz.api.keystone.js:31 -msgid "Unable to create the user." -msgstr "Unable to create the user." - -#: static/horizon/js/angular/services/hz.api.keystone.js:38 -msgid "Unable to delete the users." -msgstr "Unable to delete the users." - -#: static/horizon/js/angular/services/hz.api.keystone.js:73 -msgid "Unable to retrieve the current user session." -msgstr "Unable to retrieve the current user session." - -#: static/horizon/js/angular/services/hz.api.keystone.js:80 -msgid "Unable to retrieve the user" -msgstr "Unable to retrieve the user" - -#: static/horizon/js/angular/services/hz.api.keystone.js:88 -msgid "Unable to edit the user." -msgstr "Unable to edit the user." - -#: static/horizon/js/angular/services/hz.api.keystone.js:95 -msgid "Unable to delete the user." -msgstr "Unable to delete the user." - -#: static/horizon/js/angular/services/hz.api.keystone.js:103 -msgid "Unable to retrieve role" -msgstr "Unable to retrieve role" - -#: static/horizon/js/angular/services/hz.api.keystone.js:110 -msgid "Unable to create the role." -msgstr "Unable to create the role." - -#: static/horizon/js/angular/services/hz.api.keystone.js:117 -msgid "Unable to delete the roles." -msgstr "Unable to delete the roles." - -#: static/horizon/js/angular/services/hz.api.keystone.js:124 -msgid "Unable to retrieve the role" -msgstr "Unable to retrieve the role" - -#: static/horizon/js/angular/services/hz.api.keystone.js:132 -msgid "Unable to edit the role." -msgstr "Unable to edit the role." - -#: static/horizon/js/angular/services/hz.api.keystone.js:139 -msgid "Unable to delete the role." -msgstr "Unable to delete the role." - -#: static/horizon/js/angular/services/hz.api.keystone.js:147 -msgid "Unable to retrieve domains" -msgstr "Unable to retrieve domains" - -#: static/horizon/js/angular/services/hz.api.keystone.js:154 -msgid "Unable to create the domain." -msgstr "Unable to create the domain." - -#: static/horizon/js/angular/services/hz.api.keystone.js:161 -msgid "Unable to delete the domains." -msgstr "Unable to delete the domains." - -#: static/horizon/js/angular/services/hz.api.keystone.js:168 -msgid "Unable to retrieve the domain" -msgstr "Unable to retrieve the domain" - -#: static/horizon/js/angular/services/hz.api.keystone.js:176 -msgid "Unable to edit the domain." -msgstr "Unable to edit the domain." - -#: static/horizon/js/angular/services/hz.api.keystone.js:183 -msgid "Unable to delete the domain." -msgstr "Unable to delete the domain." - -#: static/horizon/js/angular/services/hz.api.keystone.js:192 -msgid "Unable to retrieve projects" -msgstr "Unable to retrieve projects" - -#: static/horizon/js/angular/services/hz.api.keystone.js:199 -msgid "Unable to create the project." -msgstr "Unable to create the project." - -#: static/horizon/js/angular/services/hz.api.keystone.js:206 -msgid "Unable to delete the projects." -msgstr "Unable to delete the projects." - -#: static/horizon/js/angular/services/hz.api.keystone.js:213 -msgid "Unable to retrieve the project" -msgstr "Unable to retrieve the project" - -#: static/horizon/js/angular/services/hz.api.keystone.js:221 -msgid "Unable to edit the project." -msgstr "Unable to edit the project." - -#: static/horizon/js/angular/services/hz.api.keystone.js:228 -msgid "Unable to delete the project." -msgstr "Unable to delete the project." - -#: static/horizon/js/angular/services/hz.api.keystone.js:236 -msgid "Unable to grant the role." -msgstr "Unable to grant the role." - -#: static/horizon/js/angular/services/hz.api.keystone.js:250 -msgid "Unable to fetch the service catalog." -msgstr "Unable to fetch the service catalogue." - -#: static/horizon/js/angular/services/hz.api.keystone.js:385 -msgid "Service type is not enabled: %(desiredType)s" -msgstr "Service type is not enabled: %(desiredType)s" - -#: static/horizon/js/angular/services/hz.api.keystone.js:392 -msgid "Cannot get service catalog from keystone." -msgstr "Cannot get service catalogue from keystone." - -#: static/horizon/js/angular/services/hz.api.neutron.js:39 -msgid "Unable to retrieve networks." -msgstr "Unable to retrieve networks." - -#: static/horizon/js/angular/services/hz.api.neutron.js:88 -msgid "Unable to create the network." -msgstr "Unable to create the network." - -#: static/horizon/js/angular/services/hz.api.neutron.js:108 -msgid "Unable to retrieve subnets." -msgstr "Unable to retrieve subnets." - -#: static/horizon/js/angular/services/hz.api.neutron.js:172 -msgid "Unable to create the subnet." -msgstr "Unable to create the subnet." - -#: static/horizon/js/angular/services/hz.api.neutron.js:192 -msgid "Unable to retrieve ports." -msgstr "Unable to retrieve ports." - -#: static/horizon/js/angular/services/hz.api.nova.js:40 -msgid "Unable to retrieve keypairs." -msgstr "Unable to retrieve keypairs." - -#: static/horizon/js/angular/services/hz.api.nova.js:62 -msgid "Unable to import the keypair." -msgstr "Unable to import the keypair." - -#: static/horizon/js/angular/services/hz.api.nova.js:64 -msgid "Unable to create the keypair." -msgstr "Unable to create the keypair." - -#: static/horizon/js/angular/services/hz.api.nova.js:83 -msgid "Unable to retrieve availability zones." -msgstr "Unable to retrieve availability zones." - -#: static/horizon/js/angular/services/hz.api.nova.js:121 -msgid "Unable to retrieve limits." -msgstr "Unable to retrieve limits." - -#: static/horizon/js/angular/services/hz.api.nova.js:148 -msgid "Unable to create the server." -msgstr "Unable to create the server." - -#: static/horizon/js/angular/services/hz.api.nova.js:162 -msgid "Unable to retrieve server." -msgstr "Unable to retrieve server." - -#: static/horizon/js/angular/services/hz.api.nova.js:192 -msgid "Unable to retrieve extensions." -msgstr "Unable to retrieve extensions." - -#: static/horizon/js/angular/services/hz.api.nova.js:237 -msgid "Unable to retrieve flavors." -msgstr "Unable to retrieve flavours." - -#: static/horizon/js/angular/services/hz.api.nova.js:255 -msgid "Unable to retrieve flavor." -msgstr "Unable to retrieve flavour." - -#: static/horizon/js/angular/services/hz.api.nova.js:269 -msgid "Unable to retrieve flavor extra specs." -msgstr "Unable to retrieve flavour extra specs." - -#: static/horizon/js/angular/services/hz.api.nova.js:311 -msgid "Extension is not enabled: %(extension)s" -msgstr "Extension is not enabled: %(extension)s" - -#: static/horizon/js/angular/services/hz.api.nova.js:318 -msgid "Cannot get nova extension list." -msgstr "Cannot get nova extension list." - -#: static/horizon/js/angular/services/hz.api.policy.js:65 -msgid "Policy check failed." -msgstr "Policy check failed." - -#: static/horizon/js/angular/services/hz.api.security-group.js:64 -msgid "Unable to retrieve security groups." -msgstr "Unable to retrieve security groups." - -#: static/horizon/js/horizon.accordion_nav.js:78 -#: static/horizon/js/horizon.modals.js:315 -#: static/horizon/js/horizon.tabs.js:21 -msgid "Loading" -msgstr "Loading" - -#: static/horizon/js/horizon.d3linechart.js:394 -#: static/horizon/js/horizon.d3linechart.js:404 -msgid "No data available." -msgstr "No data available." - -#: static/horizon/js/horizon.d3linechart.js:410 -#: static/horizon/js/horizon.modals.js:334 -#: static/horizon/js/horizon.tables_inline_edit.js:94 -#: static/horizon/js/horizon.tables_inline_edit.js:157 -msgid "An error occurred. Please try again later." -msgstr "An error occurred. Please try again later." - -#: static/horizon/js/horizon.firewalls.js:32 -#: static/horizon/js/horizon.instances.js:31 -msgid "There was a problem communicating with the server, please try again." -msgstr "There was a problem communicating with the server, please try again." - -#: static/horizon/js/horizon.instances.js:273 -msgid "Could not read the file" -msgstr "Could not read the file" - -#: static/horizon/js/horizon.instances.js:279 -#: static/horizon/js/horizon.instances.js:308 -msgid "Could not decrypt the password" -msgstr "Could not decrypt the password" - -#: static/horizon/js/horizon.membership.js:190 -msgid "No roles" -msgstr "No roles" - -#: static/horizon/js/horizon.membership.js:222 -msgid "Roles" -msgstr "Roles" - -#: static/horizon/js/horizon.messages.js:9 -msgid "Danger: " -msgstr "Danger: " - -#: static/horizon/js/horizon.messages.js:10 -msgid "Warning: " -msgstr "Warning: " - -#: static/horizon/js/horizon.messages.js:11 -msgid "Notice: " -msgstr "Notice: " - -#: static/horizon/js/horizon.messages.js:12 -msgid "Success: " -msgstr "Success: " - -#: static/horizon/js/horizon.messages.js:13 -msgid "Error: " -msgstr "Error: " - -#: static/horizon/js/horizon.modals.js:229 -#: static/horizon/js/horizon.tables.js:218 -msgid "Working" -msgstr "Working" - -#: static/horizon/js/horizon.modals.js:263 -msgid "There was an error submitting the form. Please try again." -msgstr "There was an error submitting the form. Please try again." - -#: static/horizon/js/horizon.networktopology.js:530 -#: static/horizon/js/horizon.networktopology.js:536 -msgid "None" -msgstr "None" - -#: static/horizon/js/horizon.networktopology.js:549 -msgid "Delete" -msgstr "Delete" - -#: static/horizon/js/horizon.networktopology.js:552 -msgid "STATUS" -msgstr "STATUS" - -#: static/horizon/js/horizon.networktopology.js:553 -msgid "ID" -msgstr "ID" - -#: static/horizon/js/horizon.networktopology.js:554 -msgid "Interfaces" -msgstr "Interfaces" - -#: static/horizon/js/horizon.networktopology.js:555 -msgid "Delete Interface" -msgstr "Delete Interface" - -#: static/horizon/js/horizon.networktopology.js:556 -msgid "Open Console" -msgstr "Open Console" - -#: static/horizon/js/horizon.networktopology.js:557 -msgid "View Details" -msgstr "View Details" - -#: static/horizon/js/horizon.networktopology.js:560 -msgid "Delete Router" -msgstr "Delete Router" - -#: static/horizon/js/horizon.networktopology.js:561 -msgid "View Router Details" -msgstr "View Router Details" - -#: static/horizon/js/horizon.networktopology.js:564 -msgid "Add Interface" -msgstr "Add Interface" - -#: static/horizon/js/horizon.networktopology.js:570 -msgid "Terminate Instance" -msgstr "Terminate Instance" - -#: static/horizon/js/horizon.networktopology.js:571 -msgid "View Instance Details" -msgstr "View Instance Details" - -#: static/horizon/js/horizon.tables.js:39 -#: static/horizon/js/horizon.tables.js:406 -msgid "No items to display." -msgstr "No items to display." - -#: static/horizon/js/horizon.tables.js:52 -#: static/horizon/js/horizon.tables.js:120 -msgid "An error occurred while updating." -msgstr "An error occurred while updating." - -#: static/horizon/js/horizon.tables.js:201 -#, c-format -msgid "You have selected %s. " -msgstr "You have selected %s. " - -#: static/horizon/js/horizon.tables.js:203 -#, c-format -msgid "Confirm %s" -msgstr "Confirm %s" - -#: static/horizon/js/horizon.tables.js:204 -msgid "Please confirm your selection. " -msgstr "Please confirm your selection. " - -#: static/horizon/js/horizon.tables_inline_edit.js:88 -#: static/horizon/js/horizon.tables_inline_edit.js:151 -msgid "Not authorized to do this operation." -msgstr "Not authorised to do this operation." - -#: static/horizon/js/horizon.users.js:18 -msgid "Passwords do not match." -msgstr "Passwords do not match." diff --git a/code/horizon/horizon/locale/es/LC_MESSAGES/django.po b/code/horizon/horizon/locale/es/LC_MESSAGES/django.po deleted file mode 100644 index 546f5f3f..00000000 --- a/code/horizon/horizon/locale/es/LC_MESSAGES/django.po +++ /dev/null @@ -1,514 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Alberto Molina Coballes , 2015 -# cametiope , 2014 -# Orizhial , 2015 -# Marian Tort , 2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-07 01:16-0500\n" -"PO-Revision-Date: 2015-04-20 07:07+0000\n" -"Last-Translator: Alberto Molina Coballes \n" -"Language-Team: Spanish (http://www.transifex.com/projects/p/horizon/language/es/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: es\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: base.py:475 -msgid "Other" -msgstr "Otro" - -#: browsers/base.py:88 -msgid "Navigation Item" -msgstr "Ítem de navegación" - -#: browsers/views.py:41 -#, python-format -msgid "Select a %s to browse." -msgstr "Seleccione una %s para navegar." - -#: conf/default.py:41 -msgid "Password is not accepted" -msgstr "La contraseña no se ha aceptado" - -#: decorators.py:53 -msgid "Please log in to continue." -msgstr "Inicie sesión para continuar." - -#: decorators.py:85 -#, python-format -msgid "You are not authorized to access %s" -msgstr "No está autorizado para acceder a %s" - -#: exceptions.py:163 -#, python-format -msgid "A %(resource)s with the name \"%(name)s\" already exists." -msgstr "Un %(resource)s con el nombre \"%(name)s\" ya existe." - -#: exceptions.py:235 -#, python-format -msgid "Unauthorized: %s" -msgstr "No autorizado: %s" - -#: exceptions.py:238 -msgid "Unauthorized. Please try logging in again." -msgstr "No autorizado. Inicie sesión de nuevo." - -#: forms/fields.py:64 -msgid "Incorrect format for IP address" -msgstr "Formato de dirección IP incorrecto" - -#: forms/fields.py:65 -msgid "Invalid version for IP address" -msgstr "Versión de dirección IP no válida" - -#: forms/fields.py:66 -msgid "Invalid subnet mask" -msgstr "Máscara de red no válida" - -#: forms/views.py:132 templates/horizon/common/_usage_summary.html:16 -msgid "Submit" -msgstr "Enviar" - -#: forms/views.py:133 -#: templates/horizon/common/_modal_form_update_metadata.html:25 -#: templates/horizon/common/_workflow.html:49 -msgid "Cancel" -msgstr "Cancelar " - -#: middleware.py:103 -msgid "Session timed out." -msgstr "La sesión ha expirado." - -#: tables/actions.py:460 -#: templates/horizon/common/_data_table_table_actions.html:21 -#: templates/horizon/common/_data_table_table_actions.html:33 -#: templates/horizon/common/_workflow_step_update_members.html:14 -#: templates/horizon/common/_workflow_step_update_members.html:23 -msgid "Filter" -msgstr "Filtrar" - -#: tables/actions.py:645 -msgid "This action cannot be undone." -msgstr "No se puede deshacer esta acción." - -#: tables/actions.py:767 -#, python-format -msgctxt "past" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:769 -#, python-format -msgctxt "present" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:832 -#, python-format -msgid "You are not allowed to %(action)s: %(objs)s" -msgstr "No le está permitido %(action)s: %(objs)s" - -#: tables/actions.py:839 -#, python-format -msgid "Unable to %(action)s: %(objs)s" -msgstr "No ha sido posible %(action)s: %(objs)s" - -#: tables/actions.py:845 -#, python-format -msgid "%(action)s: %(objs)s" -msgstr "%(action)s: %(objs)s" - -#: tables/actions.py:915 -msgid "Delete" -msgstr "Eliminar" - -#: tables/actions.py:917 -msgid "Deleted" -msgstr "Eliminado" - -#: tables/actions.py:948 -msgid "Update" -msgstr "Actualizar" - -#: tables/actions.py:949 -msgid "Updated" -msgstr "Actualizada" - -#: tables/base.py:305 -msgid "-" -msgstr "-" - -#: tables/base.py:361 -#, python-format -msgid "The attribute %(attr)s doesn't exist on %(obj)s." -msgstr "El atributo %(attr)s no existe en %(obj)s." - -#: tables/base.py:990 -msgid "No items to display." -msgstr "No hay ítems que mostrar." - -#: tables/base.py:1099 -#: templates/horizon/common/_data_table_table_actions.html:47 -msgid "Actions" -msgstr "Acciones" - -#: tables/base.py:1329 -#, python-format -msgid "No match returned for the id \"%s\"." -msgstr "Ninguna coincidencia para el id \"%s\"." - -#: tables/base.py:1486 -msgid "Please select a row before taking that action." -msgstr "Seleccione una fila antes de realizar la acción." - -#: tables/base.py:1570 -msgid "N/A" -msgstr "N/A" - -#: templates/_header.html:5 -#, python-format -msgid "Logged in as: %(username)s" -msgstr "Sesión iniciada como: %(username)s" - -#: templates/_header.html:7 -msgid "Help" -msgstr "Ayuda" - -#: templates/_header.html:9 -msgid "Sign Out" -msgstr "Salir" - -#: templates/auth/_description.html:9 -msgid "" -"\n" -" If you are not sure which authentication method to use, contact your administrator.\n" -" " -msgstr "\nSi no está seguro del método de autenticación a utilizar, contacte con su administrador." - -#: templates/auth/_login.html:5 -msgid "Log In" -msgstr "Iniciar sesión" - -#: templates/auth/_login.html:27 -msgid "You do not have permission to access the resource:" -msgstr "No tiene permisos para acceder al recurso:" - -#: templates/auth/_login.html:29 -#, python-format -msgid "" -"Login as different user or go back to home " -"page" -msgstr "Inicie sesión con otro usuario o volver a la página de inicio" - -#: templates/auth/_login.html:45 -msgid "Sign In" -msgstr "Iniciar sesión" - -#: templates/auth/_login.html:46 -msgid "Connect" -msgstr "Conectar" - -#: templates/auth/login.html:4 -msgid "Login" -msgstr "Usuario" - -#: templates/horizon/_messages.html:7 -msgid "Info: " -msgstr "Info:" - -#: templates/horizon/_messages.html:13 -msgid "Warning: " -msgstr "Advertencia:" - -#: templates/horizon/_messages.html:19 -msgid "Success: " -msgstr "Correcto:" - -#: templates/horizon/_messages.html:25 -msgid "Error: " -msgstr "Error: " - -#: templates/horizon/common/_data_table.html:63 -msgid "Summary" -msgstr "Resumen" - -#: templates/horizon/common/_data_table.html:72 -#, python-format -msgid "Displaying %(counter)s item" -msgid_plural "Displaying %(counter)s items" -msgstr[0] "Mostrando %(counter)s articulo" -msgstr[1] "Mostrando %(counter)s articulos" - -#: templates/horizon/common/_data_table.html:77 -msgid "« Prev" -msgstr "« Prev" - -#: templates/horizon/common/_data_table.html:80 -msgid "Next »" -msgstr "Siguiente »" - -#: templates/horizon/common/_data_table_table_actions.html:45 -msgid "More Actions" -msgstr "Más acciones" - -#: templates/horizon/common/_domain_page_header.html:6 -#, python-format -msgid "%(context_name)s:" -msgstr "%(context_name)s:" - -#: templates/horizon/common/_formset_table.html:35 -msgid "Add a row" -msgstr "Agregar una fila" - -#: templates/horizon/common/_formset_table_row.html:15 -#, python-format -msgid "%(name)s: %(error)s" -msgstr "%(name)s: %(error)s" - -#: templates/horizon/common/_limit_summary.html:4 -msgid "Limit Summary" -msgstr "Resumen" - -#: templates/horizon/common/_limit_summary.html:7 -msgid "Instances" -msgstr "Instancias" - -#: templates/horizon/common/_limit_summary.html:8 -#: templates/horizon/common/_limit_summary.html:15 -#: templates/horizon/common/_limit_summary.html:22 -#: templates/horizon/common/_limit_summary.html:36 -#: templates/horizon/common/_limit_summary.html:43 -#: templates/horizon/common/_limit_summary.html:50 -#, python-format -msgid "Used %(used)s of %(available)s " -msgstr " %(used)s usado de %(available)s " - -#: templates/horizon/common/_limit_summary.html:14 -msgid "VCPUs" -msgstr "VCPU" - -#: templates/horizon/common/_limit_summary.html:21 -msgid "RAM" -msgstr "RAM" - -#: templates/horizon/common/_limit_summary.html:28 -msgid "Floating IPs" -msgstr "IPs flotantes" - -#: templates/horizon/common/_limit_summary.html:29 -#, python-format -msgid "Allocated %(used)s of %(available)s " -msgstr "Asignados %(used)s de %(available)s " - -#: templates/horizon/common/_limit_summary.html:35 -msgid "Security Groups" -msgstr "Grupos de seguridad" - -#: templates/horizon/common/_limit_summary.html:42 -msgid "Volumes" -msgstr "Volúmenes" - -#: templates/horizon/common/_limit_summary.html:49 -msgid "Volume Storage" -msgstr "Almacenamiento de volúmenes" - -#: templates/horizon/common/_modal_form_update_metadata.html:24 -#: workflows/base.py:594 -msgid "Save" -msgstr "Guardar" - -#: templates/horizon/common/_resource_browser.html:10 -#, python-format -msgid "Displaying %(nav_items)s item" -msgid_plural "Displaying %(nav_items)s items" -msgstr[0] "Mostrando %(nav_items)s articulo" -msgstr[1] "Mostrando %(nav_items)s articulos" - -#: templates/horizon/common/_resource_browser.html:11 -#, python-format -msgid "Displaying %(content_items)s item" -msgid_plural "Displaying %(content_items)s items" -msgstr[0] "Mostrando %(content_items)s articulo" -msgstr[1] "Mostrando %(content_items)s articulos" - -#: templates/horizon/common/_usage_summary.html:3 -msgid "Usage Summary" -msgstr "Resumen del uso" - -#: templates/horizon/common/_usage_summary.html:7 -msgid "Select a period of time to query its usage:" -msgstr "Seleccione un periodo de tiempo para consultar su uso: " - -#: templates/horizon/common/_usage_summary.html:9 -#, python-format -msgid "" -"\n" -" %(start)s" -msgstr "\n %(start)s" - -#: templates/horizon/common/_usage_summary.html:13 -#, python-format -msgid "" -"\n" -" %(end)s" -msgstr "\n %(end)s" - -#: templates/horizon/common/_usage_summary.html:17 -msgid "The date should be in YYYY-mm-dd format." -msgstr "La fecha debe estar en formato AAAA-MM-DD." - -#: templates/horizon/common/_usage_summary.html:20 -msgid "Active Instances:" -msgstr "Instancias activas:" - -#: templates/horizon/common/_usage_summary.html:21 -msgid "Active RAM:" -msgstr "RAM activa:" - -#: templates/horizon/common/_usage_summary.html:22 -msgid "This Period's VCPU-Hours:" -msgstr "Este periodo en horas VCPU:" - -#: templates/horizon/common/_usage_summary.html:23 -msgid "This Period's GB-Hours:" -msgstr "Este periodo en horas GB:" - -#: templates/horizon/common/_usage_summary.html:24 -msgid "This Period's RAM-Hours:" -msgstr "Horas-RAM de este periodo:" - -#: templates/horizon/common/_workflow.html:40 -msgid "Back" -msgstr "Anterior" - -#: templates/horizon/common/_workflow.html:43 -msgid "Next" -msgstr "Siguiente" - -#: templatetags/branding.py:34 -msgid "Horizon" -msgstr "Horizon" - -#: templatetags/horizon.py:137 templatetags/horizon.py:148 -msgid "No Limit" -msgstr "Sin límite" - -#: templatetags/horizon.py:140 templatetags/horizon.py:142 -msgid "Available" -msgstr "Disponible" - -#: templatetags/sizeformat.py:51 templatetags/sizeformat.py:56 -#, python-format -msgid "%(size)d Byte" -msgid_plural "%(size)d Bytes" -msgstr[0] "%(size)d bite" -msgstr[1] "%(size)d bites" - -#: templatetags/sizeformat.py:59 -#, python-format -msgid "%s KB" -msgstr "%s KB" - -#: templatetags/sizeformat.py:61 -#, python-format -msgid "%s MB" -msgstr "%s MB" - -#: templatetags/sizeformat.py:63 -#, python-format -msgid "%s GB" -msgstr "%s GB" - -#: templatetags/sizeformat.py:65 -#, python-format -msgid "%s TB" -msgstr "%s TB" - -#: templatetags/sizeformat.py:66 -#, python-format -msgid "%s PB" -msgstr "%s PB" - -#: templatetags/sizeformat.py:74 -msgid "0 Bytes" -msgstr "0 Bytes" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:31 -msgid "Sell Puppy" -msgid_plural "Sell Puppies" -msgstr[0] "Vender Mascota" -msgstr[1] "Vender Mascotas" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:40 -msgid "Sold Puppy" -msgid_plural "Sold Puppies" -msgstr[0] "Mascota Vendida" -msgstr[1] "Mascotas Vendidas" - -#: test/tests/views.py:59 -msgid "Fake" -msgstr "Falso" - -#: utils/filters.py:49 -msgid "Never" -msgstr "Nunca" - -#: utils/validators.py:26 utils/validators.py:50 -msgid "Not a valid port number" -msgstr "Número de puerto no válido" - -#: utils/validators.py:31 -msgid "Not a valid IP protocol number" -msgstr "Número de protocolo IP no válido" - -#: utils/validators.py:45 -msgid "One colon allowed in port range" -msgstr "Un punto permitido en el rango de puerto" - -#: utils/validators.py:52 -msgid "Port number must be integer" -msgstr "El número de puerto debe ser un entero" - -#: utils/validators.py:59 -msgid "The string may only contain ASCII printable characters." -msgstr "La cadena sólo puede incluir caracteres imprimibles ASCII." - -#: workflows/base.py:71 -msgid "Processing..." -msgstr "Procesando..." - -#: workflows/base.py:475 -msgid "All available" -msgstr "Todos los disponibles" - -#: workflows/base.py:476 -msgid "Members" -msgstr "Miembros" - -#: workflows/base.py:477 -msgid "None available." -msgstr "Ninguno disponible." - -#: workflows/base.py:478 -msgid "No members." -msgstr "Sin miembros." - -#: workflows/base.py:595 -#, python-format -msgid "%s completed successfully." -msgstr "%s completado correctamente." - -#: workflows/base.py:596 -#, python-format -msgid "%s did not complete." -msgstr "%s no completado." diff --git a/code/horizon/horizon/locale/es/LC_MESSAGES/djangojs.po b/code/horizon/horizon/locale/es/LC_MESSAGES/djangojs.po deleted file mode 100644 index 3497f420..00000000 --- a/code/horizon/horizon/locale/es/LC_MESSAGES/djangojs.po +++ /dev/null @@ -1,621 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Alberto Molina Coballes , 2015 -# cametiope , 2014 -# Marian Tort , 2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-12 01:16-0500\n" -"PO-Revision-Date: 2015-04-20 07:06+0000\n" -"Last-Translator: Alberto Molina Coballes \n" -"Language-Team: Spanish (http://www.transifex.com/projects/p/horizon/language/es/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: es\n" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" - -#: static/angular/action-list/button-tooltip.js:15 -msgid "" -"The action cannot be performed. The contents of this row have errors or are " -"missing information." -msgstr "Esta acción no se puede llevar a cabo. Esta columna contiene errores o carece de información." - -#: static/angular/metadata-display/metadata-display.js:33 -msgid "Detail Information" -msgstr "Información detallada" - -#: static/angular/metadata-tree/metadata-tree.js:35 -msgid "" -"You can specify resource metadata by moving items from the left column to " -"the right column. In the left columns there are metadata definitions from " -"the Glance Metadata Catalog. Use the \"Other\" option to add metadata with " -"the key of your choice." -msgstr "Puede especificar los metadatos de los recursos moviendo los ítems de la columna de la izquierda a la de la derecha. En las columnas de la izquierda hay definiciones de metadatos del Glance Metadata Catalog. Utilice la opcion \"Otro\" para añadir metadatos con la clave que desee. " - -#: static/angular/metadata-tree/metadata-tree.js:36 -msgid "Min" -msgstr "Mín." - -#: static/angular/metadata-tree/metadata-tree.js:37 -msgid "Max" -msgstr "Máx." - -#: static/angular/metadata-tree/metadata-tree.js:38 -msgid "Min length" -msgstr "Longitud mín." - -#: static/angular/metadata-tree/metadata-tree.js:39 -msgid "Max length" -msgstr "Longitud máx." - -#: static/angular/metadata-tree/metadata-tree.js:40 -msgid "Pattern mismatch" -msgstr "Discrepancia en el patrón" - -#: static/angular/metadata-tree/metadata-tree.js:41 -msgid "Integer required" -msgstr "Entero obligatorio" - -#: static/angular/metadata-tree/metadata-tree.js:42 -msgid "Decimal required" -msgstr "Decimal obligatorio" - -#: static/angular/metadata-tree/metadata-tree.js:43 -msgid "Required" -msgstr "Obligatorio" - -#: static/angular/metadata-tree/metadata-tree.js:44 -msgid "Duplicate keys are not allowed" -msgstr "Las claves duplicadas no están permitidas" - -#: static/angular/metadata-tree/metadata-tree.js:45 -#: static/angular/table/basic-table.js:6 -#: static/horizon/js/horizon.forms.js:184 -msgid "Filter" -msgstr "Filtrar" - -#: static/angular/metadata-tree/metadata-tree.js:46 -msgid "Available Metadata" -msgstr "Metadatos disponibles" - -#: static/angular/metadata-tree/metadata-tree.js:47 -msgid "Existing Metadata" -msgstr "Metadatos existentes" - -#: static/angular/metadata-tree/metadata-tree.js:48 -msgid "Custom" -msgstr "Personalizar" - -#: static/angular/metadata-tree/metadata-tree.js:49 -msgid "No available metadata" -msgstr "Metadatos no disponibles" - -#: static/angular/metadata-tree/metadata-tree.js:50 -msgid "No existing metadata" -msgstr "No hay metadatos existentes" - -#: static/angular/modal/modal.js:83 -msgid "Submit" -msgstr "Enviar" - -#: static/angular/modal/modal.js:84 static/angular/wizard/wizard.js:11 -#: static/horizon/js/horizon.modals.js:33 -msgid "Cancel" -msgstr "Cancelar " - -#: static/angular/transfer-table/transfer-table.js:39 -msgid "Allocated" -msgstr "Asignados" - -#: static/angular/transfer-table/transfer-table.js:40 -msgid "Available" -msgstr "Disponible" - -#: static/angular/transfer-table/transfer-table.js:41 -msgid "Select one" -msgstr "Seleccione uno" - -#: static/angular/transfer-table/transfer-table.js:42 -msgid "Select an item from Available items below" -msgstr "Seleccione un ítem de los disponibles abajo" - -#: static/angular/transfer-table/transfer-table.js:43 -msgid "No available items" -msgstr "No hay ítems disponibles" - -#: static/angular/transfer-table/transfer-table.js:44 -msgid "Expand to see allocated items" -msgstr "Expandir para ver los ítems asociados" - -#: static/angular/transfer-table/transfer-table.js:45 -msgid "Expand to see available items" -msgstr "Expandir para ver los ítems disponibles" - -#: static/angular/transfer-table/transfer-table.js:46 -msgid "Click to show or hide" -msgstr "Haga click para mostrar u ocultar" - -#: static/angular/transfer-table/transfer-table.js:47 -msgid "Re-order items using drag and drop" -msgstr "Reordene los ítems arrastrando y soltando." - -#: static/angular/transfer-table/transfer-table.js:48 -msgid "Click to see more details" -msgstr "Haga click para ver más detalles" - -#: static/angular/transfer-table/transfer-table.js:100 -msgid "Found %(found)s of %(total)s" -msgstr "%(found)s de %(total)s encontrado" - -#: static/angular/transfer-table/transfer-table.js:166 -msgid "Click here to expand the row and view the errors." -msgstr "Haga click aquí para ver los errores." - -#: static/angular/wizard/wizard.js:12 -msgid "Back" -msgstr "Anterior" - -#: static/angular/wizard/wizard.js:13 -msgid "Next" -msgstr "Siguiente" - -#: static/angular/wizard/wizard.js:14 -msgid "Finish" -msgstr "Finalizar" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Connecting" -msgstr "Conectando" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Open" -msgstr "Abierta" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closing" -msgstr "Cerrando" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closed" -msgstr "Cerrada" - -#: static/horizon/js/angular/directives/serialConsole.js:85 -#, c-format -msgid "Status: %s" -msgstr "Estado: %s" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "Yes" -msgstr "Sí" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "No" -msgstr "No" - -#: static/horizon/js/angular/filters/filters.js:53 -#: static/horizon/js/angular/filters/filters.js:140 -#, c-format -msgid "%s GB" -msgstr "%s GB" - -#: static/horizon/js/angular/filters/filters.js:70 -#: static/horizon/js/angular/filters/filters.js:142 -#, c-format -msgid "%s MB" -msgstr "%s MB" - -#: static/horizon/js/angular/filters/filters.js:138 -#, c-format -msgid "%s TB" -msgstr "%s TB" - -#: static/horizon/js/angular/filters/filters.js:144 -#, c-format -msgid "%s KB" -msgstr "%s KB" - -#: static/horizon/js/angular/filters/filters.js:146 -#, c-format -msgid "%s bytes" -msgstr "%s bytes" - -#: static/horizon/js/angular/filters/filters.js:163 -#: static/horizon/js/horizon.tables.js:393 -#, c-format -msgid "Displaying %s item" -msgid_plural "Displaying %s items" -msgstr[0] "Mostrando %s articulo" -msgstr[1] "Mostrando %s articulos" - -#: static/horizon/js/angular/services/hz.api.cinder.js:47 -msgid "Unable to retrieve volumes." -msgstr "No ha sido posible obtener volúmenes." - -#: static/horizon/js/angular/services/hz.api.cinder.js:74 -msgid "Unable to retrieve volume snapshots." -msgstr "No ha sido posible obtener las snapshots de volúmenes." - -#: static/horizon/js/angular/services/hz.api.config.js:43 -msgid "Unable to retrieve user configuration." -msgstr "No ha sido posible obtener la configuración de usuario." - -#: static/horizon/js/angular/services/hz.api.config.js:62 -msgid "Unable to retrieve admin configuration." -msgstr "No ha sido posible obtener la configuración de admin." - -#: static/horizon/js/angular/services/hz.api.config.js:105 -msgid "Unable to retrieve settings." -msgstr "No ha sido posible obtener los ajustes." - -#: static/horizon/js/angular/services/hz.api.config.js:289 -msgid "Setting is not enabled: %(setting)s" -msgstr "Ajuste no habilitado: %(setting)s" - -#: static/horizon/js/angular/services/hz.api.glance.js:38 -msgid "Unable to retrieve image." -msgstr "No ha sido posible obtener la imagen." - -#: static/horizon/js/angular/services/hz.api.glance.js:81 -msgid "Unable to retrieve images." -msgstr "No ha sido posible obtener las imágenes." - -#: static/horizon/js/angular/services/hz.api.glance.js:144 -msgid "Unable to retrieve namespaces." -msgstr "No ha sido posible obtener los espacios de nombres." - -#: static/horizon/js/angular/services/hz.api.keystone.js:24 -msgid "Unable to retrieve users" -msgstr "No ha sido posible obtener los usuarios" - -#: static/horizon/js/angular/services/hz.api.keystone.js:31 -msgid "Unable to create the user." -msgstr "No ha sido posible crear el usuario." - -#: static/horizon/js/angular/services/hz.api.keystone.js:38 -msgid "Unable to delete the users." -msgstr "No ha sido posible borrar los usuarios." - -#: static/horizon/js/angular/services/hz.api.keystone.js:73 -msgid "Unable to retrieve the current user session." -msgstr "No ha sido posible obtener la sesión de usuario actual." - -#: static/horizon/js/angular/services/hz.api.keystone.js:80 -msgid "Unable to retrieve the user" -msgstr "No ha sido posible obtener el usuario" - -#: static/horizon/js/angular/services/hz.api.keystone.js:88 -msgid "Unable to edit the user." -msgstr "No ha sido posible editar el usuario." - -#: static/horizon/js/angular/services/hz.api.keystone.js:95 -msgid "Unable to delete the user." -msgstr "No ha sido posible borrar el usuario." - -#: static/horizon/js/angular/services/hz.api.keystone.js:103 -msgid "Unable to retrieve role" -msgstr "No ha sido posible obtener el rol" - -#: static/horizon/js/angular/services/hz.api.keystone.js:110 -msgid "Unable to create the role." -msgstr "No ha sido posible crear el rol." - -#: static/horizon/js/angular/services/hz.api.keystone.js:117 -msgid "Unable to delete the roles." -msgstr "No ha sido posible borrar los roles." - -#: static/horizon/js/angular/services/hz.api.keystone.js:124 -msgid "Unable to retrieve the role" -msgstr "No ha sido posible obtener el rol" - -#: static/horizon/js/angular/services/hz.api.keystone.js:132 -msgid "Unable to edit the role." -msgstr "No ha sido posible editar el rol." - -#: static/horizon/js/angular/services/hz.api.keystone.js:139 -msgid "Unable to delete the role." -msgstr "No ha sido posible borrar el rol." - -#: static/horizon/js/angular/services/hz.api.keystone.js:147 -msgid "Unable to retrieve domains" -msgstr "No ha sido posible obtener los dominios" - -#: static/horizon/js/angular/services/hz.api.keystone.js:154 -msgid "Unable to create the domain." -msgstr "No ha sido posible crear el dominio." - -#: static/horizon/js/angular/services/hz.api.keystone.js:161 -msgid "Unable to delete the domains." -msgstr "No ha sido posible borrar los dominios." - -#: static/horizon/js/angular/services/hz.api.keystone.js:168 -msgid "Unable to retrieve the domain" -msgstr "No ha sido posible obtener el dominio" - -#: static/horizon/js/angular/services/hz.api.keystone.js:176 -msgid "Unable to edit the domain." -msgstr "No ha sido posible editar el dominio." - -#: static/horizon/js/angular/services/hz.api.keystone.js:183 -msgid "Unable to delete the domain." -msgstr "No ha sido posible borrar el dominio." - -#: static/horizon/js/angular/services/hz.api.keystone.js:192 -msgid "Unable to retrieve projects" -msgstr "No ha sido posible obtener los proyectos" - -#: static/horizon/js/angular/services/hz.api.keystone.js:199 -msgid "Unable to create the project." -msgstr "No ha sido posible crear el proyecto." - -#: static/horizon/js/angular/services/hz.api.keystone.js:206 -msgid "Unable to delete the projects." -msgstr "No ha sido posible borrar los proyectos." - -#: static/horizon/js/angular/services/hz.api.keystone.js:213 -msgid "Unable to retrieve the project" -msgstr "No ha sido posible obtener el proyecto" - -#: static/horizon/js/angular/services/hz.api.keystone.js:221 -msgid "Unable to edit the project." -msgstr "No ha sido posible editar el proyecto." - -#: static/horizon/js/angular/services/hz.api.keystone.js:228 -msgid "Unable to delete the project." -msgstr "No ha sido posible borrar el proyecto." - -#: static/horizon/js/angular/services/hz.api.keystone.js:236 -msgid "Unable to grant the role." -msgstr "No ha sido posible asignar el rol." - -#: static/horizon/js/angular/services/hz.api.keystone.js:250 -msgid "Unable to fetch the service catalog." -msgstr "No ha sido posible obtener el catálogo de servicios." - -#: static/horizon/js/angular/services/hz.api.keystone.js:385 -msgid "Service type is not enabled: %(desiredType)s" -msgstr "Tipo de servicio no habilitado: %(desiredType)s" - -#: static/horizon/js/angular/services/hz.api.keystone.js:392 -msgid "Cannot get service catalog from keystone." -msgstr "No se puede obtener el catálogo de servicios desde keystone." - -#: static/horizon/js/angular/services/hz.api.neutron.js:39 -msgid "Unable to retrieve networks." -msgstr "No ha sido posible obtener las redes." - -#: static/horizon/js/angular/services/hz.api.neutron.js:88 -msgid "Unable to create the network." -msgstr "No ha sido posible crear la red." - -#: static/horizon/js/angular/services/hz.api.neutron.js:108 -msgid "Unable to retrieve subnets." -msgstr "No ha sido posible obtener las subredes." - -#: static/horizon/js/angular/services/hz.api.neutron.js:172 -msgid "Unable to create the subnet." -msgstr "No ha sido posible crear la subred." - -#: static/horizon/js/angular/services/hz.api.neutron.js:192 -msgid "Unable to retrieve ports." -msgstr "No ha sido posible obtener los puertos." - -#: static/horizon/js/angular/services/hz.api.nova.js:40 -msgid "Unable to retrieve keypairs." -msgstr "No ha sido posible obtener los pares de claves." - -#: static/horizon/js/angular/services/hz.api.nova.js:62 -msgid "Unable to import the keypair." -msgstr "No ha sido posible importar el par de claves." - -#: static/horizon/js/angular/services/hz.api.nova.js:64 -msgid "Unable to create the keypair." -msgstr "No ha sido posible crear el par de claves." - -#: static/horizon/js/angular/services/hz.api.nova.js:83 -msgid "Unable to retrieve availability zones." -msgstr "No ha sido posible obtener las zonas de disponibilidad." - -#: static/horizon/js/angular/services/hz.api.nova.js:121 -msgid "Unable to retrieve limits." -msgstr "No ha sido posible obtener los límites." - -#: static/horizon/js/angular/services/hz.api.nova.js:148 -msgid "Unable to create the server." -msgstr "No ha sido posible crear el servidor." - -#: static/horizon/js/angular/services/hz.api.nova.js:162 -msgid "Unable to retrieve server." -msgstr "No ha sido posible obtener el servidor." - -#: static/horizon/js/angular/services/hz.api.nova.js:192 -msgid "Unable to retrieve extensions." -msgstr "No ha sido posible obtener las extensiones." - -#: static/horizon/js/angular/services/hz.api.nova.js:237 -msgid "Unable to retrieve flavors." -msgstr "No ha sido posible obtener los sabores." - -#: static/horizon/js/angular/services/hz.api.nova.js:255 -msgid "Unable to retrieve flavor." -msgstr "No ha sido posible obtener el sabor." - -#: static/horizon/js/angular/services/hz.api.nova.js:269 -msgid "Unable to retrieve flavor extra specs." -msgstr "No ha sido posible obtener las especificaciones extra del sabor." - -#: static/horizon/js/angular/services/hz.api.nova.js:311 -msgid "Extension is not enabled: %(extension)s" -msgstr "Extensión no habilitada: %(extension)s" - -#: static/horizon/js/angular/services/hz.api.nova.js:318 -msgid "Cannot get nova extension list." -msgstr "No se puede obtener la lista de extensiones de nova." - -#: static/horizon/js/angular/services/hz.api.policy.js:65 -msgid "Policy check failed." -msgstr "Ha fallado la comprobación de política." - -#: static/horizon/js/angular/services/hz.api.security-group.js:64 -msgid "Unable to retrieve security groups." -msgstr "No ha sido posible obtener los grupos de seguridad." - -#: static/horizon/js/horizon.accordion_nav.js:78 -#: static/horizon/js/horizon.modals.js:315 -#: static/horizon/js/horizon.tabs.js:21 -msgid "Loading" -msgstr "Cargando" - -#: static/horizon/js/horizon.d3linechart.js:394 -#: static/horizon/js/horizon.d3linechart.js:404 -msgid "No data available." -msgstr "No hay datos disponibles." - -#: static/horizon/js/horizon.d3linechart.js:410 -#: static/horizon/js/horizon.modals.js:334 -#: static/horizon/js/horizon.tables_inline_edit.js:94 -#: static/horizon/js/horizon.tables_inline_edit.js:157 -msgid "An error occurred. Please try again later." -msgstr "Ha ocurrido un error. Inténtelo de nuevo más tarde." - -#: static/horizon/js/horizon.firewalls.js:32 -#: static/horizon/js/horizon.instances.js:31 -msgid "There was a problem communicating with the server, please try again." -msgstr "Ha ocurrido un problema en la comunicación con el servidor, inténtelo de nuevo." - -#: static/horizon/js/horizon.instances.js:273 -msgid "Could not read the file" -msgstr "No se ha podido leer el fichero" - -#: static/horizon/js/horizon.instances.js:279 -#: static/horizon/js/horizon.instances.js:308 -msgid "Could not decrypt the password" -msgstr "No se ha podido descifrar la contraseña" - -#: static/horizon/js/horizon.membership.js:190 -msgid "No roles" -msgstr "Sin roles" - -#: static/horizon/js/horizon.membership.js:222 -msgid "Roles" -msgstr "Roles" - -#: static/horizon/js/horizon.messages.js:9 -msgid "Danger: " -msgstr "Peligro:" - -#: static/horizon/js/horizon.messages.js:10 -msgid "Warning: " -msgstr "Advertencia:" - -#: static/horizon/js/horizon.messages.js:11 -msgid "Notice: " -msgstr "Aviso:" - -#: static/horizon/js/horizon.messages.js:12 -msgid "Success: " -msgstr "Correcto:" - -#: static/horizon/js/horizon.messages.js:13 -msgid "Error: " -msgstr "Error: " - -#: static/horizon/js/horizon.modals.js:229 -#: static/horizon/js/horizon.tables.js:218 -msgid "Working" -msgstr "Trabajando" - -#: static/horizon/js/horizon.modals.js:263 -msgid "There was an error submitting the form. Please try again." -msgstr "Ha ocurrido un error al enviar el formulario. Inténtelo de nuevo." - -#: static/horizon/js/horizon.networktopology.js:530 -#: static/horizon/js/horizon.networktopology.js:536 -msgid "None" -msgstr "Ninguno" - -#: static/horizon/js/horizon.networktopology.js:549 -msgid "Delete" -msgstr "Eliminar" - -#: static/horizon/js/horizon.networktopology.js:552 -msgid "STATUS" -msgstr "ESTADO" - -#: static/horizon/js/horizon.networktopology.js:553 -msgid "ID" -msgstr "ID" - -#: static/horizon/js/horizon.networktopology.js:554 -msgid "Interfaces" -msgstr "Interfaces" - -#: static/horizon/js/horizon.networktopology.js:555 -msgid "Delete Interface" -msgstr "Eliminar interfaz" - -#: static/horizon/js/horizon.networktopology.js:556 -msgid "Open Console" -msgstr "Abrir consola" - -#: static/horizon/js/horizon.networktopology.js:557 -msgid "View Details" -msgstr "Ver detalles" - -#: static/horizon/js/horizon.networktopology.js:560 -msgid "Delete Router" -msgstr "Eliminar router" - -#: static/horizon/js/horizon.networktopology.js:561 -msgid "View Router Details" -msgstr "Ver detalles del router" - -#: static/horizon/js/horizon.networktopology.js:564 -msgid "Add Interface" -msgstr "Añadir interfaz" - -#: static/horizon/js/horizon.networktopology.js:570 -msgid "Terminate Instance" -msgstr "Terminar instancia" - -#: static/horizon/js/horizon.networktopology.js:571 -msgid "View Instance Details" -msgstr "Ver detalles de la instancia" - -#: static/horizon/js/horizon.tables.js:39 -#: static/horizon/js/horizon.tables.js:406 -msgid "No items to display." -msgstr "No hay ítems que mostrar." - -#: static/horizon/js/horizon.tables.js:52 -#: static/horizon/js/horizon.tables.js:120 -msgid "An error occurred while updating." -msgstr "Ha ocurrido un error durante la actualización." - -#: static/horizon/js/horizon.tables.js:201 -#, c-format -msgid "You have selected %s. " -msgstr "Ha seleccionado %s." - -#: static/horizon/js/horizon.tables.js:203 -#, c-format -msgid "Confirm %s" -msgstr "Confirmar %s" - -#: static/horizon/js/horizon.tables.js:204 -msgid "Please confirm your selection. " -msgstr "Confirme su selección." - -#: static/horizon/js/horizon.tables_inline_edit.js:88 -#: static/horizon/js/horizon.tables_inline_edit.js:151 -msgid "Not authorized to do this operation." -msgstr "No tiene autorización para realizar esta operación." - -#: static/horizon/js/horizon.users.js:18 -msgid "Passwords do not match." -msgstr "Las contraseñas no coinciden." diff --git a/code/horizon/horizon/locale/fr/LC_MESSAGES/django.po b/code/horizon/horizon/locale/fr/LC_MESSAGES/django.po deleted file mode 100644 index ea971aee..00000000 --- a/code/horizon/horizon/locale/fr/LC_MESSAGES/django.po +++ /dev/null @@ -1,514 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Bruno Cornec , 2015 -# François Bureau, 2015 -# Frédéric , 2014 -# Maxime COQUEREL , 2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-06 21:07-0500\n" -"PO-Revision-Date: 2015-04-03 13:28+0000\n" -"Last-Translator: François Bureau\n" -"Language-Team: French (http://www.transifex.com/projects/p/horizon/language/fr/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: fr\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: base.py:475 -msgid "Other" -msgstr "Autre" - -#: browsers/base.py:88 -msgid "Navigation Item" -msgstr "Elément de navigation" - -#: browsers/views.py:41 -#, python-format -msgid "Select a %s to browse." -msgstr "Sélectionner une %s à parcourir." - -#: conf/default.py:41 -msgid "Password is not accepted" -msgstr "Le mot de passe n'est pas accepté" - -#: decorators.py:53 -msgid "Please log in to continue." -msgstr "Merci de vous connecter pour continuer." - -#: decorators.py:85 -#, python-format -msgid "You are not authorized to access %s" -msgstr "Vous n'êtes pas autorisé à accéder à %s" - -#: exceptions.py:163 -#, python-format -msgid "A %(resource)s with the name \"%(name)s\" already exists." -msgstr "Des %(resource)s avec le nom \"%(name)s\" existent déjà." - -#: exceptions.py:235 -#, python-format -msgid "Unauthorized: %s" -msgstr "%s : non autorisé" - -#: exceptions.py:238 -msgid "Unauthorized. Please try logging in again." -msgstr "Accès non autorisé. Merci de vous reconnecter." - -#: forms/fields.py:64 -msgid "Incorrect format for IP address" -msgstr "Format d'adresse IP incorrect" - -#: forms/fields.py:65 -msgid "Invalid version for IP address" -msgstr "Version d'adresse IP invalide" - -#: forms/fields.py:66 -msgid "Invalid subnet mask" -msgstr "Masque de sous-réseau invalide" - -#: forms/views.py:132 templates/horizon/common/_usage_summary.html:16 -msgid "Submit" -msgstr "Envoyer" - -#: forms/views.py:133 -#: templates/horizon/common/_modal_form_update_metadata.html:25 -#: templates/horizon/common/_workflow.html:49 -msgid "Cancel" -msgstr "Annuler" - -#: middleware.py:103 -msgid "Session timed out." -msgstr "La session a expiré." - -#: tables/actions.py:460 -#: templates/horizon/common/_data_table_table_actions.html:21 -#: templates/horizon/common/_data_table_table_actions.html:33 -#: templates/horizon/common/_workflow_step_update_members.html:14 -#: templates/horizon/common/_workflow_step_update_members.html:23 -msgid "Filter" -msgstr "Filtrer" - -#: tables/actions.py:645 -msgid "This action cannot be undone." -msgstr "Cette action ne peut pas être réalisée." - -#: tables/actions.py:767 -#, python-format -msgctxt "past" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:769 -#, python-format -msgctxt "present" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:832 -#, python-format -msgid "You are not allowed to %(action)s: %(objs)s" -msgstr "Vous n'êtes pas autorisé à %(action)s : %(objs)s" - -#: tables/actions.py:839 -#, python-format -msgid "Unable to %(action)s: %(objs)s" -msgstr "Impossible de %(action)s : %(objs)s" - -#: tables/actions.py:845 -#, python-format -msgid "%(action)s: %(objs)s" -msgstr "%(action)s : %(objs)s" - -#: tables/actions.py:915 -msgid "Delete" -msgstr "Supprimer" - -#: tables/actions.py:917 -msgid "Deleted" -msgstr "Supprimée" - -#: tables/actions.py:948 -msgid "Update" -msgstr "Mettre à jour" - -#: tables/actions.py:949 -msgid "Updated" -msgstr "Mis à jour" - -#: tables/base.py:305 -msgid "-" -msgstr "-" - -#: tables/base.py:361 -#, python-format -msgid "The attribute %(attr)s doesn't exist on %(obj)s." -msgstr "L'attribut %(attr)s n'existe pas sur %(obj)s." - -#: tables/base.py:990 -msgid "No items to display." -msgstr "Aucun élément à afficher." - -#: tables/base.py:1099 -#: templates/horizon/common/_data_table_table_actions.html:47 -msgid "Actions" -msgstr "Actions" - -#: tables/base.py:1329 -#, python-format -msgid "No match returned for the id \"%s\"." -msgstr "Aucun résultat retourné pour l'id \"%s\"." - -#: tables/base.py:1486 -msgid "Please select a row before taking that action." -msgstr "Merci de sélectionner une ligne avant de faire cette action." - -#: tables/base.py:1570 -msgid "N/A" -msgstr "N/D" - -#: templates/_header.html:5 -#, python-format -msgid "Logged in as: %(username)s" -msgstr "Utilisateur connecté : %(username)s" - -#: templates/_header.html:7 -msgid "Help" -msgstr "Aide" - -#: templates/_header.html:9 -msgid "Sign Out" -msgstr "Se déconnecter" - -#: templates/auth/_description.html:9 -msgid "" -"\n" -" If you are not sure which authentication method to use, contact your administrator.\n" -" " -msgstr "\nSi vous n'êtes pas sûr de la méthode d'identification à utiliser, veuillez contacter votre administrateur" - -#: templates/auth/_login.html:5 -msgid "Log In" -msgstr "Se connecter" - -#: templates/auth/_login.html:27 -msgid "You do not have permission to access the resource:" -msgstr "Vous n'avez pas la permission d'accéder à la ressource :" - -#: templates/auth/_login.html:29 -#, python-format -msgid "" -"Login as different user or go back to home " -"page" -msgstr "Connectez-vous avec un autre nom d'utilisateur ou revenez à la page d’accueil" - -#: templates/auth/_login.html:45 -msgid "Sign In" -msgstr "Se connecter" - -#: templates/auth/_login.html:46 -msgid "Connect" -msgstr "Connection" - -#: templates/auth/login.html:4 -msgid "Login" -msgstr "Identifiant" - -#: templates/horizon/_messages.html:7 -msgid "Info: " -msgstr "Information :" - -#: templates/horizon/_messages.html:13 -msgid "Warning: " -msgstr "Avertissement :" - -#: templates/horizon/_messages.html:19 -msgid "Success: " -msgstr "Succès :" - -#: templates/horizon/_messages.html:25 -msgid "Error: " -msgstr "Erreur :" - -#: templates/horizon/common/_data_table.html:63 -msgid "Summary" -msgstr "Résumé" - -#: templates/horizon/common/_data_table.html:72 -#, python-format -msgid "Displaying %(counter)s item" -msgid_plural "Displaying %(counter)s items" -msgstr[0] "Affichage de %(counter)s item" -msgstr[1] "Affichage de %(counter)s items" - -#: templates/horizon/common/_data_table.html:77 -msgid "« Prev" -msgstr "« Aperçu" - -#: templates/horizon/common/_data_table.html:80 -msgid "Next »" -msgstr "Suivant »" - -#: templates/horizon/common/_data_table_table_actions.html:45 -msgid "More Actions" -msgstr "Plus d'Actions" - -#: templates/horizon/common/_domain_page_header.html:6 -#, python-format -msgid "%(context_name)s:" -msgstr "%(context_name)s : " - -#: templates/horizon/common/_formset_table.html:35 -msgid "Add a row" -msgstr "Ajouter une ligne" - -#: templates/horizon/common/_formset_table_row.html:15 -#, python-format -msgid "%(name)s: %(error)s" -msgstr "%(name)s : %(error)s" - -#: templates/horizon/common/_limit_summary.html:4 -msgid "Limit Summary" -msgstr "Synthèse des Quotas" - -#: templates/horizon/common/_limit_summary.html:7 -msgid "Instances" -msgstr "Instances" - -#: templates/horizon/common/_limit_summary.html:8 -#: templates/horizon/common/_limit_summary.html:15 -#: templates/horizon/common/_limit_summary.html:22 -#: templates/horizon/common/_limit_summary.html:36 -#: templates/horizon/common/_limit_summary.html:43 -#: templates/horizon/common/_limit_summary.html:50 -#, python-format -msgid "Used %(used)s of %(available)s " -msgstr " %(used)s utilisé(es) sur %(available)s " - -#: templates/horizon/common/_limit_summary.html:14 -msgid "VCPUs" -msgstr "VCPUs" - -#: templates/horizon/common/_limit_summary.html:21 -msgid "RAM" -msgstr "RAM" - -#: templates/horizon/common/_limit_summary.html:28 -msgid "Floating IPs" -msgstr "IP flottantes" - -#: templates/horizon/common/_limit_summary.html:29 -#, python-format -msgid "Allocated %(used)s of %(available)s " -msgstr "Alloué %(used)s de %(available)s " - -#: templates/horizon/common/_limit_summary.html:35 -msgid "Security Groups" -msgstr "Groupes de sécurité" - -#: templates/horizon/common/_limit_summary.html:42 -msgid "Volumes" -msgstr "Volumes" - -#: templates/horizon/common/_limit_summary.html:49 -msgid "Volume Storage" -msgstr "Stockage de volumes" - -#: templates/horizon/common/_modal_form_update_metadata.html:24 -#: workflows/base.py:594 -msgid "Save" -msgstr "Enregistrer" - -#: templates/horizon/common/_resource_browser.html:10 -#, python-format -msgid "Displaying %(nav_items)s item" -msgid_plural "Displaying %(nav_items)s items" -msgstr[0] "Affichage de l'item %(nav_items)s" -msgstr[1] "Affichage des items %(nav_items)s" - -#: templates/horizon/common/_resource_browser.html:11 -#, python-format -msgid "Displaying %(content_items)s item" -msgid_plural "Displaying %(content_items)s items" -msgstr[0] "Affichage de l'item %(content_items)s" -msgstr[1] "Affichage des items %(content_items)s" - -#: templates/horizon/common/_usage_summary.html:3 -msgid "Usage Summary" -msgstr "Résumé de l'Utilisation" - -#: templates/horizon/common/_usage_summary.html:7 -msgid "Select a period of time to query its usage:" -msgstr "Sélectionnez une période de temps pour interroger son utilisation :" - -#: templates/horizon/common/_usage_summary.html:9 -#, python-format -msgid "" -"\n" -" %(start)s" -msgstr "\n %(start)s" - -#: templates/horizon/common/_usage_summary.html:13 -#, python-format -msgid "" -"\n" -" %(end)s" -msgstr "\n%(end)s" - -#: templates/horizon/common/_usage_summary.html:17 -msgid "The date should be in YYYY-mm-dd format." -msgstr "La date doit être au format AAAA-mm-jj" - -#: templates/horizon/common/_usage_summary.html:20 -msgid "Active Instances:" -msgstr "Instances Actives :" - -#: templates/horizon/common/_usage_summary.html:21 -msgid "Active RAM:" -msgstr "RAM Active :" - -#: templates/horizon/common/_usage_summary.html:22 -msgid "This Period's VCPU-Hours:" -msgstr "VCPU-Heures de cette Période :" - -#: templates/horizon/common/_usage_summary.html:23 -msgid "This Period's GB-Hours:" -msgstr "GB-Heures de cette période :" - -#: templates/horizon/common/_usage_summary.html:24 -msgid "This Period's RAM-Hours:" -msgstr "Dans cette période RAM-Heures:" - -#: templates/horizon/common/_workflow.html:40 -msgid "Back" -msgstr "Retour" - -#: templates/horizon/common/_workflow.html:43 -msgid "Next" -msgstr "Suivant" - -#: templatetags/branding.py:34 -msgid "Horizon" -msgstr "Horizon" - -#: templatetags/horizon.py:137 templatetags/horizon.py:148 -msgid "No Limit" -msgstr "Pas de limite" - -#: templatetags/horizon.py:140 templatetags/horizon.py:142 -msgid "Available" -msgstr "disponible(s)" - -#: templatetags/sizeformat.py:51 templatetags/sizeformat.py:56 -#, python-format -msgid "%(size)d Byte" -msgid_plural "%(size)d Bytes" -msgstr[0] "%(size)d Octet" -msgstr[1] "%(size)d Octets" - -#: templatetags/sizeformat.py:59 -#, python-format -msgid "%s KB" -msgstr "%s Ko" - -#: templatetags/sizeformat.py:61 -#, python-format -msgid "%s MB" -msgstr "%s Mo" - -#: templatetags/sizeformat.py:63 -#, python-format -msgid "%s GB" -msgstr "%s Go" - -#: templatetags/sizeformat.py:65 -#, python-format -msgid "%s TB" -msgstr "%s To" - -#: templatetags/sizeformat.py:66 -#, python-format -msgid "%s PB" -msgstr "%s Po" - -#: templatetags/sizeformat.py:74 -msgid "0 Bytes" -msgstr "0 Octets" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:31 -msgid "Sell Puppy" -msgid_plural "Sell Puppies" -msgstr[0] "Chiot à vendre" -msgstr[1] "Chiots à vendre" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:40 -msgid "Sold Puppy" -msgid_plural "Sold Puppies" -msgstr[0] "Chiot vendu" -msgstr[1] "Chiots Vendus" - -#: test/tests/views.py:59 -msgid "Fake" -msgstr "Faux" - -#: utils/filters.py:49 -msgid "Never" -msgstr "Jamais" - -#: utils/validators.py:26 utils/validators.py:50 -msgid "Not a valid port number" -msgstr "Numéro de port invalide" - -#: utils/validators.py:31 -msgid "Not a valid IP protocol number" -msgstr "Numéro de protocole IP invalide " - -#: utils/validators.py:45 -msgid "One colon allowed in port range" -msgstr "Un seul caractère deux-points autorisé dans une plage de ports" - -#: utils/validators.py:52 -msgid "Port number must be integer" -msgstr "Le numéro de port doit être un nombre entier" - -#: utils/validators.py:59 -msgid "The string may only contain ASCII printable characters." -msgstr "La chaîne ne peut contenir que des caractères ASCII imprimables." - -#: workflows/base.py:71 -msgid "Processing..." -msgstr "Traitement en cours..." - -#: workflows/base.py:475 -msgid "All available" -msgstr "Disponibles" - -#: workflows/base.py:476 -msgid "Members" -msgstr "Membres" - -#: workflows/base.py:477 -msgid "None available." -msgstr "Aucun disponible." - -#: workflows/base.py:478 -msgid "No members." -msgstr "Aucun membre." - -#: workflows/base.py:595 -#, python-format -msgid "%s completed successfully." -msgstr "%s terminé avec succès." - -#: workflows/base.py:596 -#, python-format -msgid "%s did not complete." -msgstr "%s ne s'est pas terminé." diff --git a/code/horizon/horizon/locale/fr/LC_MESSAGES/djangojs.po b/code/horizon/horizon/locale/fr/LC_MESSAGES/djangojs.po deleted file mode 100644 index e7b4ac28..00000000 --- a/code/horizon/horizon/locale/fr/LC_MESSAGES/djangojs.po +++ /dev/null @@ -1,627 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# alexandre ignjatovic , 2015 -# Bruno Cornec , 2015 -# Corina Roe , 2015 -# EVEILLARD , 2015 -# François Bureau, 2015 -# Frédéric , 2014 -# JF Taltavull , 2015 -# Maxime COQUEREL , 2015 -# Patte D , 2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-12 01:16-0500\n" -"PO-Revision-Date: 2015-04-23 12:36+0000\n" -"Last-Translator: JF Taltavull \n" -"Language-Team: French (http://www.transifex.com/projects/p/horizon/language/fr/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: fr\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: static/angular/action-list/button-tooltip.js:15 -msgid "" -"The action cannot be performed. The contents of this row have errors or are " -"missing information." -msgstr "L'action n'a pas pu être effectuée. Le contenu de cette ligne contient des erreurs ou des informations manquantes." - -#: static/angular/metadata-display/metadata-display.js:33 -msgid "Detail Information" -msgstr "Informations détaillées" - -#: static/angular/metadata-tree/metadata-tree.js:35 -msgid "" -"You can specify resource metadata by moving items from the left column to " -"the right column. In the left columns there are metadata definitions from " -"the Glance Metadata Catalog. Use the \"Other\" option to add metadata with " -"the key of your choice." -msgstr "Vous pouvez spécifier les ressources de métadonnées en déplaçant les éléments de la colonne de gauche vers la colonne de droite. Les colonnes de gauche contiennent des définitions de métadonnées du Catalogue de métadonnées Glance. Utiliser l'option \"Autre\" pour ajouter des métadonnées avec la clé de votre choix." - -#: static/angular/metadata-tree/metadata-tree.js:36 -msgid "Min" -msgstr "Min" - -#: static/angular/metadata-tree/metadata-tree.js:37 -msgid "Max" -msgstr "Max" - -#: static/angular/metadata-tree/metadata-tree.js:38 -msgid "Min length" -msgstr "Longueur mini" - -#: static/angular/metadata-tree/metadata-tree.js:39 -msgid "Max length" -msgstr "Longueur max" - -#: static/angular/metadata-tree/metadata-tree.js:40 -msgid "Pattern mismatch" -msgstr "Modèle ne correspondant pas" - -#: static/angular/metadata-tree/metadata-tree.js:41 -msgid "Integer required" -msgstr "Entier requis" - -#: static/angular/metadata-tree/metadata-tree.js:42 -msgid "Decimal required" -msgstr "Nombre décimal requis" - -#: static/angular/metadata-tree/metadata-tree.js:43 -msgid "Required" -msgstr "Requis" - -#: static/angular/metadata-tree/metadata-tree.js:44 -msgid "Duplicate keys are not allowed" -msgstr "Les clés dupliquées ne sont pas autorisées" - -#: static/angular/metadata-tree/metadata-tree.js:45 -#: static/angular/table/basic-table.js:6 -#: static/horizon/js/horizon.forms.js:184 -msgid "Filter" -msgstr "Filtrer" - -#: static/angular/metadata-tree/metadata-tree.js:46 -msgid "Available Metadata" -msgstr "Métadonnées disponibles" - -#: static/angular/metadata-tree/metadata-tree.js:47 -msgid "Existing Metadata" -msgstr "Métadonnées existantes" - -#: static/angular/metadata-tree/metadata-tree.js:48 -msgid "Custom" -msgstr "Personnaliser" - -#: static/angular/metadata-tree/metadata-tree.js:49 -msgid "No available metadata" -msgstr "Pas de métadonnées disponibles" - -#: static/angular/metadata-tree/metadata-tree.js:50 -msgid "No existing metadata" -msgstr "Pas de métadonnées existantes" - -#: static/angular/modal/modal.js:83 -msgid "Submit" -msgstr "Envoyer" - -#: static/angular/modal/modal.js:84 static/angular/wizard/wizard.js:11 -#: static/horizon/js/horizon.modals.js:33 -msgid "Cancel" -msgstr "Annuler" - -#: static/angular/transfer-table/transfer-table.js:39 -msgid "Allocated" -msgstr "Alloué" - -#: static/angular/transfer-table/transfer-table.js:40 -msgid "Available" -msgstr "disponible(s)" - -#: static/angular/transfer-table/transfer-table.js:41 -msgid "Select one" -msgstr "Sélectionner un" - -#: static/angular/transfer-table/transfer-table.js:42 -msgid "Select an item from Available items below" -msgstr "Sélectionner un élément depuis les éléments disponibles ci-dessous" - -#: static/angular/transfer-table/transfer-table.js:43 -msgid "No available items" -msgstr "Pas d'élément disponible" - -#: static/angular/transfer-table/transfer-table.js:44 -msgid "Expand to see allocated items" -msgstr "Développer pour voir les éléments alloués" - -#: static/angular/transfer-table/transfer-table.js:45 -msgid "Expand to see available items" -msgstr "Développer pour voir les éléments disponibles" - -#: static/angular/transfer-table/transfer-table.js:46 -msgid "Click to show or hide" -msgstr "Cliquer pour montrer ou cacher" - -#: static/angular/transfer-table/transfer-table.js:47 -msgid "Re-order items using drag and drop" -msgstr "Ordonnancer les éléments à nouveau en utilisant l'opération glisser-déplacer" - -#: static/angular/transfer-table/transfer-table.js:48 -msgid "Click to see more details" -msgstr "Cliquer pour une vue plus détaillée" - -#: static/angular/transfer-table/transfer-table.js:100 -msgid "Found %(found)s of %(total)s" -msgstr "Résultat %(found)s parmi %(total)s" - -#: static/angular/transfer-table/transfer-table.js:166 -msgid "Click here to expand the row and view the errors." -msgstr "Cliquez ici pour étendre la ligne et voir les erreurs" - -#: static/angular/wizard/wizard.js:12 -msgid "Back" -msgstr "Retour" - -#: static/angular/wizard/wizard.js:13 -msgid "Next" -msgstr "Suivant" - -#: static/angular/wizard/wizard.js:14 -msgid "Finish" -msgstr "Terminer" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Connecting" -msgstr "En cours de connexion" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Open" -msgstr "Ouvert" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closing" -msgstr "En cours de fermeture" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closed" -msgstr "Fermé" - -#: static/horizon/js/angular/directives/serialConsole.js:85 -#, c-format -msgid "Status: %s" -msgstr "État : %s" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "Yes" -msgstr "Oui" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "No" -msgstr "Non" - -#: static/horizon/js/angular/filters/filters.js:53 -#: static/horizon/js/angular/filters/filters.js:140 -#, c-format -msgid "%s GB" -msgstr "%s Go" - -#: static/horizon/js/angular/filters/filters.js:70 -#: static/horizon/js/angular/filters/filters.js:142 -#, c-format -msgid "%s MB" -msgstr "%s Mo" - -#: static/horizon/js/angular/filters/filters.js:138 -#, c-format -msgid "%s TB" -msgstr "%s To" - -#: static/horizon/js/angular/filters/filters.js:144 -#, c-format -msgid "%s KB" -msgstr "%s Ko" - -#: static/horizon/js/angular/filters/filters.js:146 -#, c-format -msgid "%s bytes" -msgstr "%s octets" - -#: static/horizon/js/angular/filters/filters.js:163 -#: static/horizon/js/horizon.tables.js:393 -#, c-format -msgid "Displaying %s item" -msgid_plural "Displaying %s items" -msgstr[0] "Affichage de %s élément" -msgstr[1] "Affichage de %s éléments" - -#: static/horizon/js/angular/services/hz.api.cinder.js:47 -msgid "Unable to retrieve volumes." -msgstr "Impossible de récupérer les volumes." - -#: static/horizon/js/angular/services/hz.api.cinder.js:74 -msgid "Unable to retrieve volume snapshots." -msgstr "Impossible de récupérer les instantanés de volume." - -#: static/horizon/js/angular/services/hz.api.config.js:43 -msgid "Unable to retrieve user configuration." -msgstr "Impossible de récupérer la configuration utilisateur." - -#: static/horizon/js/angular/services/hz.api.config.js:62 -msgid "Unable to retrieve admin configuration." -msgstr "Impossible d'extraire la configuration admin." - -#: static/horizon/js/angular/services/hz.api.config.js:105 -msgid "Unable to retrieve settings." -msgstr "Impossible de récupérer les paramètres." - -#: static/horizon/js/angular/services/hz.api.config.js:289 -msgid "Setting is not enabled: %(setting)s" -msgstr "Le paramètre n'est pas activé : %(setting)s" - -#: static/horizon/js/angular/services/hz.api.glance.js:38 -msgid "Unable to retrieve image." -msgstr "Impossible de récupérer l'image." - -#: static/horizon/js/angular/services/hz.api.glance.js:81 -msgid "Unable to retrieve images." -msgstr "Impossible de récupérer les images." - -#: static/horizon/js/angular/services/hz.api.glance.js:144 -msgid "Unable to retrieve namespaces." -msgstr "Impossible de récupérer les espaces de nommage" - -#: static/horizon/js/angular/services/hz.api.keystone.js:24 -msgid "Unable to retrieve users" -msgstr "Impossible de récupérer les utilisateurs" - -#: static/horizon/js/angular/services/hz.api.keystone.js:31 -msgid "Unable to create the user." -msgstr "Impossible de créer l'utilisateur." - -#: static/horizon/js/angular/services/hz.api.keystone.js:38 -msgid "Unable to delete the users." -msgstr "Impossible de supprimer les utilisateurs." - -#: static/horizon/js/angular/services/hz.api.keystone.js:73 -msgid "Unable to retrieve the current user session." -msgstr "Impossible de récupérer les informations de session de l'utilisateur courant." - -#: static/horizon/js/angular/services/hz.api.keystone.js:80 -msgid "Unable to retrieve the user" -msgstr "Impossible de récupérer l'utilisateur" - -#: static/horizon/js/angular/services/hz.api.keystone.js:88 -msgid "Unable to edit the user." -msgstr "Impossible d'éditer l'utilisateur" - -#: static/horizon/js/angular/services/hz.api.keystone.js:95 -msgid "Unable to delete the user." -msgstr "Impossible de supprimer l'utilisateur." - -#: static/horizon/js/angular/services/hz.api.keystone.js:103 -msgid "Unable to retrieve role" -msgstr "Impossible de récupérer le rôle." - -#: static/horizon/js/angular/services/hz.api.keystone.js:110 -msgid "Unable to create the role." -msgstr "Impossible de créer le rôle." - -#: static/horizon/js/angular/services/hz.api.keystone.js:117 -msgid "Unable to delete the roles." -msgstr "Impossible de supprimer les rôles." - -#: static/horizon/js/angular/services/hz.api.keystone.js:124 -msgid "Unable to retrieve the role" -msgstr "Impossible de récupérer le rôle." - -#: static/horizon/js/angular/services/hz.api.keystone.js:132 -msgid "Unable to edit the role." -msgstr "Impossible d'éditer le rôle." - -#: static/horizon/js/angular/services/hz.api.keystone.js:139 -msgid "Unable to delete the role." -msgstr "Impossible de supprimer le rôle." - -#: static/horizon/js/angular/services/hz.api.keystone.js:147 -msgid "Unable to retrieve domains" -msgstr "Impossible de récupérer les domaines." - -#: static/horizon/js/angular/services/hz.api.keystone.js:154 -msgid "Unable to create the domain." -msgstr "Impossible de créer le domaine." - -#: static/horizon/js/angular/services/hz.api.keystone.js:161 -msgid "Unable to delete the domains." -msgstr "Impossible de supprimer les domaines." - -#: static/horizon/js/angular/services/hz.api.keystone.js:168 -msgid "Unable to retrieve the domain" -msgstr "Impossible de récupérer le domaine." - -#: static/horizon/js/angular/services/hz.api.keystone.js:176 -msgid "Unable to edit the domain." -msgstr "Impossible d'éditer le domaine." - -#: static/horizon/js/angular/services/hz.api.keystone.js:183 -msgid "Unable to delete the domain." -msgstr "Impossible de supprimer le domaine." - -#: static/horizon/js/angular/services/hz.api.keystone.js:192 -msgid "Unable to retrieve projects" -msgstr "Impossible de récupérer les projets." - -#: static/horizon/js/angular/services/hz.api.keystone.js:199 -msgid "Unable to create the project." -msgstr "Impossible de créer le projet." - -#: static/horizon/js/angular/services/hz.api.keystone.js:206 -msgid "Unable to delete the projects." -msgstr "Impossible de supprimer les projets." - -#: static/horizon/js/angular/services/hz.api.keystone.js:213 -msgid "Unable to retrieve the project" -msgstr "Impossible de récupérer le projet." - -#: static/horizon/js/angular/services/hz.api.keystone.js:221 -msgid "Unable to edit the project." -msgstr "Impossible d'éditer le projet." - -#: static/horizon/js/angular/services/hz.api.keystone.js:228 -msgid "Unable to delete the project." -msgstr "Impossible de supprimer le projet." - -#: static/horizon/js/angular/services/hz.api.keystone.js:236 -msgid "Unable to grant the role." -msgstr "Impossible d'accorder le rôle" - -#: static/horizon/js/angular/services/hz.api.keystone.js:250 -msgid "Unable to fetch the service catalog." -msgstr "Impossible d'extraire le catalogue de services." - -#: static/horizon/js/angular/services/hz.api.keystone.js:385 -msgid "Service type is not enabled: %(desiredType)s" -msgstr "Type de service non activé: %(desiredType)s" - -#: static/horizon/js/angular/services/hz.api.keystone.js:392 -msgid "Cannot get service catalog from keystone." -msgstr "Impossible d'obtenir le catalogue de services Keystone" - -#: static/horizon/js/angular/services/hz.api.neutron.js:39 -msgid "Unable to retrieve networks." -msgstr "Impossible de récupérer les réseaux." - -#: static/horizon/js/angular/services/hz.api.neutron.js:88 -msgid "Unable to create the network." -msgstr "Impossible de créer le réseau." - -#: static/horizon/js/angular/services/hz.api.neutron.js:108 -msgid "Unable to retrieve subnets." -msgstr "Impossible de récupérer les sous-réseaux." - -#: static/horizon/js/angular/services/hz.api.neutron.js:172 -msgid "Unable to create the subnet." -msgstr "Impossible de créer le sous-réseau." - -#: static/horizon/js/angular/services/hz.api.neutron.js:192 -msgid "Unable to retrieve ports." -msgstr "Impossible de récupérer les ports." - -#: static/horizon/js/angular/services/hz.api.nova.js:40 -msgid "Unable to retrieve keypairs." -msgstr "Impossible de récupérer les paires de clés." - -#: static/horizon/js/angular/services/hz.api.nova.js:62 -msgid "Unable to import the keypair." -msgstr "Impossible d'importer la paire de clés." - -#: static/horizon/js/angular/services/hz.api.nova.js:64 -msgid "Unable to create the keypair." -msgstr "Impossible de créer la paire de clés" - -#: static/horizon/js/angular/services/hz.api.nova.js:83 -msgid "Unable to retrieve availability zones." -msgstr "Impossible de récupérer les zones de disponibilité." - -#: static/horizon/js/angular/services/hz.api.nova.js:121 -msgid "Unable to retrieve limits." -msgstr "Impossible de récupérer les limites." - -#: static/horizon/js/angular/services/hz.api.nova.js:148 -msgid "Unable to create the server." -msgstr "Impossible de créer le serveur." - -#: static/horizon/js/angular/services/hz.api.nova.js:162 -msgid "Unable to retrieve server." -msgstr "Impossible de récupérer le serveur." - -#: static/horizon/js/angular/services/hz.api.nova.js:192 -msgid "Unable to retrieve extensions." -msgstr "Impossible d'obtenir les extensions." - -#: static/horizon/js/angular/services/hz.api.nova.js:237 -msgid "Unable to retrieve flavors." -msgstr "Impossible de récupérer les gabarits." - -#: static/horizon/js/angular/services/hz.api.nova.js:255 -msgid "Unable to retrieve flavor." -msgstr "Impossible de récupérer le gabarit." - -#: static/horizon/js/angular/services/hz.api.nova.js:269 -msgid "Unable to retrieve flavor extra specs." -msgstr "Impossible de récupérer les paramètres supplémentaires du gabarit." - -#: static/horizon/js/angular/services/hz.api.nova.js:311 -msgid "Extension is not enabled: %(extension)s" -msgstr "L'extension n'est pas activée : %(extension)s" - -#: static/horizon/js/angular/services/hz.api.nova.js:318 -msgid "Cannot get nova extension list." -msgstr "Impossible d'obtenir la liste des extensions Nova." - -#: static/horizon/js/angular/services/hz.api.policy.js:65 -msgid "Policy check failed." -msgstr "La vérification de la stratégie a échoué." - -#: static/horizon/js/angular/services/hz.api.security-group.js:64 -msgid "Unable to retrieve security groups." -msgstr "Impossible de récupérer les groupes de sécurité." - -#: static/horizon/js/horizon.accordion_nav.js:78 -#: static/horizon/js/horizon.modals.js:315 -#: static/horizon/js/horizon.tabs.js:21 -msgid "Loading" -msgstr "Chargement..." - -#: static/horizon/js/horizon.d3linechart.js:394 -#: static/horizon/js/horizon.d3linechart.js:404 -msgid "No data available." -msgstr "Pas de données disponibles." - -#: static/horizon/js/horizon.d3linechart.js:410 -#: static/horizon/js/horizon.modals.js:334 -#: static/horizon/js/horizon.tables_inline_edit.js:94 -#: static/horizon/js/horizon.tables_inline_edit.js:157 -msgid "An error occurred. Please try again later." -msgstr "Une erreur s'est produite. Veuillez réessayer ultérieurement." - -#: static/horizon/js/horizon.firewalls.js:32 -#: static/horizon/js/horizon.instances.js:31 -msgid "There was a problem communicating with the server, please try again." -msgstr "Problème de communication avec le serveur, veuillez réessayer." - -#: static/horizon/js/horizon.instances.js:273 -msgid "Could not read the file" -msgstr "Le fichier n'a pu être lu" - -#: static/horizon/js/horizon.instances.js:279 -#: static/horizon/js/horizon.instances.js:308 -msgid "Could not decrypt the password" -msgstr "Le mot de passe n'a pu être déchiffré" - -#: static/horizon/js/horizon.membership.js:190 -msgid "No roles" -msgstr "Aucun rôle" - -#: static/horizon/js/horizon.membership.js:222 -msgid "Roles" -msgstr "Rôles" - -#: static/horizon/js/horizon.messages.js:9 -msgid "Danger: " -msgstr "Danger :" - -#: static/horizon/js/horizon.messages.js:10 -msgid "Warning: " -msgstr "Avertissement :" - -#: static/horizon/js/horizon.messages.js:11 -msgid "Notice: " -msgstr "Notification :" - -#: static/horizon/js/horizon.messages.js:12 -msgid "Success: " -msgstr "Succès :" - -#: static/horizon/js/horizon.messages.js:13 -msgid "Error: " -msgstr "Erreur :" - -#: static/horizon/js/horizon.modals.js:229 -#: static/horizon/js/horizon.tables.js:218 -msgid "Working" -msgstr "Traitement en cours..." - -#: static/horizon/js/horizon.modals.js:263 -msgid "There was an error submitting the form. Please try again." -msgstr "Erreur lors de la soumission du formulaire. Veuillez réessayer. " - -#: static/horizon/js/horizon.networktopology.js:530 -#: static/horizon/js/horizon.networktopology.js:536 -msgid "None" -msgstr "Aucun" - -#: static/horizon/js/horizon.networktopology.js:549 -msgid "Delete" -msgstr "Supprimer" - -#: static/horizon/js/horizon.networktopology.js:552 -msgid "STATUS" -msgstr "STATUT" - -#: static/horizon/js/horizon.networktopology.js:553 -msgid "ID" -msgstr "ID" - -#: static/horizon/js/horizon.networktopology.js:554 -msgid "Interfaces" -msgstr "Interfaces" - -#: static/horizon/js/horizon.networktopology.js:555 -msgid "Delete Interface" -msgstr "Supprimer l'Interface" - -#: static/horizon/js/horizon.networktopology.js:556 -msgid "Open Console" -msgstr "Ouvrir une Console" - -#: static/horizon/js/horizon.networktopology.js:557 -msgid "View Details" -msgstr "Voir les détails" - -#: static/horizon/js/horizon.networktopology.js:560 -msgid "Delete Router" -msgstr "Supprimer un Routeur" - -#: static/horizon/js/horizon.networktopology.js:561 -msgid "View Router Details" -msgstr "Voir les Détails du Routeur" - -#: static/horizon/js/horizon.networktopology.js:564 -msgid "Add Interface" -msgstr "Ajouter une interface" - -#: static/horizon/js/horizon.networktopology.js:570 -msgid "Terminate Instance" -msgstr "Terminer l'Instance" - -#: static/horizon/js/horizon.networktopology.js:571 -msgid "View Instance Details" -msgstr "Voir les Détails de l'Instance" - -#: static/horizon/js/horizon.tables.js:39 -#: static/horizon/js/horizon.tables.js:406 -msgid "No items to display." -msgstr "Aucun élément à afficher." - -#: static/horizon/js/horizon.tables.js:52 -#: static/horizon/js/horizon.tables.js:120 -msgid "An error occurred while updating." -msgstr "Une erreur s'est produite durant la mise à jour." - -#: static/horizon/js/horizon.tables.js:201 -#, c-format -msgid "You have selected %s. " -msgstr "Vous avez sélectionné %s." - -#: static/horizon/js/horizon.tables.js:203 -#, c-format -msgid "Confirm %s" -msgstr "Confirmez %s" - -#: static/horizon/js/horizon.tables.js:204 -msgid "Please confirm your selection. " -msgstr "Merci de confirmer votre sélection." - -#: static/horizon/js/horizon.tables_inline_edit.js:88 -#: static/horizon/js/horizon.tables_inline_edit.js:151 -msgid "Not authorized to do this operation." -msgstr "Vous n'êtes pas autorisé à effectuer cette opération." - -#: static/horizon/js/horizon.users.js:18 -msgid "Passwords do not match." -msgstr "Les mots de passe ne correspondent pas." diff --git a/code/horizon/horizon/locale/ja/LC_MESSAGES/django.po b/code/horizon/horizon/locale/ja/LC_MESSAGES/django.po deleted file mode 100644 index eb7d7e32..00000000 --- a/code/horizon/horizon/locale/ja/LC_MESSAGES/django.po +++ /dev/null @@ -1,507 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Akihiro Motoki , 2014-2015 -# myamamot , 2014-2015 -# ykatabam , 2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-06 21:07-0500\n" -"PO-Revision-Date: 2015-04-06 23:21+0000\n" -"Last-Translator: myamamot \n" -"Language-Team: Japanese (http://www.transifex.com/projects/p/horizon/language/ja/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ja\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: base.py:475 -msgid "Other" -msgstr "その他" - -#: browsers/base.py:88 -msgid "Navigation Item" -msgstr "ナビゲーション項目" - -#: browsers/views.py:41 -#, python-format -msgid "Select a %s to browse." -msgstr "表示する %s を選択してください。" - -#: conf/default.py:41 -msgid "Password is not accepted" -msgstr "パスワードを受け付けられません" - -#: decorators.py:53 -msgid "Please log in to continue." -msgstr "続行するには、ログインしてください。" - -#: decorators.py:85 -#, python-format -msgid "You are not authorized to access %s" -msgstr "%s へのアクセスが許可されていません。" - -#: exceptions.py:163 -#, python-format -msgid "A %(resource)s with the name \"%(name)s\" already exists." -msgstr "名前が \"%(name)s\" の %(resource)s がすでに存在します。" - -#: exceptions.py:235 -#, python-format -msgid "Unauthorized: %s" -msgstr "権限がありません: %s" - -#: exceptions.py:238 -msgid "Unauthorized. Please try logging in again." -msgstr "認証されていません。もう一度ログインしてください。" - -#: forms/fields.py:64 -msgid "Incorrect format for IP address" -msgstr "不正な形式の IP アドレス" - -#: forms/fields.py:65 -msgid "Invalid version for IP address" -msgstr "無効な IP アドレスのバージョン" - -#: forms/fields.py:66 -msgid "Invalid subnet mask" -msgstr "無効なサブネットマスク" - -#: forms/views.py:132 templates/horizon/common/_usage_summary.html:16 -msgid "Submit" -msgstr "送信" - -#: forms/views.py:133 -#: templates/horizon/common/_modal_form_update_metadata.html:25 -#: templates/horizon/common/_workflow.html:49 -msgid "Cancel" -msgstr "取り消し" - -#: middleware.py:103 -msgid "Session timed out." -msgstr "セッションがタイムアウトしました。" - -#: tables/actions.py:460 -#: templates/horizon/common/_data_table_table_actions.html:21 -#: templates/horizon/common/_data_table_table_actions.html:33 -#: templates/horizon/common/_workflow_step_update_members.html:14 -#: templates/horizon/common/_workflow_step_update_members.html:23 -msgid "Filter" -msgstr "フィルター" - -#: tables/actions.py:645 -msgid "This action cannot be undone." -msgstr "この操作は取り消せません。" - -#: tables/actions.py:767 -#, python-format -msgctxt "past" -msgid "%(action)s %(data_type)s" -msgstr "%(data_type)sの%(action)s" - -#: tables/actions.py:769 -#, python-format -msgctxt "present" -msgid "%(action)s %(data_type)s" -msgstr "%(data_type)sの%(action)s" - -#: tables/actions.py:832 -#, python-format -msgid "You are not allowed to %(action)s: %(objs)s" -msgstr "%(action)s は許可されていません: %(objs)s" - -#: tables/actions.py:839 -#, python-format -msgid "Unable to %(action)s: %(objs)s" -msgstr "%(action)s を実行できません: %(objs)s" - -#: tables/actions.py:845 -#, python-format -msgid "%(action)s: %(objs)s" -msgstr "%(action)s: %(objs)s" - -#: tables/actions.py:915 -msgid "Delete" -msgstr "削除" - -#: tables/actions.py:917 -msgid "Deleted" -msgstr "削除" - -#: tables/actions.py:948 -msgid "Update" -msgstr "更新" - -#: tables/actions.py:949 -msgid "Updated" -msgstr "更新日時" - -#: tables/base.py:305 -msgid "-" -msgstr "-" - -#: tables/base.py:361 -#, python-format -msgid "The attribute %(attr)s doesn't exist on %(obj)s." -msgstr "%(obj)s に 属性 %(attr)s が存在しません。" - -#: tables/base.py:990 -msgid "No items to display." -msgstr "表示する項目がありません" - -#: tables/base.py:1099 -#: templates/horizon/common/_data_table_table_actions.html:47 -msgid "Actions" -msgstr "アクション" - -#: tables/base.py:1329 -#, python-format -msgid "No match returned for the id \"%s\"." -msgstr "ID \"%s\" に一致するものがありません。" - -#: tables/base.py:1486 -msgid "Please select a row before taking that action." -msgstr "このアクションを実行する前に、対象を選択してください。" - -#: tables/base.py:1570 -msgid "N/A" -msgstr "N/A" - -#: templates/_header.html:5 -#, python-format -msgid "Logged in as: %(username)s" -msgstr "%(username)s としてログイン中" - -#: templates/_header.html:7 -msgid "Help" -msgstr "ヘルプ" - -#: templates/_header.html:9 -msgid "Sign Out" -msgstr "ログアウト" - -#: templates/auth/_description.html:9 -msgid "" -"\n" -" If you are not sure which authentication method to use, contact your administrator.\n" -" " -msgstr "\n 使用する認証メソッドが不明な場合は、管理者に問い合わせてください。\n " - -#: templates/auth/_login.html:5 -msgid "Log In" -msgstr "ログイン" - -#: templates/auth/_login.html:27 -msgid "You do not have permission to access the resource:" -msgstr "リソースにアクセスする権限がありません:" - -#: templates/auth/_login.html:29 -#, python-format -msgid "" -"Login as different user or go back to home " -"page" -msgstr "他のユーザーとしてログインするか、ホームページに戻ってください。" - -#: templates/auth/_login.html:45 -msgid "Sign In" -msgstr "ログイン" - -#: templates/auth/_login.html:46 -msgid "Connect" -msgstr "接続" - -#: templates/auth/login.html:4 -msgid "Login" -msgstr "ログイン" - -#: templates/horizon/_messages.html:7 -msgid "Info: " -msgstr "情報: " - -#: templates/horizon/_messages.html:13 -msgid "Warning: " -msgstr "警告: " - -#: templates/horizon/_messages.html:19 -msgid "Success: " -msgstr "成功: " - -#: templates/horizon/_messages.html:25 -msgid "Error: " -msgstr "エラー: " - -#: templates/horizon/common/_data_table.html:63 -msgid "Summary" -msgstr "概要" - -#: templates/horizon/common/_data_table.html:72 -#, python-format -msgid "Displaying %(counter)s item" -msgid_plural "Displaying %(counter)s items" -msgstr[0] "%(counter)s件表示" - -#: templates/horizon/common/_data_table.html:77 -msgid "« Prev" -msgstr "« 前へ" - -#: templates/horizon/common/_data_table.html:80 -msgid "Next »" -msgstr "次へ »" - -#: templates/horizon/common/_data_table_table_actions.html:45 -msgid "More Actions" -msgstr "その他のアクション" - -#: templates/horizon/common/_domain_page_header.html:6 -#, python-format -msgid "%(context_name)s:" -msgstr "%(context_name)s:" - -#: templates/horizon/common/_formset_table.html:35 -msgid "Add a row" -msgstr "行の追加" - -#: templates/horizon/common/_formset_table_row.html:15 -#, python-format -msgid "%(name)s: %(error)s" -msgstr "%(name)s: %(error)s" - -#: templates/horizon/common/_limit_summary.html:4 -msgid "Limit Summary" -msgstr "利用可能リソース概要" - -#: templates/horizon/common/_limit_summary.html:7 -msgid "Instances" -msgstr "インスタンス" - -#: templates/horizon/common/_limit_summary.html:8 -#: templates/horizon/common/_limit_summary.html:15 -#: templates/horizon/common/_limit_summary.html:22 -#: templates/horizon/common/_limit_summary.html:36 -#: templates/horizon/common/_limit_summary.html:43 -#: templates/horizon/common/_limit_summary.html:50 -#, python-format -msgid "Used %(used)s of %(available)s " -msgstr "%(used)s / %(available)s 使用中" - -#: templates/horizon/common/_limit_summary.html:14 -msgid "VCPUs" -msgstr "仮想 CPU" - -#: templates/horizon/common/_limit_summary.html:21 -msgid "RAM" -msgstr "メモリー" - -#: templates/horizon/common/_limit_summary.html:28 -msgid "Floating IPs" -msgstr "Floating IP" - -#: templates/horizon/common/_limit_summary.html:29 -#, python-format -msgid "Allocated %(used)s of %(available)s " -msgstr " %(used)s / %(available)s 割り当て済み" - -#: templates/horizon/common/_limit_summary.html:35 -msgid "Security Groups" -msgstr "セキュリティーグループ" - -#: templates/horizon/common/_limit_summary.html:42 -msgid "Volumes" -msgstr "ボリューム" - -#: templates/horizon/common/_limit_summary.html:49 -msgid "Volume Storage" -msgstr "ボリューム容量" - -#: templates/horizon/common/_modal_form_update_metadata.html:24 -#: workflows/base.py:594 -msgid "Save" -msgstr "保存" - -#: templates/horizon/common/_resource_browser.html:10 -#, python-format -msgid "Displaying %(nav_items)s item" -msgid_plural "Displaying %(nav_items)s items" -msgstr[0] "%(nav_items)s件表示" - -#: templates/horizon/common/_resource_browser.html:11 -#, python-format -msgid "Displaying %(content_items)s item" -msgid_plural "Displaying %(content_items)s items" -msgstr[0] "%(content_items)s件表示" - -#: templates/horizon/common/_usage_summary.html:3 -msgid "Usage Summary" -msgstr "使用状況の概要" - -#: templates/horizon/common/_usage_summary.html:7 -msgid "Select a period of time to query its usage:" -msgstr "使用状況を照会する期間を選択してください:" - -#: templates/horizon/common/_usage_summary.html:9 -#, python-format -msgid "" -"\n" -" %(start)s" -msgstr "\n%(start)s " - -#: templates/horizon/common/_usage_summary.html:13 -#, python-format -msgid "" -"\n" -" %(end)s" -msgstr "\n%(end)s " - -#: templates/horizon/common/_usage_summary.html:17 -msgid "The date should be in YYYY-mm-dd format." -msgstr "日付は YYYY-mm-dd 形式にする必要があります。" - -#: templates/horizon/common/_usage_summary.html:20 -msgid "Active Instances:" -msgstr "稼働中のインスタンス:" - -#: templates/horizon/common/_usage_summary.html:21 -msgid "Active RAM:" -msgstr "使用中のメモリー:" - -#: templates/horizon/common/_usage_summary.html:22 -msgid "This Period's VCPU-Hours:" -msgstr "指定期間中の仮想 CPU 時間:" - -#: templates/horizon/common/_usage_summary.html:23 -msgid "This Period's GB-Hours:" -msgstr "指定期間中の GB 時間:" - -#: templates/horizon/common/_usage_summary.html:24 -msgid "This Period's RAM-Hours:" -msgstr "指定期間中のメモリー時間" - -#: templates/horizon/common/_workflow.html:40 -msgid "Back" -msgstr "戻る" - -#: templates/horizon/common/_workflow.html:43 -msgid "Next" -msgstr "次へ" - -#: templatetags/branding.py:34 -msgid "Horizon" -msgstr "Horizon" - -#: templatetags/horizon.py:137 templatetags/horizon.py:148 -msgid "No Limit" -msgstr "制限なし" - -#: templatetags/horizon.py:140 templatetags/horizon.py:142 -msgid "Available" -msgstr "利用可能" - -#: templatetags/sizeformat.py:51 templatetags/sizeformat.py:56 -#, python-format -msgid "%(size)d Byte" -msgid_plural "%(size)d Bytes" -msgstr[0] "%(size)dB" - -#: templatetags/sizeformat.py:59 -#, python-format -msgid "%s KB" -msgstr "%s KB" - -#: templatetags/sizeformat.py:61 -#, python-format -msgid "%s MB" -msgstr "%s MB" - -#: templatetags/sizeformat.py:63 -#, python-format -msgid "%s GB" -msgstr "%s GB" - -#: templatetags/sizeformat.py:65 -#, python-format -msgid "%s TB" -msgstr "%s TB" - -#: templatetags/sizeformat.py:66 -#, python-format -msgid "%s PB" -msgstr "%s PB" - -#: templatetags/sizeformat.py:74 -msgid "0 Bytes" -msgstr "0 バイト" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:31 -msgid "Sell Puppy" -msgid_plural "Sell Puppies" -msgstr[0] "子犬を売る" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:40 -msgid "Sold Puppy" -msgid_plural "Sold Puppies" -msgstr[0] "子犬を売りました" - -#: test/tests/views.py:59 -msgid "Fake" -msgstr "Fake" - -#: utils/filters.py:49 -msgid "Never" -msgstr "なし" - -#: utils/validators.py:26 utils/validators.py:50 -msgid "Not a valid port number" -msgstr "有効なポート番号ではありません" - -#: utils/validators.py:31 -msgid "Not a valid IP protocol number" -msgstr "有効な IP プロトコル番号ではありません" - -#: utils/validators.py:45 -msgid "One colon allowed in port range" -msgstr "ポート範囲で使用できるコロンは 1 つだけです。" - -#: utils/validators.py:52 -msgid "Port number must be integer" -msgstr "ポート番号は整数でなければなりません" - -#: utils/validators.py:59 -msgid "The string may only contain ASCII printable characters." -msgstr "文字列に含めることができるのは ASCII 印字可能文字のみです。" - -#: workflows/base.py:71 -msgid "Processing..." -msgstr "処理中..." - -#: workflows/base.py:475 -msgid "All available" -msgstr "利用可能な全項目" - -#: workflows/base.py:476 -msgid "Members" -msgstr "メンバー" - -#: workflows/base.py:477 -msgid "None available." -msgstr "利用可能な項目がありません。" - -#: workflows/base.py:478 -msgid "No members." -msgstr "メンバーがいません。" - -#: workflows/base.py:595 -#, python-format -msgid "%s completed successfully." -msgstr "%s が正常に完了しました。" - -#: workflows/base.py:596 -#, python-format -msgid "%s did not complete." -msgstr "%s が完了しませんでした。" diff --git a/code/horizon/horizon/locale/ja/LC_MESSAGES/djangojs.po b/code/horizon/horizon/locale/ja/LC_MESSAGES/djangojs.po deleted file mode 100644 index b826db0a..00000000 --- a/code/horizon/horizon/locale/ja/LC_MESSAGES/djangojs.po +++ /dev/null @@ -1,621 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Akihiro Motoki , 2014-2015 -# myamamot , 2015 -# Tom Fifield , 2015 -# ykatabam , 2014-2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-12 01:16-0500\n" -"PO-Revision-Date: 2015-04-20 07:06+0000\n" -"Last-Translator: ykatabam \n" -"Language-Team: Japanese (http://www.transifex.com/projects/p/horizon/language/ja/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ja\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: static/angular/action-list/button-tooltip.js:15 -msgid "" -"The action cannot be performed. The contents of this row have errors or are " -"missing information." -msgstr "操作を実行できません。この行の内容にエラーがあるか、情報が見つかりません。" - -#: static/angular/metadata-display/metadata-display.js:33 -msgid "Detail Information" -msgstr "詳細情報" - -#: static/angular/metadata-tree/metadata-tree.js:35 -msgid "" -"You can specify resource metadata by moving items from the left column to " -"the right column. In the left columns there are metadata definitions from " -"the Glance Metadata Catalog. Use the \"Other\" option to add metadata with " -"the key of your choice." -msgstr "左の列から右の列にアイテムを移動して、リソースのメタデータを指定できます。左の列には、Glance のメタデータカタログに登録されているメタデータの定義が表示されています。任意のキーのメタデータを追加するには、\"Other\" オプションを使ってください。" - -#: static/angular/metadata-tree/metadata-tree.js:36 -msgid "Min" -msgstr "最小値" - -#: static/angular/metadata-tree/metadata-tree.js:37 -msgid "Max" -msgstr "最大値" - -#: static/angular/metadata-tree/metadata-tree.js:38 -msgid "Min length" -msgstr "最小長" - -#: static/angular/metadata-tree/metadata-tree.js:39 -msgid "Max length" -msgstr "最大長" - -#: static/angular/metadata-tree/metadata-tree.js:40 -msgid "Pattern mismatch" -msgstr "パターンが一致しません。" - -#: static/angular/metadata-tree/metadata-tree.js:41 -msgid "Integer required" -msgstr "整数を指定する必要があります。" - -#: static/angular/metadata-tree/metadata-tree.js:42 -msgid "Decimal required" -msgstr "十進数を指定する必要があります。" - -#: static/angular/metadata-tree/metadata-tree.js:43 -msgid "Required" -msgstr "必須" - -#: static/angular/metadata-tree/metadata-tree.js:44 -msgid "Duplicate keys are not allowed" -msgstr "重複するキーは使用できません" - -#: static/angular/metadata-tree/metadata-tree.js:45 -#: static/angular/table/basic-table.js:6 -#: static/horizon/js/horizon.forms.js:184 -msgid "Filter" -msgstr "フィルター" - -#: static/angular/metadata-tree/metadata-tree.js:46 -msgid "Available Metadata" -msgstr "利用可能なメタデータ" - -#: static/angular/metadata-tree/metadata-tree.js:47 -msgid "Existing Metadata" -msgstr "選択済みのメタデータ" - -#: static/angular/metadata-tree/metadata-tree.js:48 -msgid "Custom" -msgstr "カスタム" - -#: static/angular/metadata-tree/metadata-tree.js:49 -msgid "No available metadata" -msgstr "利用可能なメタデータはありません" - -#: static/angular/metadata-tree/metadata-tree.js:50 -msgid "No existing metadata" -msgstr "選択済みのメタデータはありません" - -#: static/angular/modal/modal.js:83 -msgid "Submit" -msgstr "送信" - -#: static/angular/modal/modal.js:84 static/angular/wizard/wizard.js:11 -#: static/horizon/js/horizon.modals.js:33 -msgid "Cancel" -msgstr "取り消し" - -#: static/angular/transfer-table/transfer-table.js:39 -msgid "Allocated" -msgstr "割り当て済み" - -#: static/angular/transfer-table/transfer-table.js:40 -msgid "Available" -msgstr "利用可能" - -#: static/angular/transfer-table/transfer-table.js:41 -msgid "Select one" -msgstr "1 つ選択してください。" - -#: static/angular/transfer-table/transfer-table.js:42 -msgid "Select an item from Available items below" -msgstr "以下の利用可能なアイテムから 1 つ選択してください。" - -#: static/angular/transfer-table/transfer-table.js:43 -msgid "No available items" -msgstr "利用できるアイテムがありません。" - -#: static/angular/transfer-table/transfer-table.js:44 -msgid "Expand to see allocated items" -msgstr "割り当て済みのアイテムを表示するには展開してください。" - -#: static/angular/transfer-table/transfer-table.js:45 -msgid "Expand to see available items" -msgstr "利用可能なアイテムを表示するには展開してください。" - -#: static/angular/transfer-table/transfer-table.js:46 -msgid "Click to show or hide" -msgstr "クリックして表示/非表示を切り替えてください。" - -#: static/angular/transfer-table/transfer-table.js:47 -msgid "Re-order items using drag and drop" -msgstr "順番を並べ替えるには、アイテムをドラッグ&ドロップしてください。" - -#: static/angular/transfer-table/transfer-table.js:48 -msgid "Click to see more details" -msgstr "クリックすると詳しい情報が表示されます。" - -#: static/angular/transfer-table/transfer-table.js:100 -msgid "Found %(found)s of %(total)s" -msgstr "%(total)s 中 %(found)s 見つかりました。" - -#: static/angular/transfer-table/transfer-table.js:166 -msgid "Click here to expand the row and view the errors." -msgstr "行を展開してエラーを表示するには、ここをクリックしてください。" - -#: static/angular/wizard/wizard.js:12 -msgid "Back" -msgstr "戻る" - -#: static/angular/wizard/wizard.js:13 -msgid "Next" -msgstr "次へ" - -#: static/angular/wizard/wizard.js:14 -msgid "Finish" -msgstr "完了" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Connecting" -msgstr "接続中" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Open" -msgstr "オープン" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closing" -msgstr "切断中" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closed" -msgstr "切断済み" - -#: static/horizon/js/angular/directives/serialConsole.js:85 -#, c-format -msgid "Status: %s" -msgstr "ステータス: %s" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "Yes" -msgstr "はい" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "No" -msgstr "いいえ" - -#: static/horizon/js/angular/filters/filters.js:53 -#: static/horizon/js/angular/filters/filters.js:140 -#, c-format -msgid "%s GB" -msgstr "%s GB" - -#: static/horizon/js/angular/filters/filters.js:70 -#: static/horizon/js/angular/filters/filters.js:142 -#, c-format -msgid "%s MB" -msgstr "%s MB" - -#: static/horizon/js/angular/filters/filters.js:138 -#, c-format -msgid "%s TB" -msgstr "%s TB" - -#: static/horizon/js/angular/filters/filters.js:144 -#, c-format -msgid "%s KB" -msgstr "%s KB" - -#: static/horizon/js/angular/filters/filters.js:146 -#, c-format -msgid "%s bytes" -msgstr "%s バイト" - -#: static/horizon/js/angular/filters/filters.js:163 -#: static/horizon/js/horizon.tables.js:393 -#, c-format -msgid "Displaying %s item" -msgid_plural "Displaying %s items" -msgstr[0] "%s件表示" - -#: static/horizon/js/angular/services/hz.api.cinder.js:47 -msgid "Unable to retrieve volumes." -msgstr "ボリューム情報を取得できません。" - -#: static/horizon/js/angular/services/hz.api.cinder.js:74 -msgid "Unable to retrieve volume snapshots." -msgstr "ボリュームスナップショットの一覧を取得できません。" - -#: static/horizon/js/angular/services/hz.api.config.js:43 -msgid "Unable to retrieve user configuration." -msgstr "ユーザーの設定を取得できません。" - -#: static/horizon/js/angular/services/hz.api.config.js:62 -msgid "Unable to retrieve admin configuration." -msgstr "管理者の設定を取得できません。" - -#: static/horizon/js/angular/services/hz.api.config.js:105 -msgid "Unable to retrieve settings." -msgstr "設定を取得できません。" - -#: static/horizon/js/angular/services/hz.api.config.js:289 -msgid "Setting is not enabled: %(setting)s" -msgstr "設定 %(setting)s が有効になっていません。" - -#: static/horizon/js/angular/services/hz.api.glance.js:38 -msgid "Unable to retrieve image." -msgstr "イメージ情報を取得できません。" - -#: static/horizon/js/angular/services/hz.api.glance.js:81 -msgid "Unable to retrieve images." -msgstr "イメージ一覧を取得できません。" - -#: static/horizon/js/angular/services/hz.api.glance.js:144 -msgid "Unable to retrieve namespaces." -msgstr "名前空間を取得できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:24 -msgid "Unable to retrieve users" -msgstr "ユーザー一覧を取得できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:31 -msgid "Unable to create the user." -msgstr "ユーザーを作成できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:38 -msgid "Unable to delete the users." -msgstr "ユーザーを削除できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:73 -msgid "Unable to retrieve the current user session." -msgstr "現在のユーザーセッションを取得できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:80 -msgid "Unable to retrieve the user" -msgstr "ユーザーを取得できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:88 -msgid "Unable to edit the user." -msgstr "ユーザーを編集できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:95 -msgid "Unable to delete the user." -msgstr "ユーザーを削除できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:103 -msgid "Unable to retrieve role" -msgstr "ロールを取得できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:110 -msgid "Unable to create the role." -msgstr "ロールを作成できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:117 -msgid "Unable to delete the roles." -msgstr "ロールを削除できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:124 -msgid "Unable to retrieve the role" -msgstr "ロールを取得できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:132 -msgid "Unable to edit the role." -msgstr "ロールを編集できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:139 -msgid "Unable to delete the role." -msgstr "ロールを削除できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:147 -msgid "Unable to retrieve domains" -msgstr "ドメイン一覧を取得できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:154 -msgid "Unable to create the domain." -msgstr "ドメインを作成できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:161 -msgid "Unable to delete the domains." -msgstr "ドメインを削除できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:168 -msgid "Unable to retrieve the domain" -msgstr "ドメインを取得できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:176 -msgid "Unable to edit the domain." -msgstr "ドメインを編集できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:183 -msgid "Unable to delete the domain." -msgstr "ドメインを削除できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:192 -msgid "Unable to retrieve projects" -msgstr "プロジェクト一覧を取得できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:199 -msgid "Unable to create the project." -msgstr "プロジェクトを作成できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:206 -msgid "Unable to delete the projects." -msgstr "プロジェクトを削除できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:213 -msgid "Unable to retrieve the project" -msgstr "プロジェクトを取得できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:221 -msgid "Unable to edit the project." -msgstr "プロジェクトを編集できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:228 -msgid "Unable to delete the project." -msgstr "プロジェクトを削除できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:236 -msgid "Unable to grant the role." -msgstr "ロールを許可できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:250 -msgid "Unable to fetch the service catalog." -msgstr "サービスカタログを取得できません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:385 -msgid "Service type is not enabled: %(desiredType)s" -msgstr "サービスタイプ %(desiredType)s が有効になっていません。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:392 -msgid "Cannot get service catalog from keystone." -msgstr "keystone からサービスカタログを取得できません。" - -#: static/horizon/js/angular/services/hz.api.neutron.js:39 -msgid "Unable to retrieve networks." -msgstr "ネットワーク一覧を取得できません。" - -#: static/horizon/js/angular/services/hz.api.neutron.js:88 -msgid "Unable to create the network." -msgstr "ネットワークを作成できません。" - -#: static/horizon/js/angular/services/hz.api.neutron.js:108 -msgid "Unable to retrieve subnets." -msgstr "サブネットを取得できません。" - -#: static/horizon/js/angular/services/hz.api.neutron.js:172 -msgid "Unable to create the subnet." -msgstr "サブネットを作成できません。" - -#: static/horizon/js/angular/services/hz.api.neutron.js:192 -msgid "Unable to retrieve ports." -msgstr "ポートを取得できません。" - -#: static/horizon/js/angular/services/hz.api.nova.js:40 -msgid "Unable to retrieve keypairs." -msgstr "キーペアの一覧を取得できません。" - -#: static/horizon/js/angular/services/hz.api.nova.js:62 -msgid "Unable to import the keypair." -msgstr "キーペアをインポートできません。" - -#: static/horizon/js/angular/services/hz.api.nova.js:64 -msgid "Unable to create the keypair." -msgstr "キーペアを取得できません。" - -#: static/horizon/js/angular/services/hz.api.nova.js:83 -msgid "Unable to retrieve availability zones." -msgstr "アベイラビリティーゾーンを取得できません。" - -#: static/horizon/js/angular/services/hz.api.nova.js:121 -msgid "Unable to retrieve limits." -msgstr "上限を取得できません。" - -#: static/horizon/js/angular/services/hz.api.nova.js:148 -msgid "Unable to create the server." -msgstr "サーバーを作成できません。" - -#: static/horizon/js/angular/services/hz.api.nova.js:162 -msgid "Unable to retrieve server." -msgstr "サーバーを取得できません。" - -#: static/horizon/js/angular/services/hz.api.nova.js:192 -msgid "Unable to retrieve extensions." -msgstr "拡張機能を取得できません。" - -#: static/horizon/js/angular/services/hz.api.nova.js:237 -msgid "Unable to retrieve flavors." -msgstr "フレーバーの一覧を取得できません。" - -#: static/horizon/js/angular/services/hz.api.nova.js:255 -msgid "Unable to retrieve flavor." -msgstr "フレーバーを取得できません。" - -#: static/horizon/js/angular/services/hz.api.nova.js:269 -msgid "Unable to retrieve flavor extra specs." -msgstr "フレーバーの追加スペックを取得できません。" - -#: static/horizon/js/angular/services/hz.api.nova.js:311 -msgid "Extension is not enabled: %(extension)s" -msgstr "拡張機能 %(extension)s が有効ではありません。" - -#: static/horizon/js/angular/services/hz.api.nova.js:318 -msgid "Cannot get nova extension list." -msgstr "nova の拡張機能一覧を取得できません。" - -#: static/horizon/js/angular/services/hz.api.policy.js:65 -msgid "Policy check failed." -msgstr "ポリシーチェックに失敗しました。" - -#: static/horizon/js/angular/services/hz.api.security-group.js:64 -msgid "Unable to retrieve security groups." -msgstr "セキュリティーグループの一覧を取得できません。" - -#: static/horizon/js/horizon.accordion_nav.js:78 -#: static/horizon/js/horizon.modals.js:315 -#: static/horizon/js/horizon.tabs.js:21 -msgid "Loading" -msgstr "読み込み中" - -#: static/horizon/js/horizon.d3linechart.js:394 -#: static/horizon/js/horizon.d3linechart.js:404 -msgid "No data available." -msgstr "データがありません。" - -#: static/horizon/js/horizon.d3linechart.js:410 -#: static/horizon/js/horizon.modals.js:334 -#: static/horizon/js/horizon.tables_inline_edit.js:94 -#: static/horizon/js/horizon.tables_inline_edit.js:157 -msgid "An error occurred. Please try again later." -msgstr "エラーが発生しました。後からもう一度お試しください。" - -#: static/horizon/js/horizon.firewalls.js:32 -#: static/horizon/js/horizon.instances.js:31 -msgid "There was a problem communicating with the server, please try again." -msgstr "サーバーとの通信中に問題がありました。再度お試しください。" - -#: static/horizon/js/horizon.instances.js:273 -msgid "Could not read the file" -msgstr "ファイルを読み取ることができませんでした。" - -#: static/horizon/js/horizon.instances.js:279 -#: static/horizon/js/horizon.instances.js:308 -msgid "Could not decrypt the password" -msgstr "パスワードの復号化できませんでした。" - -#: static/horizon/js/horizon.membership.js:190 -msgid "No roles" -msgstr "ロールがありません" - -#: static/horizon/js/horizon.membership.js:222 -msgid "Roles" -msgstr "ロール" - -#: static/horizon/js/horizon.messages.js:9 -msgid "Danger: " -msgstr "危険:" - -#: static/horizon/js/horizon.messages.js:10 -msgid "Warning: " -msgstr "警告: " - -#: static/horizon/js/horizon.messages.js:11 -msgid "Notice: " -msgstr "注意:" - -#: static/horizon/js/horizon.messages.js:12 -msgid "Success: " -msgstr "成功: " - -#: static/horizon/js/horizon.messages.js:13 -msgid "Error: " -msgstr "エラー: " - -#: static/horizon/js/horizon.modals.js:229 -#: static/horizon/js/horizon.tables.js:218 -msgid "Working" -msgstr "反映中" - -#: static/horizon/js/horizon.modals.js:263 -msgid "There was an error submitting the form. Please try again." -msgstr "フォームの送信中にエラーが発生しました。再度お試しください。" - -#: static/horizon/js/horizon.networktopology.js:530 -#: static/horizon/js/horizon.networktopology.js:536 -msgid "None" -msgstr "なし" - -#: static/horizon/js/horizon.networktopology.js:549 -msgid "Delete" -msgstr "削除" - -#: static/horizon/js/horizon.networktopology.js:552 -msgid "STATUS" -msgstr "ステータス" - -#: static/horizon/js/horizon.networktopology.js:553 -msgid "ID" -msgstr "ID" - -#: static/horizon/js/horizon.networktopology.js:554 -msgid "Interfaces" -msgstr "インターフェース" - -#: static/horizon/js/horizon.networktopology.js:555 -msgid "Delete Interface" -msgstr "インタフェースの削除" - -#: static/horizon/js/horizon.networktopology.js:556 -msgid "Open Console" -msgstr "コンソールを開く" - -#: static/horizon/js/horizon.networktopology.js:557 -msgid "View Details" -msgstr "詳細の表示" - -#: static/horizon/js/horizon.networktopology.js:560 -msgid "Delete Router" -msgstr "ルーターの削除" - -#: static/horizon/js/horizon.networktopology.js:561 -msgid "View Router Details" -msgstr "ルーターの詳細の表示" - -#: static/horizon/js/horizon.networktopology.js:564 -msgid "Add Interface" -msgstr "インターフェースの追加" - -#: static/horizon/js/horizon.networktopology.js:570 -msgid "Terminate Instance" -msgstr "インスタンスの終了" - -#: static/horizon/js/horizon.networktopology.js:571 -msgid "View Instance Details" -msgstr "インスタンスの詳細の表示" - -#: static/horizon/js/horizon.tables.js:39 -#: static/horizon/js/horizon.tables.js:406 -msgid "No items to display." -msgstr "表示する項目がありません" - -#: static/horizon/js/horizon.tables.js:52 -#: static/horizon/js/horizon.tables.js:120 -msgid "An error occurred while updating." -msgstr "更新中にエラーが発生しました。" - -#: static/horizon/js/horizon.tables.js:201 -#, c-format -msgid "You have selected %s. " -msgstr "%s を選択しました。" - -#: static/horizon/js/horizon.tables.js:203 -#, c-format -msgid "Confirm %s" -msgstr "%sの確認" - -#: static/horizon/js/horizon.tables.js:204 -msgid "Please confirm your selection. " -msgstr "選択内容を確認してください。" - -#: static/horizon/js/horizon.tables_inline_edit.js:88 -#: static/horizon/js/horizon.tables_inline_edit.js:151 -msgid "Not authorized to do this operation." -msgstr "この操作を行う権限がありません。" - -#: static/horizon/js/horizon.users.js:18 -msgid "Passwords do not match." -msgstr "パスワードが一致しません。" diff --git a/code/horizon/horizon/locale/ko_KR/LC_MESSAGES/django.po b/code/horizon/horizon/locale/ko_KR/LC_MESSAGES/django.po deleted file mode 100644 index f97316dc..00000000 --- a/code/horizon/horizon/locale/ko_KR/LC_MESSAGES/django.po +++ /dev/null @@ -1,508 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Ian Y. Choi , 2015 -# Ian Y. Choi , 2015 -# jaekwon.park , 2014 -# Sungjin Kang , 2014-2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-06 21:07-0500\n" -"PO-Revision-Date: 2015-04-06 17:01+0000\n" -"Last-Translator: Sungjin Kang \n" -"Language-Team: Korean (Korea) (http://www.transifex.com/projects/p/horizon/language/ko_KR/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ko_KR\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: base.py:475 -msgid "Other" -msgstr "기타" - -#: browsers/base.py:88 -msgid "Navigation Item" -msgstr "네비게이션 항목" - -#: browsers/views.py:41 -#, python-format -msgid "Select a %s to browse." -msgstr "브라우져에서 %s를 선택하십시오." - -#: conf/default.py:41 -msgid "Password is not accepted" -msgstr "허용되지 않는 비밀번호입니다." - -#: decorators.py:53 -msgid "Please log in to continue." -msgstr "계속 진행하려면 로그인하십시오." - -#: decorators.py:85 -#, python-format -msgid "You are not authorized to access %s" -msgstr "%s에 접근 권한이 없습니다. " - -#: exceptions.py:163 -#, python-format -msgid "A %(resource)s with the name \"%(name)s\" already exists." -msgstr "이름 \"%(name)s\"과 %(resource)s이 이미 존재합니다." - -#: exceptions.py:235 -#, python-format -msgid "Unauthorized: %s" -msgstr "권한이 없습니다: %s" - -#: exceptions.py:238 -msgid "Unauthorized. Please try logging in again." -msgstr "권한이 없습니다. 다시 로그인 해주십시오." - -#: forms/fields.py:64 -msgid "Incorrect format for IP address" -msgstr "IP 주소 형식이 잘못 되었습니다." - -#: forms/fields.py:65 -msgid "Invalid version for IP address" -msgstr "IP 주소 버전이 잘못되었습니다." - -#: forms/fields.py:66 -msgid "Invalid subnet mask" -msgstr "서브넷 마스크가 잘못되었습니다." - -#: forms/views.py:132 templates/horizon/common/_usage_summary.html:16 -msgid "Submit" -msgstr "제출" - -#: forms/views.py:133 -#: templates/horizon/common/_modal_form_update_metadata.html:25 -#: templates/horizon/common/_workflow.html:49 -msgid "Cancel" -msgstr "취소" - -#: middleware.py:103 -msgid "Session timed out." -msgstr "세션 타임 아웃." - -#: tables/actions.py:460 -#: templates/horizon/common/_data_table_table_actions.html:21 -#: templates/horizon/common/_data_table_table_actions.html:33 -#: templates/horizon/common/_workflow_step_update_members.html:14 -#: templates/horizon/common/_workflow_step_update_members.html:23 -msgid "Filter" -msgstr "필터" - -#: tables/actions.py:645 -msgid "This action cannot be undone." -msgstr "이 작업은 취소할 수 없습니다." - -#: tables/actions.py:767 -#, python-format -msgctxt "past" -msgid "%(action)s %(data_type)s" -msgstr "%(data_type)s %(action)s" - -#: tables/actions.py:769 -#, python-format -msgctxt "present" -msgid "%(action)s %(data_type)s" -msgstr "%(data_type)s %(action)s" - -#: tables/actions.py:832 -#, python-format -msgid "You are not allowed to %(action)s: %(objs)s" -msgstr " %(action)s 이(가) 허용되지 않습니다: %(objs)s " - -#: tables/actions.py:839 -#, python-format -msgid "Unable to %(action)s: %(objs)s" -msgstr "%(action)s을(를) 할 수 없습니다.: %(objs)s" - -#: tables/actions.py:845 -#, python-format -msgid "%(action)s: %(objs)s" -msgstr "%(action)s: %(objs)s" - -#: tables/actions.py:915 -msgid "Delete" -msgstr "삭제" - -#: tables/actions.py:917 -msgid "Deleted" -msgstr "삭제 완료" - -#: tables/actions.py:948 -msgid "Update" -msgstr "업데이트" - -#: tables/actions.py:949 -msgid "Updated" -msgstr "업데이트 완료" - -#: tables/base.py:305 -msgid "-" -msgstr "-" - -#: tables/base.py:361 -#, python-format -msgid "The attribute %(attr)s doesn't exist on %(obj)s." -msgstr "%(obj)s 에 %(attr)s 속성이 없습니다." - -#: tables/base.py:990 -msgid "No items to display." -msgstr "표시할 항목이 없습니다." - -#: tables/base.py:1099 -#: templates/horizon/common/_data_table_table_actions.html:47 -msgid "Actions" -msgstr "작업" - -#: tables/base.py:1329 -#, python-format -msgid "No match returned for the id \"%s\"." -msgstr "ID \"%s\" 에 일치되는 항목이 없습니다." - -#: tables/base.py:1486 -msgid "Please select a row before taking that action." -msgstr "해당 작업을 실행하기 전에 열(row)을 선택하십시오." - -#: tables/base.py:1570 -msgid "N/A" -msgstr "N/A" - -#: templates/_header.html:5 -#, python-format -msgid "Logged in as: %(username)s" -msgstr "로그인됨: %(username)s" - -#: templates/_header.html:7 -msgid "Help" -msgstr "도움말" - -#: templates/_header.html:9 -msgid "Sign Out" -msgstr "로그아웃" - -#: templates/auth/_description.html:9 -msgid "" -"\n" -" If you are not sure which authentication method to use, contact your administrator.\n" -" " -msgstr "\n당신이 인증 방법을 모르는경우, 관리자에게 문의하십시오." - -#: templates/auth/_login.html:5 -msgid "Log In" -msgstr "로그인" - -#: templates/auth/_login.html:27 -msgid "You do not have permission to access the resource:" -msgstr "당신은 리소스에 접근할 권한이 없습니다.:" - -#: templates/auth/_login.html:29 -#, python-format -msgid "" -"Login as different user or go back to home " -"page" -msgstr "다른 사용자로 로그인하거나 홈페이지로 되돌아가기" - -#: templates/auth/_login.html:45 -msgid "Sign In" -msgstr "등록" - -#: templates/auth/_login.html:46 -msgid "Connect" -msgstr "연결" - -#: templates/auth/login.html:4 -msgid "Login" -msgstr "로그인" - -#: templates/horizon/_messages.html:7 -msgid "Info: " -msgstr "정보:" - -#: templates/horizon/_messages.html:13 -msgid "Warning: " -msgstr "경고:" - -#: templates/horizon/_messages.html:19 -msgid "Success: " -msgstr "완료:" - -#: templates/horizon/_messages.html:25 -msgid "Error: " -msgstr "오류:" - -#: templates/horizon/common/_data_table.html:63 -msgid "Summary" -msgstr "요약" - -#: templates/horizon/common/_data_table.html:72 -#, python-format -msgid "Displaying %(counter)s item" -msgid_plural "Displaying %(counter)s items" -msgstr[0] "%(counter)s 항목 표시" - -#: templates/horizon/common/_data_table.html:77 -msgid "« Prev" -msgstr "« 이전" - -#: templates/horizon/common/_data_table.html:80 -msgid "Next »" -msgstr "다음 »" - -#: templates/horizon/common/_data_table_table_actions.html:45 -msgid "More Actions" -msgstr "기타 작업" - -#: templates/horizon/common/_domain_page_header.html:6 -#, python-format -msgid "%(context_name)s:" -msgstr "%(context_name)s:" - -#: templates/horizon/common/_formset_table.html:35 -msgid "Add a row" -msgstr "열 추가" - -#: templates/horizon/common/_formset_table_row.html:15 -#, python-format -msgid "%(name)s: %(error)s" -msgstr "%(name)s: %(error)s" - -#: templates/horizon/common/_limit_summary.html:4 -msgid "Limit Summary" -msgstr "간략한 요약" - -#: templates/horizon/common/_limit_summary.html:7 -msgid "Instances" -msgstr "인스턴스" - -#: templates/horizon/common/_limit_summary.html:8 -#: templates/horizon/common/_limit_summary.html:15 -#: templates/horizon/common/_limit_summary.html:22 -#: templates/horizon/common/_limit_summary.html:36 -#: templates/horizon/common/_limit_summary.html:43 -#: templates/horizon/common/_limit_summary.html:50 -#, python-format -msgid "Used %(used)s of %(available)s " -msgstr " %(available)s 중에서 %(used)s 사용" - -#: templates/horizon/common/_limit_summary.html:14 -msgid "VCPUs" -msgstr "VCPUs" - -#: templates/horizon/common/_limit_summary.html:21 -msgid "RAM" -msgstr "RAM" - -#: templates/horizon/common/_limit_summary.html:28 -msgid "Floating IPs" -msgstr "유동 IP" - -#: templates/horizon/common/_limit_summary.html:29 -#, python-format -msgid "Allocated %(used)s of %(available)s " -msgstr " %(available)s 중에서 %(used)s 할당" - -#: templates/horizon/common/_limit_summary.html:35 -msgid "Security Groups" -msgstr "보안 그룹" - -#: templates/horizon/common/_limit_summary.html:42 -msgid "Volumes" -msgstr "볼륨" - -#: templates/horizon/common/_limit_summary.html:49 -msgid "Volume Storage" -msgstr "볼륨 스토리지" - -#: templates/horizon/common/_modal_form_update_metadata.html:24 -#: workflows/base.py:594 -msgid "Save" -msgstr "저장" - -#: templates/horizon/common/_resource_browser.html:10 -#, python-format -msgid "Displaying %(nav_items)s item" -msgid_plural "Displaying %(nav_items)s items" -msgstr[0] "%(nav_items)s 항목 표시" - -#: templates/horizon/common/_resource_browser.html:11 -#, python-format -msgid "Displaying %(content_items)s item" -msgid_plural "Displaying %(content_items)s items" -msgstr[0] "%(content_items)s 항목 표시" - -#: templates/horizon/common/_usage_summary.html:3 -msgid "Usage Summary" -msgstr "사용량 요약" - -#: templates/horizon/common/_usage_summary.html:7 -msgid "Select a period of time to query its usage:" -msgstr "사용량을 조회할 기간을 선택하세요:" - -#: templates/horizon/common/_usage_summary.html:9 -#, python-format -msgid "" -"\n" -" %(start)s" -msgstr "\n %(start)s" - -#: templates/horizon/common/_usage_summary.html:13 -#, python-format -msgid "" -"\n" -" %(end)s" -msgstr "\n%(end)s" - -#: templates/horizon/common/_usage_summary.html:17 -msgid "The date should be in YYYY-mm-dd format." -msgstr "날짜는 YYYY-mm-dd 형식이어야 합니다." - -#: templates/horizon/common/_usage_summary.html:20 -msgid "Active Instances:" -msgstr "동작 중인 인스턴스:" - -#: templates/horizon/common/_usage_summary.html:21 -msgid "Active RAM:" -msgstr "사용 중인 RAM:" - -#: templates/horizon/common/_usage_summary.html:22 -msgid "This Period's VCPU-Hours:" -msgstr "이 기간의 VCPU 사용 시간:" - -#: templates/horizon/common/_usage_summary.html:23 -msgid "This Period's GB-Hours:" -msgstr "이 기간의 GB-Hours 사용 시간:" - -#: templates/horizon/common/_usage_summary.html:24 -msgid "This Period's RAM-Hours:" -msgstr "이 기간의 RAM 사용 시간:" - -#: templates/horizon/common/_workflow.html:40 -msgid "Back" -msgstr "뒤로" - -#: templates/horizon/common/_workflow.html:43 -msgid "Next" -msgstr "다음" - -#: templatetags/branding.py:34 -msgid "Horizon" -msgstr "Horizon" - -#: templatetags/horizon.py:137 templatetags/horizon.py:148 -msgid "No Limit" -msgstr "제한 없음" - -#: templatetags/horizon.py:140 templatetags/horizon.py:142 -msgid "Available" -msgstr "사용 가능" - -#: templatetags/sizeformat.py:51 templatetags/sizeformat.py:56 -#, python-format -msgid "%(size)d Byte" -msgid_plural "%(size)d Bytes" -msgstr[0] "%(size)d 바이트" - -#: templatetags/sizeformat.py:59 -#, python-format -msgid "%s KB" -msgstr "%s KB" - -#: templatetags/sizeformat.py:61 -#, python-format -msgid "%s MB" -msgstr "%s MB" - -#: templatetags/sizeformat.py:63 -#, python-format -msgid "%s GB" -msgstr "%s GB" - -#: templatetags/sizeformat.py:65 -#, python-format -msgid "%s TB" -msgstr "%s TB" - -#: templatetags/sizeformat.py:66 -#, python-format -msgid "%s PB" -msgstr "%s PB" - -#: templatetags/sizeformat.py:74 -msgid "0 Bytes" -msgstr "0 Bytes" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:31 -msgid "Sell Puppy" -msgid_plural "Sell Puppies" -msgstr[0] "강아지 판매" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:40 -msgid "Sold Puppy" -msgid_plural "Sold Puppies" -msgstr[0] "강아지 판매함" - -#: test/tests/views.py:59 -msgid "Fake" -msgstr "페이크" - -#: utils/filters.py:49 -msgid "Never" -msgstr "없음" - -#: utils/validators.py:26 utils/validators.py:50 -msgid "Not a valid port number" -msgstr "유효하지 않은 포트 번호" - -#: utils/validators.py:31 -msgid "Not a valid IP protocol number" -msgstr "유효하지 않은 IP 프로토콜 번호" - -#: utils/validators.py:45 -msgid "One colon allowed in port range" -msgstr "포트 범위에서 콜론은 하나만 사용할 수 있습니다." - -#: utils/validators.py:52 -msgid "Port number must be integer" -msgstr "포트 번호는 정수이어야 합니다." - -#: utils/validators.py:59 -msgid "The string may only contain ASCII printable characters." -msgstr "문자열은 ASCII 인쇄 문자를 포함할 수 있습니다." - -#: workflows/base.py:71 -msgid "Processing..." -msgstr "작업 중..." - -#: workflows/base.py:475 -msgid "All available" -msgstr "모두 사용가능" - -#: workflows/base.py:476 -msgid "Members" -msgstr "구성원" - -#: workflows/base.py:477 -msgid "None available." -msgstr "사용할 수 있는 것이 없음." - -#: workflows/base.py:478 -msgid "No members." -msgstr "구성원이 없습니다." - -#: workflows/base.py:595 -#, python-format -msgid "%s completed successfully." -msgstr "%s가 성공적으로 완료되었습니다." - -#: workflows/base.py:596 -#, python-format -msgid "%s did not complete." -msgstr "%s가 완료되지 않았습니다." diff --git a/code/horizon/horizon/locale/ko_KR/LC_MESSAGES/djangojs.po b/code/horizon/horizon/locale/ko_KR/LC_MESSAGES/djangojs.po deleted file mode 100644 index 0ee47a4b..00000000 --- a/code/horizon/horizon/locale/ko_KR/LC_MESSAGES/djangojs.po +++ /dev/null @@ -1,621 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Ian Y. Choi , 2015 -# jaekwon.park , 2014 -# jaekwon.park , 2014 -# Sungjin Kang , 2014-2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-11 11:47-0500\n" -"PO-Revision-Date: 2015-04-12 02:21+0000\n" -"Last-Translator: Sungjin Kang \n" -"Language-Team: Korean (Korea) (http://www.transifex.com/projects/p/horizon/language/ko_KR/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ko_KR\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: static/angular/action-list/button-tooltip.js:15 -msgid "" -"The action cannot be performed. The contents of this row have errors or are " -"missing information." -msgstr "작업을 진행할 수 없습니다. 이 행의 내용에 오류가 있거나 정보가 누락되어 있습니다." - -#: static/angular/metadata-display/metadata-display.js:33 -msgid "Detail Information" -msgstr "상세 정보" - -#: static/angular/metadata-tree/metadata-tree.js:35 -msgid "" -"You can specify resource metadata by moving items from the left column to " -"the right column. In the left columns there are metadata definitions from " -"the Glance Metadata Catalog. Use the \"Other\" option to add metadata with " -"the key of your choice." -msgstr "왼쪽 열에서 오른쪽 열로 항목을 이동하여 리소스 메타데이터를 지정할 수 있습니다. 왼쪽 열에서 Glance 메타데이터 카탈로그에서 메타데이터를 정의할 수 있습니다. \"Other\" 옵션을 사용하여 선택한 키를 메타데이터에 추가할 수 있습니다." - -#: static/angular/metadata-tree/metadata-tree.js:36 -msgid "Min" -msgstr "최소" - -#: static/angular/metadata-tree/metadata-tree.js:37 -msgid "Max" -msgstr "최대" - -#: static/angular/metadata-tree/metadata-tree.js:38 -msgid "Min length" -msgstr "최소 길이" - -#: static/angular/metadata-tree/metadata-tree.js:39 -msgid "Max length" -msgstr "최대 길이" - -#: static/angular/metadata-tree/metadata-tree.js:40 -msgid "Pattern mismatch" -msgstr "패턴 불일치" - -#: static/angular/metadata-tree/metadata-tree.js:41 -msgid "Integer required" -msgstr "정수 필요" - -#: static/angular/metadata-tree/metadata-tree.js:42 -msgid "Decimal required" -msgstr "실수 필요" - -#: static/angular/metadata-tree/metadata-tree.js:43 -msgid "Required" -msgstr "필요" - -#: static/angular/metadata-tree/metadata-tree.js:44 -msgid "Duplicate keys are not allowed" -msgstr "중복 키를 허용하지 않습니다." - -#: static/angular/metadata-tree/metadata-tree.js:45 -#: static/angular/table/basic-table.js:6 -#: static/horizon/js/horizon.forms.js:184 -msgid "Filter" -msgstr "필터" - -#: static/angular/metadata-tree/metadata-tree.js:46 -msgid "Available Metadata" -msgstr "사용 가능한 메타데이터" - -#: static/angular/metadata-tree/metadata-tree.js:47 -msgid "Existing Metadata" -msgstr "기존 메타데이터" - -#: static/angular/metadata-tree/metadata-tree.js:48 -msgid "Custom" -msgstr "사용자 지정" - -#: static/angular/metadata-tree/metadata-tree.js:49 -msgid "No available metadata" -msgstr "사용 가능한 메타데이터가 없습니다." - -#: static/angular/metadata-tree/metadata-tree.js:50 -msgid "No existing metadata" -msgstr "기존 메타데이터가 없습니다." - -#: static/angular/modal/modal.js:83 -msgid "Submit" -msgstr "제출" - -#: static/angular/modal/modal.js:84 static/angular/wizard/wizard.js:11 -#: static/horizon/js/horizon.modals.js:33 -msgid "Cancel" -msgstr "취소" - -#: static/angular/transfer-table/transfer-table.js:39 -msgid "Allocated" -msgstr "할당됨" - -#: static/angular/transfer-table/transfer-table.js:40 -msgid "Available" -msgstr "사용 가능" - -#: static/angular/transfer-table/transfer-table.js:41 -msgid "Select one" -msgstr "하나 선택" - -#: static/angular/transfer-table/transfer-table.js:42 -msgid "Select an item from Available items below" -msgstr "아래의 사용 가능한 항목에서 항목을 선택" - -#: static/angular/transfer-table/transfer-table.js:43 -msgid "No available items" -msgstr "사용 가능한 항목 없음" - -#: static/angular/transfer-table/transfer-table.js:44 -msgid "Expand to see allocated items" -msgstr "할당된 항목을 볼 수 있도록 확장" - -#: static/angular/transfer-table/transfer-table.js:45 -msgid "Expand to see available items" -msgstr "사용 가능한 항목을 볼 수 있도록 확장" - -#: static/angular/transfer-table/transfer-table.js:46 -msgid "Click to show or hide" -msgstr "클릭하여 보기 또는 감추기" - -#: static/angular/transfer-table/transfer-table.js:47 -msgid "Re-order items using drag and drop" -msgstr "다시 주문할 아이템은 드래그 앤 드롭으로 가져옵니다." - -#: static/angular/transfer-table/transfer-table.js:48 -msgid "Click to see more details" -msgstr "클릭하여 세부 사항 보기" - -#: static/angular/transfer-table/transfer-table.js:100 -msgid "Found %(found)s of %(total)s" -msgstr "%(total)s 의 %(found)s 찾기" - -#: static/angular/transfer-table/transfer-table.js:166 -msgid "Click here to expand the row and view the errors." -msgstr "클릭하여 열을 확장하고 에러를 확인할 수 있습니다." - -#: static/angular/wizard/wizard.js:12 -msgid "Back" -msgstr "뒤로" - -#: static/angular/wizard/wizard.js:13 -msgid "Next" -msgstr "다음" - -#: static/angular/wizard/wizard.js:14 -msgid "Finish" -msgstr "완료" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Connecting" -msgstr "연결중" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Open" -msgstr "열림" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closing" -msgstr "닫는중" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closed" -msgstr "닫음" - -#: static/horizon/js/angular/directives/serialConsole.js:85 -#, c-format -msgid "Status: %s" -msgstr "상태: %s" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "Yes" -msgstr "예" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "No" -msgstr "아니오" - -#: static/horizon/js/angular/filters/filters.js:53 -#: static/horizon/js/angular/filters/filters.js:140 -#, c-format -msgid "%s GB" -msgstr "%s GB" - -#: static/horizon/js/angular/filters/filters.js:70 -#: static/horizon/js/angular/filters/filters.js:142 -#, c-format -msgid "%s MB" -msgstr "%s MB" - -#: static/horizon/js/angular/filters/filters.js:138 -#, c-format -msgid "%s TB" -msgstr "%s TB" - -#: static/horizon/js/angular/filters/filters.js:144 -#, c-format -msgid "%s KB" -msgstr "%s KB" - -#: static/horizon/js/angular/filters/filters.js:146 -#, c-format -msgid "%s bytes" -msgstr "%s 바이트" - -#: static/horizon/js/angular/filters/filters.js:163 -#: static/horizon/js/horizon.tables.js:393 -#, c-format -msgid "Displaying %s item" -msgid_plural "Displaying %s items" -msgstr[0] "%s 항목 표시" - -#: static/horizon/js/angular/services/hz.api.cinder.js:47 -msgid "Unable to retrieve volumes." -msgstr "볼륨을 찾지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.cinder.js:74 -msgid "Unable to retrieve volume snapshots." -msgstr "볼륨 스냅샷을 찾지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.config.js:43 -msgid "Unable to retrieve user configuration." -msgstr "사용자 구성을 찾지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.config.js:62 -msgid "Unable to retrieve admin configuration." -msgstr "관리자 구성을 찾지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.config.js:105 -msgid "Unable to retrieve settings." -msgstr "설정을 찾지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.config.js:289 -msgid "Setting is not enabled: %(setting)s" -msgstr "설정을 활성하지 못했습니다: %(setting)s" - -#: static/horizon/js/angular/services/hz.api.glance.js:38 -msgid "Unable to retrieve image." -msgstr "이미지를 찾지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.glance.js:81 -msgid "Unable to retrieve images." -msgstr "이미지를 찾지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.glance.js:144 -msgid "Unable to retrieve namespaces." -msgstr "네임스페이스를 찾지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:24 -msgid "Unable to retrieve users" -msgstr "사용자를 찾지 못했습니다" - -#: static/horizon/js/angular/services/hz.api.keystone.js:31 -msgid "Unable to create the user." -msgstr "사용자를 만들지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:38 -msgid "Unable to delete the users." -msgstr "사용자를 삭제하지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:73 -msgid "Unable to retrieve the current user session." -msgstr "현재 사용자 섹션을 찾을 수 없습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:80 -msgid "Unable to retrieve the user" -msgstr "사용자를 찾지 못했습니다" - -#: static/horizon/js/angular/services/hz.api.keystone.js:88 -msgid "Unable to edit the user." -msgstr "사용자를 수정하지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:95 -msgid "Unable to delete the user." -msgstr "사용자를 삭제하지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:103 -msgid "Unable to retrieve role" -msgstr "Role을 찾지 못했습니다" - -#: static/horizon/js/angular/services/hz.api.keystone.js:110 -msgid "Unable to create the role." -msgstr "Role을 만들지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:117 -msgid "Unable to delete the roles." -msgstr "Role을 삭제하지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:124 -msgid "Unable to retrieve the role" -msgstr "Role을 찾지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:132 -msgid "Unable to edit the role." -msgstr "Role을 수정하지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:139 -msgid "Unable to delete the role." -msgstr "Role을 삭제하지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:147 -msgid "Unable to retrieve domains" -msgstr "도메인을 찾지 못했습니다" - -#: static/horizon/js/angular/services/hz.api.keystone.js:154 -msgid "Unable to create the domain." -msgstr "도메인을 만들지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:161 -msgid "Unable to delete the domains." -msgstr "도메인을 삭제하지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:168 -msgid "Unable to retrieve the domain" -msgstr "도메인을 찾지 못했습니다" - -#: static/horizon/js/angular/services/hz.api.keystone.js:176 -msgid "Unable to edit the domain." -msgstr "도메인을 수정하지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:183 -msgid "Unable to delete the domain." -msgstr "도메인을 삭제하지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:192 -msgid "Unable to retrieve projects" -msgstr "프로젝트를 찾지 못했습니다" - -#: static/horizon/js/angular/services/hz.api.keystone.js:199 -msgid "Unable to create the project." -msgstr "프로젝트를 만들지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:206 -msgid "Unable to delete the projects." -msgstr "프로젝트를 삭제하지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:213 -msgid "Unable to retrieve the project" -msgstr "프로젝트를 찾지 못했습니다" - -#: static/horizon/js/angular/services/hz.api.keystone.js:221 -msgid "Unable to edit the project." -msgstr "프로젝트를 수정하지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:228 -msgid "Unable to delete the project." -msgstr "프로젝트를 삭제하지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:236 -msgid "Unable to grant the role." -msgstr "Role을 부여하지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:250 -msgid "Unable to fetch the service catalog." -msgstr "서비스 카탈로그를 가져올 수 없습니다." - -#: static/horizon/js/angular/services/hz.api.keystone.js:385 -msgid "Service type is not enabled: %(desiredType)s" -msgstr "서비스 타입을 활성화하지 못 했습니다: %(desiredType)s" - -#: static/horizon/js/angular/services/hz.api.keystone.js:392 -msgid "Cannot get service catalog from keystone." -msgstr "Keystone으로부터 서비스 목록을 가져올 수 없습니다." - -#: static/horizon/js/angular/services/hz.api.neutron.js:39 -msgid "Unable to retrieve networks." -msgstr "네트워크를 찾지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.neutron.js:88 -msgid "Unable to create the network." -msgstr "네트워크를 생성하지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.neutron.js:108 -msgid "Unable to retrieve subnets." -msgstr "서브넷을 찾지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.neutron.js:172 -msgid "Unable to create the subnet." -msgstr "서브넷을 생성하지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.neutron.js:192 -msgid "Unable to retrieve ports." -msgstr "포트를 검색하지 못했습니다" - -#: static/horizon/js/angular/services/hz.api.nova.js:40 -msgid "Unable to retrieve keypairs." -msgstr "Keypair를 찾을 수 없습니다." - -#: static/horizon/js/angular/services/hz.api.nova.js:62 -msgid "Unable to import the keypair." -msgstr "키페어를 가져올 수 없습니다." - -#: static/horizon/js/angular/services/hz.api.nova.js:64 -msgid "Unable to create the keypair." -msgstr "Keypair를 생성하지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.nova.js:83 -msgid "Unable to retrieve availability zones." -msgstr "가용성 존에 대한 정보를 찾지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.nova.js:121 -msgid "Unable to retrieve limits." -msgstr "제한을 찾지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.nova.js:148 -msgid "Unable to create the server." -msgstr "서버를 생성하지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.nova.js:162 -msgid "Unable to retrieve server." -msgstr "서버를 찾지 못했습니다" - -#: static/horizon/js/angular/services/hz.api.nova.js:192 -msgid "Unable to retrieve extensions." -msgstr "확장을 찾지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.nova.js:237 -msgid "Unable to retrieve flavors." -msgstr "Flavor를 찾지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.nova.js:255 -msgid "Unable to retrieve flavor." -msgstr "Flavor를 찾지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.nova.js:269 -msgid "Unable to retrieve flavor extra specs." -msgstr "Flavor 확장 스팩을 찾지 못했습니다." - -#: static/horizon/js/angular/services/hz.api.nova.js:311 -msgid "Extension is not enabled: %(extension)s" -msgstr "확장을 활성화하지 못 했습니다: %(extension)s" - -#: static/horizon/js/angular/services/hz.api.nova.js:318 -msgid "Cannot get nova extension list." -msgstr "Nova 확장 목록을 가져올 수 없습니다." - -#: static/horizon/js/angular/services/hz.api.policy.js:65 -msgid "Policy check failed." -msgstr "정책 확인 실패함." - -#: static/horizon/js/angular/services/hz.api.security-group.js:64 -msgid "Unable to retrieve security groups." -msgstr "시큐리티 그룹을 찾지 못했습니다." - -#: static/horizon/js/horizon.accordion_nav.js:78 -#: static/horizon/js/horizon.modals.js:315 -#: static/horizon/js/horizon.tabs.js:21 -msgid "Loading" -msgstr "불러오는 중" - -#: static/horizon/js/horizon.d3linechart.js:394 -#: static/horizon/js/horizon.d3linechart.js:404 -msgid "No data available." -msgstr "데이터가 없습니다." - -#: static/horizon/js/horizon.d3linechart.js:410 -#: static/horizon/js/horizon.modals.js:334 -#: static/horizon/js/horizon.tables_inline_edit.js:94 -#: static/horizon/js/horizon.tables_inline_edit.js:157 -msgid "An error occurred. Please try again later." -msgstr "오류가 발생했습니다. 나중에 다시 시도하십시오." - -#: static/horizon/js/horizon.firewalls.js:32 -#: static/horizon/js/horizon.instances.js:31 -msgid "There was a problem communicating with the server, please try again." -msgstr "서버와의 통신에 문제가 발생하였으니, 다시 시도하세요." - -#: static/horizon/js/horizon.instances.js:273 -msgid "Could not read the file" -msgstr "파일을 읽을 수 없습니다" - -#: static/horizon/js/horizon.instances.js:279 -#: static/horizon/js/horizon.instances.js:308 -msgid "Could not decrypt the password" -msgstr "암호를 해독할 수 없습니다." - -#: static/horizon/js/horizon.membership.js:190 -msgid "No roles" -msgstr "Role 없음" - -#: static/horizon/js/horizon.membership.js:222 -msgid "Roles" -msgstr "Roles" - -#: static/horizon/js/horizon.messages.js:9 -msgid "Danger: " -msgstr "위험:" - -#: static/horizon/js/horizon.messages.js:10 -msgid "Warning: " -msgstr "경고:" - -#: static/horizon/js/horizon.messages.js:11 -msgid "Notice: " -msgstr "주의:" - -#: static/horizon/js/horizon.messages.js:12 -msgid "Success: " -msgstr "완료:" - -#: static/horizon/js/horizon.messages.js:13 -msgid "Error: " -msgstr "오류:" - -#: static/horizon/js/horizon.modals.js:229 -#: static/horizon/js/horizon.tables.js:218 -msgid "Working" -msgstr "작동 중" - -#: static/horizon/js/horizon.modals.js:263 -msgid "There was an error submitting the form. Please try again." -msgstr "양식을 제출하는 동안 오류가 발생하였습니다. 다시 시도하세요." - -#: static/horizon/js/horizon.networktopology.js:530 -#: static/horizon/js/horizon.networktopology.js:536 -msgid "None" -msgstr "None" - -#: static/horizon/js/horizon.networktopology.js:549 -msgid "Delete" -msgstr "삭제" - -#: static/horizon/js/horizon.networktopology.js:552 -msgid "STATUS" -msgstr "STATUS" - -#: static/horizon/js/horizon.networktopology.js:553 -msgid "ID" -msgstr "ID" - -#: static/horizon/js/horizon.networktopology.js:554 -msgid "Interfaces" -msgstr "인터페이스" - -#: static/horizon/js/horizon.networktopology.js:555 -msgid "Delete Interface" -msgstr "인터페이스 삭제" - -#: static/horizon/js/horizon.networktopology.js:556 -msgid "Open Console" -msgstr "콘솔 열기" - -#: static/horizon/js/horizon.networktopology.js:557 -msgid "View Details" -msgstr "세부 정보 보기" - -#: static/horizon/js/horizon.networktopology.js:560 -msgid "Delete Router" -msgstr "라우터 삭제" - -#: static/horizon/js/horizon.networktopology.js:561 -msgid "View Router Details" -msgstr "라우터 정보 자세히 보기" - -#: static/horizon/js/horizon.networktopology.js:564 -msgid "Add Interface" -msgstr "인터페이스 추가" - -#: static/horizon/js/horizon.networktopology.js:570 -msgid "Terminate Instance" -msgstr "인스턴스 종료" - -#: static/horizon/js/horizon.networktopology.js:571 -msgid "View Instance Details" -msgstr "인스턴스 정보 자세히 보기" - -#: static/horizon/js/horizon.tables.js:39 -#: static/horizon/js/horizon.tables.js:406 -msgid "No items to display." -msgstr "표시할 항목이 없습니다." - -#: static/horizon/js/horizon.tables.js:52 -#: static/horizon/js/horizon.tables.js:120 -msgid "An error occurred while updating." -msgstr "업데이트 도중 오류가 발생하였습니다." - -#: static/horizon/js/horizon.tables.js:201 -#, c-format -msgid "You have selected %s. " -msgstr "%s를 선택하였습니다. " - -#: static/horizon/js/horizon.tables.js:203 -#, c-format -msgid "Confirm %s" -msgstr "%s를 확인하세요." - -#: static/horizon/js/horizon.tables.js:204 -msgid "Please confirm your selection. " -msgstr "선택 사항을 확인하십시오." - -#: static/horizon/js/horizon.tables_inline_edit.js:88 -#: static/horizon/js/horizon.tables_inline_edit.js:151 -msgid "Not authorized to do this operation." -msgstr "이 작업에 대한 권한이 없습니다." - -#: static/horizon/js/horizon.users.js:18 -msgid "Passwords do not match." -msgstr "비밀번호가 일치하지 않습니다." diff --git a/code/horizon/horizon/locale/pl_PL/LC_MESSAGES/django.po b/code/horizon/horizon/locale/pl_PL/LC_MESSAGES/django.po deleted file mode 100644 index c253aa63..00000000 --- a/code/horizon/horizon/locale/pl_PL/LC_MESSAGES/django.po +++ /dev/null @@ -1,517 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Łukasz Jernaś , 2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-07 01:16-0500\n" -"PO-Revision-Date: 2015-04-21 12:54+0000\n" -"Last-Translator: Łukasz Jernaś \n" -"Language-Team: Polish (Poland) (http://www.transifex.com/projects/p/horizon/language/pl_PL/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: pl_PL\n" -"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - -#: base.py:475 -msgid "Other" -msgstr "Inne" - -#: browsers/base.py:88 -msgid "Navigation Item" -msgstr "Pozycja nawigacyjna" - -#: browsers/views.py:41 -#, python-format -msgid "Select a %s to browse." -msgstr "Wybierz %s by przeglądać." - -#: conf/default.py:41 -msgid "Password is not accepted" -msgstr "Hasło nie zostało zaakceptowane" - -#: decorators.py:53 -msgid "Please log in to continue." -msgstr "Należy się zalogować, aby można było kontynuować." - -#: decorators.py:85 -#, python-format -msgid "You are not authorized to access %s" -msgstr "Brak uprawnień dostępu do %s" - -#: exceptions.py:163 -#, python-format -msgid "A %(resource)s with the name \"%(name)s\" already exists." -msgstr "%(resource)s o nazwie \"%(name)s\" już istnieje." - -#: exceptions.py:235 -#, python-format -msgid "Unauthorized: %s" -msgstr "Nieupoważniono: %s" - -#: exceptions.py:238 -msgid "Unauthorized. Please try logging in again." -msgstr "Brak uprawnień. Proszę spróbować się wylogować i zalogować ponownie." - -#: forms/fields.py:64 -msgid "Incorrect format for IP address" -msgstr "Błędny format adresu IP" - -#: forms/fields.py:65 -msgid "Invalid version for IP address" -msgstr "Błędna wersja adresu IP" - -#: forms/fields.py:66 -msgid "Invalid subnet mask" -msgstr "Błędna maska podsieci" - -#: forms/views.py:132 templates/horizon/common/_usage_summary.html:16 -msgid "Submit" -msgstr "Wyślij" - -#: forms/views.py:133 -#: templates/horizon/common/_modal_form_update_metadata.html:25 -#: templates/horizon/common/_workflow.html:49 -msgid "Cancel" -msgstr "Anuluj" - -#: middleware.py:103 -msgid "Session timed out." -msgstr "Sesja wygasła." - -#: tables/actions.py:460 -#: templates/horizon/common/_data_table_table_actions.html:21 -#: templates/horizon/common/_data_table_table_actions.html:33 -#: templates/horizon/common/_workflow_step_update_members.html:14 -#: templates/horizon/common/_workflow_step_update_members.html:23 -msgid "Filter" -msgstr "Filtr" - -#: tables/actions.py:645 -msgid "This action cannot be undone." -msgstr "Tej czynności nie można cofnąć." - -#: tables/actions.py:767 -#, python-format -msgctxt "past" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:769 -#, python-format -msgctxt "present" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:832 -#, python-format -msgid "You are not allowed to %(action)s: %(objs)s" -msgstr "Brak uprawnień do %(action)s: %(objs)s" - -#: tables/actions.py:839 -#, python-format -msgid "Unable to %(action)s: %(objs)s" -msgstr "Nie można %(action)s: %(objs)s" - -#: tables/actions.py:845 -#, python-format -msgid "%(action)s: %(objs)s" -msgstr "%(action)s: %(objs)s" - -#: tables/actions.py:915 -msgid "Delete" -msgstr "Usuń" - -#: tables/actions.py:917 -msgid "Deleted" -msgstr "Usunięto" - -#: tables/actions.py:948 -msgid "Update" -msgstr "Aktualizuj" - -#: tables/actions.py:949 -msgid "Updated" -msgstr "Zaktualizowany" - -#: tables/base.py:305 -msgid "-" -msgstr "-" - -#: tables/base.py:361 -#, python-format -msgid "The attribute %(attr)s doesn't exist on %(obj)s." -msgstr "Atrybut %(attr)s nie istnieje dla %(obj)s." - -#: tables/base.py:990 -msgid "No items to display." -msgstr "Brak pozycji do wyświetlenia." - -#: tables/base.py:1099 -#: templates/horizon/common/_data_table_table_actions.html:47 -msgid "Actions" -msgstr "Czynności" - -#: tables/base.py:1329 -#, python-format -msgid "No match returned for the id \"%s\"." -msgstr "Nie znaleziono wyników dla identyfikatora „%s”." - -#: tables/base.py:1486 -msgid "Please select a row before taking that action." -msgstr "Należy wybrać wiersz przed wykonaniem tej czynności." - -#: tables/base.py:1570 -msgid "N/A" -msgstr "n.d." - -#: templates/_header.html:5 -#, python-format -msgid "Logged in as: %(username)s" -msgstr "Zalogowano jako: %(username)s" - -#: templates/_header.html:7 -msgid "Help" -msgstr "Pomoc" - -#: templates/_header.html:9 -msgid "Sign Out" -msgstr "Wyloguj" - -#: templates/auth/_description.html:9 -msgid "" -"\n" -" If you are not sure which authentication method to use, contact your administrator.\n" -" " -msgstr "\nJeśli nie wiadomo, którego sposobu uwierzytelniania użyć, należy skontaktować się z administratorem." - -#: templates/auth/_login.html:5 -msgid "Log In" -msgstr "Zaloguj" - -#: templates/auth/_login.html:27 -msgid "You do not have permission to access the resource:" -msgstr "Brak uprawnień do zasobu:" - -#: templates/auth/_login.html:29 -#, python-format -msgid "" -"Login as different user or go back to home " -"page" -msgstr "Należy zalogować się jako inny użytkownik lub wrócić do strony domowej" - -#: templates/auth/_login.html:45 -msgid "Sign In" -msgstr "Wpisz się" - -#: templates/auth/_login.html:46 -msgid "Connect" -msgstr "Połącz" - -#: templates/auth/login.html:4 -msgid "Login" -msgstr "Login" - -#: templates/horizon/_messages.html:7 -msgid "Info: " -msgstr "Informacja:" - -#: templates/horizon/_messages.html:13 -msgid "Warning: " -msgstr "Ostrzeżenie:" - -#: templates/horizon/_messages.html:19 -msgid "Success: " -msgstr "Powodzenie:" - -#: templates/horizon/_messages.html:25 -msgid "Error: " -msgstr "Błąd:" - -#: templates/horizon/common/_data_table.html:63 -msgid "Summary" -msgstr "Podsumowanie" - -#: templates/horizon/common/_data_table.html:72 -#, python-format -msgid "Displaying %(counter)s item" -msgid_plural "Displaying %(counter)s items" -msgstr[0] "Wyświetlanie %(counter)s pozycji" -msgstr[1] "Wyświetlanie %(counter)s pozycji" -msgstr[2] "Wyświetlanie %(counter)s pozycji" - -#: templates/horizon/common/_data_table.html:77 -msgid "« Prev" -msgstr "« Poprzednie" - -#: templates/horizon/common/_data_table.html:80 -msgid "Next »" -msgstr "Następne »" - -#: templates/horizon/common/_data_table_table_actions.html:45 -msgid "More Actions" -msgstr "Pozostałe akcje" - -#: templates/horizon/common/_domain_page_header.html:6 -#, python-format -msgid "%(context_name)s:" -msgstr "%(context_name)s:" - -#: templates/horizon/common/_formset_table.html:35 -msgid "Add a row" -msgstr "Dodaj wiersz" - -#: templates/horizon/common/_formset_table_row.html:15 -#, python-format -msgid "%(name)s: %(error)s" -msgstr "%(name)s: %(error)s" - -#: templates/horizon/common/_limit_summary.html:4 -msgid "Limit Summary" -msgstr "Podsumowanie limitów" - -#: templates/horizon/common/_limit_summary.html:7 -msgid "Instances" -msgstr "Instancje" - -#: templates/horizon/common/_limit_summary.html:8 -#: templates/horizon/common/_limit_summary.html:15 -#: templates/horizon/common/_limit_summary.html:22 -#: templates/horizon/common/_limit_summary.html:36 -#: templates/horizon/common/_limit_summary.html:43 -#: templates/horizon/common/_limit_summary.html:50 -#, python-format -msgid "Used %(used)s of %(available)s " -msgstr "Wykorzystano %(used)s z %(available)s " - -#: templates/horizon/common/_limit_summary.html:14 -msgid "VCPUs" -msgstr "VCPU" - -#: templates/horizon/common/_limit_summary.html:21 -msgid "RAM" -msgstr "RAM" - -#: templates/horizon/common/_limit_summary.html:28 -msgid "Floating IPs" -msgstr "Pływające adresy IP" - -#: templates/horizon/common/_limit_summary.html:29 -#, python-format -msgid "Allocated %(used)s of %(available)s " -msgstr "Przydzielono %(used)s z %(available)s " - -#: templates/horizon/common/_limit_summary.html:35 -msgid "Security Groups" -msgstr "Grupy zabezpieczeń" - -#: templates/horizon/common/_limit_summary.html:42 -msgid "Volumes" -msgstr "Wolumeny" - -#: templates/horizon/common/_limit_summary.html:49 -msgid "Volume Storage" -msgstr "Przechowywanie danych" - -#: templates/horizon/common/_modal_form_update_metadata.html:24 -#: workflows/base.py:594 -msgid "Save" -msgstr "Zapisz" - -#: templates/horizon/common/_resource_browser.html:10 -#, python-format -msgid "Displaying %(nav_items)s item" -msgid_plural "Displaying %(nav_items)s items" -msgstr[0] "Wyświetlanie %(nav_items)s pozycję" -msgstr[1] "Wyświetlanie %(nav_items)s pozycji" -msgstr[2] "Wyświetlanie %(nav_items)s pozycji" - -#: templates/horizon/common/_resource_browser.html:11 -#, python-format -msgid "Displaying %(content_items)s item" -msgid_plural "Displaying %(content_items)s items" -msgstr[0] "Wyświetlanie %(content_items)s pozycji" -msgstr[1] "Wyświetlanie %(content_items)s pozycji" -msgstr[2] "Wyświetlanie %(content_items)s pozycji" - -#: templates/horizon/common/_usage_summary.html:3 -msgid "Usage Summary" -msgstr "Podsumowanie wykorzystania" - -#: templates/horizon/common/_usage_summary.html:7 -msgid "Select a period of time to query its usage:" -msgstr "Wybierz okres, za który należy wyświetlić wykorzystanie:" - -#: templates/horizon/common/_usage_summary.html:9 -#, python-format -msgid "" -"\n" -" %(start)s" -msgstr "\n %(start)s" - -#: templates/horizon/common/_usage_summary.html:13 -#, python-format -msgid "" -"\n" -" %(end)s" -msgstr "\n %(end)s" - -#: templates/horizon/common/_usage_summary.html:17 -msgid "The date should be in YYYY-mm-dd format." -msgstr "Data powinna być podana w formacie YYYY-mm-dd." - -#: templates/horizon/common/_usage_summary.html:20 -msgid "Active Instances:" -msgstr "Aktywne instancje:" - -#: templates/horizon/common/_usage_summary.html:21 -msgid "Active RAM:" -msgstr "Aktywna pamięć RAM:" - -#: templates/horizon/common/_usage_summary.html:22 -msgid "This Period's VCPU-Hours:" -msgstr "VCPU-godziny w tym okresie:" - -#: templates/horizon/common/_usage_summary.html:23 -msgid "This Period's GB-Hours:" -msgstr "GB-godziny w tym okresie:" - -#: templates/horizon/common/_usage_summary.html:24 -msgid "This Period's RAM-Hours:" -msgstr "RAM-godziny w tym okresie:" - -#: templates/horizon/common/_workflow.html:40 -msgid "Back" -msgstr "Wstecz" - -#: templates/horizon/common/_workflow.html:43 -msgid "Next" -msgstr "Następny" - -#: templatetags/branding.py:34 -msgid "Horizon" -msgstr "Horizon" - -#: templatetags/horizon.py:137 templatetags/horizon.py:148 -msgid "No Limit" -msgstr "Bez ograniczeń" - -#: templatetags/horizon.py:140 templatetags/horizon.py:142 -msgid "Available" -msgstr "Dostępne" - -#: templatetags/sizeformat.py:51 templatetags/sizeformat.py:56 -#, python-format -msgid "%(size)d Byte" -msgid_plural "%(size)d Bytes" -msgstr[0] "%(size)d bajt" -msgstr[1] "%(size)d bajty" -msgstr[2] "%(size)d bajtów" - -#: templatetags/sizeformat.py:59 -#, python-format -msgid "%s KB" -msgstr "%s KB" - -#: templatetags/sizeformat.py:61 -#, python-format -msgid "%s MB" -msgstr "%s MB" - -#: templatetags/sizeformat.py:63 -#, python-format -msgid "%s GB" -msgstr "%s GB" - -#: templatetags/sizeformat.py:65 -#, python-format -msgid "%s TB" -msgstr "%s TB" - -#: templatetags/sizeformat.py:66 -#, python-format -msgid "%s PB" -msgstr "%s PB" - -#: templatetags/sizeformat.py:74 -msgid "0 Bytes" -msgstr "0 bajtów" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:31 -msgid "Sell Puppy" -msgid_plural "Sell Puppies" -msgstr[0] "Sprzedaj pieska" -msgstr[1] "Sprzedaj pieski" -msgstr[2] "Sprzedaj pieski" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:40 -msgid "Sold Puppy" -msgid_plural "Sold Puppies" -msgstr[0] "Sprzedano pieska" -msgstr[1] "Sprzedano pieski" -msgstr[2] "Sprzedano pieski" - -#: test/tests/views.py:59 -msgid "Fake" -msgstr "Fałszywe" - -#: utils/filters.py:49 -msgid "Never" -msgstr "Nigdy" - -#: utils/validators.py:26 utils/validators.py:50 -msgid "Not a valid port number" -msgstr "Błędny numer portu" - -#: utils/validators.py:31 -msgid "Not a valid IP protocol number" -msgstr "Błędny numer protokołu IP" - -#: utils/validators.py:45 -msgid "One colon allowed in port range" -msgstr "Tylko jeden dwukropek jest dozwolony w zakresie portów" - -#: utils/validators.py:52 -msgid "Port number must be integer" -msgstr "Numer portu musi być liczbą całkowitą" - -#: utils/validators.py:59 -msgid "The string may only contain ASCII printable characters." -msgstr "Ciąg może zawierać wyłącznie drukowalne znaki ASCII." - -#: workflows/base.py:71 -msgid "Processing..." -msgstr "Przetwarzanie…" - -#: workflows/base.py:475 -msgid "All available" -msgstr "Całość dostępna" - -#: workflows/base.py:476 -msgid "Members" -msgstr "Członkowie" - -#: workflows/base.py:477 -msgid "None available." -msgstr "Całość wykorzystana" - -#: workflows/base.py:478 -msgid "No members." -msgstr "Brak członków." - -#: workflows/base.py:595 -#, python-format -msgid "%s completed successfully." -msgstr "%s zakończona pomyślnie." - -#: workflows/base.py:596 -#, python-format -msgid "%s did not complete." -msgstr "%s nie została zakończona." diff --git a/code/horizon/horizon/locale/pl_PL/LC_MESSAGES/djangojs.po b/code/horizon/horizon/locale/pl_PL/LC_MESSAGES/djangojs.po deleted file mode 100644 index b23c8e08..00000000 --- a/code/horizon/horizon/locale/pl_PL/LC_MESSAGES/djangojs.po +++ /dev/null @@ -1,620 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Łukasz Jernaś , 2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-12 01:16-0500\n" -"PO-Revision-Date: 2015-04-20 07:06+0000\n" -"Last-Translator: Łukasz Jernaś \n" -"Language-Team: Polish (Poland) (http://www.transifex.com/projects/p/horizon/language/pl_PL/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: pl_PL\n" -"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - -#: static/angular/action-list/button-tooltip.js:15 -msgid "" -"The action cannot be performed. The contents of this row have errors or are " -"missing information." -msgstr "Nie można wykonać czynności. Zawartość tego wiersza zawiera błędy lub brakujące dane." - -#: static/angular/metadata-display/metadata-display.js:33 -msgid "Detail Information" -msgstr "Szczegółowe informacje" - -#: static/angular/metadata-tree/metadata-tree.js:35 -msgid "" -"You can specify resource metadata by moving items from the left column to " -"the right column. In the left columns there are metadata definitions from " -"the Glance Metadata Catalog. Use the \"Other\" option to add metadata with " -"the key of your choice." -msgstr "Można podać metadane zasobów przesuwając pozycje z lewej kolumny do prawej. W lewej kolumnie znajdują się definicje metadanych z Katalogu Metadanych Glance. Można podać metadane z własnym kluczem, po wybraniu opcji „Inne”." - -#: static/angular/metadata-tree/metadata-tree.js:36 -msgid "Min" -msgstr "Min." - -#: static/angular/metadata-tree/metadata-tree.js:37 -msgid "Max" -msgstr "Maks." - -#: static/angular/metadata-tree/metadata-tree.js:38 -msgid "Min length" -msgstr "Min. długość" - -#: static/angular/metadata-tree/metadata-tree.js:39 -msgid "Max length" -msgstr "Maks. długość" - -#: static/angular/metadata-tree/metadata-tree.js:40 -msgid "Pattern mismatch" -msgstr "Szablon się nie zgadza" - -#: static/angular/metadata-tree/metadata-tree.js:41 -msgid "Integer required" -msgstr "Wymagana liczba całkowita" - -#: static/angular/metadata-tree/metadata-tree.js:42 -msgid "Decimal required" -msgstr "Wymagana liczba dziesiętna" - -#: static/angular/metadata-tree/metadata-tree.js:43 -msgid "Required" -msgstr "Wymagane" - -#: static/angular/metadata-tree/metadata-tree.js:44 -msgid "Duplicate keys are not allowed" -msgstr "Ponowne użycie nazwy klucza jest niedozwolone." - -#: static/angular/metadata-tree/metadata-tree.js:45 -#: static/angular/table/basic-table.js:6 -#: static/horizon/js/horizon.forms.js:184 -msgid "Filter" -msgstr "Filtr" - -#: static/angular/metadata-tree/metadata-tree.js:46 -msgid "Available Metadata" -msgstr "Dostępne metadane" - -#: static/angular/metadata-tree/metadata-tree.js:47 -msgid "Existing Metadata" -msgstr "Istniejące metadane" - -#: static/angular/metadata-tree/metadata-tree.js:48 -msgid "Custom" -msgstr "Własne" - -#: static/angular/metadata-tree/metadata-tree.js:49 -msgid "No available metadata" -msgstr "Metadane niedostępne" - -#: static/angular/metadata-tree/metadata-tree.js:50 -msgid "No existing metadata" -msgstr "Brak metadanych" - -#: static/angular/modal/modal.js:83 -msgid "Submit" -msgstr "Wyślij" - -#: static/angular/modal/modal.js:84 static/angular/wizard/wizard.js:11 -#: static/horizon/js/horizon.modals.js:33 -msgid "Cancel" -msgstr "Anuluj" - -#: static/angular/transfer-table/transfer-table.js:39 -msgid "Allocated" -msgstr "Przydzielono" - -#: static/angular/transfer-table/transfer-table.js:40 -msgid "Available" -msgstr "Dostępne" - -#: static/angular/transfer-table/transfer-table.js:41 -msgid "Select one" -msgstr "Wybierz jedno" - -#: static/angular/transfer-table/transfer-table.js:42 -msgid "Select an item from Available items below" -msgstr "Należy wybrać pozycję z listy dostępnych pozycji poniżej" - -#: static/angular/transfer-table/transfer-table.js:43 -msgid "No available items" -msgstr "Brak dostępnych pozycji" - -#: static/angular/transfer-table/transfer-table.js:44 -msgid "Expand to see allocated items" -msgstr "Rozszerz, aby zobaczyć przydzielone pozycje" - -#: static/angular/transfer-table/transfer-table.js:45 -msgid "Expand to see available items" -msgstr "Rozszerz, aby zobaczyć dostepne pozycje" - -#: static/angular/transfer-table/transfer-table.js:46 -msgid "Click to show or hide" -msgstr "Kliknij by pokazać lub ukryć" - -#: static/angular/transfer-table/transfer-table.js:47 -msgid "Re-order items using drag and drop" -msgstr "Zmień kolejność pozycji poprzez przesuwanie i upuszczanie" - -#: static/angular/transfer-table/transfer-table.js:48 -msgid "Click to see more details" -msgstr "Kliknij, aby wyświetlić szczegóły" - -#: static/angular/transfer-table/transfer-table.js:100 -msgid "Found %(found)s of %(total)s" -msgstr "Znaleziono %(found)s z %(total)s" - -#: static/angular/transfer-table/transfer-table.js:166 -msgid "Click here to expand the row and view the errors." -msgstr "Kliknij tutaj, aby rozszerzyć wiersz i wyświetlić błędy." - -#: static/angular/wizard/wizard.js:12 -msgid "Back" -msgstr "Wstecz" - -#: static/angular/wizard/wizard.js:13 -msgid "Next" -msgstr "Następny" - -#: static/angular/wizard/wizard.js:14 -msgid "Finish" -msgstr "Zakończ" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Connecting" -msgstr "Łączenie" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Open" -msgstr "Otwórz" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closing" -msgstr "Zamykanie" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closed" -msgstr "Zamknięto" - -#: static/horizon/js/angular/directives/serialConsole.js:85 -#, c-format -msgid "Status: %s" -msgstr "Stan: %s" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "Yes" -msgstr "Tak" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "No" -msgstr "Nie" - -#: static/horizon/js/angular/filters/filters.js:53 -#: static/horizon/js/angular/filters/filters.js:140 -#, c-format -msgid "%s GB" -msgstr "%s GB" - -#: static/horizon/js/angular/filters/filters.js:70 -#: static/horizon/js/angular/filters/filters.js:142 -#, c-format -msgid "%s MB" -msgstr "%s MB" - -#: static/horizon/js/angular/filters/filters.js:138 -#, c-format -msgid "%s TB" -msgstr "%s TB" - -#: static/horizon/js/angular/filters/filters.js:144 -#, c-format -msgid "%s KB" -msgstr "%s KB" - -#: static/horizon/js/angular/filters/filters.js:146 -#, c-format -msgid "%s bytes" -msgstr "%s bajtów" - -#: static/horizon/js/angular/filters/filters.js:163 -#: static/horizon/js/horizon.tables.js:393 -#, c-format -msgid "Displaying %s item" -msgid_plural "Displaying %s items" -msgstr[0] "Wyświetlanie %s pozycji" -msgstr[1] "Wyświetlanie %s pozycji" -msgstr[2] "Wyświetlanie %s pozycji" - -#: static/horizon/js/angular/services/hz.api.cinder.js:47 -msgid "Unable to retrieve volumes." -msgstr "Nie można pobrać wolumenów." - -#: static/horizon/js/angular/services/hz.api.cinder.js:74 -msgid "Unable to retrieve volume snapshots." -msgstr "Nie można pobrać migawek wolumenów." - -#: static/horizon/js/angular/services/hz.api.config.js:43 -msgid "Unable to retrieve user configuration." -msgstr "Nie można pobrać ustawień użytkownika." - -#: static/horizon/js/angular/services/hz.api.config.js:62 -msgid "Unable to retrieve admin configuration." -msgstr "Nie można pobrać ustawień administratora." - -#: static/horizon/js/angular/services/hz.api.config.js:105 -msgid "Unable to retrieve settings." -msgstr "Nie można pobrać ustawień." - -#: static/horizon/js/angular/services/hz.api.config.js:289 -msgid "Setting is not enabled: %(setting)s" -msgstr "Ustawienie jest wyłączone: %(setting)s" - -#: static/horizon/js/angular/services/hz.api.glance.js:38 -msgid "Unable to retrieve image." -msgstr "Nie można pobrać obrazu." - -#: static/horizon/js/angular/services/hz.api.glance.js:81 -msgid "Unable to retrieve images." -msgstr "Nie można pobrać obrazów" - -#: static/horizon/js/angular/services/hz.api.glance.js:144 -msgid "Unable to retrieve namespaces." -msgstr "Nie można pobrać przestrzeni nazw." - -#: static/horizon/js/angular/services/hz.api.keystone.js:24 -msgid "Unable to retrieve users" -msgstr "Nie można pobrać użytkowników" - -#: static/horizon/js/angular/services/hz.api.keystone.js:31 -msgid "Unable to create the user." -msgstr "Nie można utworzyć użytkownika." - -#: static/horizon/js/angular/services/hz.api.keystone.js:38 -msgid "Unable to delete the users." -msgstr "Nie mozna usunąć użytkowników." - -#: static/horizon/js/angular/services/hz.api.keystone.js:73 -msgid "Unable to retrieve the current user session." -msgstr "Nie można pobrać bieżącej sesji użytkownika." - -#: static/horizon/js/angular/services/hz.api.keystone.js:80 -msgid "Unable to retrieve the user" -msgstr "Nie można pobrać użytkownika" - -#: static/horizon/js/angular/services/hz.api.keystone.js:88 -msgid "Unable to edit the user." -msgstr "Nie można edytować użytkownika." - -#: static/horizon/js/angular/services/hz.api.keystone.js:95 -msgid "Unable to delete the user." -msgstr "Nie można usunąć użytkownika." - -#: static/horizon/js/angular/services/hz.api.keystone.js:103 -msgid "Unable to retrieve role" -msgstr "Nie można pobrać roli" - -#: static/horizon/js/angular/services/hz.api.keystone.js:110 -msgid "Unable to create the role." -msgstr "Nie można utworzyć roli." - -#: static/horizon/js/angular/services/hz.api.keystone.js:117 -msgid "Unable to delete the roles." -msgstr "Nie mozna usunąć ról." - -#: static/horizon/js/angular/services/hz.api.keystone.js:124 -msgid "Unable to retrieve the role" -msgstr "Nie można pobrać roli" - -#: static/horizon/js/angular/services/hz.api.keystone.js:132 -msgid "Unable to edit the role." -msgstr "Nie można edytować roli." - -#: static/horizon/js/angular/services/hz.api.keystone.js:139 -msgid "Unable to delete the role." -msgstr "Nie można usunąć roli." - -#: static/horizon/js/angular/services/hz.api.keystone.js:147 -msgid "Unable to retrieve domains" -msgstr "Nie można pobrać domen" - -#: static/horizon/js/angular/services/hz.api.keystone.js:154 -msgid "Unable to create the domain." -msgstr "Nie można utworzyć domeny." - -#: static/horizon/js/angular/services/hz.api.keystone.js:161 -msgid "Unable to delete the domains." -msgstr "Nie można usunąć domen." - -#: static/horizon/js/angular/services/hz.api.keystone.js:168 -msgid "Unable to retrieve the domain" -msgstr "Nie można pobrać domeny" - -#: static/horizon/js/angular/services/hz.api.keystone.js:176 -msgid "Unable to edit the domain." -msgstr "Nie można edytować domeny." - -#: static/horizon/js/angular/services/hz.api.keystone.js:183 -msgid "Unable to delete the domain." -msgstr "Nie można usunąć domeny." - -#: static/horizon/js/angular/services/hz.api.keystone.js:192 -msgid "Unable to retrieve projects" -msgstr "Nie można pobrać projektów" - -#: static/horizon/js/angular/services/hz.api.keystone.js:199 -msgid "Unable to create the project." -msgstr "Nie można utworzyć projektu." - -#: static/horizon/js/angular/services/hz.api.keystone.js:206 -msgid "Unable to delete the projects." -msgstr "Nie można usunąć projektów." - -#: static/horizon/js/angular/services/hz.api.keystone.js:213 -msgid "Unable to retrieve the project" -msgstr "Nie można pobrać projektu." - -#: static/horizon/js/angular/services/hz.api.keystone.js:221 -msgid "Unable to edit the project." -msgstr "Nie można edytować projektu." - -#: static/horizon/js/angular/services/hz.api.keystone.js:228 -msgid "Unable to delete the project." -msgstr "Nie można usunąć projektu." - -#: static/horizon/js/angular/services/hz.api.keystone.js:236 -msgid "Unable to grant the role." -msgstr "Nie można nadać roli." - -#: static/horizon/js/angular/services/hz.api.keystone.js:250 -msgid "Unable to fetch the service catalog." -msgstr "Nie można pobrać katalogu usług." - -#: static/horizon/js/angular/services/hz.api.keystone.js:385 -msgid "Service type is not enabled: %(desiredType)s" -msgstr "Typ usługi nie jest włączony: %(desiredType)s" - -#: static/horizon/js/angular/services/hz.api.keystone.js:392 -msgid "Cannot get service catalog from keystone." -msgstr "Nie można pobrać katalogu usług z keystone." - -#: static/horizon/js/angular/services/hz.api.neutron.js:39 -msgid "Unable to retrieve networks." -msgstr "Nie można pobrać sieci." - -#: static/horizon/js/angular/services/hz.api.neutron.js:88 -msgid "Unable to create the network." -msgstr "Nie można utworzyć sieci." - -#: static/horizon/js/angular/services/hz.api.neutron.js:108 -msgid "Unable to retrieve subnets." -msgstr "Nie można pobrać podsieci." - -#: static/horizon/js/angular/services/hz.api.neutron.js:172 -msgid "Unable to create the subnet." -msgstr "Nie można utworzyć podsieci." - -#: static/horizon/js/angular/services/hz.api.neutron.js:192 -msgid "Unable to retrieve ports." -msgstr "Nie można pobrać portów." - -#: static/horizon/js/angular/services/hz.api.nova.js:40 -msgid "Unable to retrieve keypairs." -msgstr "Nie można pobrać par kluczy." - -#: static/horizon/js/angular/services/hz.api.nova.js:62 -msgid "Unable to import the keypair." -msgstr "Nie można zaimportować pary kluczy." - -#: static/horizon/js/angular/services/hz.api.nova.js:64 -msgid "Unable to create the keypair." -msgstr "Nie można utworzyć pary kluczy." - -#: static/horizon/js/angular/services/hz.api.nova.js:83 -msgid "Unable to retrieve availability zones." -msgstr "Nie można pobrać stref dostępności." - -#: static/horizon/js/angular/services/hz.api.nova.js:121 -msgid "Unable to retrieve limits." -msgstr "Nie można pobrać ograniczeń." - -#: static/horizon/js/angular/services/hz.api.nova.js:148 -msgid "Unable to create the server." -msgstr "Nie można utworzyć serwera." - -#: static/horizon/js/angular/services/hz.api.nova.js:162 -msgid "Unable to retrieve server." -msgstr "Nie można pobrać serwera." - -#: static/horizon/js/angular/services/hz.api.nova.js:192 -msgid "Unable to retrieve extensions." -msgstr "Nie można pobrać rozszerzeń." - -#: static/horizon/js/angular/services/hz.api.nova.js:237 -msgid "Unable to retrieve flavors." -msgstr "Nie można pobrać odmian." - -#: static/horizon/js/angular/services/hz.api.nova.js:255 -msgid "Unable to retrieve flavor." -msgstr "Nie można pobrać odmiany." - -#: static/horizon/js/angular/services/hz.api.nova.js:269 -msgid "Unable to retrieve flavor extra specs." -msgstr "Nie można pobrać dodatkowych danych odmiany." - -#: static/horizon/js/angular/services/hz.api.nova.js:311 -msgid "Extension is not enabled: %(extension)s" -msgstr "Rozszerzenie nie jest włączone: %(extension)s" - -#: static/horizon/js/angular/services/hz.api.nova.js:318 -msgid "Cannot get nova extension list." -msgstr "Nie można pobrać listy rozszerzeń novy." - -#: static/horizon/js/angular/services/hz.api.policy.js:65 -msgid "Policy check failed." -msgstr "Sprawdzenie polityki się nie powiodło." - -#: static/horizon/js/angular/services/hz.api.security-group.js:64 -msgid "Unable to retrieve security groups." -msgstr "Nie można pobrać grup zabezpieczeń." - -#: static/horizon/js/horizon.accordion_nav.js:78 -#: static/horizon/js/horizon.modals.js:315 -#: static/horizon/js/horizon.tabs.js:21 -msgid "Loading" -msgstr "Wczytywanie" - -#: static/horizon/js/horizon.d3linechart.js:394 -#: static/horizon/js/horizon.d3linechart.js:404 -msgid "No data available." -msgstr "Brak dostępnych danych." - -#: static/horizon/js/horizon.d3linechart.js:410 -#: static/horizon/js/horizon.modals.js:334 -#: static/horizon/js/horizon.tables_inline_edit.js:94 -#: static/horizon/js/horizon.tables_inline_edit.js:157 -msgid "An error occurred. Please try again later." -msgstr "Wystąpił błąd. Proszę spróbować później." - -#: static/horizon/js/horizon.firewalls.js:32 -#: static/horizon/js/horizon.instances.js:31 -msgid "There was a problem communicating with the server, please try again." -msgstr "Wystąpił problem w komunikacji z serwerem, proszę spróbować ponownie." - -#: static/horizon/js/horizon.instances.js:273 -msgid "Could not read the file" -msgstr "Nie można odczytać pliku" - -#: static/horizon/js/horizon.instances.js:279 -#: static/horizon/js/horizon.instances.js:308 -msgid "Could not decrypt the password" -msgstr "Nie można odszyfrować hasła" - -#: static/horizon/js/horizon.membership.js:190 -msgid "No roles" -msgstr "Brak ról" - -#: static/horizon/js/horizon.membership.js:222 -msgid "Roles" -msgstr "Role" - -#: static/horizon/js/horizon.messages.js:9 -msgid "Danger: " -msgstr "Zagrożenie:" - -#: static/horizon/js/horizon.messages.js:10 -msgid "Warning: " -msgstr "Ostrzeżenie:" - -#: static/horizon/js/horizon.messages.js:11 -msgid "Notice: " -msgstr "Powiadomienie:" - -#: static/horizon/js/horizon.messages.js:12 -msgid "Success: " -msgstr "Powodzenie:" - -#: static/horizon/js/horizon.messages.js:13 -msgid "Error: " -msgstr "Błąd:" - -#: static/horizon/js/horizon.modals.js:229 -#: static/horizon/js/horizon.tables.js:218 -msgid "Working" -msgstr "Praca" - -#: static/horizon/js/horizon.modals.js:263 -msgid "There was an error submitting the form. Please try again." -msgstr "Wystąpił błąd podczas wysyłania formularza. Proszę spróbować ponownie." - -#: static/horizon/js/horizon.networktopology.js:530 -#: static/horizon/js/horizon.networktopology.js:536 -msgid "None" -msgstr "Brak" - -#: static/horizon/js/horizon.networktopology.js:549 -msgid "Delete" -msgstr "Usuń" - -#: static/horizon/js/horizon.networktopology.js:552 -msgid "STATUS" -msgstr "STATUS" - -#: static/horizon/js/horizon.networktopology.js:553 -msgid "ID" -msgstr "ID" - -#: static/horizon/js/horizon.networktopology.js:554 -msgid "Interfaces" -msgstr "Interfejsy" - -#: static/horizon/js/horizon.networktopology.js:555 -msgid "Delete Interface" -msgstr "Usuń interfejs" - -#: static/horizon/js/horizon.networktopology.js:556 -msgid "Open Console" -msgstr "Otwórz konsolę" - -#: static/horizon/js/horizon.networktopology.js:557 -msgid "View Details" -msgstr "Wyświetl szczegóły" - -#: static/horizon/js/horizon.networktopology.js:560 -msgid "Delete Router" -msgstr "Usuń router" - -#: static/horizon/js/horizon.networktopology.js:561 -msgid "View Router Details" -msgstr "Wyświetl szczegóły routera" - -#: static/horizon/js/horizon.networktopology.js:564 -msgid "Add Interface" -msgstr "Dodaj interfejs" - -#: static/horizon/js/horizon.networktopology.js:570 -msgid "Terminate Instance" -msgstr "Zniszcz instancję" - -#: static/horizon/js/horizon.networktopology.js:571 -msgid "View Instance Details" -msgstr "Wyświetl szczegóły instancji" - -#: static/horizon/js/horizon.tables.js:39 -#: static/horizon/js/horizon.tables.js:406 -msgid "No items to display." -msgstr "Brak pozycji do wyświetlenia." - -#: static/horizon/js/horizon.tables.js:52 -#: static/horizon/js/horizon.tables.js:120 -msgid "An error occurred while updating." -msgstr "Wystąpił błąd podczas aktualizacji." - -#: static/horizon/js/horizon.tables.js:201 -#, c-format -msgid "You have selected %s. " -msgstr "Wybrano %s." - -#: static/horizon/js/horizon.tables.js:203 -#, c-format -msgid "Confirm %s" -msgstr "Potwierdź %s" - -#: static/horizon/js/horizon.tables.js:204 -msgid "Please confirm your selection. " -msgstr "Należy potwierdzić wybór." - -#: static/horizon/js/horizon.tables_inline_edit.js:88 -#: static/horizon/js/horizon.tables_inline_edit.js:151 -msgid "Not authorized to do this operation." -msgstr "Nie upoważniono do przeprowadzenie tej czynności." - -#: static/horizon/js/horizon.users.js:18 -msgid "Passwords do not match." -msgstr "Hasła nie pasują" diff --git a/code/horizon/horizon/locale/pt_BR/LC_MESSAGES/django.po b/code/horizon/horizon/locale/pt_BR/LC_MESSAGES/django.po deleted file mode 100644 index 92d8f038..00000000 --- a/code/horizon/horizon/locale/pt_BR/LC_MESSAGES/django.po +++ /dev/null @@ -1,514 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Fernando F. Rodrigues , 2015 -# Gabriel Wainer, 2015 -# Remulo Carvalho , 2015 -# Rodrigo Felix de Almeida , 2014 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-06 21:07-0500\n" -"PO-Revision-Date: 2015-04-07 15:52+0000\n" -"Last-Translator: Remulo Carvalho \n" -"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/horizon/language/pt_BR/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: pt_BR\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: base.py:475 -msgid "Other" -msgstr "Outro" - -#: browsers/base.py:88 -msgid "Navigation Item" -msgstr "Item de Navegação" - -#: browsers/views.py:41 -#, python-format -msgid "Select a %s to browse." -msgstr "Selecione um %s para navegar." - -#: conf/default.py:41 -msgid "Password is not accepted" -msgstr "Senha não foi aceita" - -#: decorators.py:53 -msgid "Please log in to continue." -msgstr "Por favor faça login para continuar." - -#: decorators.py:85 -#, python-format -msgid "You are not authorized to access %s" -msgstr "Você não está autorizado a acessar %s" - -#: exceptions.py:163 -#, python-format -msgid "A %(resource)s with the name \"%(name)s\" already exists." -msgstr "Um %(resource)s com o nome \"%(name)s\" já existe." - -#: exceptions.py:235 -#, python-format -msgid "Unauthorized: %s" -msgstr "Não autorizado: %s" - -#: exceptions.py:238 -msgid "Unauthorized. Please try logging in again." -msgstr "Não autorizado. Por favor tente efetuar login novamente." - -#: forms/fields.py:64 -msgid "Incorrect format for IP address" -msgstr "Formato incorreto para o endereço IP" - -#: forms/fields.py:65 -msgid "Invalid version for IP address" -msgstr "Versão inválida para o endereço IP" - -#: forms/fields.py:66 -msgid "Invalid subnet mask" -msgstr "Máscara de sub-rede inválida" - -#: forms/views.py:132 templates/horizon/common/_usage_summary.html:16 -msgid "Submit" -msgstr "Enviar" - -#: forms/views.py:133 -#: templates/horizon/common/_modal_form_update_metadata.html:25 -#: templates/horizon/common/_workflow.html:49 -msgid "Cancel" -msgstr "Cancelar" - -#: middleware.py:103 -msgid "Session timed out." -msgstr "Tempo limite da sessão esgotou." - -#: tables/actions.py:460 -#: templates/horizon/common/_data_table_table_actions.html:21 -#: templates/horizon/common/_data_table_table_actions.html:33 -#: templates/horizon/common/_workflow_step_update_members.html:14 -#: templates/horizon/common/_workflow_step_update_members.html:23 -msgid "Filter" -msgstr "Filtro" - -#: tables/actions.py:645 -msgid "This action cannot be undone." -msgstr "Esta ação não pode ser desfeita." - -#: tables/actions.py:767 -#, python-format -msgctxt "past" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:769 -#, python-format -msgctxt "present" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:832 -#, python-format -msgid "You are not allowed to %(action)s: %(objs)s" -msgstr "Você não possui permissão para %(action)s: %(objs)s" - -#: tables/actions.py:839 -#, python-format -msgid "Unable to %(action)s: %(objs)s" -msgstr "Não foi possível %(action)s: %(objs)s" - -#: tables/actions.py:845 -#, python-format -msgid "%(action)s: %(objs)s" -msgstr "%(action)s: %(objs)s" - -#: tables/actions.py:915 -msgid "Delete" -msgstr "Excluir" - -#: tables/actions.py:917 -msgid "Deleted" -msgstr "Excluído" - -#: tables/actions.py:948 -msgid "Update" -msgstr "Atualizar" - -#: tables/actions.py:949 -msgid "Updated" -msgstr "Atualizado" - -#: tables/base.py:305 -msgid "-" -msgstr "-" - -#: tables/base.py:361 -#, python-format -msgid "The attribute %(attr)s doesn't exist on %(obj)s." -msgstr "O atributo %(attr)s não existe em %(obj)s." - -#: tables/base.py:990 -msgid "No items to display." -msgstr "Sem itens para exibir." - -#: tables/base.py:1099 -#: templates/horizon/common/_data_table_table_actions.html:47 -msgid "Actions" -msgstr "Ações" - -#: tables/base.py:1329 -#, python-format -msgid "No match returned for the id \"%s\"." -msgstr "Não foi encontrada correspondência para o ID \"%s\"." - -#: tables/base.py:1486 -msgid "Please select a row before taking that action." -msgstr "Por favor selecione uma linha antes de realizar esta ação." - -#: tables/base.py:1570 -msgid "N/A" -msgstr "N/A" - -#: templates/_header.html:5 -#, python-format -msgid "Logged in as: %(username)s" -msgstr "Logado como: %(username)s" - -#: templates/_header.html:7 -msgid "Help" -msgstr "Ajuda" - -#: templates/_header.html:9 -msgid "Sign Out" -msgstr "Sair" - -#: templates/auth/_description.html:9 -msgid "" -"\n" -" If you are not sure which authentication method to use, contact your administrator.\n" -" " -msgstr "\nSe você não tem certeza do método de autenticação a ser utilizado, entre em contato com o seu administrador." - -#: templates/auth/_login.html:5 -msgid "Log In" -msgstr "Entrar" - -#: templates/auth/_login.html:27 -msgid "You do not have permission to access the resource:" -msgstr "Você não tem permissão para acessar o recurso:" - -#: templates/auth/_login.html:29 -#, python-format -msgid "" -"Login as different user or go back to home " -"page" -msgstr "Faça login com um usuário diferente ou volte para a página inicial" - -#: templates/auth/_login.html:45 -msgid "Sign In" -msgstr "Entrar" - -#: templates/auth/_login.html:46 -msgid "Connect" -msgstr "Conectado" - -#: templates/auth/login.html:4 -msgid "Login" -msgstr "Logar" - -#: templates/horizon/_messages.html:7 -msgid "Info: " -msgstr "Informação:" - -#: templates/horizon/_messages.html:13 -msgid "Warning: " -msgstr "Alerta:" - -#: templates/horizon/_messages.html:19 -msgid "Success: " -msgstr "Sucesso:" - -#: templates/horizon/_messages.html:25 -msgid "Error: " -msgstr "Erro:" - -#: templates/horizon/common/_data_table.html:63 -msgid "Summary" -msgstr "Resumo" - -#: templates/horizon/common/_data_table.html:72 -#, python-format -msgid "Displaying %(counter)s item" -msgid_plural "Displaying %(counter)s items" -msgstr[0] "Exibindo %(counter)s item" -msgstr[1] "Exibindo %(counter)s itens" - -#: templates/horizon/common/_data_table.html:77 -msgid "« Prev" -msgstr "« Prev" - -#: templates/horizon/common/_data_table.html:80 -msgid "Next »" -msgstr "Next »" - -#: templates/horizon/common/_data_table_table_actions.html:45 -msgid "More Actions" -msgstr "Mais Ações" - -#: templates/horizon/common/_domain_page_header.html:6 -#, python-format -msgid "%(context_name)s:" -msgstr "%(context_name)s:" - -#: templates/horizon/common/_formset_table.html:35 -msgid "Add a row" -msgstr "Adicionar uma linha" - -#: templates/horizon/common/_formset_table_row.html:15 -#, python-format -msgid "%(name)s: %(error)s" -msgstr "%(name)s: %(error)s" - -#: templates/horizon/common/_limit_summary.html:4 -msgid "Limit Summary" -msgstr "Resumo de Limites" - -#: templates/horizon/common/_limit_summary.html:7 -msgid "Instances" -msgstr "Instâncias" - -#: templates/horizon/common/_limit_summary.html:8 -#: templates/horizon/common/_limit_summary.html:15 -#: templates/horizon/common/_limit_summary.html:22 -#: templates/horizon/common/_limit_summary.html:36 -#: templates/horizon/common/_limit_summary.html:43 -#: templates/horizon/common/_limit_summary.html:50 -#, python-format -msgid "Used %(used)s of %(available)s " -msgstr "Utilizado %(used)s de %(available)s " - -#: templates/horizon/common/_limit_summary.html:14 -msgid "VCPUs" -msgstr "vCPUs" - -#: templates/horizon/common/_limit_summary.html:21 -msgid "RAM" -msgstr "RAM" - -#: templates/horizon/common/_limit_summary.html:28 -msgid "Floating IPs" -msgstr "IPs Flutuantes" - -#: templates/horizon/common/_limit_summary.html:29 -#, python-format -msgid "Allocated %(used)s of %(available)s " -msgstr "Alocado %(used)s de %(available)s " - -#: templates/horizon/common/_limit_summary.html:35 -msgid "Security Groups" -msgstr "Grupos de Segurança" - -#: templates/horizon/common/_limit_summary.html:42 -msgid "Volumes" -msgstr "Volumes" - -#: templates/horizon/common/_limit_summary.html:49 -msgid "Volume Storage" -msgstr "Armazenamento de volume" - -#: templates/horizon/common/_modal_form_update_metadata.html:24 -#: workflows/base.py:594 -msgid "Save" -msgstr "Salvar" - -#: templates/horizon/common/_resource_browser.html:10 -#, python-format -msgid "Displaying %(nav_items)s item" -msgid_plural "Displaying %(nav_items)s items" -msgstr[0] "Exibindo %(nav_items)s item" -msgstr[1] "Exibindo %(nav_items)s itens" - -#: templates/horizon/common/_resource_browser.html:11 -#, python-format -msgid "Displaying %(content_items)s item" -msgid_plural "Displaying %(content_items)s items" -msgstr[0] "Exibindo %(content_items)s item" -msgstr[1] "Exibindo %(content_items)s itens" - -#: templates/horizon/common/_usage_summary.html:3 -msgid "Usage Summary" -msgstr "Resumo de Utilização" - -#: templates/horizon/common/_usage_summary.html:7 -msgid "Select a period of time to query its usage:" -msgstr "Selecione um período de tempo para consultar seu uso:" - -#: templates/horizon/common/_usage_summary.html:9 -#, python-format -msgid "" -"\n" -" %(start)s" -msgstr "\n %(start)s" - -#: templates/horizon/common/_usage_summary.html:13 -#, python-format -msgid "" -"\n" -" %(end)s" -msgstr "\n %(end)s" - -#: templates/horizon/common/_usage_summary.html:17 -msgid "The date should be in YYYY-mm-dd format." -msgstr "A data deve estar no formato YYYY-mm-dd." - -#: templates/horizon/common/_usage_summary.html:20 -msgid "Active Instances:" -msgstr "Instâncias ativas:" - -#: templates/horizon/common/_usage_summary.html:21 -msgid "Active RAM:" -msgstr "RAM ativa:" - -#: templates/horizon/common/_usage_summary.html:22 -msgid "This Period's VCPU-Hours:" -msgstr "VCPU-Horas desse Período:" - -#: templates/horizon/common/_usage_summary.html:23 -msgid "This Period's GB-Hours:" -msgstr "GB-Horas desse Período:" - -#: templates/horizon/common/_usage_summary.html:24 -msgid "This Period's RAM-Hours:" -msgstr "Quantidade de RAM-Horas deste período:" - -#: templates/horizon/common/_workflow.html:40 -msgid "Back" -msgstr "Voltar" - -#: templates/horizon/common/_workflow.html:43 -msgid "Next" -msgstr "Próximo" - -#: templatetags/branding.py:34 -msgid "Horizon" -msgstr "Horizon" - -#: templatetags/horizon.py:137 templatetags/horizon.py:148 -msgid "No Limit" -msgstr "Sem Limite" - -#: templatetags/horizon.py:140 templatetags/horizon.py:142 -msgid "Available" -msgstr "Disponível" - -#: templatetags/sizeformat.py:51 templatetags/sizeformat.py:56 -#, python-format -msgid "%(size)d Byte" -msgid_plural "%(size)d Bytes" -msgstr[0] "%(size)d Byte" -msgstr[1] "%(size)d Bytes" - -#: templatetags/sizeformat.py:59 -#, python-format -msgid "%s KB" -msgstr "%s KB" - -#: templatetags/sizeformat.py:61 -#, python-format -msgid "%s MB" -msgstr "%s MB" - -#: templatetags/sizeformat.py:63 -#, python-format -msgid "%s GB" -msgstr "%s GB" - -#: templatetags/sizeformat.py:65 -#, python-format -msgid "%s TB" -msgstr "%s TB" - -#: templatetags/sizeformat.py:66 -#, python-format -msgid "%s PB" -msgstr "%s PB" - -#: templatetags/sizeformat.py:74 -msgid "0 Bytes" -msgstr "0 Bytes" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:31 -msgid "Sell Puppy" -msgid_plural "Sell Puppies" -msgstr[0] "Vender Puppy" -msgstr[1] "Vender Puppies" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:40 -msgid "Sold Puppy" -msgid_plural "Sold Puppies" -msgstr[0] "Puppy Vendido" -msgstr[1] "Puppies Vendidos" - -#: test/tests/views.py:59 -msgid "Fake" -msgstr "Falso" - -#: utils/filters.py:49 -msgid "Never" -msgstr "Nunca" - -#: utils/validators.py:26 utils/validators.py:50 -msgid "Not a valid port number" -msgstr "Não é um número de porta válido" - -#: utils/validators.py:31 -msgid "Not a valid IP protocol number" -msgstr "Não é um número de protocolo IP válido" - -#: utils/validators.py:45 -msgid "One colon allowed in port range" -msgstr "Uma pontução de dois pontos permitida no intervalo de portas" - -#: utils/validators.py:52 -msgid "Port number must be integer" -msgstr "Número de porta deve ser inteiro" - -#: utils/validators.py:59 -msgid "The string may only contain ASCII printable characters." -msgstr "A string somente deve conter caracteres ASCII imprimíveis." - -#: workflows/base.py:71 -msgid "Processing..." -msgstr "Processando..." - -#: workflows/base.py:475 -msgid "All available" -msgstr "Tudo disponível" - -#: workflows/base.py:476 -msgid "Members" -msgstr "Membros" - -#: workflows/base.py:477 -msgid "None available." -msgstr "Nenhum disponível." - -#: workflows/base.py:478 -msgid "No members." -msgstr "Sem membros." - -#: workflows/base.py:595 -#, python-format -msgid "%s completed successfully." -msgstr "%s concluído com sucesso." - -#: workflows/base.py:596 -#, python-format -msgid "%s did not complete." -msgstr "%s não completou." diff --git a/code/horizon/horizon/locale/pt_BR/LC_MESSAGES/djangojs.po b/code/horizon/horizon/locale/pt_BR/LC_MESSAGES/djangojs.po deleted file mode 100644 index 6c6c8a68..00000000 --- a/code/horizon/horizon/locale/pt_BR/LC_MESSAGES/djangojs.po +++ /dev/null @@ -1,622 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Fernando Pimenta , 2015 -# Gabriel Wainer, 2015 -# maurosr , 2015 -# Rodrigo Felix de Almeida , 2014 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-12 16:36-0500\n" -"PO-Revision-Date: 2015-04-14 01:40+0000\n" -"Last-Translator: Fernando Pimenta \n" -"Language-Team: Portuguese (Brazil) (http://www.transifex.com/projects/p/horizon/language/pt_BR/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: pt_BR\n" -"Plural-Forms: nplurals=2; plural=(n > 1);\n" - -#: static/angular/action-list/button-tooltip.js:15 -msgid "" -"The action cannot be performed. The contents of this row have errors or are " -"missing information." -msgstr "A ação não pôde ser executada. O conteúdo desta linha possui erros ou informações indisponíveis" - -#: static/angular/metadata-display/metadata-display.js:33 -msgid "Detail Information" -msgstr "Informações delhadas" - -#: static/angular/metadata-tree/metadata-tree.js:35 -msgid "" -"You can specify resource metadata by moving items from the left column to " -"the right column. In the left columns there are metadata definitions from " -"the Glance Metadata Catalog. Use the \"Other\" option to add metadata with " -"the key of your choice." -msgstr "Você pode especificar metadados de recurso movendo itens da coluna da esquerda para a coluna da direita. Nas colunas da esquerda existem definições de metadados do catálogo de metadados do Glance. Utilize a opção \"Outros\" para adicionar metadados com a chave de sua escolha." - -#: static/angular/metadata-tree/metadata-tree.js:36 -msgid "Min" -msgstr "Mín. " - -#: static/angular/metadata-tree/metadata-tree.js:37 -msgid "Max" -msgstr "Máx." - -#: static/angular/metadata-tree/metadata-tree.js:38 -msgid "Min length" -msgstr "Tamanho mínimo" - -#: static/angular/metadata-tree/metadata-tree.js:39 -msgid "Max length" -msgstr "Tamanho máximo" - -#: static/angular/metadata-tree/metadata-tree.js:40 -msgid "Pattern mismatch" -msgstr "Incompatibilidade de padrão" - -#: static/angular/metadata-tree/metadata-tree.js:41 -msgid "Integer required" -msgstr "Inteiro requerido" - -#: static/angular/metadata-tree/metadata-tree.js:42 -msgid "Decimal required" -msgstr "Decimal requerido" - -#: static/angular/metadata-tree/metadata-tree.js:43 -msgid "Required" -msgstr "Requerido" - -#: static/angular/metadata-tree/metadata-tree.js:44 -msgid "Duplicate keys are not allowed" -msgstr "Chaves duplicadas não são permitidas" - -#: static/angular/metadata-tree/metadata-tree.js:45 -#: static/angular/table/basic-table.js:6 -#: static/horizon/js/horizon.forms.js:184 -msgid "Filter" -msgstr "Filtro" - -#: static/angular/metadata-tree/metadata-tree.js:46 -msgid "Available Metadata" -msgstr "Metadados disponível" - -#: static/angular/metadata-tree/metadata-tree.js:47 -msgid "Existing Metadata" -msgstr "Metadados existente" - -#: static/angular/metadata-tree/metadata-tree.js:48 -msgid "Custom" -msgstr "Customizado" - -#: static/angular/metadata-tree/metadata-tree.js:49 -msgid "No available metadata" -msgstr "Metadados não disponível" - -#: static/angular/metadata-tree/metadata-tree.js:50 -msgid "No existing metadata" -msgstr "Metadados não existente" - -#: static/angular/modal/modal.js:83 -msgid "Submit" -msgstr "Enviar" - -#: static/angular/modal/modal.js:84 static/angular/wizard/wizard.js:11 -#: static/horizon/js/horizon.modals.js:33 -msgid "Cancel" -msgstr "Cancelar" - -#: static/angular/transfer-table/transfer-table.js:39 -msgid "Allocated" -msgstr "Alocado" - -#: static/angular/transfer-table/transfer-table.js:40 -msgid "Available" -msgstr "Disponível" - -#: static/angular/transfer-table/transfer-table.js:41 -msgid "Select one" -msgstr "Selecione" - -#: static/angular/transfer-table/transfer-table.js:42 -msgid "Select an item from Available items below" -msgstr "Selecione um item dentre os disponíveis abaixo" - -#: static/angular/transfer-table/transfer-table.js:43 -msgid "No available items" -msgstr "Itens indisponíveis" - -#: static/angular/transfer-table/transfer-table.js:44 -msgid "Expand to see allocated items" -msgstr "Expanda para ver os itens alocados" - -#: static/angular/transfer-table/transfer-table.js:45 -msgid "Expand to see available items" -msgstr "Expanda para ver os itens disponíveis" - -#: static/angular/transfer-table/transfer-table.js:46 -msgid "Click to show or hide" -msgstr "Clique para exibir ou esconder" - -#: static/angular/transfer-table/transfer-table.js:47 -msgid "Re-order items using drag and drop" -msgstr "reordene os itens clicando em um deles e arrastando-o" - -#: static/angular/transfer-table/transfer-table.js:48 -msgid "Click to see more details" -msgstr "Clique para ver mais detalhes." - -#: static/angular/transfer-table/transfer-table.js:100 -msgid "Found %(found)s of %(total)s" -msgstr "Encontrado %(found)s de %(total)s" - -#: static/angular/transfer-table/transfer-table.js:166 -msgid "Click here to expand the row and view the errors." -msgstr "Clique aqui para expandir a linha e ver os erros." - -#: static/angular/wizard/wizard.js:12 -msgid "Back" -msgstr "Voltar" - -#: static/angular/wizard/wizard.js:13 -msgid "Next" -msgstr "Próximo" - -#: static/angular/wizard/wizard.js:14 -msgid "Finish" -msgstr "Encerrar" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Connecting" -msgstr "Conectando" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Open" -msgstr "Abrir" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closing" -msgstr "Encerramento" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closed" -msgstr "Encerrado" - -#: static/horizon/js/angular/directives/serialConsole.js:85 -#, c-format -msgid "Status: %s" -msgstr "Status: %s" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "Yes" -msgstr "Sim" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "No" -msgstr "Não" - -#: static/horizon/js/angular/filters/filters.js:53 -#: static/horizon/js/angular/filters/filters.js:140 -#, c-format -msgid "%s GB" -msgstr "%s GB" - -#: static/horizon/js/angular/filters/filters.js:70 -#: static/horizon/js/angular/filters/filters.js:142 -#, c-format -msgid "%s MB" -msgstr "%s MB" - -#: static/horizon/js/angular/filters/filters.js:138 -#, c-format -msgid "%s TB" -msgstr "%s TB" - -#: static/horizon/js/angular/filters/filters.js:144 -#, c-format -msgid "%s KB" -msgstr "%s KB" - -#: static/horizon/js/angular/filters/filters.js:146 -#, c-format -msgid "%s bytes" -msgstr "%s bytes" - -#: static/horizon/js/angular/filters/filters.js:163 -#: static/horizon/js/horizon.tables.js:393 -#, c-format -msgid "Displaying %s item" -msgid_plural "Displaying %s items" -msgstr[0] "Exibindo %s item" -msgstr[1] "Exibindo %s itens" - -#: static/horizon/js/angular/services/hz.api.cinder.js:47 -msgid "Unable to retrieve volumes." -msgstr "Não foi possível obter a lista de volumes." - -#: static/horizon/js/angular/services/hz.api.cinder.js:74 -msgid "Unable to retrieve volume snapshots." -msgstr "Não é possível recuperar snapshots de volume." - -#: static/horizon/js/angular/services/hz.api.config.js:43 -msgid "Unable to retrieve user configuration." -msgstr "Não foi possível recuperar as configurações de usuário" - -#: static/horizon/js/angular/services/hz.api.config.js:62 -msgid "Unable to retrieve admin configuration." -msgstr "Não foi possível recuperar as configurações de administrador" - -#: static/horizon/js/angular/services/hz.api.config.js:105 -msgid "Unable to retrieve settings." -msgstr "Não é possível recuperar as configurações." - -#: static/horizon/js/angular/services/hz.api.config.js:289 -msgid "Setting is not enabled: %(setting)s" -msgstr "Configuração não está habilitada: %(setting)s" - -#: static/horizon/js/angular/services/hz.api.glance.js:38 -msgid "Unable to retrieve image." -msgstr "Não foi possível recuperar a imagem." - -#: static/horizon/js/angular/services/hz.api.glance.js:81 -msgid "Unable to retrieve images." -msgstr "Não foi possível obter as imagems" - -#: static/horizon/js/angular/services/hz.api.glance.js:144 -msgid "Unable to retrieve namespaces." -msgstr "Não é possível recuperar namespaces." - -#: static/horizon/js/angular/services/hz.api.keystone.js:24 -msgid "Unable to retrieve users" -msgstr "Não foi possível obter os usuários" - -#: static/horizon/js/angular/services/hz.api.keystone.js:31 -msgid "Unable to create the user." -msgstr "Não foi possível criar o usuário." - -#: static/horizon/js/angular/services/hz.api.keystone.js:38 -msgid "Unable to delete the users." -msgstr "Não foi possível excluir os usuários." - -#: static/horizon/js/angular/services/hz.api.keystone.js:73 -msgid "Unable to retrieve the current user session." -msgstr "Não é possível recuperar a sessão atual do usuário." - -#: static/horizon/js/angular/services/hz.api.keystone.js:80 -msgid "Unable to retrieve the user" -msgstr "Não foi possível obter o usuário" - -#: static/horizon/js/angular/services/hz.api.keystone.js:88 -msgid "Unable to edit the user." -msgstr "Não foi possível editar o usuário." - -#: static/horizon/js/angular/services/hz.api.keystone.js:95 -msgid "Unable to delete the user." -msgstr "Não foi possível excluir o usuário." - -#: static/horizon/js/angular/services/hz.api.keystone.js:103 -msgid "Unable to retrieve role" -msgstr "Não foi possível obter o papel" - -#: static/horizon/js/angular/services/hz.api.keystone.js:110 -msgid "Unable to create the role." -msgstr "Não foi possível criar o papel." - -#: static/horizon/js/angular/services/hz.api.keystone.js:117 -msgid "Unable to delete the roles." -msgstr "Não foi possível excluir os papéis." - -#: static/horizon/js/angular/services/hz.api.keystone.js:124 -msgid "Unable to retrieve the role" -msgstr "Não foi possível obter o papel" - -#: static/horizon/js/angular/services/hz.api.keystone.js:132 -msgid "Unable to edit the role." -msgstr "Não foi possível editar o papel." - -#: static/horizon/js/angular/services/hz.api.keystone.js:139 -msgid "Unable to delete the role." -msgstr "Não foi possível excluir o papel." - -#: static/horizon/js/angular/services/hz.api.keystone.js:147 -msgid "Unable to retrieve domains" -msgstr "Não foi possível obter os domínios" - -#: static/horizon/js/angular/services/hz.api.keystone.js:154 -msgid "Unable to create the domain." -msgstr "Não foi possível criar o domínio." - -#: static/horizon/js/angular/services/hz.api.keystone.js:161 -msgid "Unable to delete the domains." -msgstr "Não foi possível excluir os domínios." - -#: static/horizon/js/angular/services/hz.api.keystone.js:168 -msgid "Unable to retrieve the domain" -msgstr "Não foi possível obter o domínio" - -#: static/horizon/js/angular/services/hz.api.keystone.js:176 -msgid "Unable to edit the domain." -msgstr "Não foi possível editar o domínio." - -#: static/horizon/js/angular/services/hz.api.keystone.js:183 -msgid "Unable to delete the domain." -msgstr "Não foi possível excluir o domínio." - -#: static/horizon/js/angular/services/hz.api.keystone.js:192 -msgid "Unable to retrieve projects" -msgstr "Não foi possível obter os projetos" - -#: static/horizon/js/angular/services/hz.api.keystone.js:199 -msgid "Unable to create the project." -msgstr "Não foi possível criar o projeto." - -#: static/horizon/js/angular/services/hz.api.keystone.js:206 -msgid "Unable to delete the projects." -msgstr "Não foi possível excluir os projetos." - -#: static/horizon/js/angular/services/hz.api.keystone.js:213 -msgid "Unable to retrieve the project" -msgstr "Não foi possível obter o projeto" - -#: static/horizon/js/angular/services/hz.api.keystone.js:221 -msgid "Unable to edit the project." -msgstr "Não foi possível editar o projeto." - -#: static/horizon/js/angular/services/hz.api.keystone.js:228 -msgid "Unable to delete the project." -msgstr "Não foi possível excluir o projeto." - -#: static/horizon/js/angular/services/hz.api.keystone.js:236 -msgid "Unable to grant the role." -msgstr "Não foi possível permitir o papel." - -#: static/horizon/js/angular/services/hz.api.keystone.js:250 -msgid "Unable to fetch the service catalog." -msgstr "Não é possível obter o catálogo de serviços." - -#: static/horizon/js/angular/services/hz.api.keystone.js:385 -msgid "Service type is not enabled: %(desiredType)s" -msgstr "Tipo de serviço não está habilitado: %(desiredType)s" - -#: static/horizon/js/angular/services/hz.api.keystone.js:392 -msgid "Cannot get service catalog from keystone." -msgstr "Não é possível obter o catálogo de serviços a partir do keystone." - -#: static/horizon/js/angular/services/hz.api.neutron.js:39 -msgid "Unable to retrieve networks." -msgstr "Não é possível recuperar redes." - -#: static/horizon/js/angular/services/hz.api.neutron.js:88 -msgid "Unable to create the network." -msgstr "Não foi possível criar a rede" - -#: static/horizon/js/angular/services/hz.api.neutron.js:108 -msgid "Unable to retrieve subnets." -msgstr "Não é possível recuperar a subredes." - -#: static/horizon/js/angular/services/hz.api.neutron.js:172 -msgid "Unable to create the subnet." -msgstr "Não foi possível criar sub-rede" - -#: static/horizon/js/angular/services/hz.api.neutron.js:192 -msgid "Unable to retrieve ports." -msgstr "Não foi possível obter lista de portas." - -#: static/horizon/js/angular/services/hz.api.nova.js:40 -msgid "Unable to retrieve keypairs." -msgstr "Não é possível recuperar pares de chaves." - -#: static/horizon/js/angular/services/hz.api.nova.js:62 -msgid "Unable to import the keypair." -msgstr "Não é possível importar o par de chaves." - -#: static/horizon/js/angular/services/hz.api.nova.js:64 -msgid "Unable to create the keypair." -msgstr "Não foi possível criar o par de chaves." - -#: static/horizon/js/angular/services/hz.api.nova.js:83 -msgid "Unable to retrieve availability zones." -msgstr "Não é possível recuperar todas zonas de disponibilidade." - -#: static/horizon/js/angular/services/hz.api.nova.js:121 -msgid "Unable to retrieve limits." -msgstr "Não foi possível obter informações de limite." - -#: static/horizon/js/angular/services/hz.api.nova.js:148 -msgid "Unable to create the server." -msgstr "Não foi possível criar a instância" - -#: static/horizon/js/angular/services/hz.api.nova.js:162 -msgid "Unable to retrieve server." -msgstr "Não é possível recuperar servidor." - -#: static/horizon/js/angular/services/hz.api.nova.js:192 -msgid "Unable to retrieve extensions." -msgstr "Não é possível recuperar extensões." - -#: static/horizon/js/angular/services/hz.api.nova.js:237 -msgid "Unable to retrieve flavors." -msgstr "Não foi possível recuperar flavors." - -#: static/horizon/js/angular/services/hz.api.nova.js:255 -msgid "Unable to retrieve flavor." -msgstr "Não é possível recuperar flavor." - -#: static/horizon/js/angular/services/hz.api.nova.js:269 -msgid "Unable to retrieve flavor extra specs." -msgstr "Não é possível recuperar especificações extras do flavor." - -#: static/horizon/js/angular/services/hz.api.nova.js:311 -msgid "Extension is not enabled: %(extension)s" -msgstr "Extensão não está habilitada: %(extension)s" - -#: static/horizon/js/angular/services/hz.api.nova.js:318 -msgid "Cannot get nova extension list." -msgstr "Não é possível obter lista de extensão do nova." - -#: static/horizon/js/angular/services/hz.api.policy.js:65 -msgid "Policy check failed." -msgstr "Verificação de política falhou." - -#: static/horizon/js/angular/services/hz.api.security-group.js:64 -msgid "Unable to retrieve security groups." -msgstr "Não é possível recuperar grupos de segurança" - -#: static/horizon/js/horizon.accordion_nav.js:78 -#: static/horizon/js/horizon.modals.js:315 -#: static/horizon/js/horizon.tabs.js:21 -msgid "Loading" -msgstr "Carregando" - -#: static/horizon/js/horizon.d3linechart.js:394 -#: static/horizon/js/horizon.d3linechart.js:404 -msgid "No data available." -msgstr "Não há dados disponíveis." - -#: static/horizon/js/horizon.d3linechart.js:410 -#: static/horizon/js/horizon.modals.js:334 -#: static/horizon/js/horizon.tables_inline_edit.js:94 -#: static/horizon/js/horizon.tables_inline_edit.js:157 -msgid "An error occurred. Please try again later." -msgstr "Um erro ocorreu. Por favor tente novamente mais tarde." - -#: static/horizon/js/horizon.firewalls.js:32 -#: static/horizon/js/horizon.instances.js:31 -msgid "There was a problem communicating with the server, please try again." -msgstr "Houve um problema ao comunicar-se com o servidor, por favor tente novamente." - -#: static/horizon/js/horizon.instances.js:273 -msgid "Could not read the file" -msgstr "Não foi possivel ler o arquivo" - -#: static/horizon/js/horizon.instances.js:279 -#: static/horizon/js/horizon.instances.js:308 -msgid "Could not decrypt the password" -msgstr "Não foi possível descriptografar a senha" - -#: static/horizon/js/horizon.membership.js:190 -msgid "No roles" -msgstr "Sem papéis" - -#: static/horizon/js/horizon.membership.js:222 -msgid "Roles" -msgstr "Papéis" - -#: static/horizon/js/horizon.messages.js:9 -msgid "Danger: " -msgstr "Perigo:" - -#: static/horizon/js/horizon.messages.js:10 -msgid "Warning: " -msgstr "Alerta:" - -#: static/horizon/js/horizon.messages.js:11 -msgid "Notice: " -msgstr "Notificação:" - -#: static/horizon/js/horizon.messages.js:12 -msgid "Success: " -msgstr "Sucesso:" - -#: static/horizon/js/horizon.messages.js:13 -msgid "Error: " -msgstr "Erro:" - -#: static/horizon/js/horizon.modals.js:229 -#: static/horizon/js/horizon.tables.js:218 -msgid "Working" -msgstr "Trabalhando" - -#: static/horizon/js/horizon.modals.js:263 -msgid "There was an error submitting the form. Please try again." -msgstr "Houve um erro ao enviar o formulário. Por favor tente novamente." - -#: static/horizon/js/horizon.networktopology.js:530 -#: static/horizon/js/horizon.networktopology.js:536 -msgid "None" -msgstr "Nenhum" - -#: static/horizon/js/horizon.networktopology.js:549 -msgid "Delete" -msgstr "Excluir" - -#: static/horizon/js/horizon.networktopology.js:552 -msgid "STATUS" -msgstr "STATUS" - -#: static/horizon/js/horizon.networktopology.js:553 -msgid "ID" -msgstr "ID" - -#: static/horizon/js/horizon.networktopology.js:554 -msgid "Interfaces" -msgstr "Interfaces" - -#: static/horizon/js/horizon.networktopology.js:555 -msgid "Delete Interface" -msgstr "Excluir Interface" - -#: static/horizon/js/horizon.networktopology.js:556 -msgid "Open Console" -msgstr "Abrir Console" - -#: static/horizon/js/horizon.networktopology.js:557 -msgid "View Details" -msgstr "Ver Detalhes" - -#: static/horizon/js/horizon.networktopology.js:560 -msgid "Delete Router" -msgstr "Excluir Roteador" - -#: static/horizon/js/horizon.networktopology.js:561 -msgid "View Router Details" -msgstr "Ver Detalhes do Roteador" - -#: static/horizon/js/horizon.networktopology.js:564 -msgid "Add Interface" -msgstr "Adicionar Interface" - -#: static/horizon/js/horizon.networktopology.js:570 -msgid "Terminate Instance" -msgstr "Terminar Instância" - -#: static/horizon/js/horizon.networktopology.js:571 -msgid "View Instance Details" -msgstr "Ver Detalhes da Instância" - -#: static/horizon/js/horizon.tables.js:39 -#: static/horizon/js/horizon.tables.js:406 -msgid "No items to display." -msgstr "Sem itens para exibir." - -#: static/horizon/js/horizon.tables.js:52 -#: static/horizon/js/horizon.tables.js:120 -msgid "An error occurred while updating." -msgstr "Um erro ocorreu ao atualizar." - -#: static/horizon/js/horizon.tables.js:201 -#, c-format -msgid "You have selected %s. " -msgstr "Você selecionou %s." - -#: static/horizon/js/horizon.tables.js:203 -#, c-format -msgid "Confirm %s" -msgstr "Confirma %s" - -#: static/horizon/js/horizon.tables.js:204 -msgid "Please confirm your selection. " -msgstr "Por favor confirme a sua seleção." - -#: static/horizon/js/horizon.tables_inline_edit.js:88 -#: static/horizon/js/horizon.tables_inline_edit.js:151 -msgid "Not authorized to do this operation." -msgstr "Não autorizado para realizar esta operação." - -#: static/horizon/js/horizon.users.js:18 -msgid "Passwords do not match." -msgstr "As senhas não conferem." diff --git a/code/horizon/horizon/locale/ru/LC_MESSAGES/django.po b/code/horizon/horizon/locale/ru/LC_MESSAGES/django.po deleted file mode 100644 index 72167675..00000000 --- a/code/horizon/horizon/locale/ru/LC_MESSAGES/django.po +++ /dev/null @@ -1,518 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Ilya Alekseyev , 2015 -# Nikita Burtsev, 2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-12 16:36-0500\n" -"PO-Revision-Date: 2015-04-13 12:42+0000\n" -"Last-Translator: Ilya Alekseyev \n" -"Language-Team: Russian (http://www.transifex.com/projects/p/horizon/language/ru/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ru\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - -#: base.py:475 -msgid "Other" -msgstr "Другое" - -#: browsers/base.py:88 -msgid "Navigation Item" -msgstr "Элемент навигации" - -#: browsers/views.py:41 -#, python-format -msgid "Select a %s to browse." -msgstr "Выберите %s для просмотра" - -#: conf/default.py:41 -msgid "Password is not accepted" -msgstr "Пароль не принят" - -#: decorators.py:53 -msgid "Please log in to continue." -msgstr "Войдите в систему для продолжения." - -#: decorators.py:85 -#, python-format -msgid "You are not authorized to access %s" -msgstr "Нет права доступа к %s" - -#: exceptions.py:163 -#, python-format -msgid "A %(resource)s with the name \"%(name)s\" already exists." -msgstr "%(resource)s с именем\"%(name)s\" уже существует." - -#: exceptions.py:235 -#, python-format -msgid "Unauthorized: %s" -msgstr "Не авторизован: %s" - -#: exceptions.py:238 -msgid "Unauthorized. Please try logging in again." -msgstr "Вы не авторизованы. Попробуйте войти в систему еще раз." - -#: forms/fields.py:64 -msgid "Incorrect format for IP address" -msgstr "Неправильный формат IP-адреса" - -#: forms/fields.py:65 -msgid "Invalid version for IP address" -msgstr "Неправильная версия IP-адреса" - -#: forms/fields.py:66 -msgid "Invalid subnet mask" -msgstr "Неправильная маска подсети" - -#: forms/views.py:132 templates/horizon/common/_usage_summary.html:16 -msgid "Submit" -msgstr "Отправить" - -#: forms/views.py:133 -#: templates/horizon/common/_modal_form_update_metadata.html:25 -#: templates/horizon/common/_workflow.html:49 -msgid "Cancel" -msgstr "Отмена" - -#: middleware.py:103 -msgid "Session timed out." -msgstr "Время сеанса истекло." - -#: tables/actions.py:460 -#: templates/horizon/common/_data_table_table_actions.html:21 -#: templates/horizon/common/_data_table_table_actions.html:33 -#: templates/horizon/common/_workflow_step_update_members.html:14 -#: templates/horizon/common/_workflow_step_update_members.html:23 -msgid "Filter" -msgstr "Фильтр" - -#: tables/actions.py:645 -msgid "This action cannot be undone." -msgstr "Это действие не может быть отменено." - -#: tables/actions.py:767 -#, python-format -msgctxt "past" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:769 -#, python-format -msgctxt "present" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:832 -#, python-format -msgid "You are not allowed to %(action)s: %(objs)s" -msgstr "Вам не разрешено выполнение: %(action)s: %(objs)s" - -#: tables/actions.py:839 -#, python-format -msgid "Unable to %(action)s: %(objs)s" -msgstr "Невозможно выполнить %(action)s: %(objs)s" - -#: tables/actions.py:845 -#, python-format -msgid "%(action)s: %(objs)s" -msgstr "%(action)s: %(objs)s" - -#: tables/actions.py:915 -msgid "Delete" -msgstr "Удалить" - -#: tables/actions.py:917 -msgid "Deleted" -msgstr "Удалено" - -#: tables/actions.py:948 -msgid "Update" -msgstr "Обновить" - -#: tables/actions.py:949 -msgid "Updated" -msgstr "Обновлено" - -#: tables/base.py:305 -msgid "-" -msgstr "-" - -#: tables/base.py:361 -#, python-format -msgid "The attribute %(attr)s doesn't exist on %(obj)s." -msgstr "Атрибут %(attr)s не существует для %(obj)s." - -#: tables/base.py:990 -msgid "No items to display." -msgstr "Нет элементов для отображения." - -#: tables/base.py:1099 -#: templates/horizon/common/_data_table_table_actions.html:47 -msgid "Actions" -msgstr "Действия" - -#: tables/base.py:1329 -#, python-format -msgid "No match returned for the id \"%s\"." -msgstr "Нет совпадений для id \"%s\"." - -#: tables/base.py:1486 -msgid "Please select a row before taking that action." -msgstr "Выберите строку перед выполнением этого действия." - -#: tables/base.py:1570 -msgid "N/A" -msgstr "Н/Д" - -#: templates/_header.html:5 -#, python-format -msgid "Logged in as: %(username)s" -msgstr "Пользователь: %(username)s" - -#: templates/_header.html:7 -msgid "Help" -msgstr "Помощь" - -#: templates/_header.html:9 -msgid "Sign Out" -msgstr "Выход" - -#: templates/auth/_description.html:9 -msgid "" -"\n" -" If you are not sure which authentication method to use, contact your administrator.\n" -" " -msgstr "\n Если вы не уверены какой метод аутентификации выбрать, свяжитесь с вашим системным администратором.\n " - -#: templates/auth/_login.html:5 -msgid "Log In" -msgstr "Войти" - -#: templates/auth/_login.html:27 -msgid "You do not have permission to access the resource:" -msgstr "Вы не имеете права на доступ к ресурсу:" - -#: templates/auth/_login.html:29 -#, python-format -msgid "" -"Login as different user or go back to home " -"page" -msgstr "Войдите под другим пользователем или вернитесь на домашнюю страницу" - -#: templates/auth/_login.html:45 -msgid "Sign In" -msgstr "Вход" - -#: templates/auth/_login.html:46 -msgid "Connect" -msgstr "Подключиться" - -#: templates/auth/login.html:4 -msgid "Login" -msgstr "Имя пользователя" - -#: templates/horizon/_messages.html:7 -msgid "Info: " -msgstr "Информация:" - -#: templates/horizon/_messages.html:13 -msgid "Warning: " -msgstr "Внимание:" - -#: templates/horizon/_messages.html:19 -msgid "Success: " -msgstr "Успешно:" - -#: templates/horizon/_messages.html:25 -msgid "Error: " -msgstr "Ошибка:" - -#: templates/horizon/common/_data_table.html:63 -msgid "Summary" -msgstr "Итого" - -#: templates/horizon/common/_data_table.html:72 -#, python-format -msgid "Displaying %(counter)s item" -msgid_plural "Displaying %(counter)s items" -msgstr[0] "Показан %(counter)s элемент" -msgstr[1] "Показано %(counter)s элементов" -msgstr[2] "Показано %(counter)s элементов" - -#: templates/horizon/common/_data_table.html:77 -msgid "« Prev" -msgstr "« Предыдущее" - -#: templates/horizon/common/_data_table.html:80 -msgid "Next »" -msgstr "Следующее »" - -#: templates/horizon/common/_data_table_table_actions.html:45 -msgid "More Actions" -msgstr "Еще действия" - -#: templates/horizon/common/_domain_page_header.html:6 -#, python-format -msgid "%(context_name)s:" -msgstr "%(context_name)s:" - -#: templates/horizon/common/_formset_table.html:35 -msgid "Add a row" -msgstr "Добавить строку" - -#: templates/horizon/common/_formset_table_row.html:15 -#, python-format -msgid "%(name)s: %(error)s" -msgstr "%(name)s: %(error)s" - -#: templates/horizon/common/_limit_summary.html:4 -msgid "Limit Summary" -msgstr "Сводка лимитов" - -#: templates/horizon/common/_limit_summary.html:7 -msgid "Instances" -msgstr "Машины" - -#: templates/horizon/common/_limit_summary.html:8 -#: templates/horizon/common/_limit_summary.html:15 -#: templates/horizon/common/_limit_summary.html:22 -#: templates/horizon/common/_limit_summary.html:36 -#: templates/horizon/common/_limit_summary.html:43 -#: templates/horizon/common/_limit_summary.html:50 -#, python-format -msgid "Used %(used)s of %(available)s " -msgstr "Использовано %(used)s из %(available)s " - -#: templates/horizon/common/_limit_summary.html:14 -msgid "VCPUs" -msgstr "VCPU" - -#: templates/horizon/common/_limit_summary.html:21 -msgid "RAM" -msgstr "RAM" - -#: templates/horizon/common/_limit_summary.html:28 -msgid "Floating IPs" -msgstr "Назначаемые IP" - -#: templates/horizon/common/_limit_summary.html:29 -#, python-format -msgid "Allocated %(used)s of %(available)s " -msgstr "Выделено %(used)s из %(available)s " - -#: templates/horizon/common/_limit_summary.html:35 -msgid "Security Groups" -msgstr "Группы безопасности" - -#: templates/horizon/common/_limit_summary.html:42 -msgid "Volumes" -msgstr "Диски" - -#: templates/horizon/common/_limit_summary.html:49 -msgid "Volume Storage" -msgstr "Хранилище" - -#: templates/horizon/common/_modal_form_update_metadata.html:24 -#: workflows/base.py:594 -msgid "Save" -msgstr "Сохранить" - -#: templates/horizon/common/_resource_browser.html:10 -#, python-format -msgid "Displaying %(nav_items)s item" -msgid_plural "Displaying %(nav_items)s items" -msgstr[0] "Показан %(nav_items)s элемент" -msgstr[1] "Показано %(nav_items)s элементов" -msgstr[2] "Показано %(nav_items)s элементов" - -#: templates/horizon/common/_resource_browser.html:11 -#, python-format -msgid "Displaying %(content_items)s item" -msgid_plural "Displaying %(content_items)s items" -msgstr[0] "Показан %(content_items)s элемент" -msgstr[1] "Показано %(content_items)s элементов" -msgstr[2] "Показано %(content_items)s элементов" - -#: templates/horizon/common/_usage_summary.html:3 -msgid "Usage Summary" -msgstr "Сводка использования" - -#: templates/horizon/common/_usage_summary.html:7 -msgid "Select a period of time to query its usage:" -msgstr "Выберите временной интервал для запроса использования:" - -#: templates/horizon/common/_usage_summary.html:9 -#, python-format -msgid "" -"\n" -" %(start)s" -msgstr "\n %(start)s" - -#: templates/horizon/common/_usage_summary.html:13 -#, python-format -msgid "" -"\n" -" %(end)s" -msgstr "\n %(end)s" - -#: templates/horizon/common/_usage_summary.html:17 -msgid "The date should be in YYYY-mm-dd format." -msgstr "Дата должна иметь формат YYYY-mm-dd." - -#: templates/horizon/common/_usage_summary.html:20 -msgid "Active Instances:" -msgstr "Активные машины:" - -#: templates/horizon/common/_usage_summary.html:21 -msgid "Active RAM:" -msgstr "Используемая RAM:" - -#: templates/horizon/common/_usage_summary.html:22 -msgid "This Period's VCPU-Hours:" -msgstr "vCPU-часов за период:" - -#: templates/horizon/common/_usage_summary.html:23 -msgid "This Period's GB-Hours:" -msgstr "ГБ-часов за период:" - -#: templates/horizon/common/_usage_summary.html:24 -msgid "This Period's RAM-Hours:" -msgstr "RAM-часов за период:" - -#: templates/horizon/common/_workflow.html:40 -msgid "Back" -msgstr "Назад" - -#: templates/horizon/common/_workflow.html:43 -msgid "Next" -msgstr "Следующий" - -#: templatetags/branding.py:34 -msgid "Horizon" -msgstr "Horizon" - -#: templatetags/horizon.py:137 templatetags/horizon.py:148 -msgid "No Limit" -msgstr "Без ограничений" - -#: templatetags/horizon.py:140 templatetags/horizon.py:142 -msgid "Available" -msgstr "Доступно" - -#: templatetags/sizeformat.py:51 templatetags/sizeformat.py:56 -#, python-format -msgid "%(size)d Byte" -msgid_plural "%(size)d Bytes" -msgstr[0] "%(size)d байт" -msgstr[1] "%(size)d байт" -msgstr[2] "%(size)d байт" - -#: templatetags/sizeformat.py:59 -#, python-format -msgid "%s KB" -msgstr "%s КБ" - -#: templatetags/sizeformat.py:61 -#, python-format -msgid "%s MB" -msgstr "%s МБ" - -#: templatetags/sizeformat.py:63 -#, python-format -msgid "%s GB" -msgstr "%s ГБ" - -#: templatetags/sizeformat.py:65 -#, python-format -msgid "%s TB" -msgstr "%s ТБ" - -#: templatetags/sizeformat.py:66 -#, python-format -msgid "%s PB" -msgstr "%s ПБ" - -#: templatetags/sizeformat.py:74 -msgid "0 Bytes" -msgstr "0 байт" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:31 -msgid "Sell Puppy" -msgid_plural "Sell Puppies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "Sell Puppies" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:40 -msgid "Sold Puppy" -msgid_plural "Sold Puppies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "Sold Puppies" - -#: test/tests/views.py:59 -msgid "Fake" -msgstr "Fake" - -#: utils/filters.py:49 -msgid "Never" -msgstr "Никогда" - -#: utils/validators.py:26 utils/validators.py:50 -msgid "Not a valid port number" -msgstr "Недопустимый номер порта" - -#: utils/validators.py:31 -msgid "Not a valid IP protocol number" -msgstr "Недопустимый номер IP-протокола" - -#: utils/validators.py:45 -msgid "One colon allowed in port range" -msgstr "В списке портов допустима одна запятая" - -#: utils/validators.py:52 -msgid "Port number must be integer" -msgstr "Номер порта должен быть целым числом" - -#: utils/validators.py:59 -msgid "The string may only contain ASCII printable characters." -msgstr "Строка может содержать только печатные ASCII символы." - -#: workflows/base.py:71 -msgid "Processing..." -msgstr "Обработка…" - -#: workflows/base.py:475 -msgid "All available" -msgstr "Все доступные" - -#: workflows/base.py:476 -msgid "Members" -msgstr "Участники" - -#: workflows/base.py:477 -msgid "None available." -msgstr "Нет доступных." - -#: workflows/base.py:478 -msgid "No members." -msgstr "Нет участников." - -#: workflows/base.py:595 -#, python-format -msgid "%s completed successfully." -msgstr "%s успешно завершено." - -#: workflows/base.py:596 -#, python-format -msgid "%s did not complete." -msgstr "%s не завершено." diff --git a/code/horizon/horizon/locale/ru/LC_MESSAGES/djangojs.po b/code/horizon/horizon/locale/ru/LC_MESSAGES/djangojs.po deleted file mode 100644 index 664dd0c7..00000000 --- a/code/horizon/horizon/locale/ru/LC_MESSAGES/djangojs.po +++ /dev/null @@ -1,623 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Ainur Shakirov , 2015 -# Fedor Tarasenko , 2015 -# Ilya Alekseyev , 2015 -# Yury Sakarinen, 2014 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-12 16:36-0500\n" -"PO-Revision-Date: 2015-04-13 12:00+0000\n" -"Last-Translator: Ilya Alekseyev \n" -"Language-Team: Russian (http://www.transifex.com/projects/p/horizon/language/ru/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: ru\n" -"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" - -#: static/angular/action-list/button-tooltip.js:15 -msgid "" -"The action cannot be performed. The contents of this row have errors or are " -"missing information." -msgstr "Действие не может быть выполнено. Эта строка содержит ошибки или недостаточную информацию. " - -#: static/angular/metadata-display/metadata-display.js:33 -msgid "Detail Information" -msgstr "Подробная информация" - -#: static/angular/metadata-tree/metadata-tree.js:35 -msgid "" -"You can specify resource metadata by moving items from the left column to " -"the right column. In the left columns there are metadata definitions from " -"the Glance Metadata Catalog. Use the \"Other\" option to add metadata with " -"the key of your choice." -msgstr "Вы можете указать метаданные ресурса перемещением элементов из левого столбца в правый. В левом столбце имеются определения метаданных из каталога метаданных Glance. Используйте опцию \"Другой\" для добавления выбранных вами ключей." - -#: static/angular/metadata-tree/metadata-tree.js:36 -msgid "Min" -msgstr "Мин." - -#: static/angular/metadata-tree/metadata-tree.js:37 -msgid "Max" -msgstr "Макс." - -#: static/angular/metadata-tree/metadata-tree.js:38 -msgid "Min length" -msgstr "Мин. длина" - -#: static/angular/metadata-tree/metadata-tree.js:39 -msgid "Max length" -msgstr "Макс. длина" - -#: static/angular/metadata-tree/metadata-tree.js:40 -msgid "Pattern mismatch" -msgstr "Несоответствие шаблону" - -#: static/angular/metadata-tree/metadata-tree.js:41 -msgid "Integer required" -msgstr "Требуется целое число" - -#: static/angular/metadata-tree/metadata-tree.js:42 -msgid "Decimal required" -msgstr "Требуется десятичное число" - -#: static/angular/metadata-tree/metadata-tree.js:43 -msgid "Required" -msgstr "Требуется" - -#: static/angular/metadata-tree/metadata-tree.js:44 -msgid "Duplicate keys are not allowed" -msgstr "Повторяющиеся ключи не допускаются" - -#: static/angular/metadata-tree/metadata-tree.js:45 -#: static/angular/table/basic-table.js:6 -#: static/horizon/js/horizon.forms.js:184 -msgid "Filter" -msgstr "Фильтр" - -#: static/angular/metadata-tree/metadata-tree.js:46 -msgid "Available Metadata" -msgstr "Доступные метаданные" - -#: static/angular/metadata-tree/metadata-tree.js:47 -msgid "Existing Metadata" -msgstr "Имеющиеся метаданные" - -#: static/angular/metadata-tree/metadata-tree.js:48 -msgid "Custom" -msgstr "Выборочный" - -#: static/angular/metadata-tree/metadata-tree.js:49 -msgid "No available metadata" -msgstr "Метаданные недоступны" - -#: static/angular/metadata-tree/metadata-tree.js:50 -msgid "No existing metadata" -msgstr "Нет метаданных" - -#: static/angular/modal/modal.js:83 -msgid "Submit" -msgstr "Отправить" - -#: static/angular/modal/modal.js:84 static/angular/wizard/wizard.js:11 -#: static/horizon/js/horizon.modals.js:33 -msgid "Cancel" -msgstr "Отмена" - -#: static/angular/transfer-table/transfer-table.js:39 -msgid "Allocated" -msgstr "Выделенный" - -#: static/angular/transfer-table/transfer-table.js:40 -msgid "Available" -msgstr "Доступно" - -#: static/angular/transfer-table/transfer-table.js:41 -msgid "Select one" -msgstr "Выберите один" - -#: static/angular/transfer-table/transfer-table.js:42 -msgid "Select an item from Available items below" -msgstr "Выберите элемент из доступных элементов ниже" - -#: static/angular/transfer-table/transfer-table.js:43 -msgid "No available items" -msgstr "Нет доступных элементов" - -#: static/angular/transfer-table/transfer-table.js:44 -msgid "Expand to see allocated items" -msgstr "Показать выделенные элементы" - -#: static/angular/transfer-table/transfer-table.js:45 -msgid "Expand to see available items" -msgstr "Показать все доступные элементы" - -#: static/angular/transfer-table/transfer-table.js:46 -msgid "Click to show or hide" -msgstr "Нажмите для показа или скрытия" - -#: static/angular/transfer-table/transfer-table.js:47 -msgid "Re-order items using drag and drop" -msgstr "Переопределите элементы перемещением" - -#: static/angular/transfer-table/transfer-table.js:48 -msgid "Click to see more details" -msgstr "Нажмите для подробностей" - -#: static/angular/transfer-table/transfer-table.js:100 -msgid "Found %(found)s of %(total)s" -msgstr "Найдено %(found)s из %(total)s" - -#: static/angular/transfer-table/transfer-table.js:166 -msgid "Click here to expand the row and view the errors." -msgstr "Нажмите для показа ошибок." - -#: static/angular/wizard/wizard.js:12 -msgid "Back" -msgstr "Назад" - -#: static/angular/wizard/wizard.js:13 -msgid "Next" -msgstr "Вперёд" - -#: static/angular/wizard/wizard.js:14 -msgid "Finish" -msgstr "Закончить" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Connecting" -msgstr "Подключение" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Open" -msgstr "Открыт" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closing" -msgstr "Закрытие" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closed" -msgstr "Закрыт" - -#: static/horizon/js/angular/directives/serialConsole.js:85 -#, c-format -msgid "Status: %s" -msgstr "Статус: %s" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "Yes" -msgstr "Да" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "No" -msgstr "Нет" - -#: static/horizon/js/angular/filters/filters.js:53 -#: static/horizon/js/angular/filters/filters.js:140 -#, c-format -msgid "%s GB" -msgstr "%s ГБ" - -#: static/horizon/js/angular/filters/filters.js:70 -#: static/horizon/js/angular/filters/filters.js:142 -#, c-format -msgid "%s MB" -msgstr "%s МБ" - -#: static/horizon/js/angular/filters/filters.js:138 -#, c-format -msgid "%s TB" -msgstr "%s ТБ" - -#: static/horizon/js/angular/filters/filters.js:144 -#, c-format -msgid "%s KB" -msgstr "%s кБ" - -#: static/horizon/js/angular/filters/filters.js:146 -#, c-format -msgid "%s bytes" -msgstr "%s байт" - -#: static/horizon/js/angular/filters/filters.js:163 -#: static/horizon/js/horizon.tables.js:393 -#, c-format -msgid "Displaying %s item" -msgid_plural "Displaying %s items" -msgstr[0] "Отображено %s значение" -msgstr[1] "Отображено %s значений" -msgstr[2] "Отображено %s значений" - -#: static/horizon/js/angular/services/hz.api.cinder.js:47 -msgid "Unable to retrieve volumes." -msgstr "Не удалось получить диски." - -#: static/horizon/js/angular/services/hz.api.cinder.js:74 -msgid "Unable to retrieve volume snapshots." -msgstr "Не удалось получить снимки диска." - -#: static/horizon/js/angular/services/hz.api.config.js:43 -msgid "Unable to retrieve user configuration." -msgstr "Не удалось получить конфигурацию пользователя." - -#: static/horizon/js/angular/services/hz.api.config.js:62 -msgid "Unable to retrieve admin configuration." -msgstr "Не удалось получить конфигурацию администратора." - -#: static/horizon/js/angular/services/hz.api.config.js:105 -msgid "Unable to retrieve settings." -msgstr "Не удалось получить настройки." - -#: static/horizon/js/angular/services/hz.api.config.js:289 -msgid "Setting is not enabled: %(setting)s" -msgstr "Настройка не включена: %(setting)s" - -#: static/horizon/js/angular/services/hz.api.glance.js:38 -msgid "Unable to retrieve image." -msgstr "Не удалось получить образ." - -#: static/horizon/js/angular/services/hz.api.glance.js:81 -msgid "Unable to retrieve images." -msgstr "Не удалось получить образы." - -#: static/horizon/js/angular/services/hz.api.glance.js:144 -msgid "Unable to retrieve namespaces." -msgstr "Не удалось получить пространство имён." - -#: static/horizon/js/angular/services/hz.api.keystone.js:24 -msgid "Unable to retrieve users" -msgstr "Не удалось получить пользователей." - -#: static/horizon/js/angular/services/hz.api.keystone.js:31 -msgid "Unable to create the user." -msgstr "Не удалось создать пользователя." - -#: static/horizon/js/angular/services/hz.api.keystone.js:38 -msgid "Unable to delete the users." -msgstr "Не удалось удалить пользователя." - -#: static/horizon/js/angular/services/hz.api.keystone.js:73 -msgid "Unable to retrieve the current user session." -msgstr "Не удалось получить текущую сессию пользователя." - -#: static/horizon/js/angular/services/hz.api.keystone.js:80 -msgid "Unable to retrieve the user" -msgstr "Не удалось получить пользователя." - -#: static/horizon/js/angular/services/hz.api.keystone.js:88 -msgid "Unable to edit the user." -msgstr "Не удалось изменить пользователя." - -#: static/horizon/js/angular/services/hz.api.keystone.js:95 -msgid "Unable to delete the user." -msgstr "Не удалось удалить пользователя." - -#: static/horizon/js/angular/services/hz.api.keystone.js:103 -msgid "Unable to retrieve role" -msgstr "Не удалось получить роль." - -#: static/horizon/js/angular/services/hz.api.keystone.js:110 -msgid "Unable to create the role." -msgstr "Не удалось создать роль." - -#: static/horizon/js/angular/services/hz.api.keystone.js:117 -msgid "Unable to delete the roles." -msgstr "Не удалось удалить роли." - -#: static/horizon/js/angular/services/hz.api.keystone.js:124 -msgid "Unable to retrieve the role" -msgstr "Не удалось получить роль" - -#: static/horizon/js/angular/services/hz.api.keystone.js:132 -msgid "Unable to edit the role." -msgstr "Не удалось изменить роль." - -#: static/horizon/js/angular/services/hz.api.keystone.js:139 -msgid "Unable to delete the role." -msgstr "Не удалось удалить роль." - -#: static/horizon/js/angular/services/hz.api.keystone.js:147 -msgid "Unable to retrieve domains" -msgstr "Не удалось получить домены." - -#: static/horizon/js/angular/services/hz.api.keystone.js:154 -msgid "Unable to create the domain." -msgstr "Не удалось создать домен." - -#: static/horizon/js/angular/services/hz.api.keystone.js:161 -msgid "Unable to delete the domains." -msgstr "Не удалось удалить домены." - -#: static/horizon/js/angular/services/hz.api.keystone.js:168 -msgid "Unable to retrieve the domain" -msgstr "Не удалось получить домен." - -#: static/horizon/js/angular/services/hz.api.keystone.js:176 -msgid "Unable to edit the domain." -msgstr "Не удалось изменить домен." - -#: static/horizon/js/angular/services/hz.api.keystone.js:183 -msgid "Unable to delete the domain." -msgstr "Не удалось удалить домен." - -#: static/horizon/js/angular/services/hz.api.keystone.js:192 -msgid "Unable to retrieve projects" -msgstr "Не удалось получить проекты" - -#: static/horizon/js/angular/services/hz.api.keystone.js:199 -msgid "Unable to create the project." -msgstr "Не удалось создать проект" - -#: static/horizon/js/angular/services/hz.api.keystone.js:206 -msgid "Unable to delete the projects." -msgstr "Не удалось удалить проекты." - -#: static/horizon/js/angular/services/hz.api.keystone.js:213 -msgid "Unable to retrieve the project" -msgstr "Не удалось получить проект" - -#: static/horizon/js/angular/services/hz.api.keystone.js:221 -msgid "Unable to edit the project." -msgstr "Не удалось изменить проект." - -#: static/horizon/js/angular/services/hz.api.keystone.js:228 -msgid "Unable to delete the project." -msgstr "Не удалось удалить проект." - -#: static/horizon/js/angular/services/hz.api.keystone.js:236 -msgid "Unable to grant the role." -msgstr "Не удалось предоставить роль." - -#: static/horizon/js/angular/services/hz.api.keystone.js:250 -msgid "Unable to fetch the service catalog." -msgstr "Не удалось получить службу каталогов." - -#: static/horizon/js/angular/services/hz.api.keystone.js:385 -msgid "Service type is not enabled: %(desiredType)s" -msgstr "Тип службы не включен: %(desiredType)s" - -#: static/horizon/js/angular/services/hz.api.keystone.js:392 -msgid "Cannot get service catalog from keystone." -msgstr "Не удалось получить службу каталогов с Keystone." - -#: static/horizon/js/angular/services/hz.api.neutron.js:39 -msgid "Unable to retrieve networks." -msgstr "Не удалось получить сети." - -#: static/horizon/js/angular/services/hz.api.neutron.js:88 -msgid "Unable to create the network." -msgstr "Не удалось создать сеть." - -#: static/horizon/js/angular/services/hz.api.neutron.js:108 -msgid "Unable to retrieve subnets." -msgstr "Не удалось получить подсети." - -#: static/horizon/js/angular/services/hz.api.neutron.js:172 -msgid "Unable to create the subnet." -msgstr "Не удалось создать подсеть." - -#: static/horizon/js/angular/services/hz.api.neutron.js:192 -msgid "Unable to retrieve ports." -msgstr "Не удалось получить порты." - -#: static/horizon/js/angular/services/hz.api.nova.js:40 -msgid "Unable to retrieve keypairs." -msgstr "Не удалось получить пары ключей." - -#: static/horizon/js/angular/services/hz.api.nova.js:62 -msgid "Unable to import the keypair." -msgstr "Не удалось импортировать пару ключей." - -#: static/horizon/js/angular/services/hz.api.nova.js:64 -msgid "Unable to create the keypair." -msgstr "Не удалось создать пару ключей." - -#: static/horizon/js/angular/services/hz.api.nova.js:83 -msgid "Unable to retrieve availability zones." -msgstr "Не удалось получить зоны доступности." - -#: static/horizon/js/angular/services/hz.api.nova.js:121 -msgid "Unable to retrieve limits." -msgstr "Не удалось получить лимиты." - -#: static/horizon/js/angular/services/hz.api.nova.js:148 -msgid "Unable to create the server." -msgstr "Не удалось создать сервер." - -#: static/horizon/js/angular/services/hz.api.nova.js:162 -msgid "Unable to retrieve server." -msgstr "Не удалось получить сервер." - -#: static/horizon/js/angular/services/hz.api.nova.js:192 -msgid "Unable to retrieve extensions." -msgstr "Не удалось получить расширения." - -#: static/horizon/js/angular/services/hz.api.nova.js:237 -msgid "Unable to retrieve flavors." -msgstr "Не удалось получить типы инстанса." - -#: static/horizon/js/angular/services/hz.api.nova.js:255 -msgid "Unable to retrieve flavor." -msgstr "Не удалось получить тип инстанса." - -#: static/horizon/js/angular/services/hz.api.nova.js:269 -msgid "Unable to retrieve flavor extra specs." -msgstr "Не удалось получить доп. параметры типа интанса." - -#: static/horizon/js/angular/services/hz.api.nova.js:311 -msgid "Extension is not enabled: %(extension)s" -msgstr "Расширение не включено: %(extension)s" - -#: static/horizon/js/angular/services/hz.api.nova.js:318 -msgid "Cannot get nova extension list." -msgstr "Не удалось получить список расширений nova." - -#: static/horizon/js/angular/services/hz.api.policy.js:65 -msgid "Policy check failed." -msgstr "Проверка политики не удалась." - -#: static/horizon/js/angular/services/hz.api.security-group.js:64 -msgid "Unable to retrieve security groups." -msgstr "Не удалось получить группы безопасности." - -#: static/horizon/js/horizon.accordion_nav.js:78 -#: static/horizon/js/horizon.modals.js:315 -#: static/horizon/js/horizon.tabs.js:21 -msgid "Loading" -msgstr "Загрузка" - -#: static/horizon/js/horizon.d3linechart.js:394 -#: static/horizon/js/horizon.d3linechart.js:404 -msgid "No data available." -msgstr "Нет данных." - -#: static/horizon/js/horizon.d3linechart.js:410 -#: static/horizon/js/horizon.modals.js:334 -#: static/horizon/js/horizon.tables_inline_edit.js:94 -#: static/horizon/js/horizon.tables_inline_edit.js:157 -msgid "An error occurred. Please try again later." -msgstr "Произошла ошибка. Повторите попытку." - -#: static/horizon/js/horizon.firewalls.js:32 -#: static/horizon/js/horizon.instances.js:31 -msgid "There was a problem communicating with the server, please try again." -msgstr "Обнаружена проблема при соединении с сервером. Повторите попытку." - -#: static/horizon/js/horizon.instances.js:273 -msgid "Could not read the file" -msgstr "Не удалось прочитать файл" - -#: static/horizon/js/horizon.instances.js:279 -#: static/horizon/js/horizon.instances.js:308 -msgid "Could not decrypt the password" -msgstr "Не удалось расшифровать пароль" - -#: static/horizon/js/horizon.membership.js:190 -msgid "No roles" -msgstr "Нет ролей" - -#: static/horizon/js/horizon.membership.js:222 -msgid "Roles" -msgstr "Роли" - -#: static/horizon/js/horizon.messages.js:9 -msgid "Danger: " -msgstr "Опасность:" - -#: static/horizon/js/horizon.messages.js:10 -msgid "Warning: " -msgstr "Внимание:" - -#: static/horizon/js/horizon.messages.js:11 -msgid "Notice: " -msgstr "Примечание:" - -#: static/horizon/js/horizon.messages.js:12 -msgid "Success: " -msgstr "Успешно:" - -#: static/horizon/js/horizon.messages.js:13 -msgid "Error: " -msgstr "Ошибка:" - -#: static/horizon/js/horizon.modals.js:229 -#: static/horizon/js/horizon.tables.js:218 -msgid "Working" -msgstr "Обработка" - -#: static/horizon/js/horizon.modals.js:263 -msgid "There was an error submitting the form. Please try again." -msgstr "При отправке формы произошла ошибка. Повторите попытку." - -#: static/horizon/js/horizon.networktopology.js:530 -#: static/horizon/js/horizon.networktopology.js:536 -msgid "None" -msgstr "Нет" - -#: static/horizon/js/horizon.networktopology.js:549 -msgid "Delete" -msgstr "Удалить" - -#: static/horizon/js/horizon.networktopology.js:552 -msgid "STATUS" -msgstr "СОСТОЯНИЕ" - -#: static/horizon/js/horizon.networktopology.js:553 -msgid "ID" -msgstr "ID" - -#: static/horizon/js/horizon.networktopology.js:554 -msgid "Interfaces" -msgstr "Интерфейсы" - -#: static/horizon/js/horizon.networktopology.js:555 -msgid "Delete Interface" -msgstr "Удалить интерфейс" - -#: static/horizon/js/horizon.networktopology.js:556 -msgid "Open Console" -msgstr "Открыть консоль" - -#: static/horizon/js/horizon.networktopology.js:557 -msgid "View Details" -msgstr "Просмотреть детали" - -#: static/horizon/js/horizon.networktopology.js:560 -msgid "Delete Router" -msgstr "Удалить маршрутизатор" - -#: static/horizon/js/horizon.networktopology.js:561 -msgid "View Router Details" -msgstr "Посмотреть информацию о маршрутизаторе" - -#: static/horizon/js/horizon.networktopology.js:564 -msgid "Add Interface" -msgstr "Добавить Интерфейс" - -#: static/horizon/js/horizon.networktopology.js:570 -msgid "Terminate Instance" -msgstr "Удалить инстанс" - -#: static/horizon/js/horizon.networktopology.js:571 -msgid "View Instance Details" -msgstr "Посмотреть информацию об инстансе." - -#: static/horizon/js/horizon.tables.js:39 -#: static/horizon/js/horizon.tables.js:406 -msgid "No items to display." -msgstr "Нет элементов для отображения." - -#: static/horizon/js/horizon.tables.js:52 -#: static/horizon/js/horizon.tables.js:120 -msgid "An error occurred while updating." -msgstr "Во время обновления произошла ошибка." - -#: static/horizon/js/horizon.tables.js:201 -#, c-format -msgid "You have selected %s. " -msgstr "Выбрано %s." - -#: static/horizon/js/horizon.tables.js:203 -#, c-format -msgid "Confirm %s" -msgstr "Подтвердите %s" - -#: static/horizon/js/horizon.tables.js:204 -msgid "Please confirm your selection. " -msgstr "Подтвердите свой выбор." - -#: static/horizon/js/horizon.tables_inline_edit.js:88 -#: static/horizon/js/horizon.tables_inline_edit.js:151 -msgid "Not authorized to do this operation." -msgstr "Нет прав для выполнения." - -#: static/horizon/js/horizon.users.js:18 -msgid "Passwords do not match." -msgstr "Пароли не совпадают." diff --git a/code/horizon/horizon/locale/zh_CN/LC_MESSAGES/django.po b/code/horizon/horizon/locale/zh_CN/LC_MESSAGES/django.po deleted file mode 100644 index 53100150..00000000 --- a/code/horizon/horizon/locale/zh_CN/LC_MESSAGES/django.po +++ /dev/null @@ -1,509 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# ChangBo Guo(gcb) , 2014 -# LIU Yulong , 2014-2015 -# Xiao Xi LIU , 2014 -# Ying Chun Guo , 2015 -# 颜海峰 , 2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-06 21:07-0500\n" -"PO-Revision-Date: 2015-04-01 22:52+0000\n" -"Last-Translator: 颜海峰 \n" -"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/horizon/language/zh_CN/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh_CN\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: base.py:475 -msgid "Other" -msgstr "其它" - -#: browsers/base.py:88 -msgid "Navigation Item" -msgstr "导航条目" - -#: browsers/views.py:41 -#, python-format -msgid "Select a %s to browse." -msgstr "选择一个%s 浏览。" - -#: conf/default.py:41 -msgid "Password is not accepted" -msgstr "密码没有接受" - -#: decorators.py:53 -msgid "Please log in to continue." -msgstr "请先登录。" - -#: decorators.py:85 -#, python-format -msgid "You are not authorized to access %s" -msgstr "您无权访问 %s" - -#: exceptions.py:163 -#, python-format -msgid "A %(resource)s with the name \"%(name)s\" already exists." -msgstr "已经存在一个资源%(resource)s名称为\"%(name)s\"。" - -#: exceptions.py:235 -#, python-format -msgid "Unauthorized: %s" -msgstr "无权: %s" - -#: exceptions.py:238 -msgid "Unauthorized. Please try logging in again." -msgstr "未授权。请尝试重新登录。" - -#: forms/fields.py:64 -msgid "Incorrect format for IP address" -msgstr "不正确的IP地址格式" - -#: forms/fields.py:65 -msgid "Invalid version for IP address" -msgstr "IP 地址版本无效" - -#: forms/fields.py:66 -msgid "Invalid subnet mask" -msgstr "无效的子网掩码" - -#: forms/views.py:132 templates/horizon/common/_usage_summary.html:16 -msgid "Submit" -msgstr "提交" - -#: forms/views.py:133 -#: templates/horizon/common/_modal_form_update_metadata.html:25 -#: templates/horizon/common/_workflow.html:49 -msgid "Cancel" -msgstr "取消" - -#: middleware.py:103 -msgid "Session timed out." -msgstr "会话超时。" - -#: tables/actions.py:460 -#: templates/horizon/common/_data_table_table_actions.html:21 -#: templates/horizon/common/_data_table_table_actions.html:33 -#: templates/horizon/common/_workflow_step_update_members.html:14 -#: templates/horizon/common/_workflow_step_update_members.html:23 -msgid "Filter" -msgstr "筛选" - -#: tables/actions.py:645 -msgid "This action cannot be undone." -msgstr "这个动作不能撤消。" - -#: tables/actions.py:767 -#, python-format -msgctxt "past" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:769 -#, python-format -msgctxt "present" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:832 -#, python-format -msgid "You are not allowed to %(action)s: %(objs)s" -msgstr "您被禁止执行 %(action)s: %(objs)s" - -#: tables/actions.py:839 -#, python-format -msgid "Unable to %(action)s: %(objs)s" -msgstr "无法执行 %(action)s: %(objs)s" - -#: tables/actions.py:845 -#, python-format -msgid "%(action)s: %(objs)s" -msgstr "%(action)s: %(objs)s" - -#: tables/actions.py:915 -msgid "Delete" -msgstr "删除" - -#: tables/actions.py:917 -msgid "Deleted" -msgstr "已删除" - -#: tables/actions.py:948 -msgid "Update" -msgstr "更新" - -#: tables/actions.py:949 -msgid "Updated" -msgstr "已更新" - -#: tables/base.py:305 -msgid "-" -msgstr "-" - -#: tables/base.py:361 -#, python-format -msgid "The attribute %(attr)s doesn't exist on %(obj)s." -msgstr "属性 %(attr)s 并不存在于 %(obj)s。" - -#: tables/base.py:990 -msgid "No items to display." -msgstr "没有条目显示。" - -#: tables/base.py:1099 -#: templates/horizon/common/_data_table_table_actions.html:47 -msgid "Actions" -msgstr "动作" - -#: tables/base.py:1329 -#, python-format -msgid "No match returned for the id \"%s\"." -msgstr "id \"%s\" 没有匹配的返回顶。" - -#: tables/base.py:1486 -msgid "Please select a row before taking that action." -msgstr "请在执行前选择一行。" - -#: tables/base.py:1570 -msgid "N/A" -msgstr "无" - -#: templates/_header.html:5 -#, python-format -msgid "Logged in as: %(username)s" -msgstr "登录身份: %(username)s" - -#: templates/_header.html:7 -msgid "Help" -msgstr "帮助" - -#: templates/_header.html:9 -msgid "Sign Out" -msgstr "退出" - -#: templates/auth/_description.html:9 -msgid "" -"\n" -" If you are not sure which authentication method to use, contact your administrator.\n" -" " -msgstr "\n如果你不确定使用哪种认证方式,请联系管理员。" - -#: templates/auth/_login.html:5 -msgid "Log In" -msgstr "登录" - -#: templates/auth/_login.html:27 -msgid "You do not have permission to access the resource:" -msgstr "你没有被授权访问这些资源:" - -#: templates/auth/_login.html:29 -#, python-format -msgid "" -"Login as different user or go back to home " -"page" -msgstr "使用其他用户登录或返回 首页" - -#: templates/auth/_login.html:45 -msgid "Sign In" -msgstr "登入" - -#: templates/auth/_login.html:46 -msgid "Connect" -msgstr "连接" - -#: templates/auth/login.html:4 -msgid "Login" -msgstr "登录" - -#: templates/horizon/_messages.html:7 -msgid "Info: " -msgstr "信息:" - -#: templates/horizon/_messages.html:13 -msgid "Warning: " -msgstr "警告:" - -#: templates/horizon/_messages.html:19 -msgid "Success: " -msgstr "成功:" - -#: templates/horizon/_messages.html:25 -msgid "Error: " -msgstr "错误:" - -#: templates/horizon/common/_data_table.html:63 -msgid "Summary" -msgstr "概要" - -#: templates/horizon/common/_data_table.html:72 -#, python-format -msgid "Displaying %(counter)s item" -msgid_plural "Displaying %(counter)s items" -msgstr[0] "正在显示 %(counter)s 项" - -#: templates/horizon/common/_data_table.html:77 -msgid "« Prev" -msgstr "« 前页" - -#: templates/horizon/common/_data_table.html:80 -msgid "Next »" -msgstr "后页 »" - -#: templates/horizon/common/_data_table_table_actions.html:45 -msgid "More Actions" -msgstr "更多操作" - -#: templates/horizon/common/_domain_page_header.html:6 -#, python-format -msgid "%(context_name)s:" -msgstr "%(context_name)s:" - -#: templates/horizon/common/_formset_table.html:35 -msgid "Add a row" -msgstr "增加一行" - -#: templates/horizon/common/_formset_table_row.html:15 -#, python-format -msgid "%(name)s: %(error)s" -msgstr "%(name)s: %(error)s" - -#: templates/horizon/common/_limit_summary.html:4 -msgid "Limit Summary" -msgstr "上限摘要" - -#: templates/horizon/common/_limit_summary.html:7 -msgid "Instances" -msgstr "实例" - -#: templates/horizon/common/_limit_summary.html:8 -#: templates/horizon/common/_limit_summary.html:15 -#: templates/horizon/common/_limit_summary.html:22 -#: templates/horizon/common/_limit_summary.html:36 -#: templates/horizon/common/_limit_summary.html:43 -#: templates/horizon/common/_limit_summary.html:50 -#, python-format -msgid "Used %(used)s of %(available)s " -msgstr " %(available)s 中的 %(used)s 已使用" - -#: templates/horizon/common/_limit_summary.html:14 -msgid "VCPUs" -msgstr "虚拟处理器(VCPU)" - -#: templates/horizon/common/_limit_summary.html:21 -msgid "RAM" -msgstr "内存" - -#: templates/horizon/common/_limit_summary.html:28 -msgid "Floating IPs" -msgstr "浮动IP" - -#: templates/horizon/common/_limit_summary.html:29 -#, python-format -msgid "Allocated %(used)s of %(available)s " -msgstr "已分配 %(used)s %(available)s " - -#: templates/horizon/common/_limit_summary.html:35 -msgid "Security Groups" -msgstr "安全组" - -#: templates/horizon/common/_limit_summary.html:42 -msgid "Volumes" -msgstr "云硬盘" - -#: templates/horizon/common/_limit_summary.html:49 -msgid "Volume Storage" -msgstr "卷存储" - -#: templates/horizon/common/_modal_form_update_metadata.html:24 -#: workflows/base.py:594 -msgid "Save" -msgstr "保存" - -#: templates/horizon/common/_resource_browser.html:10 -#, python-format -msgid "Displaying %(nav_items)s item" -msgid_plural "Displaying %(nav_items)s items" -msgstr[0] "正在显示 %(nav_items)s 项" - -#: templates/horizon/common/_resource_browser.html:11 -#, python-format -msgid "Displaying %(content_items)s item" -msgid_plural "Displaying %(content_items)s items" -msgstr[0] "正在显示 %(content_items)s 项" - -#: templates/horizon/common/_usage_summary.html:3 -msgid "Usage Summary" -msgstr "使用情况摘要" - -#: templates/horizon/common/_usage_summary.html:7 -msgid "Select a period of time to query its usage:" -msgstr "选择一段时间来查询其用量:" - -#: templates/horizon/common/_usage_summary.html:9 -#, python-format -msgid "" -"\n" -" %(start)s" -msgstr "\n %(start)s" - -#: templates/horizon/common/_usage_summary.html:13 -#, python-format -msgid "" -"\n" -" %(end)s" -msgstr "\n%(end)s" - -#: templates/horizon/common/_usage_summary.html:17 -msgid "The date should be in YYYY-mm-dd format." -msgstr "日期应是YYYY-mm-dd格式。" - -#: templates/horizon/common/_usage_summary.html:20 -msgid "Active Instances:" -msgstr "运行的云主机:" - -#: templates/horizon/common/_usage_summary.html:21 -msgid "Active RAM:" -msgstr "活跃的内存:" - -#: templates/horizon/common/_usage_summary.html:22 -msgid "This Period's VCPU-Hours:" -msgstr "这一时期的VCPU-小时数:" - -#: templates/horizon/common/_usage_summary.html:23 -msgid "This Period's GB-Hours:" -msgstr "这一时期的GB-小时数:" - -#: templates/horizon/common/_usage_summary.html:24 -msgid "This Period's RAM-Hours:" -msgstr "这一时期的内存-小时数" - -#: templates/horizon/common/_workflow.html:40 -msgid "Back" -msgstr "返回" - -#: templates/horizon/common/_workflow.html:43 -msgid "Next" -msgstr "下一步" - -#: templatetags/branding.py:34 -msgid "Horizon" -msgstr "控制面板" - -#: templatetags/horizon.py:137 templatetags/horizon.py:148 -msgid "No Limit" -msgstr "无限制" - -#: templatetags/horizon.py:140 templatetags/horizon.py:142 -msgid "Available" -msgstr "可用配额" - -#: templatetags/sizeformat.py:51 templatetags/sizeformat.py:56 -#, python-format -msgid "%(size)d Byte" -msgid_plural "%(size)d Bytes" -msgstr[0] "%(size)d 字节" - -#: templatetags/sizeformat.py:59 -#, python-format -msgid "%s KB" -msgstr "%s KB" - -#: templatetags/sizeformat.py:61 -#, python-format -msgid "%s MB" -msgstr "%s MB" - -#: templatetags/sizeformat.py:63 -#, python-format -msgid "%s GB" -msgstr "%s GB" - -#: templatetags/sizeformat.py:65 -#, python-format -msgid "%s TB" -msgstr "%s TB" - -#: templatetags/sizeformat.py:66 -#, python-format -msgid "%s PB" -msgstr "%s PB" - -#: templatetags/sizeformat.py:74 -msgid "0 Bytes" -msgstr "0字节" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:31 -msgid "Sell Puppy" -msgid_plural "Sell Puppies" -msgstr[0] "出售小狗" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:40 -msgid "Sold Puppy" -msgid_plural "Sold Puppies" -msgstr[0] "已售出的小狗" - -#: test/tests/views.py:59 -msgid "Fake" -msgstr "伪" - -#: utils/filters.py:49 -msgid "Never" -msgstr "从不" - -#: utils/validators.py:26 utils/validators.py:50 -msgid "Not a valid port number" -msgstr "不是一个有效的端口号" - -#: utils/validators.py:31 -msgid "Not a valid IP protocol number" -msgstr "不是一个有效的IP协议号" - -#: utils/validators.py:45 -msgid "One colon allowed in port range" -msgstr "用冒号分隔端口区间" - -#: utils/validators.py:52 -msgid "Port number must be integer" -msgstr "端口号必须为整数" - -#: utils/validators.py:59 -msgid "The string may only contain ASCII printable characters." -msgstr "字符串只能包含ASCII可印刷字符." - -#: workflows/base.py:71 -msgid "Processing..." -msgstr "正在处理中, 请稍候..." - -#: workflows/base.py:475 -msgid "All available" -msgstr "所有可用成员" - -#: workflows/base.py:476 -msgid "Members" -msgstr "成员" - -#: workflows/base.py:477 -msgid "None available." -msgstr "没有可用成员。" - -#: workflows/base.py:478 -msgid "No members." -msgstr "没有成员。" - -#: workflows/base.py:595 -#, python-format -msgid "%s completed successfully." -msgstr "%s 成功完成。" - -#: workflows/base.py:596 -#, python-format -msgid "%s did not complete." -msgstr "%s 没有完成。" diff --git a/code/horizon/horizon/locale/zh_CN/LC_MESSAGES/djangojs.po b/code/horizon/horizon/locale/zh_CN/LC_MESSAGES/djangojs.po deleted file mode 100644 index 173e7111..00000000 --- a/code/horizon/horizon/locale/zh_CN/LC_MESSAGES/djangojs.po +++ /dev/null @@ -1,623 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Alfred , 2015 -# johnwoo_lee , 2015 -# LIU Yulong , 2014-2015 -# Tom Fifield , 2015 -# Xiao Xi LIU , 2014 -# Ying Chun Guo , 2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-12 01:16-0500\n" -"PO-Revision-Date: 2015-04-20 07:06+0000\n" -"Last-Translator: Ying Chun Guo \n" -"Language-Team: Chinese (China) (http://www.transifex.com/projects/p/horizon/language/zh_CN/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh_CN\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: static/angular/action-list/button-tooltip.js:15 -msgid "" -"The action cannot be performed. The contents of this row have errors or are " -"missing information." -msgstr "不能执行该操作。该列的内容有错或是缺少信息。" - -#: static/angular/metadata-display/metadata-display.js:33 -msgid "Detail Information" -msgstr "详细信息" - -#: static/angular/metadata-tree/metadata-tree.js:35 -msgid "" -"You can specify resource metadata by moving items from the left column to " -"the right column. In the left columns there are metadata definitions from " -"the Glance Metadata Catalog. Use the \"Other\" option to add metadata with " -"the key of your choice." -msgstr "你可以通过从左边栏目目录选择到右边栏目来指定资源的元数据。在左边栏目是按照glance 元数据目录来定义的元数据。使用\"其他\"选项来增加元数据。" - -#: static/angular/metadata-tree/metadata-tree.js:36 -msgid "Min" -msgstr "最小" - -#: static/angular/metadata-tree/metadata-tree.js:37 -msgid "Max" -msgstr "最大" - -#: static/angular/metadata-tree/metadata-tree.js:38 -msgid "Min length" -msgstr "最小长度" - -#: static/angular/metadata-tree/metadata-tree.js:39 -msgid "Max length" -msgstr "最大长度" - -#: static/angular/metadata-tree/metadata-tree.js:40 -msgid "Pattern mismatch" -msgstr "模式不匹配" - -#: static/angular/metadata-tree/metadata-tree.js:41 -msgid "Integer required" -msgstr "必须是整数" - -#: static/angular/metadata-tree/metadata-tree.js:42 -msgid "Decimal required" -msgstr "必须是小数" - -#: static/angular/metadata-tree/metadata-tree.js:43 -msgid "Required" -msgstr "必须" - -#: static/angular/metadata-tree/metadata-tree.js:44 -msgid "Duplicate keys are not allowed" -msgstr "复制密钥是不允许的" - -#: static/angular/metadata-tree/metadata-tree.js:45 -#: static/angular/table/basic-table.js:6 -#: static/horizon/js/horizon.forms.js:184 -msgid "Filter" -msgstr "筛选" - -#: static/angular/metadata-tree/metadata-tree.js:46 -msgid "Available Metadata" -msgstr "可用的元数据" - -#: static/angular/metadata-tree/metadata-tree.js:47 -msgid "Existing Metadata" -msgstr "已存在的元数据" - -#: static/angular/metadata-tree/metadata-tree.js:48 -msgid "Custom" -msgstr "定制" - -#: static/angular/metadata-tree/metadata-tree.js:49 -msgid "No available metadata" -msgstr "没有可用的元数据" - -#: static/angular/metadata-tree/metadata-tree.js:50 -msgid "No existing metadata" -msgstr "不存在的元数据" - -#: static/angular/modal/modal.js:83 -msgid "Submit" -msgstr "提交" - -#: static/angular/modal/modal.js:84 static/angular/wizard/wizard.js:11 -#: static/horizon/js/horizon.modals.js:33 -msgid "Cancel" -msgstr "取消" - -#: static/angular/transfer-table/transfer-table.js:39 -msgid "Allocated" -msgstr "已分配" - -#: static/angular/transfer-table/transfer-table.js:40 -msgid "Available" -msgstr "可用配额" - -#: static/angular/transfer-table/transfer-table.js:41 -msgid "Select one" -msgstr "选择一个" - -#: static/angular/transfer-table/transfer-table.js:42 -msgid "Select an item from Available items below" -msgstr "从以下可选项中选择一项" - -#: static/angular/transfer-table/transfer-table.js:43 -msgid "No available items" -msgstr "没有可选项" - -#: static/angular/transfer-table/transfer-table.js:44 -msgid "Expand to see allocated items" -msgstr "展开可见已分配项" - -#: static/angular/transfer-table/transfer-table.js:45 -msgid "Expand to see available items" -msgstr "展开可见可选项" - -#: static/angular/transfer-table/transfer-table.js:46 -msgid "Click to show or hide" -msgstr "点击此处展现或隐藏" - -#: static/angular/transfer-table/transfer-table.js:47 -msgid "Re-order items using drag and drop" -msgstr "使用拖放重新排序" - -#: static/angular/transfer-table/transfer-table.js:48 -msgid "Click to see more details" -msgstr "点击查看更多细节" - -#: static/angular/transfer-table/transfer-table.js:100 -msgid "Found %(found)s of %(total)s" -msgstr "共有%(total)s已找到%(found)s" - -#: static/angular/transfer-table/transfer-table.js:166 -msgid "Click here to expand the row and view the errors." -msgstr "点击此处展开,并可浏览错误。" - -#: static/angular/wizard/wizard.js:12 -msgid "Back" -msgstr "返回" - -#: static/angular/wizard/wizard.js:13 -msgid "Next" -msgstr "下一步" - -#: static/angular/wizard/wizard.js:14 -msgid "Finish" -msgstr "结束" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Connecting" -msgstr "连接中" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Open" -msgstr "打开" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closing" -msgstr "关闭中" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closed" -msgstr "已关闭" - -#: static/horizon/js/angular/directives/serialConsole.js:85 -#, c-format -msgid "Status: %s" -msgstr "状态: %s" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "Yes" -msgstr "是" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "No" -msgstr "不" - -#: static/horizon/js/angular/filters/filters.js:53 -#: static/horizon/js/angular/filters/filters.js:140 -#, c-format -msgid "%s GB" -msgstr "%s GB" - -#: static/horizon/js/angular/filters/filters.js:70 -#: static/horizon/js/angular/filters/filters.js:142 -#, c-format -msgid "%s MB" -msgstr "%s MB" - -#: static/horizon/js/angular/filters/filters.js:138 -#, c-format -msgid "%s TB" -msgstr "%s TB" - -#: static/horizon/js/angular/filters/filters.js:144 -#, c-format -msgid "%s KB" -msgstr "%s KB" - -#: static/horizon/js/angular/filters/filters.js:146 -#, c-format -msgid "%s bytes" -msgstr "%s 字节" - -#: static/horizon/js/angular/filters/filters.js:163 -#: static/horizon/js/horizon.tables.js:393 -#, c-format -msgid "Displaying %s item" -msgid_plural "Displaying %s items" -msgstr[0] "正在显示 %s 项" - -#: static/horizon/js/angular/services/hz.api.cinder.js:47 -msgid "Unable to retrieve volumes." -msgstr "无法获取云硬盘" - -#: static/horizon/js/angular/services/hz.api.cinder.js:74 -msgid "Unable to retrieve volume snapshots." -msgstr "找不到云硬盘快照。" - -#: static/horizon/js/angular/services/hz.api.config.js:43 -msgid "Unable to retrieve user configuration." -msgstr "无法获取用户配置" - -#: static/horizon/js/angular/services/hz.api.config.js:62 -msgid "Unable to retrieve admin configuration." -msgstr "无法获取管理员配置" - -#: static/horizon/js/angular/services/hz.api.config.js:105 -msgid "Unable to retrieve settings." -msgstr "无法获取配置" - -#: static/horizon/js/angular/services/hz.api.config.js:289 -msgid "Setting is not enabled: %(setting)s" -msgstr "配置没有启用: %(setting)s" - -#: static/horizon/js/angular/services/hz.api.glance.js:38 -msgid "Unable to retrieve image." -msgstr "无法检索到镜像。" - -#: static/horizon/js/angular/services/hz.api.glance.js:81 -msgid "Unable to retrieve images." -msgstr "找不到镜像。" - -#: static/horizon/js/angular/services/hz.api.glance.js:144 -msgid "Unable to retrieve namespaces." -msgstr "无法获取命名空间" - -#: static/horizon/js/angular/services/hz.api.keystone.js:24 -msgid "Unable to retrieve users" -msgstr "无法获取用户" - -#: static/horizon/js/angular/services/hz.api.keystone.js:31 -msgid "Unable to create the user." -msgstr "无法创建用户。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:38 -msgid "Unable to delete the users." -msgstr "无法删除用户" - -#: static/horizon/js/angular/services/hz.api.keystone.js:73 -msgid "Unable to retrieve the current user session." -msgstr "无法获取当前用户会话。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:80 -msgid "Unable to retrieve the user" -msgstr "无法获取用户" - -#: static/horizon/js/angular/services/hz.api.keystone.js:88 -msgid "Unable to edit the user." -msgstr "无法编辑用户" - -#: static/horizon/js/angular/services/hz.api.keystone.js:95 -msgid "Unable to delete the user." -msgstr "无法删除用户" - -#: static/horizon/js/angular/services/hz.api.keystone.js:103 -msgid "Unable to retrieve role" -msgstr "无法获取角色" - -#: static/horizon/js/angular/services/hz.api.keystone.js:110 -msgid "Unable to create the role." -msgstr "无法创建角色。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:117 -msgid "Unable to delete the roles." -msgstr "无法删除角色" - -#: static/horizon/js/angular/services/hz.api.keystone.js:124 -msgid "Unable to retrieve the role" -msgstr "无法获取角色" - -#: static/horizon/js/angular/services/hz.api.keystone.js:132 -msgid "Unable to edit the role." -msgstr "无法编辑角色" - -#: static/horizon/js/angular/services/hz.api.keystone.js:139 -msgid "Unable to delete the role." -msgstr "无法删除角色" - -#: static/horizon/js/angular/services/hz.api.keystone.js:147 -msgid "Unable to retrieve domains" -msgstr "无法获取域" - -#: static/horizon/js/angular/services/hz.api.keystone.js:154 -msgid "Unable to create the domain." -msgstr "无法创建域" - -#: static/horizon/js/angular/services/hz.api.keystone.js:161 -msgid "Unable to delete the domains." -msgstr "无法删除域" - -#: static/horizon/js/angular/services/hz.api.keystone.js:168 -msgid "Unable to retrieve the domain" -msgstr "无法获取域" - -#: static/horizon/js/angular/services/hz.api.keystone.js:176 -msgid "Unable to edit the domain." -msgstr "无法编辑域" - -#: static/horizon/js/angular/services/hz.api.keystone.js:183 -msgid "Unable to delete the domain." -msgstr "无法删除域" - -#: static/horizon/js/angular/services/hz.api.keystone.js:192 -msgid "Unable to retrieve projects" -msgstr "无法获取项目" - -#: static/horizon/js/angular/services/hz.api.keystone.js:199 -msgid "Unable to create the project." -msgstr "无法创建项目" - -#: static/horizon/js/angular/services/hz.api.keystone.js:206 -msgid "Unable to delete the projects." -msgstr "无法删除项目" - -#: static/horizon/js/angular/services/hz.api.keystone.js:213 -msgid "Unable to retrieve the project" -msgstr "无法获取项目" - -#: static/horizon/js/angular/services/hz.api.keystone.js:221 -msgid "Unable to edit the project." -msgstr "无法编辑项目" - -#: static/horizon/js/angular/services/hz.api.keystone.js:228 -msgid "Unable to delete the project." -msgstr "无法删除项目" - -#: static/horizon/js/angular/services/hz.api.keystone.js:236 -msgid "Unable to grant the role." -msgstr "无法授予角色" - -#: static/horizon/js/angular/services/hz.api.keystone.js:250 -msgid "Unable to fetch the service catalog." -msgstr "无法取得服务目录" - -#: static/horizon/js/angular/services/hz.api.keystone.js:385 -msgid "Service type is not enabled: %(desiredType)s" -msgstr "服务类型未激活:%(desiredType)s" - -#: static/horizon/js/angular/services/hz.api.keystone.js:392 -msgid "Cannot get service catalog from keystone." -msgstr "无法由keystone获取服务目录。" - -#: static/horizon/js/angular/services/hz.api.neutron.js:39 -msgid "Unable to retrieve networks." -msgstr "无法获取网络" - -#: static/horizon/js/angular/services/hz.api.neutron.js:88 -msgid "Unable to create the network." -msgstr "无法创建网络" - -#: static/horizon/js/angular/services/hz.api.neutron.js:108 -msgid "Unable to retrieve subnets." -msgstr "无法获取子网" - -#: static/horizon/js/angular/services/hz.api.neutron.js:172 -msgid "Unable to create the subnet." -msgstr "无法创建子网" - -#: static/horizon/js/angular/services/hz.api.neutron.js:192 -msgid "Unable to retrieve ports." -msgstr "无法获取端口" - -#: static/horizon/js/angular/services/hz.api.nova.js:40 -msgid "Unable to retrieve keypairs." -msgstr "无法获取密钥对" - -#: static/horizon/js/angular/services/hz.api.nova.js:62 -msgid "Unable to import the keypair." -msgstr "无法导入密钥对" - -#: static/horizon/js/angular/services/hz.api.nova.js:64 -msgid "Unable to create the keypair." -msgstr "无法创建密匙对" - -#: static/horizon/js/angular/services/hz.api.nova.js:83 -msgid "Unable to retrieve availability zones." -msgstr "无法获取可用域。" - -#: static/horizon/js/angular/services/hz.api.nova.js:121 -msgid "Unable to retrieve limits." -msgstr "无法获取界限" - -#: static/horizon/js/angular/services/hz.api.nova.js:148 -msgid "Unable to create the server." -msgstr "无法创建服务器" - -#: static/horizon/js/angular/services/hz.api.nova.js:162 -msgid "Unable to retrieve server." -msgstr "无法获取服务器" - -#: static/horizon/js/angular/services/hz.api.nova.js:192 -msgid "Unable to retrieve extensions." -msgstr "无法获取扩展" - -#: static/horizon/js/angular/services/hz.api.nova.js:237 -msgid "Unable to retrieve flavors." -msgstr "无法获取云主机类型列表。" - -#: static/horizon/js/angular/services/hz.api.nova.js:255 -msgid "Unable to retrieve flavor." -msgstr "无法获取云主机类型" - -#: static/horizon/js/angular/services/hz.api.nova.js:269 -msgid "Unable to retrieve flavor extra specs." -msgstr "无法获取云主机类型特别设定" - -#: static/horizon/js/angular/services/hz.api.nova.js:311 -msgid "Extension is not enabled: %(extension)s" -msgstr "扩展没有启动: %(extension)s" - -#: static/horizon/js/angular/services/hz.api.nova.js:318 -msgid "Cannot get nova extension list." -msgstr "无法查询nova扩展列表" - -#: static/horizon/js/angular/services/hz.api.policy.js:65 -msgid "Policy check failed." -msgstr "策略检查失败" - -#: static/horizon/js/angular/services/hz.api.security-group.js:64 -msgid "Unable to retrieve security groups." -msgstr "无法获取安全组。" - -#: static/horizon/js/horizon.accordion_nav.js:78 -#: static/horizon/js/horizon.modals.js:315 -#: static/horizon/js/horizon.tabs.js:21 -msgid "Loading" -msgstr "加载中" - -#: static/horizon/js/horizon.d3linechart.js:394 -#: static/horizon/js/horizon.d3linechart.js:404 -msgid "No data available." -msgstr "没有可用数据" - -#: static/horizon/js/horizon.d3linechart.js:410 -#: static/horizon/js/horizon.modals.js:334 -#: static/horizon/js/horizon.tables_inline_edit.js:94 -#: static/horizon/js/horizon.tables_inline_edit.js:157 -msgid "An error occurred. Please try again later." -msgstr "发生错误。请稍后重试。" - -#: static/horizon/js/horizon.firewalls.js:32 -#: static/horizon/js/horizon.instances.js:31 -msgid "There was a problem communicating with the server, please try again." -msgstr "与服务器通信出现问题,请再试一次。" - -#: static/horizon/js/horizon.instances.js:273 -msgid "Could not read the file" -msgstr "不能读取文件" - -#: static/horizon/js/horizon.instances.js:279 -#: static/horizon/js/horizon.instances.js:308 -msgid "Could not decrypt the password" -msgstr "不能解密密码" - -#: static/horizon/js/horizon.membership.js:190 -msgid "No roles" -msgstr "不存在任何角色" - -#: static/horizon/js/horizon.membership.js:222 -msgid "Roles" -msgstr "角色" - -#: static/horizon/js/horizon.messages.js:9 -msgid "Danger: " -msgstr "危险:" - -#: static/horizon/js/horizon.messages.js:10 -msgid "Warning: " -msgstr "警告:" - -#: static/horizon/js/horizon.messages.js:11 -msgid "Notice: " -msgstr "注意:" - -#: static/horizon/js/horizon.messages.js:12 -msgid "Success: " -msgstr "成功:" - -#: static/horizon/js/horizon.messages.js:13 -msgid "Error: " -msgstr "错误:" - -#: static/horizon/js/horizon.modals.js:229 -#: static/horizon/js/horizon.tables.js:218 -msgid "Working" -msgstr "进行中" - -#: static/horizon/js/horizon.modals.js:263 -msgid "There was an error submitting the form. Please try again." -msgstr "在提交表单的时候出现错误,请再次尝试。" - -#: static/horizon/js/horizon.networktopology.js:530 -#: static/horizon/js/horizon.networktopology.js:536 -msgid "None" -msgstr "无" - -#: static/horizon/js/horizon.networktopology.js:549 -msgid "Delete" -msgstr "删除" - -#: static/horizon/js/horizon.networktopology.js:552 -msgid "STATUS" -msgstr "状态" - -#: static/horizon/js/horizon.networktopology.js:553 -msgid "ID" -msgstr "ID" - -#: static/horizon/js/horizon.networktopology.js:554 -msgid "Interfaces" -msgstr "接口" - -#: static/horizon/js/horizon.networktopology.js:555 -msgid "Delete Interface" -msgstr "删除接口" - -#: static/horizon/js/horizon.networktopology.js:556 -msgid "Open Console" -msgstr "打开控制台" - -#: static/horizon/js/horizon.networktopology.js:557 -msgid "View Details" -msgstr "查看详情" - -#: static/horizon/js/horizon.networktopology.js:560 -msgid "Delete Router" -msgstr "删除路由" - -#: static/horizon/js/horizon.networktopology.js:561 -msgid "View Router Details" -msgstr "查看路由详情" - -#: static/horizon/js/horizon.networktopology.js:564 -msgid "Add Interface" -msgstr "增加接口" - -#: static/horizon/js/horizon.networktopology.js:570 -msgid "Terminate Instance" -msgstr "终止实例" - -#: static/horizon/js/horizon.networktopology.js:571 -msgid "View Instance Details" -msgstr "查看实例详情" - -#: static/horizon/js/horizon.tables.js:39 -#: static/horizon/js/horizon.tables.js:406 -msgid "No items to display." -msgstr "没有条目显示。" - -#: static/horizon/js/horizon.tables.js:52 -#: static/horizon/js/horizon.tables.js:120 -msgid "An error occurred while updating." -msgstr "更新时发生错误。" - -#: static/horizon/js/horizon.tables.js:201 -#, c-format -msgid "You have selected %s. " -msgstr "你已经选择了 %s 。 " - -#: static/horizon/js/horizon.tables.js:203 -#, c-format -msgid "Confirm %s" -msgstr "确认 %s" - -#: static/horizon/js/horizon.tables.js:204 -msgid "Please confirm your selection. " -msgstr "请确认您的选择。" - -#: static/horizon/js/horizon.tables_inline_edit.js:88 -#: static/horizon/js/horizon.tables_inline_edit.js:151 -msgid "Not authorized to do this operation." -msgstr "未授权不能进行此操作。" - -#: static/horizon/js/horizon.users.js:18 -msgid "Passwords do not match." -msgstr "密码不匹配。" diff --git a/code/horizon/horizon/locale/zh_TW/LC_MESSAGES/django.po b/code/horizon/horizon/locale/zh_TW/LC_MESSAGES/django.po deleted file mode 100644 index fb65046f..00000000 --- a/code/horizon/horizon/locale/zh_TW/LC_MESSAGES/django.po +++ /dev/null @@ -1,507 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Chen, Shang-Pin , 2015 -# Xiao Xi LIU , 2014 -# Zhang Xiaowei , 2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-06 21:07-0500\n" -"PO-Revision-Date: 2015-04-02 05:22+0000\n" -"Last-Translator: Zhang Xiaowei \n" -"Language-Team: Chinese (Taiwan) (http://www.transifex.com/projects/p/horizon/language/zh_TW/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh_TW\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: base.py:475 -msgid "Other" -msgstr "其他" - -#: browsers/base.py:88 -msgid "Navigation Item" -msgstr "導覽項目" - -#: browsers/views.py:41 -#, python-format -msgid "Select a %s to browse." -msgstr "選擇 %s 來瀏覽。" - -#: conf/default.py:41 -msgid "Password is not accepted" -msgstr "不允許密碼" - -#: decorators.py:53 -msgid "Please log in to continue." -msgstr "請登入以繼續。" - -#: decorators.py:85 -#, python-format -msgid "You are not authorized to access %s" -msgstr "您沒有足夠的權限存取 %s" - -#: exceptions.py:163 -#, python-format -msgid "A %(resource)s with the name \"%(name)s\" already exists." -msgstr "名為「%(name)s」的 %(resource)s 已經存在。" - -#: exceptions.py:235 -#, python-format -msgid "Unauthorized: %s" -msgstr "未授權:%s" - -#: exceptions.py:238 -msgid "Unauthorized. Please try logging in again." -msgstr "未授權。請試著重新登入。" - -#: forms/fields.py:64 -msgid "Incorrect format for IP address" -msgstr "不正確的 IP 位址格式" - -#: forms/fields.py:65 -msgid "Invalid version for IP address" -msgstr "無效的 IP 位址版本" - -#: forms/fields.py:66 -msgid "Invalid subnet mask" -msgstr "無效的子網路遮罩" - -#: forms/views.py:132 templates/horizon/common/_usage_summary.html:16 -msgid "Submit" -msgstr "提交" - -#: forms/views.py:133 -#: templates/horizon/common/_modal_form_update_metadata.html:25 -#: templates/horizon/common/_workflow.html:49 -msgid "Cancel" -msgstr "取消" - -#: middleware.py:103 -msgid "Session timed out." -msgstr "連線階段過期。" - -#: tables/actions.py:460 -#: templates/horizon/common/_data_table_table_actions.html:21 -#: templates/horizon/common/_data_table_table_actions.html:33 -#: templates/horizon/common/_workflow_step_update_members.html:14 -#: templates/horizon/common/_workflow_step_update_members.html:23 -msgid "Filter" -msgstr "篩選" - -#: tables/actions.py:645 -msgid "This action cannot be undone." -msgstr "這個動作將無法回復。" - -#: tables/actions.py:767 -#, python-format -msgctxt "past" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:769 -#, python-format -msgctxt "present" -msgid "%(action)s %(data_type)s" -msgstr "%(action)s %(data_type)s" - -#: tables/actions.py:832 -#, python-format -msgid "You are not allowed to %(action)s: %(objs)s" -msgstr "不允許您%(action)s:%(objs)s" - -#: tables/actions.py:839 -#, python-format -msgid "Unable to %(action)s: %(objs)s" -msgstr "無法%(action)s:%(objs)s" - -#: tables/actions.py:845 -#, python-format -msgid "%(action)s: %(objs)s" -msgstr "%(action)s:%(objs)s" - -#: tables/actions.py:915 -msgid "Delete" -msgstr "刪除" - -#: tables/actions.py:917 -msgid "Deleted" -msgstr "已刪除" - -#: tables/actions.py:948 -msgid "Update" -msgstr "更新" - -#: tables/actions.py:949 -msgid "Updated" -msgstr "已更新" - -#: tables/base.py:305 -msgid "-" -msgstr "-" - -#: tables/base.py:361 -#, python-format -msgid "The attribute %(attr)s doesn't exist on %(obj)s." -msgstr "%(obj)s 不存在 %(attr)s 屬性。" - -#: tables/base.py:990 -msgid "No items to display." -msgstr "沒有項目可以列出。" - -#: tables/base.py:1099 -#: templates/horizon/common/_data_table_table_actions.html:47 -msgid "Actions" -msgstr "動作" - -#: tables/base.py:1329 -#, python-format -msgid "No match returned for the id \"%s\"." -msgstr "沒有符合識別號「%s」的結果。" - -#: tables/base.py:1486 -msgid "Please select a row before taking that action." -msgstr "執行動作前請選擇欄位。" - -#: tables/base.py:1570 -msgid "N/A" -msgstr "N/A" - -#: templates/_header.html:5 -#, python-format -msgid "Logged in as: %(username)s" -msgstr "以此身份登入:%(username)s" - -#: templates/_header.html:7 -msgid "Help" -msgstr "幫助" - -#: templates/_header.html:9 -msgid "Sign Out" -msgstr "登出" - -#: templates/auth/_description.html:9 -msgid "" -"\n" -" If you are not sure which authentication method to use, contact your administrator.\n" -" " -msgstr "\n 若您不確定要用哪個驗證方法,請聯絡您的管理員。\n " - -#: templates/auth/_login.html:5 -msgid "Log In" -msgstr "登入" - -#: templates/auth/_login.html:27 -msgid "You do not have permission to access the resource:" -msgstr "您沒有權限存取資源:" - -#: templates/auth/_login.html:29 -#, python-format -msgid "" -"Login as different user or go back to home " -"page" -msgstr "以不同的用戶身份登入,或者回到首頁" - -#: templates/auth/_login.html:45 -msgid "Sign In" -msgstr "登入" - -#: templates/auth/_login.html:46 -msgid "Connect" -msgstr "連線" - -#: templates/auth/login.html:4 -msgid "Login" -msgstr "登入" - -#: templates/horizon/_messages.html:7 -msgid "Info: " -msgstr "資訊:" - -#: templates/horizon/_messages.html:13 -msgid "Warning: " -msgstr "警告:" - -#: templates/horizon/_messages.html:19 -msgid "Success: " -msgstr "成功:" - -#: templates/horizon/_messages.html:25 -msgid "Error: " -msgstr "錯誤:" - -#: templates/horizon/common/_data_table.html:63 -msgid "Summary" -msgstr "摘要" - -#: templates/horizon/common/_data_table.html:72 -#, python-format -msgid "Displaying %(counter)s item" -msgid_plural "Displaying %(counter)s items" -msgstr[0] "顯示 %(counter)s 項" - -#: templates/horizon/common/_data_table.html:77 -msgid "« Prev" -msgstr "« 上一頁" - -#: templates/horizon/common/_data_table.html:80 -msgid "Next »" -msgstr "下一頁 »" - -#: templates/horizon/common/_data_table_table_actions.html:45 -msgid "More Actions" -msgstr "更多動作" - -#: templates/horizon/common/_domain_page_header.html:6 -#, python-format -msgid "%(context_name)s:" -msgstr "%(context_name)s:" - -#: templates/horizon/common/_formset_table.html:35 -msgid "Add a row" -msgstr "加入一列" - -#: templates/horizon/common/_formset_table_row.html:15 -#, python-format -msgid "%(name)s: %(error)s" -msgstr "%(name)s: %(error)s" - -#: templates/horizon/common/_limit_summary.html:4 -msgid "Limit Summary" -msgstr "限制摘要" - -#: templates/horizon/common/_limit_summary.html:7 -msgid "Instances" -msgstr "雲實例" - -#: templates/horizon/common/_limit_summary.html:8 -#: templates/horizon/common/_limit_summary.html:15 -#: templates/horizon/common/_limit_summary.html:22 -#: templates/horizon/common/_limit_summary.html:36 -#: templates/horizon/common/_limit_summary.html:43 -#: templates/horizon/common/_limit_summary.html:50 -#, python-format -msgid "Used %(used)s of %(available)s " -msgstr "已使用 %(available)s 個中的 %(used)s 個" - -#: templates/horizon/common/_limit_summary.html:14 -msgid "VCPUs" -msgstr "虛擬處理器數" - -#: templates/horizon/common/_limit_summary.html:21 -msgid "RAM" -msgstr "隨機存取記憶體" - -#: templates/horizon/common/_limit_summary.html:28 -msgid "Floating IPs" -msgstr "浮動 IP" - -#: templates/horizon/common/_limit_summary.html:29 -#, python-format -msgid "Allocated %(used)s of %(available)s " -msgstr "已配置 %(available)s 中的 %(used)s " - -#: templates/horizon/common/_limit_summary.html:35 -msgid "Security Groups" -msgstr "安全性群組" - -#: templates/horizon/common/_limit_summary.html:42 -msgid "Volumes" -msgstr "雲硬碟" - -#: templates/horizon/common/_limit_summary.html:49 -msgid "Volume Storage" -msgstr "雲硬碟儲存空間" - -#: templates/horizon/common/_modal_form_update_metadata.html:24 -#: workflows/base.py:594 -msgid "Save" -msgstr "儲存" - -#: templates/horizon/common/_resource_browser.html:10 -#, python-format -msgid "Displaying %(nav_items)s item" -msgid_plural "Displaying %(nav_items)s items" -msgstr[0] "顯示 %(nav_items)s 項" - -#: templates/horizon/common/_resource_browser.html:11 -#, python-format -msgid "Displaying %(content_items)s item" -msgid_plural "Displaying %(content_items)s items" -msgstr[0] "顯示 %(content_items)s 項" - -#: templates/horizon/common/_usage_summary.html:3 -msgid "Usage Summary" -msgstr "使用量摘要" - -#: templates/horizon/common/_usage_summary.html:7 -msgid "Select a period of time to query its usage:" -msgstr "選擇時段查詢使用量:" - -#: templates/horizon/common/_usage_summary.html:9 -#, python-format -msgid "" -"\n" -" %(start)s" -msgstr "\n %(start)s" - -#: templates/horizon/common/_usage_summary.html:13 -#, python-format -msgid "" -"\n" -" %(end)s" -msgstr "\n %(end)s" - -#: templates/horizon/common/_usage_summary.html:17 -msgid "The date should be in YYYY-mm-dd format." -msgstr "日期的格式應該為 YY-mm-dd。" - -#: templates/horizon/common/_usage_summary.html:20 -msgid "Active Instances:" -msgstr "使用中的雲實例:" - -#: templates/horizon/common/_usage_summary.html:21 -msgid "Active RAM:" -msgstr "使用中的隨機存取記憶體:" - -#: templates/horizon/common/_usage_summary.html:22 -msgid "This Period's VCPU-Hours:" -msgstr "此時段的虛擬處理器時數:" - -#: templates/horizon/common/_usage_summary.html:23 -msgid "This Period's GB-Hours:" -msgstr "此時段的硬碟 GB 時數:" - -#: templates/horizon/common/_usage_summary.html:24 -msgid "This Period's RAM-Hours:" -msgstr "此時段的虛擬記憶體時數:" - -#: templates/horizon/common/_workflow.html:40 -msgid "Back" -msgstr "上一頁" - -#: templates/horizon/common/_workflow.html:43 -msgid "Next" -msgstr "下一頁" - -#: templatetags/branding.py:34 -msgid "Horizon" -msgstr "Horizon" - -#: templatetags/horizon.py:137 templatetags/horizon.py:148 -msgid "No Limit" -msgstr "不限制" - -#: templatetags/horizon.py:140 templatetags/horizon.py:142 -msgid "Available" -msgstr "可用" - -#: templatetags/sizeformat.py:51 templatetags/sizeformat.py:56 -#, python-format -msgid "%(size)d Byte" -msgid_plural "%(size)d Bytes" -msgstr[0] "%(size)d 位元組" - -#: templatetags/sizeformat.py:59 -#, python-format -msgid "%s KB" -msgstr "%s KB" - -#: templatetags/sizeformat.py:61 -#, python-format -msgid "%s MB" -msgstr "%s MB" - -#: templatetags/sizeformat.py:63 -#, python-format -msgid "%s GB" -msgstr "%s GB" - -#: templatetags/sizeformat.py:65 -#, python-format -msgid "%s TB" -msgstr "%s TB" - -#: templatetags/sizeformat.py:66 -#, python-format -msgid "%s PB" -msgstr "%s PB" - -#: templatetags/sizeformat.py:74 -msgid "0 Bytes" -msgstr "0 位元組" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:31 -msgid "Sell Puppy" -msgid_plural "Sell Puppies" -msgstr[0] "販賣小狗" - -#. Translators: test code, don't really have to translate -#: test/test_dashboards/dogs/puppies/tables.py:40 -msgid "Sold Puppy" -msgid_plural "Sold Puppies" -msgstr[0] "已賣出小狗" - -#: test/tests/views.py:59 -msgid "Fake" -msgstr "假冒" - -#: utils/filters.py:49 -msgid "Never" -msgstr "永不" - -#: utils/validators.py:26 utils/validators.py:50 -msgid "Not a valid port number" -msgstr "不是有效的埠口號碼" - -#: utils/validators.py:31 -msgid "Not a valid IP protocol number" -msgstr "不是有效的 IP 協定號碼" - -#: utils/validators.py:45 -msgid "One colon allowed in port range" -msgstr "允許以冒號隔開埠口範圍" - -#: utils/validators.py:52 -msgid "Port number must be integer" -msgstr "埠口號碼必須是整數" - -#: utils/validators.py:59 -msgid "The string may only contain ASCII printable characters." -msgstr "字串只能包含 ASCII 可印出的字元。" - -#: workflows/base.py:71 -msgid "Processing..." -msgstr "處理中……" - -#: workflows/base.py:475 -msgid "All available" -msgstr "全部可用" - -#: workflows/base.py:476 -msgid "Members" -msgstr "成員" - -#: workflows/base.py:477 -msgid "None available." -msgstr "無可用的。" - -#: workflows/base.py:478 -msgid "No members." -msgstr "無成員。" - -#: workflows/base.py:595 -#, python-format -msgid "%s completed successfully." -msgstr "已成功地完成 %s。" - -#: workflows/base.py:596 -#, python-format -msgid "%s did not complete." -msgstr "尚未完成 %s。" diff --git a/code/horizon/horizon/locale/zh_TW/LC_MESSAGES/djangojs.po b/code/horizon/horizon/locale/zh_TW/LC_MESSAGES/djangojs.po deleted file mode 100644 index eefc2382..00000000 --- a/code/horizon/horizon/locale/zh_TW/LC_MESSAGES/djangojs.po +++ /dev/null @@ -1,620 +0,0 @@ -# SOME DESCRIPTIVE TITLE. -# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -# This file is distributed under the same license as the PACKAGE package. -# -# Translators: -# Chen, Shang-Pin , 2015 -# Xiao Xi LIU , 2014 -# Zhang Xiaowei , 2015 -msgid "" -msgstr "" -"Project-Id-Version: Horizon\n" -"Report-Msgid-Bugs-To: \n" -"POT-Creation-Date: 2015-04-12 16:36-0500\n" -"PO-Revision-Date: 2015-04-13 01:02+0000\n" -"Last-Translator: Zhang Xiaowei \n" -"Language-Team: Chinese (Taiwan) (http://www.transifex.com/projects/p/horizon/language/zh_TW/)\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: zh_TW\n" -"Plural-Forms: nplurals=1; plural=0;\n" - -#: static/angular/action-list/button-tooltip.js:15 -msgid "" -"The action cannot be performed. The contents of this row have errors or are " -"missing information." -msgstr "無法執行動作。這欄的內容有錯或者缺少資訊。" - -#: static/angular/metadata-display/metadata-display.js:33 -msgid "Detail Information" -msgstr "詳細的資訊" - -#: static/angular/metadata-tree/metadata-tree.js:35 -msgid "" -"You can specify resource metadata by moving items from the left column to " -"the right column. In the left columns there are metadata definitions from " -"the Glance Metadata Catalog. Use the \"Other\" option to add metadata with " -"the key of your choice." -msgstr "您可以從左欄移動項目到右欄來指定資源詮釋資料。左欄是來自 Glance 詮釋資料類別的詮釋檔定義。使用「其他」選項來加入您的選擇到詮釋資料裡。" - -#: static/angular/metadata-tree/metadata-tree.js:36 -msgid "Min" -msgstr "最小" - -#: static/angular/metadata-tree/metadata-tree.js:37 -msgid "Max" -msgstr "最大" - -#: static/angular/metadata-tree/metadata-tree.js:38 -msgid "Min length" -msgstr "最小長度" - -#: static/angular/metadata-tree/metadata-tree.js:39 -msgid "Max length" -msgstr "最大長度" - -#: static/angular/metadata-tree/metadata-tree.js:40 -msgid "Pattern mismatch" -msgstr "不符合的樣式" - -#: static/angular/metadata-tree/metadata-tree.js:41 -msgid "Integer required" -msgstr "需要整數" - -#: static/angular/metadata-tree/metadata-tree.js:42 -msgid "Decimal required" -msgstr "需要十進位" - -#: static/angular/metadata-tree/metadata-tree.js:43 -msgid "Required" -msgstr "需要" - -#: static/angular/metadata-tree/metadata-tree.js:44 -msgid "Duplicate keys are not allowed" -msgstr "不允許重複的鍵值" - -#: static/angular/metadata-tree/metadata-tree.js:45 -#: static/angular/table/basic-table.js:6 -#: static/horizon/js/horizon.forms.js:184 -msgid "Filter" -msgstr "篩選" - -#: static/angular/metadata-tree/metadata-tree.js:46 -msgid "Available Metadata" -msgstr "可用的詮釋資料" - -#: static/angular/metadata-tree/metadata-tree.js:47 -msgid "Existing Metadata" -msgstr "已存在的詮釋資料" - -#: static/angular/metadata-tree/metadata-tree.js:48 -msgid "Custom" -msgstr "自訂" - -#: static/angular/metadata-tree/metadata-tree.js:49 -msgid "No available metadata" -msgstr "無可用的詮釋資料" - -#: static/angular/metadata-tree/metadata-tree.js:50 -msgid "No existing metadata" -msgstr "不存在詮釋資料" - -#: static/angular/modal/modal.js:83 -msgid "Submit" -msgstr "提交" - -#: static/angular/modal/modal.js:84 static/angular/wizard/wizard.js:11 -#: static/horizon/js/horizon.modals.js:33 -msgid "Cancel" -msgstr "取消" - -#: static/angular/transfer-table/transfer-table.js:39 -msgid "Allocated" -msgstr "已分配" - -#: static/angular/transfer-table/transfer-table.js:40 -msgid "Available" -msgstr "可用" - -#: static/angular/transfer-table/transfer-table.js:41 -msgid "Select one" -msgstr "擇一" - -#: static/angular/transfer-table/transfer-table.js:42 -msgid "Select an item from Available items below" -msgstr "從下列可用的項目中選擇" - -#: static/angular/transfer-table/transfer-table.js:43 -msgid "No available items" -msgstr "無可用的項目" - -#: static/angular/transfer-table/transfer-table.js:44 -msgid "Expand to see allocated items" -msgstr "展開來顯示已分配的項目" - -#: static/angular/transfer-table/transfer-table.js:45 -msgid "Expand to see available items" -msgstr "展開來顯示可用的項目" - -#: static/angular/transfer-table/transfer-table.js:46 -msgid "Click to show or hide" -msgstr "點擊來顯示或隱藏" - -#: static/angular/transfer-table/transfer-table.js:47 -msgid "Re-order items using drag and drop" -msgstr "使用拖拉來重新排列" - -#: static/angular/transfer-table/transfer-table.js:48 -msgid "Click to see more details" -msgstr "點擊來顯示更多詳細資訊" - -#: static/angular/transfer-table/transfer-table.js:100 -msgid "Found %(found)s of %(total)s" -msgstr "已找到 %(total)s 中的 %(found)s 個" - -#: static/angular/transfer-table/transfer-table.js:166 -msgid "Click here to expand the row and view the errors." -msgstr "展開這列來檢視錯誤。" - -#: static/angular/wizard/wizard.js:12 -msgid "Back" -msgstr "上一步" - -#: static/angular/wizard/wizard.js:13 -msgid "Next" -msgstr "下一步" - -#: static/angular/wizard/wizard.js:14 -msgid "Finish" -msgstr "完成" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Connecting" -msgstr "連線中" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Open" -msgstr "開啟" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closing" -msgstr "關閉中" - -#: static/horizon/js/angular/directives/serialConsole.js:23 -msgid "Closed" -msgstr "已關閉" - -#: static/horizon/js/angular/directives/serialConsole.js:85 -#, c-format -msgid "Status: %s" -msgstr "狀態:%s" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "Yes" -msgstr "是" - -#: static/horizon/js/angular/filters/filters.js:37 -msgid "No" -msgstr "否" - -#: static/horizon/js/angular/filters/filters.js:53 -#: static/horizon/js/angular/filters/filters.js:140 -#, c-format -msgid "%s GB" -msgstr "%s GB" - -#: static/horizon/js/angular/filters/filters.js:70 -#: static/horizon/js/angular/filters/filters.js:142 -#, c-format -msgid "%s MB" -msgstr "%s MB" - -#: static/horizon/js/angular/filters/filters.js:138 -#, c-format -msgid "%s TB" -msgstr "%s TB" - -#: static/horizon/js/angular/filters/filters.js:144 -#, c-format -msgid "%s KB" -msgstr "%s KB" - -#: static/horizon/js/angular/filters/filters.js:146 -#, c-format -msgid "%s bytes" -msgstr "%s 位元組" - -#: static/horizon/js/angular/filters/filters.js:163 -#: static/horizon/js/horizon.tables.js:393 -#, c-format -msgid "Displaying %s item" -msgid_plural "Displaying %s items" -msgstr[0] "顯示 %s 項" - -#: static/horizon/js/angular/services/hz.api.cinder.js:47 -msgid "Unable to retrieve volumes." -msgstr "無法獲得雲硬碟。" - -#: static/horizon/js/angular/services/hz.api.cinder.js:74 -msgid "Unable to retrieve volume snapshots." -msgstr "無法獲得雲硬碟即時存檔。" - -#: static/horizon/js/angular/services/hz.api.config.js:43 -msgid "Unable to retrieve user configuration." -msgstr "無法獲得用戶設定檔。" - -#: static/horizon/js/angular/services/hz.api.config.js:62 -msgid "Unable to retrieve admin configuration." -msgstr "無法獲得管理員設定檔。" - -#: static/horizon/js/angular/services/hz.api.config.js:105 -msgid "Unable to retrieve settings." -msgstr "無法設定。" - -#: static/horizon/js/angular/services/hz.api.config.js:289 -msgid "Setting is not enabled: %(setting)s" -msgstr "未啟用設定:%(setting)s" - -#: static/horizon/js/angular/services/hz.api.glance.js:38 -msgid "Unable to retrieve image." -msgstr "無法獲得映像檔。" - -#: static/horizon/js/angular/services/hz.api.glance.js:81 -msgid "Unable to retrieve images." -msgstr "無法獲得映像檔。" - -#: static/horizon/js/angular/services/hz.api.glance.js:144 -msgid "Unable to retrieve namespaces." -msgstr "無法獲得名稱空間。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:24 -msgid "Unable to retrieve users" -msgstr "無法獲得名稱用戶。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:31 -msgid "Unable to create the user." -msgstr "無法新增用戶。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:38 -msgid "Unable to delete the users." -msgstr "無法刪除用戶。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:73 -msgid "Unable to retrieve the current user session." -msgstr "無法獲得目前用戶連線階段。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:80 -msgid "Unable to retrieve the user" -msgstr "無法獲得用戶。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:88 -msgid "Unable to edit the user." -msgstr "無法編輯用戶。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:95 -msgid "Unable to delete the user." -msgstr "無法刪除用戶。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:103 -msgid "Unable to retrieve role" -msgstr "無法獲得角色" - -#: static/horizon/js/angular/services/hz.api.keystone.js:110 -msgid "Unable to create the role." -msgstr "無法新增角色。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:117 -msgid "Unable to delete the roles." -msgstr "無法刪除角色" - -#: static/horizon/js/angular/services/hz.api.keystone.js:124 -msgid "Unable to retrieve the role" -msgstr "無法獲得角色" - -#: static/horizon/js/angular/services/hz.api.keystone.js:132 -msgid "Unable to edit the role." -msgstr "無法編輯角色" - -#: static/horizon/js/angular/services/hz.api.keystone.js:139 -msgid "Unable to delete the role." -msgstr "無法刪除角色" - -#: static/horizon/js/angular/services/hz.api.keystone.js:147 -msgid "Unable to retrieve domains" -msgstr "無法獲得地域" - -#: static/horizon/js/angular/services/hz.api.keystone.js:154 -msgid "Unable to create the domain." -msgstr "無法新增地域。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:161 -msgid "Unable to delete the domains." -msgstr "無法刪除地域。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:168 -msgid "Unable to retrieve the domain" -msgstr "無法獲得地域" - -#: static/horizon/js/angular/services/hz.api.keystone.js:176 -msgid "Unable to edit the domain." -msgstr "無法編輯地域。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:183 -msgid "Unable to delete the domain." -msgstr "無法刪除地域。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:192 -msgid "Unable to retrieve projects" -msgstr "無法獲得專案" - -#: static/horizon/js/angular/services/hz.api.keystone.js:199 -msgid "Unable to create the project." -msgstr "無法新增專案。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:206 -msgid "Unable to delete the projects." -msgstr "無法刪除專案。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:213 -msgid "Unable to retrieve the project" -msgstr "無法獲得專案" - -#: static/horizon/js/angular/services/hz.api.keystone.js:221 -msgid "Unable to edit the project." -msgstr "無法編輯專案。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:228 -msgid "Unable to delete the project." -msgstr "無法刪除專案。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:236 -msgid "Unable to grant the role." -msgstr "無法賦予角色權力。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:250 -msgid "Unable to fetch the service catalog." -msgstr "無法獲得伺服器類別。" - -#: static/horizon/js/angular/services/hz.api.keystone.js:385 -msgid "Service type is not enabled: %(desiredType)s" -msgstr "未啟用伺服器類型:%(desiredType)s" - -#: static/horizon/js/angular/services/hz.api.keystone.js:392 -msgid "Cannot get service catalog from keystone." -msgstr "不能從 Keystone 獲得伺服器類別。" - -#: static/horizon/js/angular/services/hz.api.neutron.js:39 -msgid "Unable to retrieve networks." -msgstr "無法獲得網路。" - -#: static/horizon/js/angular/services/hz.api.neutron.js:88 -msgid "Unable to create the network." -msgstr "無法新增網路。" - -#: static/horizon/js/angular/services/hz.api.neutron.js:108 -msgid "Unable to retrieve subnets." -msgstr "無法獲得子網路。" - -#: static/horizon/js/angular/services/hz.api.neutron.js:172 -msgid "Unable to create the subnet." -msgstr "無法新增子網路。" - -#: static/horizon/js/angular/services/hz.api.neutron.js:192 -msgid "Unable to retrieve ports." -msgstr "無法獲得接口。" - -#: static/horizon/js/angular/services/hz.api.nova.js:40 -msgid "Unable to retrieve keypairs." -msgstr "無法獲得密鑰對。" - -#: static/horizon/js/angular/services/hz.api.nova.js:62 -msgid "Unable to import the keypair." -msgstr "無法匯入密鑰對。" - -#: static/horizon/js/angular/services/hz.api.nova.js:64 -msgid "Unable to create the keypair." -msgstr "無法新增密鑰對。" - -#: static/horizon/js/angular/services/hz.api.nova.js:83 -msgid "Unable to retrieve availability zones." -msgstr "無法獲得可用區域。" - -#: static/horizon/js/angular/services/hz.api.nova.js:121 -msgid "Unable to retrieve limits." -msgstr "無法獲得限制。" - -#: static/horizon/js/angular/services/hz.api.nova.js:148 -msgid "Unable to create the server." -msgstr "無法新增伺服器。" - -#: static/horizon/js/angular/services/hz.api.nova.js:162 -msgid "Unable to retrieve server." -msgstr "無法獲得伺服器。" - -#: static/horizon/js/angular/services/hz.api.nova.js:192 -msgid "Unable to retrieve extensions." -msgstr "無法獲得擴充套件。" - -#: static/horizon/js/angular/services/hz.api.nova.js:237 -msgid "Unable to retrieve flavors." -msgstr "無法獲得虛擬硬體樣板。" - -#: static/horizon/js/angular/services/hz.api.nova.js:255 -msgid "Unable to retrieve flavor." -msgstr "無法獲得虛擬硬體樣板。" - -#: static/horizon/js/angular/services/hz.api.nova.js:269 -msgid "Unable to retrieve flavor extra specs." -msgstr "無法獲得虛擬硬體樣板額外規格。" - -#: static/horizon/js/angular/services/hz.api.nova.js:311 -msgid "Extension is not enabled: %(extension)s" -msgstr "未啟用擴充套件:%(extension)s" - -#: static/horizon/js/angular/services/hz.api.nova.js:318 -msgid "Cannot get nova extension list." -msgstr "不能獲得 Nova 擴充套件列表。" - -#: static/horizon/js/angular/services/hz.api.policy.js:65 -msgid "Policy check failed." -msgstr "檢查政策時失敗。" - -#: static/horizon/js/angular/services/hz.api.security-group.js:64 -msgid "Unable to retrieve security groups." -msgstr "無法獲得安全性群組。" - -#: static/horizon/js/horizon.accordion_nav.js:78 -#: static/horizon/js/horizon.modals.js:315 -#: static/horizon/js/horizon.tabs.js:21 -msgid "Loading" -msgstr "讀取中" - -#: static/horizon/js/horizon.d3linechart.js:394 -#: static/horizon/js/horizon.d3linechart.js:404 -msgid "No data available." -msgstr "無可用的資料。" - -#: static/horizon/js/horizon.d3linechart.js:410 -#: static/horizon/js/horizon.modals.js:334 -#: static/horizon/js/horizon.tables_inline_edit.js:94 -#: static/horizon/js/horizon.tables_inline_edit.js:157 -msgid "An error occurred. Please try again later." -msgstr "發生錯誤。請稍後再試。" - -#: static/horizon/js/horizon.firewalls.js:32 -#: static/horizon/js/horizon.instances.js:31 -msgid "There was a problem communicating with the server, please try again." -msgstr "與伺服器間的通訊有問題,請再試一次。" - -#: static/horizon/js/horizon.instances.js:273 -msgid "Could not read the file" -msgstr "不能讀取檔案" - -#: static/horizon/js/horizon.instances.js:279 -#: static/horizon/js/horizon.instances.js:308 -msgid "Could not decrypt the password" -msgstr "不能解鎖密碼" - -#: static/horizon/js/horizon.membership.js:190 -msgid "No roles" -msgstr "無角色" - -#: static/horizon/js/horizon.membership.js:222 -msgid "Roles" -msgstr "角色" - -#: static/horizon/js/horizon.messages.js:9 -msgid "Danger: " -msgstr "危險:" - -#: static/horizon/js/horizon.messages.js:10 -msgid "Warning: " -msgstr "警告:" - -#: static/horizon/js/horizon.messages.js:11 -msgid "Notice: " -msgstr "注意:" - -#: static/horizon/js/horizon.messages.js:12 -msgid "Success: " -msgstr "成功:" - -#: static/horizon/js/horizon.messages.js:13 -msgid "Error: " -msgstr "錯誤:" - -#: static/horizon/js/horizon.modals.js:229 -#: static/horizon/js/horizon.tables.js:218 -msgid "Working" -msgstr "運作中" - -#: static/horizon/js/horizon.modals.js:263 -msgid "There was an error submitting the form. Please try again." -msgstr "提交表單時有錯誤。請再試一次。" - -#: static/horizon/js/horizon.networktopology.js:530 -#: static/horizon/js/horizon.networktopology.js:536 -msgid "None" -msgstr "無" - -#: static/horizon/js/horizon.networktopology.js:549 -msgid "Delete" -msgstr "刪除" - -#: static/horizon/js/horizon.networktopology.js:552 -msgid "STATUS" -msgstr "狀態" - -#: static/horizon/js/horizon.networktopology.js:553 -msgid "ID" -msgstr "識別號" - -#: static/horizon/js/horizon.networktopology.js:554 -msgid "Interfaces" -msgstr "網路卡介面" - -#: static/horizon/js/horizon.networktopology.js:555 -msgid "Delete Interface" -msgstr "刪除網路卡介面" - -#: static/horizon/js/horizon.networktopology.js:556 -msgid "Open Console" -msgstr "開啟終端機" - -#: static/horizon/js/horizon.networktopology.js:557 -msgid "View Details" -msgstr "檢視詳細資訊" - -#: static/horizon/js/horizon.networktopology.js:560 -msgid "Delete Router" -msgstr "刪除路由器" - -#: static/horizon/js/horizon.networktopology.js:561 -msgid "View Router Details" -msgstr "檢視路由器詳細資訊" - -#: static/horizon/js/horizon.networktopology.js:564 -msgid "Add Interface" -msgstr "加入網路卡介面" - -#: static/horizon/js/horizon.networktopology.js:570 -msgid "Terminate Instance" -msgstr "終止雲實例" - -#: static/horizon/js/horizon.networktopology.js:571 -msgid "View Instance Details" -msgstr "檢視雲實例詳細資訊" - -#: static/horizon/js/horizon.tables.js:39 -#: static/horizon/js/horizon.tables.js:406 -msgid "No items to display." -msgstr "沒有項目可以列出。" - -#: static/horizon/js/horizon.tables.js:52 -#: static/horizon/js/horizon.tables.js:120 -msgid "An error occurred while updating." -msgstr "更新時發生錯誤。" - -#: static/horizon/js/horizon.tables.js:201 -#, c-format -msgid "You have selected %s. " -msgstr "您選擇了 %s。" - -#: static/horizon/js/horizon.tables.js:203 -#, c-format -msgid "Confirm %s" -msgstr "確認 %s" - -#: static/horizon/js/horizon.tables.js:204 -msgid "Please confirm your selection. " -msgstr "請確認您的選擇。" - -#: static/horizon/js/horizon.tables_inline_edit.js:88 -#: static/horizon/js/horizon.tables_inline_edit.js:151 -msgid "Not authorized to do this operation." -msgstr "沒有足夠的權限執行這個操作。" - -#: static/horizon/js/horizon.users.js:18 -msgid "Passwords do not match." -msgstr "密碼沒有相配。" diff --git a/code/horizon/horizon/management/__init__.py b/code/horizon/horizon/management/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/code/horizon/horizon/management/commands/__init__.py b/code/horizon/horizon/management/commands/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/code/horizon/horizon/management/commands/startdash.py b/code/horizon/horizon/management/commands/startdash.py deleted file mode 100644 index 4ab18daa..00000000 --- a/code/horizon/horizon/management/commands/startdash.py +++ /dev/null @@ -1,71 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import glob -from optparse import make_option # noqa -import os - -from django.core.management.base import CommandError # noqa -from django.core.management.templates import TemplateCommand # noqa -from django.utils.importlib import import_module # noqa - -import horizon - - -class Command(TemplateCommand): - template = os.path.join(horizon.__path__[0], "conf", "dash_template") - option_list = TemplateCommand.option_list + ( - make_option('--target', - dest='target', - action='store', - default=None, - help='The directory in which the panel ' - 'should be created. Defaults to the ' - 'current directory. The value "auto" ' - 'may also be used to automatically ' - 'create the panel inside the specified ' - 'dashboard module.'),) - help = ("Creates a Django app directory structure for a new dashboard " - "with the given name in the current directory or optionally in " - "the given directory.") - - def handle(self, dash_name=None, **options): - if dash_name is None: - raise CommandError("You must provide a dashboard name.") - - # Use our default template if one isn't specified. - if not options.get("template", None): - options["template"] = self.template - - # We have html templates as well, so make sure those are included. - options["extensions"].extend(["tmpl", "html", "js", "css"]) - - # Check that the app_name cannot be imported. - try: - import_module(dash_name) - except ImportError: - pass - else: - raise CommandError("%r conflicts with the name of an existing " - "Python module and cannot be used as an app " - "name. Please try another name." % dash_name) - - super(Command, self).handle('dash', dash_name, **options) - - target = options.pop("target", None) - if not target: - target = os.path.join(os.curdir, dash_name) - - # Rename our python template files. - file_names = glob.glob(os.path.join(target, "*.py.tmpl")) - for filename in file_names: - os.rename(filename, filename[:-5]) diff --git a/code/horizon/horizon/management/commands/startpanel.py b/code/horizon/horizon/management/commands/startpanel.py deleted file mode 100644 index 855fe330..00000000 --- a/code/horizon/horizon/management/commands/startpanel.py +++ /dev/null @@ -1,105 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -import glob -from optparse import make_option # noqa -import os - -from django.core.management.base import CommandError # noqa -from django.core.management.templates import TemplateCommand # noqa -from django.utils.importlib import import_module # noqa - -import horizon - - -class Command(TemplateCommand): - args = "[name] [dashboard name] [optional destination directory]" - option_list = TemplateCommand.option_list + ( - make_option('--dashboard', '-d', - dest='dashboard', - action='store', - default=None, - help='The dotted python path to the ' - 'dashboard which this panel will be ' - 'registered with.'), - make_option('--target', - dest='target', - action='store', - default=None, - help='The directory in which the panel ' - 'should be created. Defaults to the ' - 'current directory. The value "auto" ' - 'may also be used to automatically ' - 'create the panel inside the specified ' - 'dashboard module.'),) - template = os.path.join(horizon.__path__[0], "conf", "panel_template") - help = ("Creates a Django app directory structure for a new panel " - "with the given name in the current directory or optionally in " - "the given directory.") - - def handle(self, panel_name=None, **options): - if panel_name is None: - raise CommandError("You must provide a panel name.") - - if options.get('dashboard'): - dashboard_path = options.get('dashboard') - dashboard_mod_path = ".".join([dashboard_path, "dashboard"]) - - # Check the dashboard.py file in the dashboard app can be imported. - # Add the dashboard information to our options to pass along if all - # goes well. - try: - dashboard_mod = import_module(dashboard_mod_path) - options["dash_path"] = dashboard_path - options["dash_name"] = dashboard_path.split(".")[-1] - except ImportError: - raise CommandError("A dashboard.py module could not be " - "imported from the dashboard at %r." - % options.get("dashboard")) - - target = options.pop("target", None) - if target == "auto": - target = os.path.join(os.path.dirname(dashboard_mod.__file__), - panel_name) - if not os.path.exists(target): - try: - os.mkdir(target) - except OSError as exc: - raise CommandError("Unable to create panel directory: %s" - % exc) - - # Use our default template if one isn't specified. - if not options.get("template", None): - options["template"] = self.template - - # We have html templates as well, so make sure those are included. - options["extensions"].extend(["tmpl", "html"]) - - # Check that the app_name cannot be imported. - try: - import_module(panel_name) - except ImportError: - pass - else: - raise CommandError("%r conflicts with the name of an existing " - "Python module and cannot be used as an app " - "name. Please try another name." % panel_name) - - super(Command, self).handle('panel', panel_name, target, **options) - - if not target: - target = os.path.join(os.curdir, panel_name) - - # Rename our python template files. - file_names = glob.glob(os.path.join(target, "*.py.tmpl")) - for filename in file_names: - os.rename(filename, filename[:-5]) diff --git a/code/horizon/horizon/messages.py b/code/horizon/horizon/messages.py deleted file mode 100644 index b0fde0c9..00000000 --- a/code/horizon/horizon/messages.py +++ /dev/null @@ -1,83 +0,0 @@ -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -""" -Drop-in replacement for django.contrib.messages which handles Horizon's -messaging needs (e.g. AJAX communication, etc.). -""" - -from django.contrib import messages as _messages -from django.contrib.messages import constants -from django.utils.encoding import force_text -from django.utils.safestring import SafeData # noqa - - -def horizon_message_already_queued(request, message): - _message = force_text(message) - if request.is_ajax(): - for tag, msg, extra in request.horizon['async_messages']: - if _message == msg: - return True - else: - for msg in _messages.get_messages(request)._queued_messages: - if msg.message == _message: - return True - return False - - -def add_message(request, level, message, extra_tags='', fail_silently=False): - """Attempts to add a message to the request using the 'messages' app.""" - if not horizon_message_already_queued(request, message): - if request.is_ajax(): - tag = constants.DEFAULT_TAGS[level] - # if message is marked as safe, pass "safe" tag as extra_tags so - # that client can skip HTML escape for the message when rendering - if isinstance(message, SafeData): - extra_tags = extra_tags + ' safe' - request.horizon['async_messages'].append([tag, - force_text(message), - extra_tags]) - else: - return _messages.add_message(request, level, message, - extra_tags, fail_silently) - - -def debug(request, message, extra_tags='', fail_silently=False): - """Adds a message with the ``DEBUG`` level.""" - add_message(request, constants.DEBUG, message, extra_tags=extra_tags, - fail_silently=fail_silently) - - -def info(request, message, extra_tags='', fail_silently=False): - """Adds a message with the ``INFO`` level.""" - add_message(request, constants.INFO, message, extra_tags=extra_tags, - fail_silently=fail_silently) - - -def success(request, message, extra_tags='', fail_silently=False): - """Adds a message with the ``SUCCESS`` level.""" - add_message(request, constants.SUCCESS, message, extra_tags=extra_tags, - fail_silently=fail_silently) - - -def warning(request, message, extra_tags='', fail_silently=False): - """Adds a message with the ``WARNING`` level.""" - add_message(request, constants.WARNING, message, extra_tags=extra_tags, - fail_silently=fail_silently) - - -def error(request, message, extra_tags='', fail_silently=False): - """Adds a message with the ``ERROR`` level.""" - add_message(request, constants.ERROR, message, extra_tags=extra_tags, - fail_silently=fail_silently) diff --git a/code/horizon/horizon/middleware.py b/code/horizon/horizon/middleware.py deleted file mode 100755 index 538f0852..00000000 --- a/code/horizon/horizon/middleware.py +++ /dev/null @@ -1,220 +0,0 @@ -# Copyright 2012 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. -""" -Middleware provided and used by Horizon. -""" - -import json -import logging -import time - -from django.conf import settings -from django.contrib.auth import REDIRECT_FIELD_NAME # noqa -from django.contrib.auth.views import redirect_to_login # noqa -from django.contrib import messages as django_messages -from django import http -from django import shortcuts -from django.utils.encoding import iri_to_uri # noqa -from django.utils import timezone -from django.utils.translation import ugettext_lazy as _ - -from openstack_auth import utils as auth_utils -from openstack_auth import views as auth_views -import six - -from horizon import exceptions -from horizon.utils import functions as utils - - -LOG = logging.getLogger(__name__) - - -class HorizonMiddleware(object): - """The main Horizon middleware class. Required for use of Horizon.""" - - logout_reason = None - - def _check_has_timed_timeout(self, request): - """Check for session timeout and return timestamp.""" - has_timed_out = False - # Activate timezone handling - tz = request.session.get('django_timezone') - if tz: - timezone.activate(tz) - try: - timeout = settings.SESSION_TIMEOUT - except AttributeError: - timeout = 1800 - last_activity = request.session.get('last_activity', None) - timestamp = int(time.time()) - if ( - hasattr(request, "user") and - hasattr(request.user, "token") and not - auth_utils.is_token_valid(request.user.token) - ): - # The user was logged in, but his keystone token expired. - has_timed_out = True - if isinstance(last_activity, int): - if (timestamp - last_activity) > timeout: - has_timed_out = True - if has_timed_out: - request.session.pop('last_activity') - return (has_timed_out, timestamp) - - def _logout(self, request, login_url=None, message=None): - """Logout a user and display a logout message.""" - response = auth_views.logout(request, login_url) - if message is not None: - self.logout_reason = message - utils.add_logout_reason(request, response, message) - return response - - def process_request(self, request): - """Adds data necessary for Horizon to function to the request.""" - - request.horizon = {'dashboard': None, - 'panel': None, - 'async_messages': []} - if not hasattr(request, "user") or not request.user.is_authenticated(): - # proceed no further if the current request is already known - # not to be authenticated - # it is CRITICAL to perform this check as early as possible - # to avoid creating too many sessions - return None - - # Check for session timeout if user is (or was) authenticated. - has_timed_out, timestamp = self._check_has_timed_timeout(request) - if has_timed_out: - return self._logout(request, request.path, _("Session timed out.")) - - if request.is_ajax(): - # if the request is Ajax we do not want to proceed, as clients can - # 1) create pages with constant polling, which can create race - # conditions when a page navigation occurs - # 2) might leave a user seemingly left logged in forever - # 3) thrashes db backed session engines with tons of changes - return None - # If we use cookie-based sessions, check that the cookie size does not - # reach the max size accepted by common web browsers. - if ( - settings.SESSION_ENGINE == - 'django.contrib.sessions.backends.signed_cookies' - ): - max_cookie_size = getattr( - settings, 'SESSION_COOKIE_MAX_SIZE', None) - session_cookie_name = getattr( - settings, 'SESSION_COOKIE_NAME', None) - session_key = request.COOKIES.get(session_cookie_name) - if max_cookie_size is not None and session_key is not None: - cookie_size = sum(( - len(key) + len(value) - for key, value in six.iteritems(request.COOKIES) - )) - if cookie_size >= max_cookie_size: - LOG.error( - 'Total Cookie size for user_id: %(user_id)s is ' - '%(cookie_size)sB >= %(max_cookie_size)sB. ' - 'You need to configure file-based or database-backed ' - 'sessions instead of cookie-based sessions: ' - 'http://docs.openstack.org/developer/horizon/topics/' - 'deployment.html#session-storage' - % { - 'user_id': request.session.get( - 'user_id', 'Unknown'), - 'cookie_size': cookie_size, - 'max_cookie_size': max_cookie_size, - } - ) - # We have a valid session, so we set the timestamp - request.session['last_activity'] = timestamp - - def process_exception(self, request, exception): - """Catches internal Horizon exception classes such as NotAuthorized, - NotFound and Http302 and handles them gracefully. - """ - if isinstance(exception, (exceptions.NotAuthorized, - exceptions.NotAuthenticated)): - auth_url = settings.LOGIN_URL - next_url = iri_to_uri(request.get_full_path()) - if next_url != auth_url: - field_name = REDIRECT_FIELD_NAME - else: - field_name = None - login_url = request.build_absolute_uri(auth_url) - response = redirect_to_login(next_url, login_url=login_url, - redirect_field_name=field_name) - - if request.is_ajax(): - response_401 = http.HttpResponse(status=401) - response_401['X-Horizon-Location'] = response['location'] - return response_401 - - return response - - # If an internal "NotFound" error gets this far, return a real 404. - if isinstance(exception, exceptions.NotFound): - raise http.Http404(exception) - - if isinstance(exception, exceptions.Http302): - # TODO(gabriel): Find a way to display an appropriate message to - # the user *on* the login form... - return shortcuts.redirect(exception.location) - - def process_response(self, request, response): - """Convert HttpResponseRedirect to HttpResponse if request is via ajax - to allow ajax request to redirect url - """ - if request.is_ajax() and hasattr(request, 'horizon'): - queued_msgs = request.horizon['async_messages'] - if type(response) == http.HttpResponseRedirect: - # Drop our messages back into the session as per usual so they - # don't disappear during the redirect. Not that we explicitly - # use django's messages methods here. - for tag, message, extra_tags in queued_msgs: - getattr(django_messages, tag)(request, message, extra_tags) - if response['location'].startswith(settings.LOGOUT_URL): - redirect_response = http.HttpResponse(status=401) - # This header is used for handling the logout in JS - redirect_response['logout'] = True - if self.logout_reason is not None: - utils.add_logout_reason( - request, redirect_response, self.logout_reason) - else: - redirect_response = http.HttpResponse() - # Use a set while checking if we want a cookie's attributes - # copied - cookie_keys = set(('max_age', 'expires', 'path', 'domain', - 'secure', 'httponly', 'logout_reason')) - # Copy cookies from HttpResponseRedirect towards HttpResponse - for cookie_name, cookie in six.iteritems(response.cookies): - cookie_kwargs = dict(( - (key, value) for key, value in six.iteritems(cookie) - if key in cookie_keys and value - )) - redirect_response.set_cookie( - cookie_name, cookie.value, **cookie_kwargs) - redirect_response['X-Horizon-Location'] = response['location'] - return redirect_response - if queued_msgs: - # TODO(gabriel): When we have an async connection to the - # client (e.g. websockets) this should be pushed to the - # socket queue rather than being sent via a header. - # The header method has notable drawbacks (length limits, - # etc.) and is not meant as a long-term solution. - response['X-Horizon-Messages'] = json.dumps(queued_msgs) - return response diff --git a/code/horizon/horizon/site_urls.py b/code/horizon/horizon/site_urls.py deleted file mode 100644 index 5dc78e8c..00000000 --- a/code/horizon/horizon/site_urls.py +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright 2012 United States Government as represented by the -# Administrator of the National Aeronautics and Space Administration. -# All Rights Reserved. -# -# Copyright 2012 Nebula, Inc. -# -# Licensed under the Apache License, Version 2.0 (the "License"); you may -# not use this file except in compliance with the License. You may obtain -# a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations -# under the License. - -from django.conf import settings -from django.conf.urls import include -from django.conf.urls import patterns -from django.conf.urls import url -from django.views.generic import TemplateView # noqa - -from horizon.test.jasmine import jasmine - -urlpatterns = patterns( - 'horizon.views', - url(r'^home/$', 'user_home', name='user_home') -) - -# Client-side i18n URLconf. -urlpatterns += patterns( - '', - url(r'^i18n/js/(?P\S+?)/$', - 'django.views.i18n.javascript_catalog', - name='jsi18n'), - url(r'^i18n/setlang/$', - 'django.views.i18n.set_language', - name="set_language"), - url(r'^i18n/', include('django.conf.urls.i18n')) -) - -if settings.DEBUG: - urlpatterns += patterns( - '', - url(r'^qunit/$', - TemplateView.as_view(template_name="horizon/qunit.html"), - name='qunit_tests'), - url(r'^jasmine/(.*?)$', jasmine.dispatcher)) diff --git a/code/horizon/horizon/static/angular/action-list/action-list.js b/code/horizon/horizon/static/angular/action-list/action-list.js deleted file mode 100644 index 205a63e9..00000000 --- a/code/horizon/horizon/static/angular/action-list/action-list.js +++ /dev/null @@ -1,206 +0,0 @@ -(function() { - 'use strict'; - - /** - * @ngdoc overview - * @name hz.widget.action-list - * @description - * - * # hz.widget.action-list - * - * The `actionList` directive supports displaying a set of buttons - * in a Bootstrap button group or button dropdown (single or split). - * - * | Directives | - * |-----------------------------------------------------------------| - * | {@link hz.widget.action-list.directive:actionList `actionList`} | - * | {@link hz.widget.menu.directive:menu `menu`} | - * | {@link hz.widget.action.directive:action `action`} | - * - */ - angular.module('hz.widget.action-list', [ 'ui.bootstrap' ]) - - /** - * @ngdoc directive - * @name hz.widget.action-list.directive:actionList - * @element - * @description - * The `actionList` directive is the wrapper for the set of - * actions to be displayed in a Bootstrap button group or - * button dropdown. - * - * The following directives/elements can be declared within - * this directive element: action, menu, and notifications. - * Within the menu directive element, any number of `action` - * directives elements can be declared. - * - * If the action list should be a button dropdown, include - * `dropdown` as an attribute. Additionally, any attribute - * directives can be added (i.e. warning-tooltip). - * - * Notifications are displayed on the bottom right of the - * button group. Declare any number of icons to display - * within the `notifications` element. Use `ng-show` or - * `ng-hide` to dynamically show/hide the icon. Make sure - * to declare first to ensure the button - * dropdown border radius will display as expected. - * - * If a button dropdown is required, declare the dropdown - * button with the `button-type` attribute set to - * 'single-button' or 'split-button' for a single button - * dropdown or split button dropdown, respectively. See - * (http://getbootstrap.com/components/#btn-dropdowns). - * The remaining actions should be declared within the - * `menu` directive element with the `button-type` set to - * 'menu-item'. These will be converted to links in the - * dropdown menu. - * - * See the `action` and `menu` directives below for more - * information. - * - * @restrict E - * @example - * - * ``` - * - * - * - * - * - * Actions - * - * - * - * Edit - * - * - * Delete - * - * - * - * ``` - */ - .directive('actionList', [ 'basePath', function(path) { - return { - restrict: 'E', - link: function (scope, element, attrs, ctrl, transclude) { - element.addClass('btn-group'); - } - }; - } - ]) - - /** - * @ngdoc directive - * @name hz.widget.action-list.directive:menu - * @element - * @description - * The `menu` directive is the wrapper for the set of - * actions to be displayed in a dropdown menu in a - * Bootstrap button dropdown. Actions to be displayed - * should be declared within this directive element. - * - * See the `action` directive below for more information. - * - * @restrict E - * @example - * - * ``` - * - * - * Edit - * - * - * Delete - * - * - * ``` - */ - .directive('menu', [ 'basePath', function(path) { - return { - restrict: 'E', - templateUrl: path + 'action-list/menu.html', - transclude: true, - link: function(scope, element, attrs, ctrl, transclude) { - var menu = element.find('ul'); - - // Append menu items to menu - transclude(scope, function(clone) { - menu.append(clone); - }); - - // Don't include directive element since - // it will misalign component look - menu.unwrap(); - } - }; - }]) - - /** - * @ngdoc directive - * @name hz.widget.action-list.directive:action - * @element - * @description - * The `action` directive represents the actions to be - * displayed in a Bootstrap button group or button - * dropdown. Any content within this directive element - * will be appended to the button or link element. - * - * There are 4 button types available to an - * action (`button-type` attribute): - * - * Default: \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/action-list/button-tooltip.js b/code/horizon/horizon/static/angular/action-list/button-tooltip.js deleted file mode 100644 index 12ec24ba..00000000 --- a/code/horizon/horizon/static/angular/action-list/button-tooltip.js +++ /dev/null @@ -1,129 +0,0 @@ -(function() { - 'use strict'; - - angular.module('hz.widget.action-list') - - /** - * @ngdoc parameters - * @name hz.widget.action-list.constant:tooltipConfig - * @param {string} defaultTemplate Default warning tooltip template - * @param {string} defaultMessage Default warning tooltip message - */ - .constant('tooltipConfig', { - defaultTemplate: '
{$ ::message $}
', - defaultMessage: { - message: gettext('The action cannot be performed. The contents of this row have errors or are missing information.') - } - }) - - /** - * @ngdoc directive - * @name hz.widget.action-list.directive:buttonTooltip - * @element action-list - * @param {string} buttonTooltip The tooltip message - * @param {object} btModel Custom tooltip model (optional) - * @param {string} btPlacement Tooltip placement (optional) - * @param {string} btDisabled Disable the tooltip (optional) - * @description - * The `buttonTooltip` directive provides a tooltip with a general - * warning message. This directive should be added as an attribute - * to an action-list element. The content of the tooltip can be - * configured by providing a template and necessary data. - * - * Custom Tooltip Model: - * ``` - * $scope.tooltipModel = { - * data: { - * message: 'My custom message', - * anotherMessage: 'Another message', - * clickMe: function() { - * alert('You clicked me'); - * } - * }, - * templateUrl: path + 'myWarningTooltip.html' - * } - * ``` - * - * @restrict A - * @scope - * - * @example - * ``` - * - * ... - * - * ``` - */ - .directive('buttonTooltip', - [ 'basePath', '$compile', '$http', '$templateCache', 'tooltipConfig', - function(path, $compile, $http, $templateCache, tooltipConfig) { - return { - restrict: 'A', - scope: { - btMessage: '=buttonTooltip', - btModel: '=?', - btPlacement: '=?', - btDisabled: '=?' - }, - link: function (scope, element, attrs) { - - var tooltip = scope.btModel || {}; - var template = tooltip.template || tooltipConfig.defaultTemplate; - if (tooltip.templateUrl) { - $http.get(tooltip.templateUrl, { cache: $templateCache }) - .then(function(response) { - template = response.data; - }); - } - - function createTooltip() { - // If there is a custom tooltip model, use it - // Otherwise, get the message or use default message - var tooltipData = angular.extend({}, tooltip.data); - tooltipData.message = scope.btMessage || tooltipConfig.defaultMessage.message; - - // Compile the template with custom tooltip model - var tooltipScope = scope.$new(true); - angular.extend(tooltipScope, tooltipData); - tooltipScope.element = element; - var compiledTemplate = $compile(template)(tooltipScope); - tooltipScope.$apply(); - - var options = { - content: compiledTemplate, - html: true, - placement: scope.btPlacement || 'left', - trigger: 'manual' - }; - - element.popover(options); - element.popover('show'); - } - - element.on('mousedown', function(e) { - if (!scope.btDisabled) { - var popoverElt = element.next('.popover'); - if (popoverElt.length) { - element.popover('destroy'); - } else { - createTooltip(); - } - return false; - } - }); - - element.on('mouseup', function() { - if (!scope.btDisabled) { - element.find('button').first().focus(); - } - }); - - element.on('blur', 'button', function(e) { - element.popover('destroy'); - }); - } - }; - } - ]); - -})(); \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/action-list/menu-item.html b/code/horizon/horizon/static/angular/action-list/menu-item.html deleted file mode 100644 index d0d884e8..00000000 --- a/code/horizon/horizon/static/angular/action-list/menu-item.html +++ /dev/null @@ -1,8 +0,0 @@ - -
  • - - - -
  • \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/action-list/menu.html b/code/horizon/horizon/static/angular/action-list/menu.html deleted file mode 100644 index 46b2cc4d..00000000 --- a/code/horizon/horizon/static/angular/action-list/menu.html +++ /dev/null @@ -1,2 +0,0 @@ - \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/action-list/single-button.html b/code/horizon/horizon/static/angular/action-list/single-button.html deleted file mode 100644 index cddd0656..00000000 --- a/code/horizon/horizon/static/angular/action-list/single-button.html +++ /dev/null @@ -1,8 +0,0 @@ - - \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/action-list/split-button.html b/code/horizon/horizon/static/angular/action-list/split-button.html deleted file mode 100644 index f1650163..00000000 --- a/code/horizon/horizon/static/angular/action-list/split-button.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/action-list/warning-tooltip.html b/code/horizon/horizon/static/angular/action-list/warning-tooltip.html deleted file mode 100644 index 044fe93a..00000000 --- a/code/horizon/horizon/static/angular/action-list/warning-tooltip.html +++ /dev/null @@ -1,4 +0,0 @@ -

    {$ ::message $}

    - \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/bind-scope/bind-scope.js b/code/horizon/horizon/static/angular/bind-scope/bind-scope.js deleted file mode 100644 index a1791c44..00000000 --- a/code/horizon/horizon/static/angular/bind-scope/bind-scope.js +++ /dev/null @@ -1,60 +0,0 @@ -(function() { - 'use strict'; - - /** - * @ngdoc overview - * @name hz.framework.bind-scope - * @description - * - * # hz.framework.bind-scope - * - * This utility widget supports binding the scope where the directive is - * instantiated with the transcluded content. This is useful when trying - * to display transcluded content using the `ngRepeat` scope. - * - * | Directives | - * |--------------------------------------------------------------------------| - * | {@link hz.framework.bind-scope.directive:bindScope `bindScope`} | - * - */ - angular.module('hz.framework.bind-scope', []) - - /** - * @ngdoc directive - * @name hz.framework.bind-scope.directive:bindScope - * @element ng-repeat - * @description - * The `bindScope` directive injects the scope where it is - * instantiated into the transclusion function so that the - * transcluded content is rendered correctly. The content - * is then append to the element where 'bind-scope-target' - * is defined. - * - * @restrict A - * - * @example - * ``` - * - * - * - * - * - * ``` - */ - .directive('bindScope', function() { - return { - restrict: 'A', - link: function(scope, element, attrs, ctrl, transclude) { - if (transclude) { - transclude(scope, function(clone) { - var detailElt = element.find('[bind-scope-target]'); - if (detailElt.length) { - detailElt.append(clone); - } - }); - } - } - }; - }); - -})(); \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/bind-scope/bind-scope.spec.js b/code/horizon/horizon/static/angular/bind-scope/bind-scope.spec.js deleted file mode 100644 index 51efecb4..00000000 --- a/code/horizon/horizon/static/angular/bind-scope/bind-scope.spec.js +++ /dev/null @@ -1,64 +0,0 @@ -(function() { - 'use strict'; - - describe('hz.framework.bind-scope module', function() { - it('should have been defined', function() { - expect(angular.module('hz.framework.bind-scope')).toBeDefined(); - }); - }); - - describe('bind-scope directive', function() { - - var $scope, $element; - - beforeEach(module('hz')); - beforeEach(module('hz.widgets')); - beforeEach(module('hz.framework.bind-scope')); - - beforeEach(module('hz.framework.bind-scope', function($compileProvider) { - $compileProvider.directive('testBindScope', function() { - return { - restrict: 'E', - scope: { - itemList: '=' - }, - transclude: true, - template: '
    • ' + - ' ' + - '
    ' - }; - }); - })); - - beforeEach(inject(function($injector) { - var $compile = $injector.get('$compile'); - $scope = $injector.get('$rootScope').$new(); - - $scope.fakeData = [ - { id: '1', animal: 'cat' }, - { id: '2', animal: 'dog' }, - { id: '3', animal: 'fish' } - ]; - - var markup = '{$ item.animal $}'; - - $element = angular.element(markup); - $compile($element)($scope); - - $scope.$digest(); - })); - - it('should have 3 list items', function() { - expect($element.find('li').length).toBe(3); - }); - - it('should have 3 list items with values "cat", "dog" and "fish"', function() { - var listItems = $element.find('li'); - expect(listItems[0].textContent.trim()).toBe('cat'); - expect(listItems[1].textContent.trim()).toBe('dog'); - expect(listItems[2].textContent.trim()).toBe('fish'); - }); - - }); - -})(); \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/charts/chart-tooltip.html b/code/horizon/horizon/static/angular/charts/chart-tooltip.html deleted file mode 100644 index 16166b25..00000000 --- a/code/horizon/horizon/static/angular/charts/chart-tooltip.html +++ /dev/null @@ -1,9 +0,0 @@ -
    - - {$ tooltip.label $} - {$ tooltip.value $} -
    \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/charts/chart-tooltip.js b/code/horizon/horizon/static/angular/charts/chart-tooltip.js deleted file mode 100644 index 94ef156c..00000000 --- a/code/horizon/horizon/static/angular/charts/chart-tooltip.js +++ /dev/null @@ -1,47 +0,0 @@ -(function() { - 'use strict'; - - angular.module('hz.widget.charts') - - /** - * @ngdoc directive - * @name hz.widget.charts.directive:chartTooltip - * @element - * @param {object} tooltip-data The tooltip data model and styles - * @description - * The `chartTooltip` directive renders a tooltip showing a colored - * icon, label, and value. - * - * Data Model and Styles: - * ``` - * var tooltipData = { - * enabled: true, - * label: 'Applied', - * value: 1, - * icon: 'fa-square', - * iconColor: '#333333', - * iconClass: 'warning', - * style: { left: '10px', top: '10px' } - * }; - * ``` - * - * @restrict E - * @scope tooltip: '=tooltipData' - * - * @example - * ``` - * - * ``` - * - */ - .directive('chartTooltip', [ 'basePath', function (path) { - return { - restrict: 'E', - scope: { - tooltip: '=tooltipData' - }, - templateUrl: path + 'charts/chart-tooltip.html' - }; - }]); - -})(); \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/charts/chart-tooltip.scss b/code/horizon/horizon/static/angular/charts/chart-tooltip.scss deleted file mode 100644 index f3e02479..00000000 --- a/code/horizon/horizon/static/angular/charts/chart-tooltip.scss +++ /dev/null @@ -1,25 +0,0 @@ -.chart-tooltip { - background-color: $tooltip-bg-color; - border: $tooltip-border; - box-shadow: $tooltip-box-shadow; - display: none; - padding: $tooltip-padding; - position: absolute; - white-space: nowrap; - z-index: 12000; - - &.tooltip-enabled { - display: inline-block; - } - - .tooltip-key { - color: $tooltip-key-color; - font-weight: $tooltip-key-weight; - padding: $tooltip-key-padding; - } - - i.fa { - background-color: inherit; - fill: none; - } -} \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/charts/charts.js b/code/horizon/horizon/static/angular/charts/charts.js deleted file mode 100644 index 9fbaa95f..00000000 --- a/code/horizon/horizon/static/angular/charts/charts.js +++ /dev/null @@ -1,63 +0,0 @@ -(function() { - 'use strict'; - - /** - * @ngdoc overview - * @name hz.widget.charts - * @description - * - * # hz.widget.charts - * - * The `hz.widget.charts` module provides directives for simple charts - * used in Horizon, such as the pie and donut chart. Charts are - * implemented using D3. - * - * Requires {@link http://d3js.org `D3`} to be installed. - * - * | Constants | - * |-----------------------------------------------------------------| - * | {@link hz.widget.charts.constant:chartSettings `chartSettings`} | - * - * | Directives | - * |-----------------------------------------------------------------| - * | {@link hz.widget.charts.directive:pieChart `pieChart`} | - * - */ - angular.module('hz.widget.charts', []) - - /** - * @ngdoc parameters - * @name hz.widget.charts.constant:chartsettings - * @param {number} innerRadius Pie chart inner radius in pixels, default: 0 - * @param {number} outerRadius Pie chart outer radius in pixels, default: 35 - * @param {boolean} showTitle Show title, default: true - * @param {boolean} showLabel Show label, default: true - * @param {boolean} showLegend Show legend default: true - * @param {string} tooltipIcon Tooltip key icon, default: 'fa-square' - * - */ - .constant('chartSettings', { - innerRadius: 0, - outerRadius: 35, - showTitle: true, - showLabel: true, - showLegend: true, - tooltipIcon: 'fa-square' - }) - - /** - * @ngdoc filter - * @name hz.widget.charts.filter:showKeyFilter - * @function Filter based on 'hideKey' value of each slice - * @returns {function} A filtered list of keys to show in legend - * - */ - .filter('showKeyFilter', function() { - return function(items) { - return items.filter(function (item) { - return !item.hideKey; - }); - }; - }); - -})(); \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/charts/pie-chart.html b/code/horizon/horizon/static/angular/charts/pie-chart.html deleted file mode 100644 index 0c2818f1..00000000 --- a/code/horizon/horizon/static/angular/charts/pie-chart.html +++ /dev/null @@ -1,30 +0,0 @@ -
    - - -
    - {$ ::chartData.title $} ({$ model.total $} Max) -
    - - - - - - {$ chartData.label $} - - - - -
    -
    -
    - {$ slice.value $} {$ slice.label $} -
    -
    -
    \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/charts/pie-chart.js b/code/horizon/horizon/static/angular/charts/pie-chart.js deleted file mode 100644 index 50957cdd..00000000 --- a/code/horizon/horizon/static/angular/charts/pie-chart.js +++ /dev/null @@ -1,165 +0,0 @@ -(function() { - 'use strict'; - - angular.module('hz.widget.charts') - - /** - * @ngdoc directive - * @name hz.widget.charts.directive:pieChart - * @element - * @param {object} chart-data The chart data model - * @param {string} chart-settings The custom chart settings (JSON), optional - * @description - * The `pieChart` directive renders a pie or donut chart using D3. The title - * and legend is shown by default. Each slice is represented by a label, value, - * and color (hex value or CSS class). See below for the data model. - * - * Data Model: - * ``` - * var chartData = { - * title: 'Total Instances', - * label: '25%', - * data: [ - * { label: 'Current', value: 1, color: '#1f83c6' }, - * { label: 'Added', value: 1, color: '#81c1e7' }, - * { label: 'Remaining', value: 6, colorClass: 'remaining', hideKey: true } - * ] - * }; - * - * title - the chart title - * label - the text to show in center of chart - * data - the data used to render chart - * - * var chartSettings = { - * innerRadius: 35, - * outerRadius: 50, - * showLabel: false - * }; - * ``` - * - * @restrict E - * @scope true - * - * @example - * ``` - * Pie Chart: - * - * - * Donut Chart: - * - * ``` - * - */ - .directive('pieChart', [ 'basePath', 'chartSettings', function (path, chartSettings) { - return { - restrict: 'E', - scope: { - chartData: '=', - chartSettings: '=' - }, - replace: true, - templateUrl: path + 'charts/pie-chart.html', - link: function (scope, element, attrs) { - var settings = angular.extend({}, chartSettings, scope.chartSettings); - settings.diameter = settings.outerRadius * 2; - - var model = { - settings: settings, - tooltipData: { - enabled: false, - icon: settings.tooltipIcon, - style: angular.extend({}, settings.tooltip) - } - }; - - var d3Elt = d3.select(element[0]); - - var arc = d3.svg.arc() - .outerRadius(settings.outerRadius) - .innerRadius(settings.innerRadius); - - var pie = d3.layout.pie() - .sort(null) - .value(function(d) { return d.value; }); - - var tooltip = d3Elt.select('chart-tooltip'); - - var unwatch = scope.$watch('chartData', updateChart); - scope.$on('$destroy', unwatch); - - scope.model = model; - - function updateChart() { - scope.model.total = d3.sum(scope.chartData.data, function(d) { return d.value; }); - scope.model.tooltipData.enabled = false; - - // Generate or update slices - var chart = d3Elt.select('.slices') - .selectAll('path.slice') - .data(pie(scope.chartData.data)); - - chart.enter().append('path') - .attr('class', 'slice') - .attr('d', arc); - - // Set the color or CSS class for the fill - chart.each(function(d) { - var slice = d3.select(this); - if (d.data.color) { - slice.style('fill', d.data.color); - } else if (d.data.colorClass) { - slice.classed(d.data.colorClass, true); - } - }); - - chart.on('mouseenter', function(d) { showTooltip(d, this); }) - .on('mouseleave', clearTooltip); - - // Animate the slice rendering - chart.transition() - .duration(500) - .attrTween('d', function animate(d) { - this.lastAngle = this.lastAngle || { startAngle: 0, endAngle: 0 }; - var interpolate = d3.interpolate(this.lastAngle, d); - this.lastAngle = interpolate(0); - - return function(t) { - return arc(interpolate(t)); - }; - }); - - chart.exit().remove(); - } - - function showTooltip(d, elt) { - scope.$apply(function() { - var eltHeight = element[0].getBoundingClientRect().height; - var titleHeight = element[0].querySelector('div.pie-chart-title') - .getBoundingClientRect() - .height; - - var point = d3.mouse(elt); - var x = point[0] + scope.model.settings.outerRadius; - var y = eltHeight - point[1] - scope.model.settings.outerRadius - titleHeight; - - scope.model.tooltipData.label = d.data.label; - scope.model.tooltipData.value = d.data.value; - scope.model.tooltipData.enabled = true; - scope.model.tooltipData.iconColor = d.data.color; - scope.model.tooltipData.iconClass = d.data.colorClass; - scope.model.tooltipData.style.left = x + 'px'; - scope.model.tooltipData.style.bottom = y + 'px'; - }); - } - - function clearTooltip() { - scope.$apply(function() { - scope.model.tooltipData.enabled = false; - }); - } - } - }; - }]); - -})(); \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/charts/pie-chart.scss b/code/horizon/horizon/static/angular/charts/pie-chart.scss deleted file mode 100644 index f46b9d07..00000000 --- a/code/horizon/horizon/static/angular/charts/pie-chart.scss +++ /dev/null @@ -1,44 +0,0 @@ -.pie-chart { - display: inline-block; - position: relative; - - .svg-pie-chart { - float: left; - - .slice { - cursor: pointer; - } - } - - .pie-chart-title { - font-size: $chart-title-font-size; - font-weight: $chart-title-weight; - padding: $chart-title-padding; - } - - .pie-chart-label { - font-size: 1.2em; - text-anchor: middle; - } - - .pie-chart-legend { - float: left; - font-size: $chart-legend-font-size; - line-height: 1em; - padding: $chart-legend-padding; - - .slice-legend { - padding: 0.1em 0; - - .slice-key { - color: transparent; - display: inline-block; - height: 1em; - line-height: 1em; - position: relative; - top: 0.12em; - width: 0.5em; - } - } - } -} \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/charts/pie-chart.spec.js b/code/horizon/horizon/static/angular/charts/pie-chart.spec.js deleted file mode 100644 index 839829e7..00000000 --- a/code/horizon/horizon/static/angular/charts/pie-chart.spec.js +++ /dev/null @@ -1,88 +0,0 @@ -/* jshint globalstrict: true */ -'use strict'; - -describe('hz.widget.charts module', function () { - it('should be defined', function () { - expect(angular.module('hz.widget.charts')).toBeDefined(); - }); -}); - -describe('pie chart directive', function() { - - var $scope, $element; - - beforeEach(module('templates')); - beforeEach(module('hz')); - beforeEach(module('hz.widgets')); - beforeEach(module('hz.widget.charts')); - - beforeEach(inject(function($injector) { - var $compile = $injector.get('$compile'); - $scope = $injector.get('$rootScope').$new(); - - $scope.testData = { - title: 'Total Instances', - label: '25%', - data: [ - { label: 'Current', value: 1, color: '#1f83c6' }, - { label: 'Added', value: 1, color: '#81c1e7' }, - { label: 'Remaining', value: 6, color: '#d1d3d4', hideKey: true } - ] - }; - - var settings = '{ "innerRadius": 25 }'; - var markup = ""; - $element = angular.element(markup); - $compile($element)($scope); - - $scope.$digest(); - })); - - it('should be compiled', function() { - expect($element.html().trim()).not.toBe(''); - }); - - it('should have svg element', function() { - expect($element.find('svg')).toBeDefined(); - }); - - it('should have 3 path elements', function() { - expect($element.find('path.slice').length).toBe(3); - }); - - it('should have correct colors for slices', function() { - var slices = $element.find('path.slice'); - - var slice1Color = slices[0].style.fill; - - if (slice1Color.indexOf('rgb') === 0) { - expect(slices[0].style.fill).toBe('rgb(31, 131, 198)'); - expect(slices[1].style.fill).toBe('rgb(129, 193, 231)'); - expect(slices[2].style.fill).toBe('rgb(209, 211, 212)'); - } else { - expect(slices[0].style.fill).toBe('#1f83c6'); - expect(slices[1].style.fill).toBe('#81c1e7'); - expect(slices[2].style.fill).toBe('#d1d3d4'); - } - }); - - it('should have a correct title "Total Instances (8 Max)"', function() { - var title = $element.find('.pie-chart-title').text().trim(); - expect(title).toBe('Total Instances (8 Max)'); - }); - - it('should have a legend', function() { - expect($element.find('.pie-chart-legend')).toBeDefined(); - }); - - it ('should have correct legend keys and labels', function() { - var legendKeys = $element.find('.pie-chart-legend .slice-legend'); - - var firstKeyLabel = legendKeys[0]; - var secondKeyLabel = legendKeys[1]; - - expect(firstKeyLabel.textContent.trim()).toBe('1 Current'); - expect(secondKeyLabel.textContent.trim()).toBe('1 Added'); - }); - -}); \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/form/form.js b/code/horizon/horizon/static/angular/form/form.js deleted file mode 100644 index 9a69e6c5..00000000 --- a/code/horizon/horizon/static/angular/form/form.js +++ /dev/null @@ -1,71 +0,0 @@ -(function() { - 'use strict'; - - /** - * @ngdoc overview - * @name hz.widget.form - * - * # hz.widget.form - * - * The `hz.widget.form` provides form directives and services. - * - * | Components | - * |----------------------------------------------------------| - * | {@link hz.widget.form.hzPasswordMatch `hzPasswordMatch`} | - * - */ - var app = angular.module('hz.widget.form', []); - - /** - * @ngdoc directive - * @name hzPasswordMatch - * - * @description - * A directive to ensure that password matches. - * Changing the password or confirmation password triggers a validation check. - * However, only the confirmation password will show an error if match is false. - * The goal is to check that confirmation password matches the password, - * not whether the password matches the confirmation password. - * The behavior here is NOT bi-directional. - * - * @requires - * ng-model - model for confirmation password - * - * @scope - * hzPasswordMatch - form model to validate against - * - * @example: - *
    - * - * - *
    - * - * Note that id and name are required for the password input. - * This directive uses the form model and id for validation check. - */ - app.directive('hzPasswordMatch', function(){ - return { - restrict: 'A', - require: 'ngModel', - scope: { pw: '=hzPasswordMatch' }, - link: function(scope, element, attr, ctrl){ - - // helper function to check that password matches - function passwordCheck(){ - scope.$apply(function(){ - var match = (ctrl.$modelValue === scope.pw.$modelValue); - ctrl.$setValidity('match', match); - }); - } - - // this ensures that typing in either input - // will trigger the password match - var pwElement = $('#'+scope.pw.$name); - pwElement.on('keyup change', passwordCheck); - element.on('keyup change', passwordCheck); - - } // end of link - }; // end of return - }); // end of directive - -})(); diff --git a/code/horizon/horizon/static/angular/form/form.spec.js b/code/horizon/horizon/static/angular/form/form.spec.js deleted file mode 100644 index fcb7447c..00000000 --- a/code/horizon/horizon/static/angular/form/form.spec.js +++ /dev/null @@ -1,93 +0,0 @@ -/* jshint globalstrict: true */ -'use strict'; - -describe('hz.widget.form module', function(){ - it('should have been defined', function(){ - expect(angular.module('hz.widget.form')).toBeDefined(); - }); -}); - -describe('form directives', function() { - beforeEach(module('hz')); - beforeEach(module('hz.widgets')); - beforeEach(module('hz.widget.form')); - - describe('hzPasswordMatch directive', function() { - - var $compile, $rootScope; - var element, password, cpassword; - var markup = - '
    ' + - '' + - '' + - '
    '; - - beforeEach(inject(function($injector){ - $compile = $injector.get('$compile'); - $rootScope = $injector.get('$rootScope').$new(); - - // generate dom from markup - element = $compile(markup)($rootScope); - password = element.children('input[name]'); - cpassword = element.children('input[hz-password-match]'); - - // setup up initial data - $rootScope.user = {}; - $rootScope.$digest(); - })); - - it('should be initially empty', function() { - expect(password.val()).toEqual(''); - expect(password.val()).toEqual(cpassword.val()); - expect(cpassword.hasClass('ng-valid')).toBe(true); - }); - - it('should not match if user changes only password', function(done) { - $rootScope.user.password = 'password'; - $rootScope.$digest(); - cpassword.change(); - setTimeout(function(){ - expect(cpassword.val()).not.toEqual(password.val()); - expect(cpassword.hasClass('ng-invalid')).toBe(true); - done(); - }, 1000); - }); - - it('should not match if user changes only confirmation password', function(done) { - $rootScope.user.cpassword = 'password'; - $rootScope.$digest(); - cpassword.change(); - setTimeout(function(){ - expect(cpassword.val()).not.toEqual(password.val()); - expect(cpassword.hasClass('ng-invalid')).toBe(true); - done(); - }, 1000); - }); - - it('should match if both passwords are the same', function(done) { - $rootScope.user.password = 'password'; - $rootScope.user.cpassword = 'password'; - $rootScope.$digest(); - cpassword.change(); - setTimeout(function(){ - expect(cpassword.val()).toEqual(password.val()); - expect(cpassword.hasClass('ng-valid')).toBe(true); - done(); - }, 1000); - }); - - it('should not match if both passwords are different', function(done) { - $rootScope.user.password = 'password123'; - $rootScope.user.cpassword = 'password345'; - $rootScope.$digest(); - cpassword.change(); - setTimeout(function(){ - expect(cpassword.val()).not.toEqual(password.val()); - expect(cpassword.hasClass('ng-invalid')).toBe(true); - done(); - }, 1000); - }); - - }); // end of hzPasswordMatch directive -}); // end of form directives diff --git a/code/horizon/horizon/static/angular/help-panel/help-panel.html b/code/horizon/horizon/static/angular/help-panel/help-panel.html deleted file mode 100644 index 011fe59f..00000000 --- a/code/horizon/horizon/static/angular/help-panel/help-panel.html +++ /dev/null @@ -1,5 +0,0 @@ -
    - - -
    -
    diff --git a/code/horizon/horizon/static/angular/help-panel/help-panel.js b/code/horizon/horizon/static/angular/help-panel/help-panel.js deleted file mode 100644 index a05da231..00000000 --- a/code/horizon/horizon/static/angular/help-panel/help-panel.js +++ /dev/null @@ -1,13 +0,0 @@ -(function () { - 'use strict'; - - angular.module('hz.widget.help-panel', []) - .directive('helpPanel', ['basePath', - function (path) { - return { - templateUrl: path + 'help-panel/help-panel.html', - transclude: true - }; - } - ]); -})(); diff --git a/code/horizon/horizon/static/angular/help-panel/help-panel.scss b/code/horizon/horizon/static/angular/help-panel/help-panel.scss deleted file mode 100644 index b5d03f22..00000000 --- a/code/horizon/horizon/static/angular/help-panel/help-panel.scss +++ /dev/null @@ -1,86 +0,0 @@ -.help-panel { - position: absolute; - width: $helpPanelWidthDefault; - right: -$helpPanelWidthDefault; - top: 0; - bottom: 0; - color: $helpPanelColor; - background: $helpPanelBg; - -webkit-transition: right linear 0.1s; - transition: right linear 0.1s; - z-index: 10; - - .content { - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - padding: 10px 20px; - overflow-y: auto; - - h1 { - font-size: 20px; - line-height: 1.8; - margin: 0; - } - - li { - list-style-position: inside; - } - - p { - line-height: 1.4; - margin: 1em 0; - } - } - - &.open { - right: 0; - border: 1px solid $helpPanelBorderColor; - border-right: none; - margin-top: -1px; - margin-bottom: -1px; - - & > button.open { - display: none; - } - - & > button.close { - display: block; - opacity: 1; // override bootstrap - font-size: 14px; // override bootstrap - } - } - - & > button { - position: absolute; - top: 0; - left: -$helpPanelBtnSize; - width: $helpPanelBtnSize; - height: $helpPanelBtnSize; - line-height: $helpPanelBtnSize; - padding: 0; - border: none; - text-align: center; - vertical-align: middle; - background: $helpPanelBtnBg; - border: 1px solid $helpPanelBorderColor; - border-right: none; - margin-top: -1px; - - - // button icon - & > * { - display: inline-block; - vertical-align: middle; - background: $helpPanelBtnIconBg; - color: $helpPanelBtnIconColor; - font-size: $helpPanelBtnIconSize; - } - - &.close { - display: none; - } - } -} diff --git a/code/horizon/horizon/static/angular/help-panel/help-panel.spec.js b/code/horizon/horizon/static/angular/help-panel/help-panel.spec.js deleted file mode 100644 index c6cec431..00000000 --- a/code/horizon/horizon/static/angular/help-panel/help-panel.spec.js +++ /dev/null @@ -1,48 +0,0 @@ -/* jshint globalstrict: true */ -'use strict'; - -describe('hz.widget.help-panel module', function() { - it('should have been defined', function () { - expect(angular.module('hz.widget.help-panel')).toBeDefined(); - }); -}); - -describe('help-panel directive', function () { - var $compile, - $scope, - element; - - beforeEach(module('templates')); - beforeEach(module('hz')); - beforeEach(module('hz.widgets')); - beforeEach(module('hz.widget.help-panel')); - beforeEach(inject(function ($injector) { - $scope = $injector.get('$rootScope').$new(); - $compile = $injector.get('$compile'); - element = $compile('Help')($scope); - $scope.$digest(); - })); - - it('should be compiled', function () { - expect(element.html().trim()).not.toBe('Help'); - expect(element.text().trim()).toBe('Help'); - }); - - it('should be closed by default', function () { - expect(element[0].querySelector('.help-panel').className).toBe('help-panel'); - }); - - it('should add "open" to class name if $scope.openHelp===true', function () { - $scope.openHelp = true; - $scope.$digest(); - expect(element[0].querySelector('.help-panel').className).toBe('help-panel open'); - }); - - it('should remove "open" from class name if $scope.openHelp===false', function () { - $scope.openHelp = true; - $scope.$digest(); - $scope.openHelp = false; - $scope.$digest(); - expect(element[0].querySelector('.help-panel').className).toBe('help-panel'); - }); -}); diff --git a/code/horizon/horizon/static/angular/login/login.js b/code/horizon/horizon/static/angular/login/login.js deleted file mode 100644 index 33c5d922..00000000 --- a/code/horizon/horizon/static/angular/login/login.js +++ /dev/null @@ -1,104 +0,0 @@ -/** - * Copyright 2015 IBM Corp. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -(function() { - 'use strict'; - - angular.module('hz') - - /** - * @ngdoc hzLoginCtrl - * @description - * controller for determining which - * authentication method user picked. - */ - .controller('hzLoginCtrl', function($scope) { - $scope.auth_type = 'credentials'; - }) - - /** - * @ngdoc hzLoginFinder - * @description - * A directive to show or hide inputs and help text - * based on which authentication method the user selected. - * Since HTML is generated server-side via Django form, - * this directive is the hook to make it more dynamic. - * Only visible if websso is enabled. - */ - .directive('hzLoginFinder', function($timeout) { - return { - restrict: 'A', - link: function(scope, element) { - - // test code does not have access to document - // so we are restricted to search through the element - var authType = element.find('#id_auth_type'); - var userInput = element.find("#id_username").parents('.form-group'); - var passwordInput = element.find("#id_password").parents('.form-group'); - var domainInput = element.find('#id_domain').parents('form-group'); - var regionInput = element.find('#id_region').parents('form-group'); - - // helptext exists outside of element - // we have to traverse one node up - var helpText = element.parent().find('#help_text'); - helpText.hide(); - - // update the visuals - // when user selects item from dropdown - function onChange(e) { - $timeout(function() { - - // if type is credential - // show the username and password fields - // and domain and region if applicable - scope.auth_type = authType.val(); - switch(scope.auth_type) { - case 'credentials': - userInput.show(); - passwordInput.show(); - domainInput.show(); - regionInput.show(); - break; - default: - userInput.hide(); - passwordInput.hide(); - domainInput.hide(); - regionInput.hide(); - } - - }); // end of timeout - } // end of onChange - - // if authType field exists - // then websso was enabled - if (authType.length > 0) { - - // programmatically insert help text after dropdown - // this is the only way to do it since template is - // generated server side via form_fields - authType.after(helpText); - helpText.show(); - - // trigger the onChange on first load - // so that initial choice is auto-selected - onChange(); - authType.change(onChange); - } - - } // end of link - }; // end of return - }); // end of directive - -})(); \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/login/login.spec.js b/code/horizon/horizon/static/angular/login/login.spec.js deleted file mode 100644 index 02415cb0..00000000 --- a/code/horizon/horizon/static/angular/login/login.spec.js +++ /dev/null @@ -1,166 +0,0 @@ -/** - * Copyright 2015 IBM Corp. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -/* jshint globalstrict: true */ -'use strict'; - -describe('hzLoginCtrl', function(){ - - var $controller; - - beforeEach(module('hz')); - beforeEach(inject(function(_$controller_){ - $controller = _$controller_; - })); - - describe('$scope.auth_type', function(){ - it('should initialize to credentials', function(){ - var scope = {}; - var controller = $controller('hzLoginCtrl', { $scope: scope }); - expect(scope.auth_type).toEqual('credentials'); - }); - }); - -}); - -describe('hzLoginFinder', function(){ - - var $compile, $rootScope, $timeout; - - var websso_markup = - '
    ' + - '

    Some help text.

    ' + - '
    ' + - '
    ' + - '' + - '
    ' + - '
    ' + - '
    ' + - '
    ' + - '
    '; - - var regular_markup = - '
    ' + - '

    Some help text.

    ' + - '
    ' + - '
    ' + - '
    ' + - '
    ' + - '
    '; - - beforeEach(module('hz')); - beforeEach(inject(function(_$compile_, _$rootScope_, _$timeout_){ - $compile = _$compile_; - $rootScope = _$rootScope_; - $timeout = _$timeout_; - - jasmine.addMatchers({ - // jquery show is not consistent across different browsers - // on FF, it is 'block' while on chrome it is 'inline' - // to reconcile this difference, we need a custom matcher - toBeVisible: function(){ - return { - compare: function(actual){ - var pass = (actual.css('display') !== 'none'); - var result = { - pass: pass, - message: pass? - 'Expected element to be visible': - 'Expected element to be visible, but it is hidden' - }; - return result; - } - }; - } - }); - })); - - describe('when websso is not enabled', function(){ - - var element, - helpText, authType, - userInput, passwordInput; - - beforeEach(function(){ - element = $compile(regular_markup)($rootScope); - authType = element.find('#id_auth_type'); - userInput = element.find("#id_username").parents('.form-group'); - passwordInput = element.find("#id_password").parents('.form-group'); - helpText = element.find('#help_text'); - $rootScope.$digest(); - }); - - it('should not contain auth_type select input', function(){ - expect(authType.length).toEqual(0); - }); - - it('should hide help text', function(){ - expect(helpText).not.toBeVisible(); - }); - - it('should show username and password inputs', function(){ - expect(userInput).toBeVisible(); - expect(passwordInput).toBeVisible(); - }); - - }); - - describe('when websso is enabled', function(){ - - var element, - helpText, authType, - userInput, passwordInput; - - beforeEach(function(){ - element = $compile(websso_markup)($rootScope); - authType = element.find('#id_auth_type'); - userInput = element.find("#id_username").parents('.form-group'); - passwordInput = element.find("#id_password").parents('.form-group'); - helpText = element.find('#help_text'); - $rootScope.$digest(); - }); - - it('should contain auth_type select input', function(){ - expect(authType.length).toEqual(1); - }); - - it('should show help text below auth_type', function(){ - expect(authType.next().get(0)).toEqual(helpText.get(0)); - }); - - it('should show help text', function(){ - expect(helpText).toBeVisible(); - }); - - it('should show username and password inputs', function(){ - expect(userInput).toBeVisible(); - expect(passwordInput).toBeVisible(); - }); - - it('should hide username and password when user picks oidc', function(){ - authType.val('oidc'); - authType.change(); - $timeout.flush(); - expect(userInput).not.toBeVisible(); - expect(passwordInput).not.toBeVisible(); - }); - - }); - -}); \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/magic-search/magic-search.html b/code/horizon/horizon/static/angular/magic-search/magic-search.html deleted file mode 100644 index 646d1ef7..00000000 --- a/code/horizon/horizon/static/angular/magic-search/magic-search.html +++ /dev/null @@ -1,50 +0,0 @@ - - diff --git a/code/horizon/horizon/static/angular/magic-search/magic-search.js b/code/horizon/horizon/static/angular/magic-search/magic-search.js deleted file mode 100644 index dbc44498..00000000 --- a/code/horizon/horizon/static/angular/magic-search/magic-search.js +++ /dev/null @@ -1,35 +0,0 @@ -(function() { - 'use strict'; - angular.module('MagicSearch', ['ui.bootstrap']) - .directive('magicOverrides', function() { - return { - restrict: 'A', - controller: ['$scope', '$timeout', - function($scope, $timeout) { - // showMenu and hideMenu depend on foundation's dropdown. They need - // to be modified to work with another dropdown implemenation. - // For bootstrap, they are not needed at all. - $scope.showMenu = function() { - $timeout(function() { - $scope.isMenuOpen = true; - }); - }; - $scope.hideMenu = function() { - $timeout(function() { - $scope.isMenuOpen = false; - }); - }; - $scope.isMenuOpen = false; - - // magic_search.js should absorb this code? - $scope.$on('facetsChanged', function() { - $timeout(function() { - $scope.currentSearch = []; - $scope.initSearch(); - }); - }); - } - ] - }; // end of return - }); // end of directive -})(); \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/magic-search/magic-search.scss b/code/horizon/horizon/static/angular/magic-search/magic-search.scss deleted file mode 100644 index d378926e..00000000 --- a/code/horizon/horizon/static/angular/magic-search/magic-search.scss +++ /dev/null @@ -1,31 +0,0 @@ -// Augments magic_search.scss with styles for bootstrap/Horizon. - -.search-bar { - .search-entry { - .search-input { - padding: 1px 0px; - font: normal normal normal 12.6px/normal; - outline: none; - height: 24px; - width: 500px; - } - height: 24px; - position: relative; - } - .fa-filter { - padding-left: 5px; - font-size: larger; - } - .fa-times { - font-size: larger; - cursor: pointer; - } - .label { - font-size: 100%; - font-weight: normal; - } -} - -.search-main-area { - padding-left: 10px; -} \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/metadata-display/metadata-display.html b/code/horizon/horizon/static/angular/metadata-display/metadata-display.html deleted file mode 100644 index 9d97150c..00000000 --- a/code/horizon/horizon/static/angular/metadata-display/metadata-display.html +++ /dev/null @@ -1,33 +0,0 @@ - \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/metadata-display/metadata-display.js b/code/horizon/horizon/static/angular/metadata-display/metadata-display.js deleted file mode 100644 index 615c59ee..00000000 --- a/code/horizon/horizon/static/angular/metadata-display/metadata-display.js +++ /dev/null @@ -1,122 +0,0 @@ -(function () { - 'use strict'; - - /** - * @ngdoc overview - * @name hz.widget.metadata-display - * @description - * - * # hz.widget.metadata-display - * - * The `hz.widget.metadata-display` provides widget displaying metadata. - * - * | Directives | - * |---------------------------------------------------------------------------------------------| - * | {@link hz.widget.metadata-display.directive:hzMetadataDisplay `hzMetadataDisplay`} | - * |---------------------------------------------------------------------------------------------| - * | Controllers | - * |---------------------------------------------------------------------------------------------| - * | {@link hz.widget.metadata-display.controller:hzMetadataDisplayCtrl `hzMetadataDisplayCtrl`} | - * - */ - angular.module('hz.widget.metadata-display', [ - 'hz.widget.metadata-tree' - ]) - - /** - * @ngdoc parameters - * @name hz.widget.metadata-display:metadataTreeDefaults - * @param {object} text Text constants - */ - .constant('metadataDisplayDefaults', { - text: { - detail: gettext('Detail Information') - } - }) - - /** - * @ngdoc directive - * @name hz.widget.metadata-display.directive:hzMetadataDisplay - * @scope - * - * @description - * The `hzMetadataDisplay` displays existing metadata. - * - * @param {object[]} available List of available namespaces - * @param {object} existing Key-value pairs with existing properties - * @param {object=} text Text override - */ - .directive('hzMetadataDisplay', ['basePath', - function (path) { - return { - scope: { - available: '=', - existing: '=', - text: '=?' - }, - controller: 'hzMetadataDisplayCtrl', - templateUrl: path + 'metadata-display/metadata-display.html' - }; - } - ]) - - /** - * @ngdoc controller - * @name hz.widget.metadata-display.controller:hzMetadataDisplayCtrl - * @description - * Controller used by `hzMetadataDisplay` - */ - .controller('hzMetadataDisplayCtrl', [ - '$scope', 'metadataTreeService', 'metadataDisplayDefaults', - function ($scope, metadataTreeService, defaults) { - - function init() { - $scope.tree = new metadataTreeService.Tree($scope.available, $scope.existing); - angular.forEach($scope.tree.flatTree, function (item) { - if(item.added) { - if(!item.leaf) { - item.added = false; - if (item.parent) { - item.parent.addedCount -= 1; - } - } - else if(!item.custom) { - $scope.hide = false; - } - } - - }); - // select first item - $scope.tree.flatTree.some(function (item) { - if($scope.listFilter(item)) { - $scope.selected = item; - item.expand(true); - return true; // break - } - }); - } - - $scope.onSelect = function (item) { - $scope.selected.collapse(); - item.expand(true); - $scope.selected = item; - }; - - $scope.childrenFilter = function (item) { - return item.visible && item.leaf && item.added; - }; - - $scope.listFilter = function (item) { - return item.addedCount > 0; - }; - - $scope.text = angular.extend({}, defaults.text, $scope.text); - $scope.tree = null; - $scope.selected = null; - $scope.hide = true; - - init(); - } - ]); - -}()); diff --git a/code/horizon/horizon/static/angular/metadata-display/metadata-display.scss b/code/horizon/horizon/static/angular/metadata-display/metadata-display.scss deleted file mode 100644 index b5219179..00000000 --- a/code/horizon/horizon/static/angular/metadata-display/metadata-display.scss +++ /dev/null @@ -1,34 +0,0 @@ -.metadata-display { - .selector { - .selector-item { - border-top: 1px solid $metadata-display-separator-color; - padding: 10px; - color: $metadata-display-selector-color; - cursor: pointer; - - &:first-child { - border-top: none; - } - - &:hover { - color: $metadata-display-selector-hover-color; - } - - &.active { - color: $metadata-display-selector-active-color; - } - } - } - - .selected-details { - padding-top: 9px; - } - - .description { - margin-top: 20px; - } - - .auto-width { - width: auto; - } -} \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/metadata-display/metadata-display.spec.js b/code/horizon/horizon/static/angular/metadata-display/metadata-display.spec.js deleted file mode 100644 index 00d93963..00000000 --- a/code/horizon/horizon/static/angular/metadata-display/metadata-display.spec.js +++ /dev/null @@ -1,135 +0,0 @@ -/* jshint globalstrict: true */ -'use strict'; - -describe('hz.widget.metadata-display module', function() { - it('should have been defined', function () { - expect(angular.module('hz.widget.metadata-display')).toBeDefined(); - }); - - var namespaces = [ - { - "display_name": "Test Namespace A", - "description": "Test namespace description", - "properties": { - "test:A:1": { - "title": "Test A.1 - string", - "type": "string", - "default": "foo", - "enum": [ - "option-1", "option-2", "option-3" - ] - }, - "test:A:2": { - "title": "Test A.2 - integer", - "type": "integer", - "default": "1", - "minimum": 0, - "maximum": 10 - }, - "test:A:3": { - "title": "Test A.3 - number", - "type": "number", - "default": "1.1", - "minimum": 0, - "maximum": 10 - }, - "test:A:4": { - "title": "Test A.4 - boolean", - "type": "boolean", - "default": "True" - }, - "test:A:5": { - "title": "Test A.5 - boolean", - "type": "boolean", - "default": "false" - }, - "test:A:6": { - "title": "Test A.6 - array", - "type": "array", - "items": { - "type": "string", - "enum": [ - "val-1", "val-2", "val-3" - ] - } - } - } - }, - { - "display_name": "Test Namespace B", - "description": "Test namespace description", - "objects": [ - { - "name": "Test Object A", - "description": "Test object description", - "properties": { - "test:B:A:1": { - "title": "Test B.A.1", - "description": "Test description" - }, - "test:B:A:2": {} - } - }, - { - "name": "Test Object B", - "description": "Test object description", - "properties": { - "test:B:B:1": {}, - "test:B:B:2": {} - } - } - ] - } - ]; - - var existing = { - 'test:A:1': 'option-2', - 'test:A:2': '5', - 'test:B:A:1': 'foo', - 'test:B:B:1': 'bar' - }; - - describe('hzMetadataDisplay directive', function () { - var $scope, $element; - - beforeEach(module('templates')); - beforeEach(module('hz')); - beforeEach(module('hz.widgets')); - beforeEach(module('hz.widget.metadata-tree')); - beforeEach(module('hz.widget.metadata-display')); - beforeEach(inject(function ($injector) { - var $compile = $injector.get('$compile'); - $scope = $injector.get('$rootScope').$new(); - - $scope.available = namespaces; - $scope.existing = existing; - - var markup = - ''; - - $element = angular.element(markup); - $compile($element)($scope); - $scope.$digest(); - })); - - it('should have 3 rows in selector list', function() { - expect($element.find('.selector .selector-item').length).toBe(3); - }); - - it('should have 2 items in first group', function() { - expect($element.find('div[ng-repeat] div.auto-width').length).toBe(2); - }); - - it('should have 1 item in second group', function() { - $element.find('.selector .selector-item:nth-child(2)').trigger('click'); - expect($element.find('div[ng-repeat] div.auto-width').length).toBe(1); - }); - - it('should have proper description', function() { - expect($element.find('span[ng-bind="selected.description"]').text()).toBe(namespaces[0].description); - $element.find('.selector .selector-item:nth-child(2)').trigger('click'); - expect($element.find('span[ng-bind="selected.description"]').text()).toBe(namespaces[1].objects[0].description); - }); - }); - -}); diff --git a/code/horizon/horizon/static/angular/metadata-tree/metadata-tree-item.html b/code/horizon/horizon/static/angular/metadata-tree/metadata-tree-item.html deleted file mode 100644 index 07002d0b..00000000 --- a/code/horizon/horizon/static/angular/metadata-tree/metadata-tree-item.html +++ /dev/null @@ -1,115 +0,0 @@ - \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/metadata-tree/metadata-tree-service.js b/code/horizon/horizon/static/angular/metadata-tree/metadata-tree-service.js deleted file mode 100644 index 95afac5d..00000000 --- a/code/horizon/horizon/static/angular/metadata-tree/metadata-tree-service.js +++ /dev/null @@ -1,498 +0,0 @@ -(function () { - 'use strict'; - - angular.module('hz.widget.metadata-tree') - - /** - * @ngdoc service - * @name hz.widget.metadata-tree.metadataTreeService - */ - .factory('metadataTreeService', [function () { - - /** - * Parse value into boolean - * - * @param {(string|boolean)} value - * @returns {boolean} - */ - function parseBool(value) { - var value_type = typeof(value); - - if(value_type === 'boolean') { - return value; - } - else if(value_type === 'string') { - value = value.toLowerCase(); - - if(value === 'true') { - return true; - } - else if(value === 'false') { - return false; - } - } - - return null; - } - - /** - * Construct a new property - * - * @class Property - * @param {string} name - * @param {Object} [json] - * - * @property {string} name Property key name - * @property {string} title Property display name - * @property {string} description Property description - * @property {*} value Property value - * @property {string} default Property default value - * @property {string} type Property type - * @property {boolean} readonly Property readonly state - * @property {string[]} operators Property available operators when type='array' - * @property {string} operator Property operator when type='array' - */ - function Property(name, json) { - this.name = name; - this.title = name; - this.description = ''; - this.value = null; - this.default = null; - this.type = 'string'; - this.readonly = false; - this.operators = ['']; - angular.extend(this, json); - this.operator = this.operators[0]; - this.setValue(this.default); - } - - /** - * Deserialize value and assign it to {@link Property#value} - * - * @param {string} value - */ - Property.prototype.setValue = function(value) { - if(value === null) { - this.value = this.type !== 'array' ? null : []; - return; - } - - switch (this.type) { - case 'integer': this.value = parseInt(value); break; - case 'number': this.value = parseFloat(value); break; - case 'array': - var data = /^(<.*?>) (.*)$/.exec(value); - if(data) { - this.operator = data[1]; - this.value = data[2].split(','); - } break; - case 'boolean': this.value = parseBool(value); break; - default: this.value = value; - } - }; - - /** - * Serialize {@link Property#value} and returns it - * - * @returns {*} - */ - Property.prototype.getValue = function() { - switch (this.type) { - case 'array': return this.operator + ' ' + this.value.join(','); - default: return this.value; - } - }; - - /** - * Construct a new tree node - * - * @class Item - * @param {Item} parent - * - * @property {Item} parent Item parent - * @property {Item[]} children Item children - * @property {boolean} visible Item visibility - */ - function Item(parent) { - // parent as property to prevent infinite recursion in angular filter - Object.defineProperty(this, 'parent', { - value: typeof parent !== 'undefined' ? parent : null - }); - this.children = []; - // Node properties - this.visible = false; - this.expanded = false; - this.label = ''; - this.description = ''; - this.level = parent ? parent.level + 1 : 0; - this.addedCount = 0; - this.custom = false; - // Leaf properties - this.leaf = null; - this.added = false; - } - - /** - * Load Item values and child Items from namespace definition - * - * @param {object} namespace Metadata namespace definition - * @returns {Item} - */ - Item.prototype.fromNamespace = function (namespace) { - this.label = namespace.display_name; - this.description = namespace.description; - - if(namespace.objects) { - angular.forEach(namespace.objects, function (object) { - this.children.push(new Item(this).fromObject(object)); - }, this); - } - - if(namespace.properties) { - angular.forEach(namespace.properties, function (property, key) { - this.children.push(new Item(this).fromProperty(key, property)); - }, this); - } - - this.sortChildren(); - - return this; - }; - - /** - * Load Item values and child Items from object definition - * - * @param {object} object Metadata object definition - * @returns {Item} - */ - Item.prototype.fromObject = function (object) { - this.label = object.name; - this.description = object.description; - - if(object.properties) { - angular.forEach(object.properties, function (property, key) { - this.children.push(new Item(this).fromProperty(key, property)); - }, this); - } - - this.sortChildren(); - - return this; - }; - - /** - * Load Item values from property definition - * - * @param {string} name Property name - * @param {object} property Metadata property definition - * @returns {Item} - */ - Item.prototype.fromProperty = function (name, property) { - this.leaf = new Property(name, property); - this.label = this.leaf.title; - this.description = this.leaf.description; - - return this; - }; - - /** - * Load Item values from property definition and mark as custom - * - * @param {string} name Property name - * @param {object} property Metadata property definition - * @returns {Item} - */ - Item.prototype.customProperty = function (name, property) { - this.fromProperty(name, property); - this.custom = true; - - return this; - }; - - /** - * Expand Item by marking all children as visible - * - * @param {boolean} deep Whether to recursively expand all child Items - */ - Item.prototype.expand = function (deep) { - this.expanded = true; - angular.forEach(this.children, function (child) { - if(deep) { - child.expand(deep); - } - child.visible = true; - }, this); - }; - - /** - * Collapse Item by recursively unmarking all children as visible - */ - Item.prototype.collapse = function () { - this.expanded = false; - angular.forEach(this.children, function (child) { - child.collapse(); - child.visible = false; - }, this); - }; - - /** - * Sort children Items by label - */ - Item.prototype.sortChildren = function () { - this.children.sort(function (a, b) { - return a.label.localeCompare(b.label); - }); - }; - - /** - * Recursively mark Item and all children as added - * - * @param {=} caller Used internally to prevent infinite recursion - */ - Item.prototype.markAsAdded = function (caller) { - if(this.parent && !this.added) { - this.parent.addedCount += 1; - if(this.parent.addedCount === this.parent.children.length) { - this.parent.markAsAdded(this); - } - } - this.added = true; - if(!caller) { // prevent infinite recursion - angular.forEach(this.children, function (item) { - item.markAsAdded(); - }, this); - } - }; - - /** - * Recursively unmark Item and all children as added - * - * @param {boolean=} expand Whether to expand parent of unmarked Item - * @param {=} caller Used internally to prevent infinite recursion - */ - Item.prototype.unmarkAsAdded = function (expand, caller) { - if(this.parent) { - if(expand) { - this.parent.expand(); - } - if(this.added) { - this.parent.addedCount -= 1; - this.parent.unmarkAsAdded(expand, this); - } - } - this.added = false; - if(!caller) { // prevent infinite recursion - angular.forEach(this.children, function (item) { - item.unmarkAsAdded(expand); - }, this); - } - }; - - /** - * Returns list of Items from top-most parent to this Item - * - * @param {[]=} path Used internally - * @returns {Item[]} - */ - Item.prototype.path = function (path) { - path = typeof path !== 'undefined' ? path : []; - if(this.parent) { - this.parent.path(path); - } - path.push(this); - return path; - }; - - /** - * Returns breadcrumb string for this Item - * - * @returns {string} - */ - Item.prototype.breadcrumb = function () { - return this.path().map(function (item) { - return item.label; - }).join(' › '); - }; - - /** - * Parse string parameter into leaf value - * - * @param {string} value - */ - Item.prototype.setLeafValue = function (value) { - if(this.leaf) { - this.leaf.setValue(value); - } - }; - - /** - * Serialize leaf value into string - * - * @returns {string} - */ - Item.prototype.getLeafValue = function () { - if(this.leaf) { - return this.leaf.getValue(); - } - }; - - /** - * Construct a new tree - * - * @class Tree - * @param {object[]} available List of available namespaces - * @param {object} existing Key-value pairs for existing metadata - * - * @property {Item[]} tree List available namespaces parsed into Item-s - * @property {Item[]} flatTree List of Item-s flattened from tree structure - * @property {Item} selected Selected Item - */ - function Tree(available, existing) { - this.tree = []; - this.loadNamespaces(available); - this.flatTree = this.flatten(this.tree); - this.selected = null; - this.loadExisting(existing); - } - - /** - * Load Item values and child Items from namespace definition - * - * @param {object[]} namespaces list of Metadata namespace definitions - * @returns {Tree} - */ - Tree.prototype.loadNamespaces = function (namespaces) { - angular.forEach(namespaces, function (namespace) { - var item = new Item().fromNamespace(namespace); - item.visible = true; - this.tree.push(item); - }, this); - - this.tree.sort(function (a, b) { - return a.label.localeCompare(b.label); - }); - - return this; - }; - - /** - * Crete flat representation of branch - * - * @param {Item[]} branch List of Items to flatten - * @param {[]=} items Used internally - * @returns {Item[]} - */ - Tree.prototype.flatten = function (branch, items) { - items = typeof items !== 'undefined' ? items : []; - - angular.forEach(branch, function (item) { - items.push(item); - this.flatten(item.children, items); - }, this); - - return items; - }; - - /** - * Load Property.value for each value from existing and mark corresponding - * Items as added. If no corresponding Item is found new Item is added and - * marked as custom. - * - * @param {object} existing - */ - Tree.prototype.loadExisting = function (existing) { - var itemsMapping = {}; - - angular.forEach(this.flatTree, function (item) { - if(item.leaf && item.leaf.name in existing) { - itemsMapping[item.leaf.name] = item; - } - }); - - angular.forEach(existing, function (value, key) { - var item = itemsMapping[key]; - if(typeof item === 'undefined') { - item = new Item().customProperty(key); - this.flatTree.push(item); - } - item.setLeafValue(value); - item.markAsAdded(); - }, this); - }; - - /** - * Returns key-value mapping of leaf Items that was marked as added - * - * @returns {object} - */ - Tree.prototype.getExisting = function () { - var existing = {}; - angular.forEach(this.flatTree, function(item) { - if(item.added && item.leaf) { - existing[item.leaf.name] = item.getLeafValue(); - } - }); - return existing; - }; - - /** - * Selects item and expands / collapses it - * - * @param {Item} item - */ - Tree.prototype.select = function (item) { - this.selected = item; - if(!item.expanded) { - item.expand(); - } else { - item.collapse(); - } - }; - - /** - * Selects item and marks it as added - * - * @param {Item} item - */ - Tree.prototype.markAsAdded = function (item) { - this.selected = item; - item.markAsAdded(); - }; - - /** - * Selects item, unmarks it as added and expands it's parent - * - * @param {Item} item - */ - Tree.prototype.unmarkAsAdded = function (item) { - if(!item.custom) { - this.selected = item; - item.unmarkAsAdded(true); - } else { - this.selected = null; - var i = this.flatTree.indexOf(item); - if(i > -1) { - this.flatTree.splice(i, 1); - } - } - }; - - /** - * Adds new Item, selects it and marks it as custom and added - * - * @param {string} name Name of leaf - */ - Tree.prototype.addCustom = function (name) { - var item = new Item().customProperty(name); - item.markAsAdded(); - this.flatTree.push(item); - this.selected = item; - }; - - return { - Item: Item, - Property: Property, - Tree: Tree - }; - }]); -}()); diff --git a/code/horizon/horizon/static/angular/metadata-tree/metadata-tree.html b/code/horizon/horizon/static/angular/metadata-tree/metadata-tree.html deleted file mode 100644 index 2d3ea0d9..00000000 --- a/code/horizon/horizon/static/angular/metadata-tree/metadata-tree.html +++ /dev/null @@ -1,134 +0,0 @@ - diff --git a/code/horizon/horizon/static/angular/metadata-tree/metadata-tree.js b/code/horizon/horizon/static/angular/metadata-tree/metadata-tree.js deleted file mode 100644 index da1efc71..00000000 --- a/code/horizon/horizon/static/angular/metadata-tree/metadata-tree.js +++ /dev/null @@ -1,229 +0,0 @@ -(function () { - 'use strict'; - - /** - * @ngdoc overview - * @name hz.widget.metadata-tree - * @description - * - * # hz.widget.metadata-tree - * - * The `hz.widget.metadata-tree` provides widgets and service - * with logic for editing metadata. - * - * | Directives | - * |--------------------------------------------------------------------------------------------| - * | {@link hz.widget.metadata-tree.directive:hzMetadataTree `hzMetadataTree`} | - * | {@link hz.widget.metadata-tree.directive:hzMetadataTreeItem `hzMetadataTreeItem`} | - * | {@link hz.widget.metadata-tree.directive:hzMetadataTreeUnique `hzMetadataTreeUnique`} | - * |--------------------------------------------------------------------------------------------| - * | Controllers | - * |--------------------------------------------------------------------------------------------| - * | {@link hz.widget.metadata-tree.controller:hzMetadataTreeCtrl `hzMetadataTreeCtrl`} | - * | {@link hz.widget.metadata-tree.controller:hzMetadataTreeItemCtrl `hzMetadataTreeItemCtrl`} | - * - */ - angular.module('hz.widget.metadata-tree', []) - - /** - * @ngdoc parameters - * @name hz.widget.metadata-tree.constant:metadataTreeDefaults - * @param {object} text Text constants - */ - .constant('metadataTreeDefaults', { - text: { - help: gettext('You can specify resource metadata by moving items from the left column to the right column. In the left columns there are metadata definitions from the Glance Metadata Catalog. Use the "Other" option to add metadata with the key of your choice.'), - min: gettext('Min'), - max: gettext('Max'), - minLength: gettext('Min length'), - maxLength: gettext('Max length'), - patternMismatch: gettext('Pattern mismatch'), - integerRequired: gettext('Integer required'), - decimalRequired: gettext('Decimal required'), - required: gettext('Required'), - duplicate: gettext('Duplicate keys are not allowed'), - filter: gettext('Filter'), - available: gettext('Available Metadata'), - existing: gettext('Existing Metadata'), - custom: gettext('Custom'), - noAvailable: gettext('No available metadata'), - noExisting: gettext('No existing metadata') - } - }) - - /** - * @ngdoc directive - * @name hz.widget.metadata-tree.directive:hzMetadataTree - * @scope - * - * @description - * The `hzMetadataTree` directive provide support for modifying existing - * metadata properties and adding new from metadata catalog. - * - * @param {Tree=} model Model binding - * @param {object[]=} available List of available namespaces - * @param {object=} existing Key-value pairs with existing properties - * @param {object=} text Text override - */ - .directive('hzMetadataTree', ['basePath', - function (path) { - return { - scope: { - tree: '=*?model', - available: '=?', - existing: '=?', - text: '=?' - }, - controller: 'hzMetadataTreeCtrl', - templateUrl: path + 'metadata-tree/metadata-tree.html' - }; - } - ]) - - /** - * @ngdoc directive - * @name hz.widget.metadata-tree.directive:hzMetadataTreeItem - * @scope - * - * @description - * The `hzMetadataTreeItem` helper directive displays proper field for - * editing Item.leaf.value depending on Item.leaf.type - * - * @param {expression} action Action for button - * @param {Item} item Item to display - * @param {object} text Text override - */ - .directive('hzMetadataTreeItem', ['basePath', - function (path) { - return { - scope: { - action: '&', - item: '=', - text: '=' - }, - controller: 'hzMetadataTreeItemCtrl', - templateUrl: path + 'metadata-tree/metadata-tree-item.html' - }; - } - ]) - - /** - * @ngdoc directive - * @name hz.widget.metadata-tree.directive:hzMetadataTreeUnique - * @restrict A - * - * @description - * The `hzMetadataTreeUnique` helper directive provides validation - * for field which value should be unique new Item - */ - .directive('hzMetadataTreeUnique', function () { - return { - restrict: 'A', - require: 'ngModel', - link: function (scope, elm, attrs, ctrl) { - ctrl.$validators.unique = function(modelValue, viewValue) { - return !scope.tree.flatTree.some(function (item) { - return item.leaf && item.leaf.name === viewValue; - }); - }; - } - }; - }) - - /** - * @ngdoc controller - * @name hz.widget.metadata-tree.controller:hzMetadataTreeCtrl - * @description - * Controller used by `hzMetadataTree` - */ - .controller('hzMetadataTreeCtrl', [ - '$scope', 'metadataTreeService', 'metadataTreeDefaults', - function ($scope, metadataTreeService, defaults) { - - $scope.availableFilter = function (item) { - return !item.added && ( - $scope.filterText.available.length === 0 ? item.visible : true); - }; - - $scope.text = angular.extend({}, defaults.text, $scope.text); - if(!$scope.tree) { - $scope.tree = new metadataTreeService.Tree($scope.available, $scope.existing); - } - $scope.customItem = ''; - $scope.filterText = { - available: '', - existing: '' - }; - } - ]) - - /** - * @ngdoc controller - * @name hz.widget.metadata-tree.controller:hzMetadataTreeItemCtrl - * @description - * Controller used by `hzMetadataTreeItem` - */ - .controller('hzMetadataTreeItemCtrl', [ - '$scope', - function ($scope) { - $scope.formatErrorMessage = function (item, error) { - if(error.min) return $scope.text.min + ' ' + item.leaf.minimum; - if(error.max) return $scope.text.max + ' ' + item.leaf.maximum; - if(error.minlength) return $scope.text.minLength + ' ' + item.leaf.minLength; - if(error.maxlength) return $scope.text.maxLength + ' ' + item.leaf.maxLength; - if(error.pattern) { - if(item.leaf.type === 'integer') return $scope.text.integerRequired; - else return $scope.text.patternMismatch; - } - if(error.number) { - if(item.leaf.type === 'integer') return $scope.text.integerRequired; - else return $scope.text.decimalRequired; - } - if(error.required) { - return $scope.text.required; - } - }; - - function remove(array, value) { - var index = array.indexOf(value); - if (index > -1) { - array.splice(index, 1); - } - return array; - } - - $scope.opened = false; - - if($scope.item.leaf.type === 'array') { - - $scope.values = $scope.item.leaf.items.enum.filter(function(i) { - return $scope.item.leaf.value.indexOf(i) < 0; - }).sort(); - - if(!$scope.item.leaf.readonly) { - $scope.add = function (val) { - $scope.item.leaf.value.push(val); - $scope.item.leaf.value.sort(); - remove($scope.values, val); - }; - - $scope.remove = function (val) { - remove($scope.item.leaf.value, val); - $scope.values.push(val); - $scope.values.sort(); - if ($scope.item.leaf.value.length === 0) { - $scope.opened = true; - } - }; - - $scope.open = function () { - $scope.opened = !$scope.opened; - }; - - $scope.opened = $scope.item.leaf.value.length === 0; - } - } - } - ]); - -}()); diff --git a/code/horizon/horizon/static/angular/metadata-tree/metadata-tree.scss b/code/horizon/horizon/static/angular/metadata-tree/metadata-tree.scss deleted file mode 100644 index 8bb87403..00000000 --- a/code/horizon/horizon/static/angular/metadata-tree/metadata-tree.scss +++ /dev/null @@ -1,141 +0,0 @@ -.metadata-tree { - min-height: 200px; - - .metadata-list-group { - height: 400px; - overflow: auto; - } - - /* Header */ - - .panel-heading { - .v-align { - display: table; - min-height: 2.5em; - } - - .v-align > * { - display: table-cell; - vertical-align: middle; - } - } - - /* Item lists */ - - :not(.active) { - &.dark-stripe { - background-color: $table-bg-odd; - } - &.light-stripe { - background-color: white; - } - } - - .list-group-item { - &.level-0>* { - padding-left: 0; - } - - &.level-1>* { - padding-left: 15px; - } - - &.level-2>* { - padding-left: 30px; - } - - .leaf { - padding-left: 10px; - } - } - - .metadata-tree-item { - display: block; - - .input-group-addon { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - width: 50%; - max-width: 140px; - text-align: right; - } - - .multiselect { - margin: 0; - color: $text-color; - - .panel-heading { - padding: 4px; - - &>* { - display: table; - width: 100%; - - &>* { - display: table-cell; - vertical-align: middle; - } - } - } - - .panel-body { - padding: 3px 5px 5px; - } - - .panel-footer { - padding: 4px; - } - - .values .label { - display: inline-block; - text-transform: uppercase; - } - - .name { - vertical-align: text-top; - } - - .options { - max-height: 180px; - overflow-y: auto; - - &>*:last-child { - border-bottom: none; - } - } - - .disabled { - cursor: not-allowed; - background-color: $input-bg-disabled; - } - } - - .label-info { - display: none; - position: absolute; - z-index: 10; - top: 1px; - left: 25px; - max-width: 80%; - overflow: hidden; - text-overflow: ellipsis; - } - - .bool { - width: 40%; - } - } - - .label-danger { - display: inline-block; - position: absolute; - z-index: 10; - bottom: 1px; - left: 25px; - } - - .list-group-item:hover .label-info { - display: inline-block; - } -} diff --git a/code/horizon/horizon/static/angular/metadata-tree/metadata-tree.spec.js b/code/horizon/horizon/static/angular/metadata-tree/metadata-tree.spec.js deleted file mode 100644 index 23c051dc..00000000 --- a/code/horizon/horizon/static/angular/metadata-tree/metadata-tree.spec.js +++ /dev/null @@ -1,189 +0,0 @@ -/* jshint globalstrict: true */ -'use strict'; - -describe('hz.widget.metadata-tree module', function() { - it('should have been defined', function () { - expect(angular.module('hz.widget.metadata-tree')).toBeDefined(); - }); - - var namespaces = [ - { - "display_name": "Test Namespace A", - "description": "Test namespace description", - "properties": { - "test:A:1": { - "title": "Test A.1 - string", - "type": "string", - "default": "foo", - "enum": [ - "option-1", "option-2", "option-3" - ] - }, - "test:A:2": { - "title": "Test A.2 - integer", - "type": "integer", - "default": "1", - "minimum": 0, - "maximum": 10 - }, - "test:A:3": { - "title": "Test A.3 - number", - "type": "number", - "default": "1.1", - "minimum": 0, - "maximum": 10 - }, - "test:A:4": { - "title": "Test A.4 - boolean", - "type": "boolean", - "default": "True" - }, - "test:A:5": { - "title": "Test A.5 - boolean", - "type": "boolean", - "default": "false" - }, - "test:A:6": { - "title": "Test A.6 - array", - "type": "array", - "items": { - "type": "string", - "enum": [ - "val-1", "val-2", "val-3", "val-4" - ] - }, - "default": " val-2,val-3" - } - } - }, - { - "display_name": "Test Namespace B", - "description": "Test namespace description", - "objects": [ - { - "name": "Test Object A", - "description": "Test object description", - "properties": { - "test:B:A:1": { - "title": "Test B.A.1", - "description": "Test description" - }, - "test:B:A:2": {} - } - }, - { - "name": "Test Object B", - "description": "Test object description", - "properties": { - "test:B:B:1": {}, - "test:B:B:2": {} - } - } - ] - } - ]; - - describe('directives', function () { - var $scope, $element; - - beforeEach(module('templates')); - beforeEach(module('hz')); - beforeEach(module('hz.widgets')); - beforeEach(module('hz.widget.metadata-tree')); - - describe('hzMetadataTree directive', function() { - beforeEach(inject(function ($injector) { - var $compile = $injector.get('$compile'); - $scope = $injector.get('$rootScope').$new(); - - $scope.available = namespaces; - $scope.existing = {'test:B:A:1':'foo'}; - - var markup = - ''; - - $element = angular.element(markup); - $compile($element)($scope); - $scope.$digest(); - })); - - it('should have 2 rows in available list', function() { - expect($element.find('ul.list-group:first li[ng-repeat]').length).toBe(2); - }); - - it('should have 1 row in existing list', function() { - expect($element.find('ul.list-group:last li[ng-repeat]').length).toBe(1); - expect($element.find('ul.list-group:last li[ng-repeat]:first').scope().item.leaf.name).toBe('test:B:A:1'); - expect($element.find('ul.list-group:last li[ng-repeat]:first').scope().item.leaf.value).toBe('foo'); - }); - - it('should have 10 rows in available list when expanded items', function() { - $element.find('ul.list-group:first li[ng-repeat]:first').trigger('click'); - $element.find('ul.list-group:first li[ng-repeat]:last').trigger('click'); - expect($element.find('ul.list-group:first li[ng-repeat]').length).toBe(10); - }); - - it('should remove item from available and add it in existing list when added', function() { - $element.find('ul.list-group:first li[ng-repeat]:last').trigger('click'); - $element.find('ul.list-group:first li[ng-repeat]:last').trigger('click'); - expect($element.find('ul.list-group:first li[ng-repeat]').length).toBe(6); - $element.find('ul.list-group:first li[ng-repeat]:last .btn').trigger('click'); - expect($element.find('ul.list-group:first li[ng-repeat]').length).toBe(5); - expect($element.find('ul.list-group:last li[ng-repeat]').length).toBe(2); - expect($element.find('ul.list-group:last li[ng-repeat].active').scope().item.leaf.name).toBe('test:B:B:2'); - }); - - it('should add item to available and remove it from existing list when removed', function() { - $element.find('ul.list-group:last li[ng-repeat]:first .btn').trigger('click'); - expect($element.find('ul.list-group:first li[ng-repeat]').length).toBe(6); - expect($element.find('ul.list-group:last li[ng-repeat]').length).toBe(0); - expect($element.find('ul.list-group:first li[ng-repeat].active').scope().item.leaf.name).toBe('test:B:A:1'); - }); - - it('should add custom item to existing list', function() { - $element.find('ul.list-group:first li:first input').val('custom').trigger('input'); - $element.find('ul.list-group:first li:first .btn').trigger('click'); - expect($element.find('ul.list-group:last li[ng-repeat]').length).toBe(2); - expect($element.find('ul.list-group:last li[ng-repeat].active').scope().item.leaf.name).toBe('custom'); - }); - }); - - describe('hzMetadataTreeItem directive', function() { - var $scope, $element, item; - - beforeEach(inject(function ($injector) { - var $compile = $injector.get('$compile'); - $scope = $injector.get('$rootScope').$new(); - - item = new ($injector.get('metadataTreeService').Item)(); - $scope.item = item.fromProperty('test', namespaces[0].properties['test:A:6']); - - var markup = - ''; - - $element = angular.element(markup); - $compile($element)($scope); - $scope.$digest(); - })); - - it('should have additional methods for array ', function () { - expect($element.isolateScope().opened).toBe(false); - expect($element.isolateScope().add).toBeDefined(); - expect($element.isolateScope().remove).toBeDefined(); - expect($element.isolateScope().open).toBeDefined(); - }); - - it('should add values to array ', function () { - $element.find('.options li:last').trigger('click'); - expect(item.leaf.getValue()).toBe(' val-2,val-3,val-4'); - $element.find('.options li:first').trigger('click'); - expect(item.leaf.getValue()).toBe(' val-1,val-2,val-3,val-4'); - }); - - it('should remove value from array ', function () { - $element.find('.values .label:first').trigger('click'); - expect(item.leaf.getValue()).toBe(' val-3'); - }); - }); - }); -}); diff --git a/code/horizon/horizon/static/angular/modal/modal-wait-spinner.js b/code/horizon/horizon/static/angular/modal/modal-wait-spinner.js deleted file mode 100644 index 2c5cf51e..00000000 --- a/code/horizon/horizon/static/angular/modal/modal-wait-spinner.js +++ /dev/null @@ -1,113 +0,0 @@ -/* - * (c) Copyright 2015 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -(function () { - 'use strict'; - -/** - @ngdoc overview - @name hz.widget.modal-wait-spinner - @description - A "global" wait spinner that displays a line of text followed by "...". - - Requires {@link http://angular-ui.github.io/bootstrap/ `Angular-bootstrap`} - - Used when the user must wait before any additional action is possible. Can be launched from modal dialogs. - - @example - -
    -    .controller('MyController', [
    -      '$scope',
    -      'modalWaitSpinnerService',
    -      function (modalWaitSpinnerService) {
    -        $scope.showSpinner = function () {
    -          modalWaitSpinnerService.showModalSpinner(gettext("Loading"));
    -        }
    -        $scope.hideSpinner = function () {
    -          modalWaitSpinnerService.hideModalSpinner();
    -         }
    -      }
    -    ])
    -   
    -
    - - In order to provide a seamless transition to a Horizon that uses more Angular - based pages, the service is currently implemented using the existing - Spin.js library and the corresponding JQuery plugin (jquery.spin.js). This widget looks and feels - the same as the existing spinner we are familiar with in Horizon. Over time, uses of the existing - Horizon spinner ( horizon.modals.modal_spinner() ) can be phased out, or refactored to use this - component. - */ - - angular.module('hz.widget.modal-wait-spinner', [ - 'ui.bootstrap', - ]) - .factory('modalWaitSpinnerService', [ - '$modal', - function ($modal) { - var modalInstance; - - var service = { - showModalSpinner: function (spinnerText) { - var modalOptions = { - backdrop: 'static', - /* - Using
    for wait-spinner instead of a wait-spinner element - because the existing Horizon spinner CSS styling expects a div - for the modal-body - */ - template: '', - windowClass: 'modal-wait-spinner modal_wrapper loading' - }; - this.modalInstance = $modal.open(modalOptions); - }, - - hideModalSpinner: function () { - if (this.modalInstance) { - this.modalInstance.dismiss(); - delete(this.modalInstance); - } - } - }; - - return service; - } - ]) - - .directive('waitSpinner', function () { - - return { - scope: { - text: '@text' // One-direction binding (reads from parent) - }, - restrict: 'A', - link: link, - template: '

    {$text$}…

    ' - }; - - function link($scope, element, attrs) { - element.spin(horizon.conf.spinner_options.modal); - /* - At the time link is executed, element may not have been sized by the browser. - Spin.js may mistakenly places the spinner at 50% of 0 (left:0, top:0). To work around - this, explicitly set 50% left and top to center the spinner in the parent - container - */ - element.find('.spinner').css({'left': '50%', 'top': '50%'}); - } - }); -})(); diff --git a/code/horizon/horizon/static/angular/modal/modal-wait-spinner.scss b/code/horizon/horizon/static/angular/modal/modal-wait-spinner.scss deleted file mode 100644 index 44ec5374..00000000 --- a/code/horizon/horizon/static/angular/modal/modal-wait-spinner.scss +++ /dev/null @@ -1,22 +0,0 @@ -/* - * (c) Copyright 2015 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -/* - * Disable the Angular Bootstrap slide in animation for wait spinner modals - */ -.modal-wait-spinner.modal.fade .modal-dialog, .modal.in .modal-dialog { - transform: translate(0, 0); -} \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/modal/modal-wait-spinner.spec.js b/code/horizon/horizon/static/angular/modal/modal-wait-spinner.spec.js deleted file mode 100644 index f8d5b48c..00000000 --- a/code/horizon/horizon/static/angular/modal/modal-wait-spinner.spec.js +++ /dev/null @@ -1,98 +0,0 @@ -/* - * (c) Copyright 2015 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -(function() { - "use strict"; - - describe('Wait Spinner Tests', function() { - - var service, modal; - - beforeEach(module('hz.widget.modal-wait-spinner')); - - beforeEach(inject(function(modalWaitSpinnerService, $modal) { - service = modalWaitSpinnerService; - modal = $modal; - })); - - it('returns the service', function() { - expect(service).toBeDefined(); - }); - - describe('showModalSpinner', function() { - - it('is defined', function() { - expect(service.showModalSpinner).toBeDefined(); - }); - - it('opens modal with the correct object', inject(function($modal) { - var wanted = { backdrop: 'static', - template: '', - windowClass: 'modal-wait-spinner modal_wrapper loading' - }; - spyOn($modal, 'open'); - service.showModalSpinner('my text'); - expect($modal.open).toHaveBeenCalled(); - expect($modal.open.calls.count()).toBe(1); - expect($modal.open.calls.argsFor(0)).toEqual([wanted]); - })); - - }); - - describe('hideModalSpinner', function() { - - it('has hideModalSpinner', function() { - expect(service.hideModalSpinner).toBeDefined(); - }); - - it("dismisses modal when it has been opened", inject(function($modal) { - var modal = {dismiss: function() {}}; - spyOn($modal, 'open').and.returnValue(modal); - service.showModalSpinner('asdf'); - spyOn(modal, 'dismiss'); - service.hideModalSpinner(); - expect(modal.dismiss).toHaveBeenCalled(); - })); - - }); - - }); - - describe('Wait Spinner Directive', function() { - var $scope, $element, $timeout; - - beforeEach(module('ui.bootstrap')); - beforeEach(module('hz.widget.modal-wait-spinner')); - - beforeEach(inject(function($injector) { - var $compile = $injector.get('$compile'); - $scope = $injector.get('$rootScope').$new(); - $timeout = $injector.get('$timeout'); - - var markup = '
    '; - $element = angular.element(markup); - $compile($element)($scope); - - $scope.$digest(); - })); - - it("creates a p element", function() { - var elems = $element.find('p'); - expect(elems.length).toBe(1); - }); - - }); - -})(); diff --git a/code/horizon/horizon/static/angular/modal/modal.js b/code/horizon/horizon/static/angular/modal/modal.js deleted file mode 100644 index 22fe98bb..00000000 --- a/code/horizon/horizon/static/angular/modal/modal.js +++ /dev/null @@ -1,95 +0,0 @@ -(function() { - 'use strict'; - - /** - * @ngdoc overview - * @name hz.widget.modal - * - * # hz.widget.modal - * - * The `hz.widget.modal` provides modal services. - * - * Requires {@link http://angular-ui.github.io/bootstrap/ `Angular-bootstrap`} - * - * | Components | - * |--------------------------------------------------------------------------| - * | {@link hz.widget.modal.controller:simpleModalCtrl `simpleModalCtrl`} | - * | {@link hz.widget.modal.factory:simpleModalService `simpleModalService`} | - * - */ - angular.module('hz.widget.modal', ['ui.bootstrap']) - - /** - * @ngdoc controller - * @name simpleModalCtrl - * - * @param(object) scope of the controller - * @param(object) modal instance from angular-bootstrap - * @param(object) context object provided by the user - * - * @description - * Horizon's controller for confirmation dialog. - * Passes context along to the template. - * If user presses cancel button or closes dialog, modal gets dismissed. - * If user presses submit button, modal gets closed. - * This controller is automatically included in modalService. - */ - .controller('simpleModalCtrl', [ '$scope', '$modalInstance', 'context', - function($scope, $modalInstance, context) { - $scope.context = context; - $scope.submit = function(){ $modalInstance.close(); }; - $scope.cancel = function(){ $modalInstance.dismiss('cancel'); }; - } // end of function - ]) // end of controller - - /** - * @ngdoc service - * @name simpleModalService - * - * @description - * Horizon's wrapper for angular-bootstrap modal service. - * It should only be use for small confirmation dialogs. - * @param {object} the object containing title, body, submit, and cancel labels - * @param {object} the object returned from angular-bootstrap $modal - * - * @example: - * angular.controller('modalExampleCtrl', [ '$scope', 'simpleModalService', - * function($scope, simpleModalService){ - * var options = { - * title: 'Confirm Delete', - * body: 'Are you sure you want to delete this item?', - * submit: 'Yes', - * cancel: 'No', - * }; - * simpleModalService(options).result.then(function(){ - * // user clicked on submit button - * // do something useful here - * }); - * } - * ]); - */ - .factory('simpleModalService', ['$modal', 'basePath', - function($modal, path) { - return function(params) { - if (params && params.title && params.body){ - var options = { - controller: 'simpleModalCtrl', - templateUrl: path + 'modal/simple-modal.html', - resolve: { - context: function() { - return { - title: params.title, - body: params.body, - submit: params.submit || gettext('Submit'), - cancel: params.cancel || gettext('Cancel') - }; - } - } - }; - return $modal.open(options); - } - }; // end of return - } // end of function - ]); // end of factory - -})(); diff --git a/code/horizon/horizon/static/angular/modal/modal.spec.js b/code/horizon/horizon/static/angular/modal/modal.spec.js deleted file mode 100644 index 7f40c4a0..00000000 --- a/code/horizon/horizon/static/angular/modal/modal.spec.js +++ /dev/null @@ -1,167 +0,0 @@ -/* - * (c) Copyright 2015 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -(function() { - "use strict"; - - describe('hz.widget.modal module', function() { - - beforeEach(module('hz.widget.modal')); - - describe('simpleModalCtrl', function() { - var scope, modalInstance, context, ctrl; - - beforeEach(inject(function($controller) { - scope = {}; - modalInstance = { - close: function() {}, - dismiss: function() {} - }; - context = { what: 'is it' }; - ctrl = $controller('simpleModalCtrl', - {$scope: scope, $modalInstance: modalInstance, - context: context}); - })); - - it('establishes a controller', function() { - expect(ctrl).toBeDefined(); - }); - - it('sets context on the scope', function() { - expect(scope.context).toBeDefined(); - expect(scope.context).toEqual({ what: 'is it' }); - }); - - it('sets action functions', function() { - expect(scope.submit).toBeDefined(); - expect(scope.cancel).toBeDefined(); - }); - - it('makes submit close the modal instance', function() { - expect(scope.submit).toBeDefined(); - spyOn(modalInstance, 'close'); - scope.submit(); - expect(modalInstance.close.calls.count()).toBe(1); - }); - - it('makes cancel close the modal instance', function() { - expect(scope.cancel).toBeDefined(); - spyOn(modalInstance, 'dismiss'); - scope.cancel(); - expect(modalInstance.dismiss).toHaveBeenCalledWith('cancel'); - }); - - }); - - describe('simpleModalService', function() { - var service, modal; - - beforeEach(module(function($provide) { - modal = { open: function() {return 'val';} }; - $provide.value('basePath', '/this/path/'); - $provide.value('$modal', modal); - })); - - beforeEach(inject(function(simpleModalService) { - service = simpleModalService; - })); - - it('defines the service', function() { - expect(service).toBeDefined(); - }); - - it('returns undefined if called with no parameters', function() { - expect(service()).toBeUndefined(); - }); - - it('returns undefined if called without required parameters', function() { - expect(service({title: {}})).toBeUndefined(); - expect(service({body: {}})).toBeUndefined(); - }); - - describe('Maximal Values Passed to the Modal', function() { - - var returned, passed, passedContext; - - beforeEach(function() { - var opts = { title: 'my title', body: 'my body', submit: 'Yes', - cancel: 'No' }; - spyOn(modal, 'open'); - returned = service(opts); - passed = modal.open.calls.argsFor(0)[0]; - passedContext = passed.resolve.context(); - }); - - it('sets the controller', function() { - expect(passed.controller).toBe('simpleModalCtrl'); - }); - - it('sets the template URL', function() { - expect(passed.templateUrl).toBe('/this/path/modal/simple-modal.html'); - }); - - it('sets the title', function() { - expect(passedContext.title).toBe('my title'); - }); - - it('sets the body', function() { - expect(passedContext.body).toBe('my body'); - }); - - it('sets the submit', function() { - expect(passedContext.submit).toBe('Yes'); - }); - - it('sets the cancel', function() { - expect(passedContext.cancel).toBe('No'); - }); - - }); - - describe('Minimal Values Passed to the Modal', function() { - - var returned, passed, passedContext; - - beforeEach(function() { - var opts = { title: 'my title', body: 'my body' }; - spyOn(modal, 'open'); - returned = service(opts); - passed = modal.open.calls.argsFor(0)[0]; - passedContext = passed.resolve.context(); - }); - - it('sets the title', function() { - expect(passedContext.title).toBe('my title'); - }); - - it('sets the body', function() { - expect(passedContext.body).toBe('my body'); - }); - - it('defaults the submit', function() { - expect(passedContext.submit).toBe('Submit'); - }); - - it('defaults the cancel', function() { - expect(passedContext.cancel).toBe('Cancel'); - }); - - }); - - }); - - }); - -})(); diff --git a/code/horizon/horizon/static/angular/modal/simple-modal.html b/code/horizon/horizon/static/angular/modal/simple-modal.html deleted file mode 100644 index 39904f39..00000000 --- a/code/horizon/horizon/static/angular/modal/simple-modal.html +++ /dev/null @@ -1,18 +0,0 @@ - - - \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/styles.scss b/code/horizon/horizon/static/angular/styles.scss deleted file mode 100644 index e074878d..00000000 --- a/code/horizon/horizon/static/angular/styles.scss +++ /dev/null @@ -1,11 +0,0 @@ -@import "help-panel/help-panel"; -@import "wizard/wizard"; -@import "table/table"; -@import "transfer-table/transfer-table"; -@import "charts/chart-tooltip"; -@import "charts/pie-chart"; -@import "action-list/action-list"; -@import "modal/modal-wait-spinner"; -@import "metadata-tree/metadata-tree"; -@import "metadata-display/metadata-display"; -@import "magic-search/magic-search.scss"; diff --git a/code/horizon/horizon/static/angular/table/basic-table.js b/code/horizon/horizon/static/angular/table/basic-table.js deleted file mode 100644 index 0bf41a2f..00000000 --- a/code/horizon/horizon/static/angular/table/basic-table.js +++ /dev/null @@ -1,61 +0,0 @@ -(function() { - 'use strict'; - - angular.module('hz.widget.table') - - .constant('FILTER_PLACEHOLDER_TEXT', gettext('Filter')) - /** - * @ngdoc directive - * @name hz.widget.table.directive:searchBar - * @element - * @param {string} {array} groupClasses Input group classes (optional) - * @param {string} {array} iconClasses Icon classes (optional) - * @param {string} {array} inputClasses Search field classes (optional) - * @param {string} placeholder input field placeholder text (optional) - * @description - * The `searchBar` directive generates a search field that will - * trigger filtering of the associated Smart-Table. - * - * groupClasses - classes that should be applied to input group element - * iconClasses - classes that should be applied to search icon - * inputClasses - classes that should be applied to search input field - * placeholder - text that will be used for a placeholder attribute - * - * @restrict E - * - * @example - * ``` - * - * - * ``` - */ - .directive('searchBar', [ 'FILTER_PLACEHOLDER_TEXT', 'basePath', - function(FILTER_PLACEHOLDER_TEXT, path) { - return { - restrict: 'E', - templateUrl: path + 'table/search-bar.html', - transclude: true, - link: function (scope, element, attrs, ctrl, transclude) { - if (angular.isDefined(attrs.groupClasses)) { - element.find('.input-group').addClass(attrs.groupClasses); - } - if (angular.isDefined(attrs.iconClasses)) { - element.find('.fa').addClass(attrs.iconClasses); - } - var searchInput = element.find('[st-search]'); - - if (angular.isDefined(attrs.inputClasses)) { - searchInput.addClass(attrs.inputClasses); - } - var placeholderText = attrs.placeholder || FILTER_PLACEHOLDER_TEXT; - searchInput.attr('placeholder', placeholderText); - - transclude(scope, function(clone){ - element.find('.input-group').append(clone); - }); - } - }; - }]); - -}()); \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/table/basic-table.spec.js b/code/horizon/horizon/static/angular/table/basic-table.spec.js deleted file mode 100644 index 0cbab6b3..00000000 --- a/code/horizon/horizon/static/angular/table/basic-table.spec.js +++ /dev/null @@ -1,61 +0,0 @@ -(function() { - 'use strict'; - - describe('search bar directive', function() { - - var $scope, $element; - - beforeEach(module('templates')); - beforeEach(module('smart-table')); - beforeEach(module('hz')); - beforeEach(module('hz.widgets')); - beforeEach(module('hz.widget.table')); - - describe('search bar', function() { - - beforeEach(inject(function($injector) { - var $compile = $injector.get('$compile'); - $scope = $injector.get('$rootScope').$new(); - - $scope.rows = []; - - var markup = '' + - '' + - ' ' + - ' ' + - ' ' + - '' + - '' + - '
    ' + - ' ' + - ' ' + - '
    '; - - $element = angular.element(markup); - $compile($element)($scope); - - $scope.$digest(); - })); - - it('should have a text field', function() { - expect($element.find('input[st-search]').length).toBe(1); - }); - - it('should have a search icon', function() { - expect($element.find('.input-group-addon .fa-search').length).toBe(1); - }); - - it('should have a "input-group-sm" class on input group', function() { - expect($element.find('.input-group.input-group-sm').length).toBe(1); - }); - - it('should have default placeholder text set to "Filter"', function() { - expect($element.find('input[st-search]').attr('placeholder')).toEqual('Filter'); - }); - - }); - - }); - -})(); \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/table/search-bar.html b/code/horizon/horizon/static/angular/table/search-bar.html deleted file mode 100644 index fa676b3b..00000000 --- a/code/horizon/horizon/static/angular/table/search-bar.html +++ /dev/null @@ -1,8 +0,0 @@ - \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/table/table.js b/code/horizon/horizon/static/angular/table/table.js deleted file mode 100644 index 55b14eb3..00000000 --- a/code/horizon/horizon/static/angular/table/table.js +++ /dev/null @@ -1,340 +0,0 @@ -/* jshint globalstrict: true */ -(function() { - 'use strict'; - - /** - * @ngdoc overview - * @name hz.widget.table - * @description - * - * # hz.widget.table - * - * The `hz.widget.table` provides support for user interactions and checkbox - * selection in tables. - * - * Requires {@link https://github.com/lorenzofox3/Smart-Table `Smart-Table`} - * module and jQuery (for table drawer slide animation in IE9) to be installed. - * - * | Directives | - * |-------------------------------------------------------------------| - * | {@link hz.widget.table.directive:hzTable `hzTable`} | - * | {@link hz.widget.table.directive:hzSelect `hzSelect`} | - * | {@link hz.widget.table.directive:hzSelectAll `hzSelectAll`} | - * | {@link hz.widget.table.directive:hzExpandDetail `hzExpandDetail`} | - * - */ - var app = angular.module('hz.widget.table', [ 'smart-table', 'lrDragNDrop' ]); - - /** - * @ngdoc parameters - * @name hz.widget.table.constant:expandSettings - * @param {string} expandIconClasses Icon classes to be used for expand icon - * @param {number} duration The slide down animation duration/speed - */ - app.constant('expandSettings', { - expandIconClasses: 'fa-chevron-right fa-chevron-down', - duration: 100 - }); - - /** - * @ngdoc directive - * @name hz.widget.table.directive:hzTable - * @element table st-table='rowCollection' - * @description - * The `hzTable` directive extends the Smart-Table module to provide - * support for saving the checkbox selection state of each row in the - * table. A default sort key can be specified to sort the table - * initially by this key. To reverse, add default-sort-reverse='true' - * as well. - * - * Required: Use `st-table` attribute to pass in the displayed - * row collection and `st-safe-src` attribute to pass in the - * safe row collection. - * - * @restrict A - * @scope true - * @example - * - * ``` - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    - * - * Name
    - * - * Foo
    - * ``` - * - */ - app.directive('hzTable', function() { - return { - restrict: 'A', - require: 'stTable', - scope: true, - controller: function($scope) { - $scope.selected = {}; - $scope.numSelected = 0; - - // return true if the row is selected - this.isSelected = function(row) { - var rowState = $scope.selected[row.id]; - return angular.isDefined(rowState) && rowState.checked; - }; - - // set the row selection state - this.select = function(row, checkedState, broadcast) { - $scope.selected[row.id] = { - checked: checkedState, - item: row - }; - - if (checkedState) { - $scope.numSelected++; - } else { - $scope.numSelected--; - } - - if (broadcast) { - // should only walk down scope tree that has - // matching event bindings - var rowObj = { row: row, checkedState: checkedState }; - $scope.$broadcast('hzTable:rowSelected', rowObj); - } - }; - }, - link: function(scope, element, attrs, stTableCtrl) { - if (attrs.defaultSort) { - var reverse = attrs.defaultSortReverse === 'true'; - stTableCtrl.sortBy(attrs.defaultSort, reverse); - } - } - }; - }); - - /** - * @ngdoc directive - * @name hz.widget.table.directive:hzSelect - * @element input type='checkbox' - * @description - * The `hzSelect` directive updates the checkbox selection state of - * the specified row in the table. Assign this as an attribute to a - * checkbox input element, passing in the row. - * - * @restrict A - * @scope - * @example - * - * ``` - * - * - * - * - * - * ``` - * - */ - app.directive('hzSelect', [ function() { - return { - restrict: 'A', - require: '^hzTable', - scope: { - row: '=hzSelect' - }, - link: function (scope, element, attrs, hzTableCtrl) { - // select or unselect row - function clickHandler() { - scope.$apply(function() { - scope.$evalAsync(function() { - var checkedState = element.prop('checked'); - hzTableCtrl.select(scope.row, checkedState, true); - }); - }); - } - - element.click(clickHandler); - } - }; - }]); - - /** - * @ngdoc directive - * @name hz.widget.table.directive:hzSelectAll - * @element input type='checkbox' - * @description - * The `hzSelectAll` directive updates the checkbox selection state of - * every row in the table. Assign this as an attribute to a checkbox - * input element, passing in the displayed row collection data. - * - * Required: Use `st-table` attribute to pass in the displayed - * row collection and `st-safe-src` attribute to pass in the - * safe row collection. - * - * Define a `ng-model` attribute on the individual row checkboxes - * so that they will be updated when the select all checkbox is - * clicked. The `hzTable` controller provides a `selected` object - * which stores the checked state of the row. - * - * @restrict A - * @scope - * @example - * - * ``` - * - * - * - * - * - * - * - * - * - * - * - * - * ``` - * - */ - app.directive('hzSelectAll', [ function() { - return { - restrict: 'A', - require: [ '^hzTable', '^stTable' ], - scope: { - rows: '=hzSelectAll' - }, - link: function(scope, element, attrs, ctrls) { - var hzTableCtrl = ctrls[0]; - var stTableCtrl = ctrls[1]; - - // select or unselect all - function clickHandler() { - scope.$apply(function() { - scope.$evalAsync(function() { - var checkedState = element.prop('checked'); - angular.forEach(scope.rows, function(row) { - var selected = hzTableCtrl.isSelected(row); - if (selected !== checkedState) { - hzTableCtrl.select(row, checkedState); - } - }); - }); - }); - } - - // update the select all checkbox when table - // state changes (sort, filter, paginate) - function updateSelectAll() { - var visibleRows = scope.rows; - var checkedCnt = visibleRows.filter(hzTableCtrl.isSelected).length; - element.prop('checked', visibleRows.length === checkedCnt); - } - - element.click(clickHandler); - - // watch the table state for changes - // on sort, filter and pagination - scope.$watch(function() { - return stTableCtrl.tableState(); - }, - updateSelectAll, - true - ); - - // watch the row length for add/removed rows - scope.$watch('rows.length', updateSelectAll); - - // watch for row selection - scope.$on('hzTable:rowSelected', updateSelectAll); - } - }; - }]); - - /** - * @ngdoc directive - * @name hz.widget.table.directive:hzExpandDetail - * @element i class='fa fa-chevron-right' - * @param {number} duration The duration for drawer slide animation - * @description - * The `hzExpandDetail` directive toggles the detailed drawer of the row. - * The animation is implemented using jQuery's slideDown() and slideUp(). - * Assign this as an attribute to an icon that should trigger the toggle, - * passing in the two class names of the icon. If no class names are - * specified, the default 'fa-chevron-right fa-chevron-down' is used. A - * duration for the slide animation can be specified as well (default: 400). - * The detail drawer row and cell also needs to be implemented and include - * the classes 'detail-row' and 'detail', respectively. - * - * @restrict A - * @scope icons: '@hzExpandDetail', duration: '@' - * @example - * - * ``` - * - * - * - * - * - * - * - * - * ``` - * - */ - app.directive('hzExpandDetail', [ 'expandSettings', function(settings) { - return { - restrict: 'A', - scope: { - icons: '@hzExpandDetail', - duration: '@' - }, - link: function(scope, element) { - element.on('click', function() { - var iconClasses = scope.icons || settings.expandIconClasses; - element.toggleClass(iconClasses); - - var summaryRow = element.closest('tr'); - var detailCell = summaryRow.next('tr').find('.detail'); - var duration = scope.duration ? parseInt(scope.duration) : settings.duration; - - if (summaryRow.hasClass('expanded')) { - var options = { - duration: duration, - complete: function() { - // Hide the row after the slide animation finishes - summaryRow.toggleClass('expanded'); - } - }; - - detailCell.find('.detail-expanded').slideUp(options); - } else { - summaryRow.toggleClass('expanded'); - - if (detailCell.find('.detail-expanded').length === 0) { - // Slide down animation doesn't work on table cells - // so a
    wrapper needs to be added - detailCell.wrapInner('
    '); - } - - detailCell.find('.detail-expanded').slideDown(duration); - } - }); - } - }; - }]); - -})(); diff --git a/code/horizon/horizon/static/angular/table/table.scss b/code/horizon/horizon/static/angular/table/table.scss deleted file mode 100644 index 61f2c9df..00000000 --- a/code/horizon/horizon/static/angular/table/table.scss +++ /dev/null @@ -1,355 +0,0 @@ -$em-per-priority: floor($table-col-avg-width / $font-size-base) * 3; - -[hz-table] { - td.action-col { - .popover { - min-width: 15em; - } - } - - .detail-row td { - display: none; - - &.detail .detail-expanded { - display: none; - } - } - - .expanded + tr td { - display: table-cell; - } - - .fa { - cursor: pointer; - } - - .invalid { - color: $invalid-color; - } - - .no-rows-help { - font-style: italic; - font-weight: normal; - text-align: center; - } - - .reorder { - min-width: 4em; - max-width: 4em; - width: 4em; - } - - .search-header { - padding: 0; - - .btn-addon { - display: table-cell; - padding-left: 0.3em; - vertical-align: top; - width: 1%; - } - - .basic-search-bar { - margin-bottom: 0.2em; - width: 100%; - - .input-group-sm .form-control:not(:first-child):not(:last-child) { - border-top-right-radius: 3px; - border-bottom-right-radius: 3px; - } - - input[type="text"] { - @include input-placeholder { - font-weight: normal; - color: $placeholder-text-color; - } - } - } - - .search-help { - color: $transfer-help-text-color; - font-size: 0.9em; - font-style: italic; - font-weight: 400; - margin: 0.2em 0.3em 0; - visibility: hidden; - - &.searching { - visibility: visible; - } - } - } -} - -.table-rsp { - border-collapse: separate; - border-spacing: 0 $table-gap-height; - width: 100%; - - thead tr th, tfoot tr td { - background: none; - border: none; - padding: $table-padding; - } - - tbody tr { - &[lr-drag-src] td:not(.expander) { - cursor: move; - } - - &.lr-drop-target-before td { - border-top: $reorder-border !important; - } - - &.lr-drop-target-after td { - border-bottom: $reorder-border !important; - } - - td { - background-color: #ffffff; - border-top: $table-border; - border-bottom: $table-border; - padding: $table-padding; - position: relative; - white-space: nowrap; - - &:first-child, &.action-col { - border-left: $table-border; - } - - &:last-child, &.select-col { - border-right: $table-border; - } - } - } - - .select-col { - max-width: $select-col-width; - text-align: center; - width: $select-col-width; - } - - .action-col { - position: relative; - text-align: right; - vertical-align: top; - min-width: $batch-action-width; - width: $batch-action-width; - } - - .numeric { - text-align: right; - } - - [st-sort] { - cursor: pointer; - - &:after { - color: #d4d4d4; - content: '\f0dc'; - font-family: 'FontAwesome'; - margin-left: 0.5em; - opacity: 0; - } - - &:not(.st-sort-ascent):hover:after, &:not(.st-sort-descent):hover:after { - opacity: 1; - } - } - - .st-sort-ascent:after { - color: #000000; - content: '\f0dd'; - font-family: 'FontAwesome'; - margin-left: 0.5em; - opacity: 1; - } - - .st-sort-descent:after { - color: #000000; - content: '\f0de'; - font-family: 'FontAwesome'; - margin-left: 0.5em; - opacity: 1; - } - - &.modern { - border-spacing: 0; - - tbody tr { - td { - border: none; - border-top: $table-border; - } - - &:last-child td { - border-bottom: $table-border; - } - } - } - - &.table-detail { - border-spacing: 0; - - tbody { - tr td { - border-bottom: none; - } - - tr:last-child:not(.spacer-row) td { - border-bottom: $table-border; - } - - tr.expanded td { - border-bottom: $table-border; - - &[rowspan='2'].action-col { - border-bottom: none; - } - } - - tr.expanded:nth-last-child(-n+3) [rowspan='2'].action-col { - border-bottom: $table-border; - } - - tr:nth-last-child(2):not(.expanded) td { - border-bottom: $table-border; - } - - tr:nth-last-child(3).expanded + .detail-row + tr.spacer-row td { - border-top: none; - } - - tr + .detail-row + tr.spacer-row td { - border-top: $table-border; - } - } - - .detail-row td { - padding: 0; - - &.detail .detail-expanded { - border-top: none; - padding: $detail-row-padding $table-padding; - white-space: normal; - } - } - - .expanded + tr td { - border-top: none; - } - - .expander { - cursor: pointer; - max-width: $expander-width; - width: $expander-width; - } - - .spacer-row td { - background-color: inherit; - border: none; - height: $table-gap-height; - padding: 0; - position: relative; - } - - &.table-striped { - tbody { - tr { - &:nth-child(2n+1) > td, &:nth-child(2n+1) + .detail-row > td { - background-color: $table-stripe-bgcolor; - } - - &.spacer-row > td, &.spacer-row:nth-child(6n+3) + tr + tr.detail-row td, - &.detail-row:nth-child(4n+2) + tr:not(.spacer-row) td, - &.detail-row:nth-child(4n+2) + tr:not(.spacer-row) + tr.detail-row td { - background-color: transparent; - } - } - } - } - - &.modern { - .expanded + tr td { - border-top: $table-border; - } - - .expanded { - td:not(.action-col), td.action-col:not([rowspan='2']) { - border-bottom: none; - } - } - } - } - - @media only all { - .rsp-p1, .rsp-p2, - .rsp-p3, .rsp-p4 { - display: none; - } - - .rsp-alt-p1, .rsp-alt-p2, - .rsp-alt-p3, .rsp-alt-p4 { - display: inline-block; - } - } - - @media (min-width: 0em) { - $content-width: $body-min-width - $sidebar-width - (2 * $content-body-padding); - $max-priority: floor($content-width / $font-size-base / $em-per-priority); - - @for $i from 1 through $max-priority { - .rsp-p#{$i} { - display: table-cell; - } - - .rsp-alt-p#{$i} { - display: none; - } - } - } - - $p1-width: 5em + $em-per-priority * 1em; - @media (min-width: $p1-width) { - .rsp-p1 { - display: table-cell; - } - - .rsp-alt-p1 { - display: none; - } - } - - $p2-width: 5em + $em-per-priority * 2em; - @media (min-width: $p2-width) { - .rsp-p2 { - display: table-cell; - } - - .rsp-alt-p2 { - display: none; - } - } - - $p3-width: 5em + $em-per-priority * 3em; - @media (min-width: $p3-width) { - .rsp-p3 { - display: table-cell; - } - - .rsp-alt-p3 { - display: none; - } - } - - $p4-width: 5em + $em-per-priority * 4em; - @media (min-width: $p4-width) { - .rsp-p4 { - display: table-cell; - } - - .rsp-alt-p4 { - display: none; - } - } -} \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/table/table.spec.js b/code/horizon/horizon/static/angular/table/table.spec.js deleted file mode 100644 index 92b214fc..00000000 --- a/code/horizon/horizon/static/angular/table/table.spec.js +++ /dev/null @@ -1,238 +0,0 @@ -/* jshint browser: true */ -(function() { - 'use strict'; - - describe('hz.widget.table module', function() { - it('should have been defined', function () { - expect(angular.module('hz.widget.table')).toBeDefined(); - }); - }); - - describe('table directives', function () { - - var $scope, $element; - - beforeEach(module('smart-table')); - beforeEach(module('hz')); - beforeEach(module('hz.widgets')); - beforeEach(module('hz.widget.table')); - - beforeEach(inject(function($injector) { - var $compile = $injector.get('$compile'); - $scope = $injector.get('$rootScope').$new(); - - $scope.safeFakeData = [ - { id: '1', animal: 'cat' }, - { id: '2', animal: 'dog' }, - { id: '3', animal: 'fish' } - ]; - - $scope.fakeData = []; - - var markup = - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '
    Animal
    {{ row.animal }}
    '; - - $element = angular.element(markup); - $compile($element)($scope); - - $scope.$digest(); - })); - - describe('hzTable directive', function() { - - it('should have 3 summary rows', function() { - expect($element.find('tbody tr[ng-repeat-start]').length).toBe(3); - }); - - it('should have 3 detail rows', function() { - expect($element.find('tbody tr.detail-row').length).toBe(3); - }); - - it('should have each checkbox initially unchecked', function() { - var checkboxes = $element.find('input[hz-select]'); - angular.forEach(checkboxes, function(checkbox) { - expect(checkbox.checked).toBe(false); - }); - }); - - it('should return false when calling isSelected for each row', function() { - var hzTableCtrl = $element.controller('hzTable'); - angular.forEach($scope.safeFakeData, function(row) { - expect(hzTableCtrl.isSelected(row)).toBe(false); - }); - }); - - it('should update selected and numSelected when select called', function() { - var hzTableCtrl = $element.controller('hzTable'); - var firstRow = $scope.safeFakeData[0]; - hzTableCtrl.select(firstRow, true); - - var hzTableScope = $element.scope(); - expect(hzTableScope.selected[firstRow.id]).toBeDefined(); - expect(hzTableScope.numSelected).toBe(1); - }); - - }); - - describe('hzSelect directive', function() { - var checkboxes; - - beforeEach(function() { - checkboxes = $element.find('input[hz-select]'); - }); - - it('should have numSelected === 1 when first checkbox is clicked', function() { - var checkbox = checkboxes.first(); - checkbox[0].checked = true; - checkbox.triggerHandler('click'); - - expect($element.scope().numSelected).toBe(1); - }); - - it('should have numSelected === 0 when first checkbox is clicked, then unclicked', function() { - var checkbox = checkboxes.first(); - checkbox[0].checked = true; - checkbox.triggerHandler('click'); - - expect($element.scope().numSelected).toBe(1); - - checkbox[0].checked = false; - checkbox.triggerHandler('click'); - - expect($element.scope().numSelected).toBe(0); - }); - - it('should have numSelected === 3 and select-all checked when all rows selected', function() { - angular.forEach(checkboxes, function(checkbox) { - checkbox.checked = true; - angular.element(checkbox).triggerHandler('click'); - }); - - expect($element.scope().numSelected).toBe(3); - expect($element.find('input[hz-select-all]')[0].checked).toBe(true); - }); - - it('should have select-all unchecked when all rows selected, then one deselected', function() { - angular.forEach(checkboxes, function(checkbox) { - checkbox.checked = true; - angular.element(checkbox).triggerHandler('click'); - }); - - // all checkboxes selected so check-all should be checked - expect($element.scope().numSelected).toBe(3); - expect($element.find('input[hz-select-all]')[0].checked).toBe(true); - - // deselect one checkbox - var firstCheckbox = checkboxes.first(); - firstCheckbox[0].checked = false; - firstCheckbox.triggerHandler('click'); - - // check-all should be unchecked - expect($element.scope().numSelected).toBe(2); - expect($element.find('input[hz-select-all]')[0].checked).toBe(false); - }); - - }); - - describe('hzSelectAll directive', function() { - - it('should select all checkboxes if select-all checked', function() { - var selectAll = $element.find('input[hz-select-all]').first(); - selectAll[0].checked = true; - selectAll.triggerHandler('click'); - - expect($element.scope().numSelected).toBe(3); - var checkboxes = $element.find('tbody input[hz-select]'); - angular.forEach(checkboxes, function(checkbox) { - expect(checkbox.checked).toBe(true); - }); - }); - - it('should deselect all checkboxes if select-all checked, then unchecked', function() { - var selectAll = $element.find('input[hz-select-all]').first(); - selectAll[0].checked = true; - selectAll.triggerHandler('click'); - - var checkboxes = $element.find('tbody input[hz-select]'); - - expect($element.scope().numSelected).toBe(3); - angular.forEach(checkboxes, function(checkbox) { - expect(checkbox.checked).toBe(true); - }); - - selectAll[0].checked = false; - selectAll.triggerHandler('click'); - - expect($element.scope().numSelected).toBe(0); - angular.forEach(checkboxes, function(checkbox) { - expect(checkbox.checked).toBe(false); - }); - }); - - it('should select all checkboxes if select-all checked with one row selected', function() { - // select the first checkbox - var checkbox = $element.find('input[hz-select]').first(); - checkbox[0].checked = true; - checkbox.triggerHandler('click'); - - // now click select-all checkbox - var selectAll = $element.find('input[hz-select-all]').first(); - selectAll[0].checked = true; - selectAll.triggerHandler('click'); - - expect($element.scope().numSelected).toBe(3); - var checkboxes = $element.find('tbody input[hz-select]'); - angular.forEach(checkboxes, function(checkbox) { - expect(checkbox.checked).toBe(true); - }); - }); - - }); - - describe('hzExpandDetail directive', function() { - - it('should have summary row with class "expanded" when expanded', function() { - var expandIcon = $element.find('i.fa').first(); - expandIcon.click(); - - var summaryRow = expandIcon.closest('tr'); - expect(summaryRow.hasClass('expanded')).toBe(true); - }); - - it('should have summary row without class "expanded" when not expanded', function(done) { - var expandIcon = $element.find('i.fa').first(); - - // Click twice to mock expand and collapse - expandIcon.click(); - expandIcon.click(); - - // Wait for the slide down animation to complete before test - setTimeout(function() { - var summaryRow = expandIcon.closest('tr'); - expect(summaryRow.hasClass('expanded')).toBe(false); - done(); - }, 2000); - }); - - }); - }); -}()); \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/transfer-table/allocated.html.example b/code/horizon/horizon/static/angular/transfer-table/allocated.html.example deleted file mode 100644 index a540d7e1..00000000 --- a/code/horizon/horizon/static/angular/transfer-table/allocated.html.example +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    NameVCPUsRAMTotal DiskRoot DiskEphemeral DiskPublic
    -
    - {$ ::trCtrl.helpText.noneAllocText $} -
    -
    - - {$ row.name $}{$ row.vcpus $}{$ row.ram $}{$ row.totalDisk $}{$ row.rootDisk $}{$ row.ephemeralDisk $}{$ row.isPublic $} - - - - - -
    -
      -
    • Name: {$ row.name $}
    • -
    • Name: {$ row.vcpus $}
    • -
    • Name: {$ row.ram $}
    • -
    • Name: {$ row.totalDisk $}
    • -
    • Name: {$ row.rootDisk $}
    • -
    • Name: {$ row.ephemeralDisk $}
    • -
    • Name: {$ row.isPublic $}
    • -
    -
    \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/transfer-table/available.html.example b/code/horizon/horizon/static/angular/transfer-table/available.html.example deleted file mode 100644 index c82df82d..00000000 --- a/code/horizon/horizon/static/angular/transfer-table/available.html.example +++ /dev/null @@ -1,86 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    - - -
    NameVCPUsRAMTotal DiskRoot DiskEphemeral DiskPublic
    -
    - {$ ::trCtrl.helpText.noneAvailText $} -
    -
    - - {$ row.name $} - - {$ row.vcpus $} - - - {$ row.ram $} - {$ row.totalDisk $}{$ row.rootDisk $}{$ row.ephemeralDisk $}{$ row.isPublic $} - - - - - - - - -
    -
      -
    • Name: {$ row.name $}
    • -
    • Name: {$ row.vcpus $}
    • -
    • Name: {$ row.ram $}
    • -
    • Name: {$ row.totalDisk $}
    • -
    • Name: {$ row.rootDisk $}
    • -
    • Name: {$ row.ephemeralDisk $}
    • -
    • Name: {$ row.isPublic $}
    • -
    -
    \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/transfer-table/transfer-table.html b/code/horizon/horizon/static/angular/transfer-table/transfer-table.html deleted file mode 100644 index 22e7f276..00000000 --- a/code/horizon/horizon/static/angular/transfer-table/transfer-table.html +++ /dev/null @@ -1,48 +0,0 @@ -
    - -
    - -
    - - {$ ::trCtrl.helpText.allocTitle $} - {$ trCtrl.numAllocated() $} - - {$ ::trCtrl.helpText.allocHelpText $} - -
    - -
    - {$ ::trCtrl.helpText.allocHiddenText $} -
    -
    - -
    -
    - - -
    - -
    - - {$ ::trCtrl.helpText.availTitle $} - {$ trCtrl.numAvailable $} - - {$ ::trCtrl.helpText.availHelpText $} - -
    - -
    - {$ ::trCtrl.helpText.availHiddenText $} -
    -
    - -
    -
    -
    \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/transfer-table/transfer-table.js b/code/horizon/horizon/static/angular/transfer-table/transfer-table.js deleted file mode 100644 index a54bd417..00000000 --- a/code/horizon/horizon/static/angular/transfer-table/transfer-table.js +++ /dev/null @@ -1,410 +0,0 @@ -(function() { - 'use strict'; - - /** - * @ngdoc overview - * @name hz.widget.transfer-table - * @description - * - * # hz.widget.transfer-table - * - * The `hz.widget.transfer-table` module provides support for transferring - * rows between two tables (allocated and available). - * - * Requires {@link hz.widget.table.directive:hzTable `hzTable`} module to - * be installed. - * - * | Directives | - * |--------------------------------------------------------------------------| - * | {@link hz.widget.transfer-table.directive:transferTable `transferTable`} | - * - */ - angular.module('hz.widget.transfer-table', [ 'ui.bootstrap' ]) - - /** - * @ngdoc parameters - * @name hz.widget.transfer-table.constant:helpText - * @param {string} allocTitle Title for allocation section - * @param {string} availTitle Title for available section - * @param {string} availHelpText Help text shown in available section - * @param {string} noneAllocText Text shown if no allocated items - * @param {string} noneAvailText Text shown if no available items - * @param {string} allocHiddenText Text shown if allocated section hidden - * @param {string} availHiddenText Text shown if available section hidden - * @param {string} sectionToggleText Title for section toggle chevron icon - * @param {string} orderText Title for drag and drop re-order icon - * @param {string} expandDetailsText Title for expand icon - */ - .constant('helpText', { - allocTitle: gettext('Allocated'), - availTitle: gettext('Available'), - availHelpText: gettext('Select one'), - noneAllocText: gettext('Select an item from Available items below'), - noneAvailText: gettext('No available items'), - allocHiddenText: gettext('Expand to see allocated items'), - availHiddenText: gettext('Expand to see available items'), - sectionToggleText: gettext('Click to show or hide'), - orderText: gettext('Re-order items using drag and drop'), - expandDetailsText: gettext('Click to see more details') - }) - - /** - * @ngdoc parameters - * @name hz.widget.transfer-table.constant:limits - * @param {number} maxAllocation Maximum allocation allowed - */ - .constant('limits', { - maxAllocation: 1 - }) - - /* - * @ngdoc filter - * @name hz.widget.transfer-table.filter:warningText - * @returns {string} Warning text if exists or empty string - */ - .filter('warningText', function() { - return function(input, key) { - if (input && input.hasOwnProperty(key)) { - return input[key]; - } - return ''; - }; - }) - - /** - * @ngdoc filter - * @name hz.widget.transfer-table.filter:rowFilter - * @returns {array} List of filtered items based on field passed in - */ - .filter('rowFilter', function() { - return function(items, field) { - if (field) { - return items.filter(function(item) { - return !item[field]; - }); - } else { - return items; - } - }; - }) - - /** - * @ngdoc filter - * @name hz.widget.transfer-table.filter:foundText - * @returns {string} Help text for filter results - */ - .filter('foundText', function() { - return function(foundItems, total) { - var numFound = foundItems.length; - var transObj = { found: numFound, total: total }; - var message = gettext('Found %(found)s of %(total)s'); - return interpolate(message, transObj, true); - }; - }) - - /** - * @ngdoc controller - * @name hz.widget.transfer-table.controller:transferTableCtrl - * @description - * The `transferTableCtrl` controller provides functions for allocating - * and deallocating to and from the 'allocated' array, respectively. - * - * This controller can be accessed through `trCtrl`. See examples below. - * - * Functions and objects available: - * - * allocate - add row to allocated array - * Provide this as callback for the allocate button - * - * - * - * - * deallocate - remove row from allocated array - * Provide this as callback for the deallocate button - * - * - * - * - * updateAllocated - update allocated array after re-order - * This is needed if drag and drop re-ordering is enabled in - * the allocated table. - * - * ... table definition ... - *
    - * - * tooltipModel - custom warning tooltip model - * Use this with the allocate button (action-list) - * - * ... - * - * - */ - .controller('transferTableCtrl', - [ 'basePath', '$scope', '$timeout', '$parse', '$attrs', 'helpText', 'limits', - function(path, $scope, $timeout, $parse, $attrs, helpText, limits) { - var trModel = $parse($attrs.trModel)($scope); - var trHelpText = $parse($attrs.helpText)($scope); - var trLimits = $parse($attrs.limits)($scope); - - if (!angular.isArray(trModel.allocated)) { - console.error('Allocated is not an array as required.'); - } - - var model = this; - model.helpText = angular.extend({}, helpText, trHelpText); - model.limits = angular.extend({}, limits, trLimits); - model.numAvailable = trModel.available ? trModel.available.length : 0; - model.views = { allocated: true, available: true }; - - // Tooltip model - model.tooltipModel = { - templateUrl: path + 'action-list/warning-tooltip.html', - data: { - clickMessage: gettext('Click here to expand the row and view the errors.'), - expandDetail: function() { - var row = this.element.closest('tr'); - if (!row.hasClass('expanded')) { - // Timeout needed to prevent - // $apply already in progress error - $timeout(function() { - row.find('[hz-expand-detail]').click(); - }, 0, false); - } - } - } - }; - - function setAllocatedIds(allocatedRows) { - model.allocatedIds = {}; - if (allocatedRows) { - angular.forEach(allocatedRows, function(alloc) { - model.allocatedIds[alloc.id] = true; - }); - - if (trModel.available) { - model.numAvailable = trModel.available.length - allocatedRows.length; - } else { - model.numAvailable = 0; - } - } else { - trModel.allocated = []; - trModel.displayedAllocated = []; - } - } - - // Update tracking of allocated IDs when allocated changed - $scope.$watchCollection(function() { - return trModel.allocated; - }, function(newAllocated) { - setAllocatedIds(newAllocated); - }); - - // Update available count when available changed - $scope.$watchCollection(function() { - return trModel.available; - }, function(newAvailable) { - var numAvailable = newAvailable ? newAvailable.length : 0; - var numAllocated = trModel.allocated ? trModel.allocated.length : 0; - model.numAvailable = numAvailable - numAllocated; - }); - - // Initialize tracking of allocated IDs - setAllocatedIds(trModel.allocated); - - model.allocate = function(row) { - if (model.limits.maxAllocation < 0 || - trModel.allocated.length < model.limits.maxAllocation) { - // Add to allocated only if limit not reached - trModel.allocated.push(row); - - model.numAvailable -= 1; - } else if (model.limits.maxAllocation === 1) { - // Swap out rows if only one allocation allowed - trModel.allocated.pop(); - - // When swapping out, Smart-Table $watch is - // not detecting change so timeout is used - // as workaround. - $timeout(function() { - trModel.allocated.push(row); - $scope.$apply(); - }, 0, false); - } - }; - - model.deallocate = function(row) { - model.numAvailable += 1; - - var allocLen = trModel.allocated.length; - for (var i = allocLen - 1; i >= 0; i--) { - if (trModel.allocated[i].id === row.id) { - trModel.allocated.splice(i, 1); - } - } - }; - - // Show/hide allocated or available sections - model.toggleView = function(view) { - var show = model.views[view]; - model.views[view] = !show; - }; - - // Allocated array needs to be updated when rows re-ordered - model.updateAllocated = function(e, item, orderedItems) { - var allocLen = trModel.allocated.length; - trModel.allocated.splice(0, allocLen); - Array.prototype.push.apply(trModel.allocated, orderedItems); - }; - - model.numAllocated = function() { - return trModel.allocated ? trModel.allocated.length : 0; - }; - - model.numDisplayedAvailable = function() { - if (trModel.displayedAvailable) { - var filtered = trModel.displayedAvailable.filter(function(avail) { - return !model.allocatedIds[avail.id]; - }); - - return filtered.length; - } - return 0; - }; - }] - ) - - /** - * @ngdoc directive - * @name hz.widget.transfer-table.directive:transferTable - * @element - * @param {object} trModel Table data model (required) - * @param {object} helpText Help text (optional) - * @param {object} limits Max allocation (optional, default: 1) - * @description - * The `transferTable` directive generates two tables and allows the - * transfer of rows between the two tables. Help text and maximum - * allocation are configurable. The defaults for help text and limits - * are described above (constants: helpContent and limits). - * - * The data model requires 4 arrays: allocated, displayedAllocated, - * available, and displayedAvailable. Smart-Table requires 'displayed' - * arrays for sorting and re-ordering. - * - * Data model: - * ``` - * $scope.available = [ - * { id: 'u1', username: 'User 1', disabled: true, warnings: { username: 'Invalid!' } }, - * { id: 'u2', username: 'User 2', disabled: true, warningMessage: 'Invalid!' }, - * { id: 'u3', username: 'User 3' } - * ]; - * - * $scope.allocated = []; - * - * $scope.tableData = { - * available: $scope.available, - * displayedAvailable: [].concat($scope.available), - * allocated: $scope.allocated, - * displayedAllocated: [].concat($scope.allocated) - * }; - * - * $scope.helpText = { - * availHelpText: 'Select one from the list' - * }; - * - * $scope.limits = { - * maxAllocation: -1 - * }; - * ``` - * Optional arguments for each row in table data model: - * disabled - disables the allocate button in available table - * warningMessage - the message to show in warning tooltip - * warnings - show warning text and icon next to value in table cell - * - * @restrict E - * - * @example - * There are 2 examples available as a template: allocated.html.example and - * available.html.example. The `transferTableCtrl` methods are available - * via `trCtrl`. For example, for allocation, use `trCtrl.allocate`. - * ``` - * - * - * - * ... header definition ... - * - * - * - * ... more cell definitions - * - * - * - * - * - * - * - *
    {$ row.username $} - * - * - * - * - * - *
    - * ... detail row definition ... - *
    - *
    - * - * - * ... header definition ... - * - * - * - * ... more cell definitions - * - * - * - * - * - * - *
    {$ row.username $} - * - * - * - * - * - *
    - * ... detail row definition ... - *
    - *
    - *
    - * ``` - */ - .directive('transferTable', [ 'basePath', - function(path) { - return { - controller: 'transferTableCtrl', - controllerAs: 'trCtrl', - restrict: ' E', - scope: true, - transclude: true, - templateUrl: path + 'transfer-table/transfer-table.html', - link: function(scope, element, attrs, ctrl, transclude) { - var allocated = element.find('.transfer-allocated'); - var available = element.find('.transfer-available'); - - transclude(scope, function(clone) { - allocated.append(clone.filter('allocated')); - available.append(clone.filter('available')); - }); - } - }; - } - ]); - -})(); \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/transfer-table/transfer-table.scss b/code/horizon/horizon/static/angular/transfer-table/transfer-table.scss deleted file mode 100644 index 2f1e2bb9..00000000 --- a/code/horizon/horizon/static/angular/transfer-table/transfer-table.scss +++ /dev/null @@ -1,51 +0,0 @@ -.transfer-table { - - .collapsed-help { - color: $transfer-help-text-color; - font-style: italic; - font-weight: 400; - margin-bottom: 3em; - } - - .fa[title] { - cursor: pointer; - width: 20px; - } - - .transfer-heading { - border-bottom: $transfer-header-bottom-border; - font-size: 1.2em; - margin-top: 1em; - padding-bottom: 0.5em; - - .badge-info { - background-color: $badge-info-color; - } - - .help-text { - font-size: 0.9em; - font-weight: 400; - } - } - - .transfer-available, .transfer-allocated { - margin-bottom: 3em; - - table { - .action-col { - min-width: $transfer-btn-width; - width: $transfer-btn-width; - - .btn { - border-color: $transfer-btn-border-color; - padding: 2px 7px; - - &.disabled { - border-color: $transfer-disabled-btn-border-color; - color: $transfer-disabled-btn-color; - } - } - } - } - } -} diff --git a/code/horizon/horizon/static/angular/transfer-table/transfer-table.spec.js b/code/horizon/horizon/static/angular/transfer-table/transfer-table.spec.js deleted file mode 100644 index 854106a6..00000000 --- a/code/horizon/horizon/static/angular/transfer-table/transfer-table.spec.js +++ /dev/null @@ -1,268 +0,0 @@ -/* - * (c) Copyright 2015 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -(function() { - 'use strict'; - - describe('hz.widget.transfer-table module', function() { - it('should have been defined', function() { - expect(angular.module('hz.widget.transfer-table')).toBeDefined(); - }); - }); - - describe("Filters", function() { - var filter; - - beforeEach(module('hz.widget.transfer-table')); - - describe("warningText", function() { - - beforeEach(inject(function(warningTextFilter) { - filter = warningTextFilter; - })); - - it('returns value if present', function() { - expect(filter({ thing: 'stuff'}, 'thing')).toBe('stuff'); - }); - - it('returns empty string if not present', function() { - expect(filter({ thing: 'stuff'}, 'other')).toBe(''); - }); - - }); - - describe("rowFilter", function() { - - beforeEach(inject(function(rowFilterFilter) { - filter = rowFilterFilter; - })); - - it('returns item if field is falsy', function() { - expect(filter({ hi: 'there' }, false)).toEqual({ hi: 'there' }); - }); - - it('returns items only where field property is falsy', function() { - var items = [ - {hi: 'there'}, - {}, - {hi: true}, - {hi: false} - ]; - expect(filter(items, 'hi')).toEqual([{}, {hi: false}]); - }); - - }); - - describe("foundText", function() { - - beforeEach(inject(function(foundTextFilter) { - filter = foundTextFilter; - })); - - it('returns expected text', function() { - var items = [1,2,3]; - expect(filter(items, 6)).toBe('Found 3 of 6'); - }); - - }); - - }); - - describe('transfer-table directive', function() { - - var $scope, $timeout, $element; - - beforeEach(module('templates')); - beforeEach(module('smart-table')); - beforeEach(module('hz')); - beforeEach(module('hz.widgets')); - beforeEach(module('hz.widget.action-list')); - beforeEach(module('hz.widget.table')); - beforeEach(module('hz.widget.transfer-table')); - - describe('max 1 allocation', function() { - - beforeEach(inject(function($injector) { - var $compile = $injector.get('$compile'); - $scope = $injector.get('$rootScope').$new(); - $timeout = $injector.get('$timeout'); - - var available = [ - { id: '1', animal: 'cat' }, - { id: '2', animal: 'dog' }, - { id: '3', animal: 'fish' } - ]; - - $scope.tableData = { - available: available, - allocated: [], - displayedAvailable: [].concat(available), - displayedAllocated: [] - }; - - var markup = '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '
    Animal
    {$ alRow.animal $}' + - ' x' + - ' ' + - '
    ' + - '
    ' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '
    Animal
    {$ row.animal $}' + - ' x' + - ' ' + - '
    ' + - '
    ' + - '
    '; - - $element = angular.element(markup); - $compile($element)($scope); - - $scope.$digest(); - })); - - it('should have 0 allocated rows', function() { - expect($element.find('.transfer-allocated tr[ng-repeat]').length).toBe(0); - }); - - it('should have 3 available rows', function() { - expect($element.find('.transfer-available tr[ng-repeat]').length).toBe(3); - }); - - it('should have 1 allocated row if first available row allocated', function() { - $element.find('.transfer-available tbody tr:first-child button').click(); - expect($element.find('.transfer-allocated tr[ng-repeat]').length).toBe(1); - }); - - it('should swap allocated row if one already exists', function() { - var available = $element.find('.transfer-available tbody tr:first-child button'); - available.click(); - - // After first click, should be one allocated row - var allocated = $element.find('.transfer-allocated tr[ng-repeat]'); - expect(allocated.length).toBe(1); - expect(allocated.find('td:nth-child(1)').text().trim()).toBe('cat'); - - // After second click, previously allocated row swapped out for new one - available = $element.find('.transfer-available tbody tr:first-child button'); - available.click(); - - $timeout.flush(); - - allocated = $element.find('.transfer-allocated tr[ng-repeat]'); - expect(allocated.length).toBe(1); - expect(allocated.find('td:nth-child(1)').text().trim()).toBe('dog'); - }); - - it('should have 0 allocated row if allocated row de-allocated', function() { - $element.find('.transfer-allocated tr[ng-repeat] button').click(); - expect($element.find('.transfer-allocated tr[ng-repeat]').length).toBe(0); - expect($element.find('.transfer-available tr[ng-repeat]').length).toBe(3); - }); - - }); - - describe('max 2 allocations', function() { - - beforeEach(inject(function($injector) { - var $compile = $injector.get('$compile'); - $scope = $injector.get('$rootScope').$new(); - - var available = [ - { id: '1', animal: 'cat' }, - { id: '2', animal: 'dog' }, - { id: '3', animal: 'fish' } - ]; - - $scope.tableData = { - available: available, - allocated: [], - displayedAvailable: [].concat(available), - displayedAllocated: [] - }; - - $scope.limits = { - maxAllocation: 2 - }; - - var markup = '' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '
    Animal
    {$ row.animal $}' + - ' x' + - ' ' + - '
    ' + - '
    ' + - '' + - '' + - '' + - '' + - '' + - '' + - '' + - '
    Animal
    {$ alRow.animal $}' + - ' x' + - ' ' + - '
    ' + - '
    ' + - '
    '; - - $element = angular.element(markup); - $compile($element)($scope); - - $scope.$digest(); - })); - - it('should have 0 allocated rows', function() { - expect($element.find('.transfer-allocated tr[ng-repeat]').length).toBe(0); - }); - - it('should have 3 available rows', function() { - expect($element.find('.transfer-available tr[ng-repeat]').length).toBe(3); - }); - - it('should allow only 2 allocated rows', function() { - $element.find('.transfer-available tbody tr:first-child button').click(); - $element.find('.transfer-available tbody tr:first-child button').click(); - - var lastRow = $element.find('.transfer-available tbody tr:first-child'); - lastRow.find('.action-col .btn').click(); - - expect($element.find('.transfer-allocated tr[ng-repeat]').length).toBe(2); - expect($element.find('.transfer-available tr[ng-repeat]').length).toBe(1); - - // The last row should not have been added - expect(lastRow.find('td:nth-child(1)').text().trim()).toBe('fish'); - }); - }); - }); -})(); diff --git a/code/horizon/horizon/static/angular/validators/validators.js b/code/horizon/horizon/static/angular/validators/validators.js deleted file mode 100644 index dcac1d02..00000000 --- a/code/horizon/horizon/static/angular/validators/validators.js +++ /dev/null @@ -1,142 +0,0 @@ -(function() { - 'use strict'; - - /** - * @ngdoc overview - * @name hz.framework.validators - * @description - * - * # hz.framework.validators - * - * The `hz.framework.validators` module provides support for validating - * forms. - * - * | Directives | - * |---------------------------------------------------------------------------------| - * | {@link hz.framework.validators.directive:validateNumberMax `validateNumberMax`} | - * | {@link hz.framework.validators.directive:validateNumberMin `validateNumberMin`} | - * - */ - angular.module('hz.framework.validators', []) - - /** - * @ngdoc directive - * @name hz.framework.validators.directive:validateNumberMax - * @element ng-model - * @description - * The `validateNumberMax` directive provides max validation - * for the form input elements. This is an alternative to - * `max` which doesn't re-evaluate expression passed in on - * change. This allows the max value to be dynamically - * specified. - * - * The model and view value is not set to undefined if - * input does not pass validation. This is so that - * components that are watching this value can determine - * what to do with it. For example, quota charts can - * still render and display over-utilized slices in red. - * - * Validator returns true if model/view value <= max value. - * - * @restrict A - * - * @example - * ``` - * - * ``` - */ - .directive('validateNumberMax', [ function() { - return { - require: 'ngModel', - restrict: 'A', - link: function (scope, element, attrs, ctrl) { - if (!ctrl) { - return; - } - - var maxValidator = function(value) { - var max = scope.$eval(attrs.validateNumberMax); - if (angular.isDefined(max) && !ctrl.$isEmpty(value) && value > max) { - ctrl.$setValidity('validateNumberMax', false); - } else { - ctrl.$setValidity('validateNumberMax', true); - } - - // Return the value rather than undefined if invalid - return value; - }; - - // Re-validate if value is changed through the UI - // or model (programmatically) - ctrl.$parsers.push(maxValidator); - ctrl.$formatters.push(maxValidator); - - attrs.$observe('validateNumberMax', function() { - maxValidator(ctrl.$modelValue); - }); - } - }; - }]) - - /** - * @ngdoc directive - * @name hz.framework.validators.directive:validateNumberMin - * @element ng-model - * @description - * The `validateNumberMin` directive provides min validation - * for form input elements. This is an alternative to `min` - * which doesn't re-evaluate the expression passed in on - * change. This allows the min value to be dynamically - * specified. - * - * The model and view value is not set to undefined if - * input does not pass validation. This is so that - * components that are watching this value can determine - * what to do with it. For example, quota charts can - * still render and display over-utilized slices in red. - * - * Validator returns true is model/view value >= min value. - * - * @restrict A - * - * @example - * ``` - * - * ``` - */ - .directive('validateNumberMin', [ function() { - return { - require: 'ngModel', - restrict: 'A', - link: function (scope, element, attrs, ctrl) { - if (!ctrl) { - return; - } - - var minValidator = function(value) { - var min = scope.$eval(attrs.validateNumberMin); - if (angular.isDefined(min) && !ctrl.$isEmpty(value) && value < min) { - ctrl.$setValidity('validateNumberMin', false); - } else { - ctrl.$setValidity('validateNumberMin', true); - } - - // Return the value rather than undefined if invalid - return value; - }; - - // Re-validate if value is changed through the UI - // or model (programmatically) - ctrl.$parsers.push(minValidator); - ctrl.$formatters.push(minValidator); - - attrs.$observe('validateNumberMin', function() { - minValidator(ctrl.$modelValue); - }); - } - }; - }]); - -}()); \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/validators/validators.spec.js b/code/horizon/horizon/static/angular/validators/validators.spec.js deleted file mode 100644 index 661ba78b..00000000 --- a/code/horizon/horizon/static/angular/validators/validators.spec.js +++ /dev/null @@ -1,103 +0,0 @@ -(function() { - 'use strict'; - - describe('hz.framework.validators module', function() { - it('should have been defined', function() { - expect(angular.module('hz.framework.validators')).toBeDefined(); - }); - }); - - describe('validators directive', function() { - - beforeEach(module('hz')); - beforeEach(module('hz.widgets')); - beforeEach(module('hz.framework.validators')); - - describe('validateNumberMax directive', function() { - - var $scope, $form; - - beforeEach(inject(function($injector) { - var $compile = $injector.get('$compile'); - $scope = $injector.get('$rootScope').$new(); - - $scope.count = 0; - - var markup = '
    ' + - '' + - '
    '; - - $compile(angular.element(markup))($scope); - $form = $scope.testForm; - - $scope.$digest(); - })); - - it('should pass validation initially when count is 0 and max is 1', function() { - expect($form.count.$valid).toBe(true); - expect($form.$valid).toBe(true); - }); - - it('should not pass validation if count increased to 2 and max is 1', function() { - $form.count.$setViewValue(2); - $scope.$digest(); - expect($form.count.$valid).toBe(false); - expect($form.$valid).toBe(false); - }); - - it('should pass validation if count is empty', function() { - $form.count.$setViewValue(''); - $scope.$digest(); - expect($form.count.$valid).toBe(true); - expect($form.$valid).toBe(true); - }); - - }); - - describe('validateNumberMin directive', function() { - - var $scope, $form; - - beforeEach(inject(function($injector) { - var $compile = $injector.get('$compile'); - $scope = $injector.get('$rootScope').$new(); - - $scope.count = 0; - - var markup = '
    ' + - '' + - '
    '; - - $compile(angular.element(markup))($scope); - $form = $scope.testForm; - - $scope.$digest(); - })); - - it('should not pass validation initially when count is 0 and min is 1', function() { - expect($form.count.$valid).toBe(false); - expect($form.$valid).toBe(false); - }); - - it('should pass validation if count increased to 2 and min is 1', function() { - $form.count.$setViewValue(2); - $scope.$digest(); - expect($scope.count).toBe(2); - expect($form.count.$valid).toBe(true); - expect($form.$valid).toBe(true); - }); - - it('should pass validation if count is empty', function() { - $form.count.$setViewValue(''); - $scope.$digest(); - expect($form.count.$valid).toBe(true); - expect($form.$valid).toBe(true); - }); - - }); - - }); - -})(); \ No newline at end of file diff --git a/code/horizon/horizon/static/angular/widget.module.js b/code/horizon/horizon/static/angular/widget.module.js deleted file mode 100644 index 9b501639..00000000 --- a/code/horizon/horizon/static/angular/widget.module.js +++ /dev/null @@ -1,22 +0,0 @@ -(function () { - 'use strict'; - - angular.module('hz.widgets', [ - 'hz.widget.form', - 'hz.widget.help-panel', - 'hz.widget.wizard', - 'hz.widget.table', - 'hz.widget.modal', - 'hz.widget.modal-wait-spinner', - 'hz.framework.bind-scope', - 'hz.framework.workflow', - 'hz.widget.transfer-table', - 'hz.widget.charts', - 'hz.widget.action-list', - 'hz.widget.metadata-tree', - 'hz.widget.metadata-display', - 'hz.framework.validators' - ]) - .constant('basePath', '/static/angular/'); - -})(); diff --git a/code/horizon/horizon/static/angular/wizard/wizard.html b/code/horizon/horizon/static/angular/wizard/wizard.html deleted file mode 100644 index 3cc5dc2a..00000000 --- a/code/horizon/horizon/static/angular/wizard/wizard.html +++ /dev/null @@ -1,67 +0,0 @@ -
    -
    - - - -
    - - -
    - -
    -
    - -
    - -
    - - - - - - - -
    -
    - -
    - - - - -
    diff --git a/code/horizon/horizon/static/angular/wizard/wizard.js b/code/horizon/horizon/static/angular/wizard/wizard.js deleted file mode 100644 index f2715748..00000000 --- a/code/horizon/horizon/static/angular/wizard/wizard.js +++ /dev/null @@ -1,182 +0,0 @@ -(function () { - 'use strict'; - - var extend = angular.extend, - forEach = angular.forEach, - noop = angular.noop; - - angular.module('hz.widget.wizard', ['ui.bootstrap']) - - .constant('wizardLabels', { - cancel: gettext('Cancel'), - back: gettext('Back'), - next: gettext('Next'), - finish: gettext('Finish') - }) - - .constant('wizardEvents', { - ON_INIT_SUCCESS: 'ON_INIT_SUCCESS', - ON_INIT_ERROR: 'ON_INIT_ERROR', - ON_SWITCH: 'ON_SWITCH', - BEFORE_SUBMIT: 'BEFORE_SUBMIT', - AFTER_SUBMIT: 'AFTER_SUBMIT' - }) - - .directive('wizard', ['basePath', function (path) { - return { - controller: ['$scope', '$q', 'wizardLabels', 'wizardEvents', - function ($scope, $q, wizardLabels, wizardEvents) { - $scope.currentIndex = -1; - $scope.openHelp = false; - $scope.workflow = $scope.workflow || {}; - $scope.btnText = extend({}, wizardLabels, $scope.workflow.btnText); - $scope.btnIcon = $scope.workflow.btnIcon || {}; - $scope.steps = $scope.workflow.steps || []; - $scope.wizardForm = {}; - $scope.initTask = $q.defer(); - $scope.initPromise = $scope.initTask.promise; - $scope.showSpinner = false; - $scope.hasError = false; - - $scope.switchTo = function (index) { - /** - * In each step's controller, $scope.$index can be used by the step - * to identify itself. For example: - * - * var comingToMe = (event.to === $scope.$index); - */ - $scope.$broadcast(wizardEvents.ON_SWITCH, { - from: $scope.currentIndex, - to: index - }); - $scope.currentIndex = index; - $scope.openHelp = false; - }; - $scope.showError = function (errorMessage) { - $scope.showSpinner = false; - $scope.errorMessage = errorMessage; - $scope.hasError = true; - }; - $scope.beforeSubmit = function () { - $scope.$broadcast(wizardEvents.BEFORE_SUBMIT); - }; - $scope.afterSubmit = function () { - $scope.$broadcast(wizardEvents.AFTER_SUBMIT); - $scope.close(); - }; - $scope.onClickFinishBtn = function () { - $scope.beforeSubmit(); - $scope.submit().then($scope.afterSubmit, $scope.showError); - }; - $scope.initPromise.then( - function () { - $scope.$broadcast(wizardEvents.ON_INIT_SUCCESS); - }, - function () { - $scope.$broadcast(wizardEvents.ON_INIT_ERROR); - } - ); - - /** - * Each step in the workflow can provide an optional `checkReadiness` - * method, which should return a promise. When this method is provided - * with a step, the `.ready` property of the step will be set to - * `false` until the promise gets resolved. If no `checkReadiness` method - * is provided, the `.ready` property of the step will be set to `true` - * by default. - * - * This is useful for workflows where some steps are optional and/or - * displayed to the UI conditionally, and the check for the condition - * is an asynchronous operation. - * - * @return {Promise} This promise gets resolved when all the checking - * for each step's promises are done. - * - * @example - - ```js - var launchInstanceWorkFlow = { - //... - steps: [ - // ... - { - title: gettext('Network'), - templateUrl: path + 'launch-instance/network/network.html', - helpUrl: path + 'launch-instance/network/network.help.html', - formName: 'launchInstanceNetworkForm', - - checkReadiness: function () { - var d = $q.defer(); - setTimeout(function () { - d.resolve(); - }, 500); - return d.promise; - } - } - //... - ], - //... - }; - ``` - */ - function checkAllReadiness() { - var stepReadyPromises = []; - - forEach($scope.steps, function (step, index) { - step.ready = !step.checkReadiness; - - if (step.checkReadiness) { - var promise = step.checkReadiness(); - stepReadyPromises.push(promise); - promise.then( - function () { - step.ready = true; - }, - function () { - $scope.steps.splice(index, 1); - } - ); - } - }); - - $scope.ready = (stepReadyPromises.length === 0); - return $q.all(stepReadyPromises); - } - - function switchToFirstReadyStep() { - forEach($scope.steps, function (step, index) { - if ($scope.currentIndex < 0 && step.ready) { - $scope.currentIndex = index; - return; - } - }); - } - - // angular promise doesn't have #always method right now, - // this is a simple workaround. - function always() { - $scope.ready = true; - $scope.initTask.resolve(); - switchToFirstReadyStep(); - } - - checkAllReadiness().then(always, always); - }], - templateUrl: path + 'wizard/wizard.html' - }; - } - ]) - - .controller('ModalContainerCtrl', ['$scope', '$modalInstance', 'launchContext', - function ($scope, $modalInstance, launchContext) { - $scope.launchContext = launchContext; - $scope.close = function () { - $modalInstance.close(); - }; - $scope.cancel = function () { - $modalInstance.dismiss(); - }; - } - ]); - -})(); diff --git a/code/horizon/horizon/static/angular/wizard/wizard.scss b/code/horizon/horizon/static/angular/wizard/wizard.scss deleted file mode 100644 index 516e6ac0..00000000 --- a/code/horizon/horizon/static/angular/wizard/wizard.scss +++ /dev/null @@ -1,352 +0,0 @@ -.ng-wizard { - display: block; - position: absolute; - top: 0; - left: 0; - right: 0; - bottom: 0; - overflow: hidden; - font-weight: normal; - - .title { - height: $wizardTitleBarHeight; - line-height: $wizardTitleBarHeight - 6px; - vertical-align: bottom; - padding: 6px $WizardSidePadding 0 $WizardSidePadding; - color: #555; - border-bottom: 1px solid #ddd; - font-size: 22px; - font-weight: normal; - } - - .fa.invalid { - color: $invalid-color; - cursor: pointer; - } - - & > .nav { - display: inline-block; - top: 40px; - left: 0px; - bottom: 40px; - width: $wizardNavWidth; - padding: 10px 10px 10px $WizardSidePadding; - - .nav-item { - position: relative; - display: block; - height: $WizardNavItemHeight; - width: $WizardNavItemWidth; - text-align: left; - padding-left: 10px; - background: transparent; - border: none; - border-bottom: 1px solid $WizardNavItemBdColor; - margin-top: -1px; - color: $WizardNavItemColor; - font-size: 12px; - border-radius: 0; - - &::after { - content: " "; - position: absolute; - top: 0; - right: -10px; - display: block; - height: inherit; - width: 0; - border-left: none; - border-top: $WizardNavItemHeight/2 solid transparent; - border-bottom: $WizardNavItemHeight/2 solid transparent; - } - - &[disabled] { - color: #444; - background: transparent; - } - - &.current { - width: $WizardNavItemWidth; - background: $WizardNavItemBgColor; - color: $WizardButtonColorHiLight; - border-color: $WizardNextBtnBgColor; - - &::after { - border-left: $WizardNavItemBgColor 10px solid; - } - - &:focus { - outline: none; - } - - .status-indicator { - color: inherit; - } - } - - .status-indicator { - position: absolute; - right: 0; - top: 18px; - width: $WizardStatusIndicatorSize; - height: $WizardStatusIndicatorSize; - color: orange; - } - } - } - - .step { - position: absolute; - top: $wizardTitleBarHeight; - left: $wizardNavWidth; - right: 0; - bottom: $wizardToolBarHeight; - color: #888; - - h1 { - position: absolute; - top: 0; - height: 45px; - left: 10px; - right: 65px; - margin: 0; - padding-top: 20px; - } - - h2.section-title { - margin-bottom: 5px; - padding-bottom: 5px; - } - - h1, h2.section-title { - font-size: 18px; - font-weight: normal; - color: #555; - border-bottom: 1px solid #ddd; - } - - .content { - position: absolute; - top: 45px; - left: 10px; - right: 0; - bottom: 0; - padding: 5px 65px 24px 0; - overflow: auto; - - .subtitle { - margin-bottom: 30px; - } - - label { - font-weight: normal; - color: #555; - } - } - } - - .toolbar { - position: absolute; - left: 0; - right: 0; - bottom: 0; - height: $wizardToolBarHeight; - line-height: $wizardToolBarHeight; - vertical-align: middle; - background: $WizardToolbarBgColor; - border-top: 1px solid $WizardBtnBdColor; - - .secondary-btn-grp { - position: absolute; - left: $WizardSidePadding; - } - - .primary-btn-grp { - position: absolute; - right: $WizardSidePadding; - } - - .secondary-btn-grp button { - margin-right: $WizardBtnGap - 3px; // white space character takes 3px - } - - .primary-btn-grp button { - margin-left: $WizardBtnGap - 3px; // white space character takes 3px - } - - .btn-wrap { - display: inline-block; - } - - .btn-wrap.finish { - padding-left: 15px; - margin-left: 20px; - border-left: 2px solid #ddd; - } - - .separator { - display: inline-block; - width: 0; - margin-left: 20px; - margin-right: 15px; - border-left: 1px solid $WizardToolbarVerticalSeparatorBdColor; - height: $wizardToolBarHeight; - vertical-align: top; - } - - button { - height: $WizardToolbarBtnHeight; - line-height: $WizardToolbarBtnHeight - 2px; - vertical-align: baseline; - padding: 0 25px 2px 25px; - font-size: 14px; - color: $WizardBtnTextColor; - border: 1px solid $WizardBtnBdColor; - background: $WizardBtnBgColor; - - &[disabled] { - color: #ccc; - border-color: #ddd; - background: #fff; - } - - &.next { - color: $WizardButtonColorHiLight; - border-color: $WizardNextBtnBdColor; - background: $WizardNextBtnBgColor; - - &[disabled] { - color: $WizardButtonColorHiLight; - border-color: $WizardFinishBtnDisabledBdColor; - background: $WizardFinishBtnDisabledBgColor; - } - } - - &.finish { - color: $WizardButtonColorHiLight; - border-color: $WizardFinishBtnBdColor; - background: $WizardFinishBtnBgColor; - - &[disabled] { - color: $WizardButtonColorHiLight; - border-color: $WizardFinishBtnDisabledBdColor; - background: $WizardFinishBtnDisabledBgColor; - } - } - } - } - - .help-panel { - top: $wizardTitleBarHeight; - bottom: $wizardToolBarHeight; - } - - .error-message { - display: none !important; - } -} - -.modal-dialog-wizard { - - .modal-dialog { - position: relative; - margin: 0 auto; - height: $wizardHeight; - width: $wizardWidth; - - // $wizardMaxHeight is the max height of the modal content without - // padding, so need to add the padding here. - max-height: $wizardMaxHeight + $wizardTopPadding + $wizardBottomPadding; - - // $wizardMaxWidth is the max width of the modal content without - // padding, so need to add the padding here. - max-width: $wizardMaxWidth + $wizardLeftPadding + $wizardRightPadding; - - // $wizardMinHeight is the min height of the modal content without - // padding, so need to add the padding here. - min-height: $wizardMinHeight + $wizardTopPadding + $wizardBottomPadding; - - // $wizardMinWidth is the min with of the modal content without - // padding, so need to add the padding here. - min-width: $wizardMinWidth + $wizardLeftPadding + $wizardRightPadding; - overflow-x: auto; - - .modal-content { - position: absolute; - top: $wizardTopPadding; - left: $wizardLeftPadding; - right: $wizardRightPadding; - bottom: $wizardBottomPadding; - border-radius: 0; - - @media (max-width: 1000px) { - left: 0; - right: 0; - } - - @media (max-height: 600px) { - top: 0; - bottom: 0; - } - } - } -} -/* workaround for odd Bootstrap checkbox vertical alignment */ -.checkbox { - input[type="checkbox"] { - margin-top: 3px; - } -} - -.form-control { - @include input-placeholder { - font-weight: normal; - color: $placeholder-text-color; - } -} - -.form-group .required label:after { - content: " *"; - color: red; -} - -.btn-toggle { - color: #333; - background-color: #fff; - border-color: #adadad; - - &:hover, - &:focus, - &:active { - background-color: #ebebeb; - } - - &.active { - background-color: #0077b3; - border-color: #006699; - color: #fff !important; - } - - &.disabled.active, - &[disabled].active { - background-color: rgba(0, 119, 179, 0.65); - border-color: rgba(0, 102, 153, 0.65); - color: #fff; - } - - &.disabled, - &.disabled:hover, - &.disabled:focus, - &.disabled:active, - &[disabled]:hover, - &[disabled]:focus, - &[disabled]:active, - fieldset[disabled] &:hover, - fieldset[disabled] &:focus, - fieldset[disabled] &:active, - fieldset[disabled] &.active { - background-color: #fafafa; - border-color: #ccc; - color: #999; - } -} diff --git a/code/horizon/horizon/static/angular/wizard/wizard.spec.js b/code/horizon/horizon/static/angular/wizard/wizard.spec.js deleted file mode 100644 index 9ba2f092..00000000 --- a/code/horizon/horizon/static/angular/wizard/wizard.spec.js +++ /dev/null @@ -1,163 +0,0 @@ -/* jshint globalstrict: true */ -'use strict'; - -describe('hz.widget.wizard module', function () { - it('should have been defined', function () { - expect(angular.module('hz.widget.wizard')).toBeDefined(); - }); -}); - -describe('wizard directive', function () { - var $compile, - $scope, - element; - - beforeEach(module('templates')); - beforeEach(module('hz')); - beforeEach(module('hz.widgets')); - beforeEach(module('hz.widget.wizard')); - beforeEach(inject(function ($injector) { - $scope = $injector.get('$rootScope').$new(); - $compile = $injector.get('$compile'); - element = $compile('')($scope); - })); - - it('should be compiled', function () { - var element = $compile('some text')($scope); - $scope.$digest(); - expect(element.html().trim()).not.toBe('some text'); - }); - - it('should have empty title by default', function () { - $scope.workflow = {}; - $scope.$digest(); - expect(element[0].querySelector('.title').textContent).toBe(''); - }); - - it('should have title if it is specified by workflow', function () { - var titleText = 'Some title'; - $scope.workflow = {}; - $scope.workflow.title = titleText; - $scope.$digest(); - expect(element[0].querySelector('.title').textContent).toBe(titleText); - }); - - it('should have no steps if no steps defined', function () { - $scope.workflow = {}; - $scope.$digest(); - expect(element[0].querySelectorAll('.step').length).toBe(0); - }); - - it('should have 3 steps if 3 steps defined', function () { - $scope.workflow = { - steps: [ {}, {}, {} ] - }; - $scope.$digest(); - expect(element[0].querySelectorAll('.step').length).toBe(3); - }); - - it('should have no nav items if no steps defined', function () { - $scope.workflow = {}; - $scope.$digest(); - expect(element[0].querySelectorAll('.nav-item').length).toBe(0); - }); - - it('should have 3 nav items if 3 steps defined', function () { - $scope.workflow = { - steps: [ {}, {}, {} ] - }; - $scope.$digest(); - expect(element[0].querySelectorAll('.nav-item').length).toBe(3); - }); - - it('should navigate correctly', function () { - $scope.workflow = { - steps: [ {}, {}, {} ] - }; - - $scope.$digest(); - expect($scope.currentIndex).toBe(0); - expect($(element).find('.step').eq(0).hasClass('ng-hide')).toBe(false); - expect($(element).find('.step').eq(1).hasClass('ng-hide')).toBe(true); - expect($(element).find('.step').eq(2).hasClass('ng-hide')).toBe(true); - expect($(element).find('.nav-item').eq(0).hasClass('current')).toBe(true); - expect($(element).find('.nav-item').eq(1).hasClass('current')).toBe(false); - expect($(element).find('.nav-item').eq(2).hasClass('current')).toBe(false); - - $scope.switchTo(1); - $scope.$digest(); - expect($scope.currentIndex).toBe(1); - expect($(element).find('.step').eq(0).hasClass('ng-hide')).toBe(true); - expect($(element).find('.step').eq(1).hasClass('ng-hide')).toBe(false); - expect($(element).find('.step').eq(2).hasClass('ng-hide')).toBe(true); - expect($(element).find('.nav-item').eq(0).hasClass('current')).toBe(false); - expect($(element).find('.nav-item').eq(1).hasClass('current')).toBe(true); - expect($(element).find('.nav-item').eq(2).hasClass('current')).toBe(false); - - $scope.switchTo(2); - $scope.$digest(); - expect($scope.currentIndex).toBe(2); - expect($(element).find('.step').eq(0).hasClass('ng-hide')).toBe(true); - expect($(element).find('.step').eq(1).hasClass('ng-hide')).toBe(true); - expect($(element).find('.step').eq(2).hasClass('ng-hide')).toBe(false); - expect($(element).find('.nav-item').eq(0).hasClass('current')).toBe(false); - expect($(element).find('.nav-item').eq(1).hasClass('current')).toBe(false); - expect($(element).find('.nav-item').eq(2).hasClass('current')).toBe(true); - }); - - it('should not show back button in step 1/3', function () { - $scope.workflow = { - steps: [{}, {}, {}] - }; - $scope.$digest(); - expect($(element).find('button.back').hasClass('ng-hide')).toBe(true); - expect($(element).find('button.next').hasClass('ng-hide')).toBe(false); - }); - - it('should show both back and next button in step 2/3', function () { - $scope.workflow = { - steps: [{}, {}, {}] - }; - $scope.$digest(); - $scope.switchTo(1); - $scope.$digest(); - expect($(element).find('button.back').hasClass('ng-hide')).toBe(false); - expect($(element).find('button.next').hasClass('ng-hide')).toBe(false); - }); - - it('should not show next button in step 3/3', function () { - $scope.workflow = { - steps: [{}, {}, {}] - }; - $scope.$digest(); - $scope.switchTo(2); - $scope.$digest(); - expect($(element).find('button.back').hasClass('ng-hide')).toBe(false); - expect($(element).find('button.next').hasClass('ng-hide')).toBe(true); - }); - - it('should have finish button disabled if wizardForm is invalid', function () { - $scope.wizardForm = { }; - $scope.$digest(); - $scope.wizardForm.$invalid = true; - $scope.$digest(); - expect(element[0].querySelector('button.finish').hasAttribute('disabled')).toBe(true); - }); - - it('should have finish button enabled if wizardForm is valid', function () { - $scope.wizardForm = { }; - $scope.$digest(); - $scope.wizardForm.$invalid = false; - $scope.$digest(); - expect(element[0].querySelector('button.finish').hasAttribute('disabled')).toBe(false); - }); - - it('should show error message after calling method showError', function () { - var errorMessage = 'some error message'; - $scope.$digest(); - $scope.showError(errorMessage); - $scope.$digest(); - expect(element[0].querySelector('.error-message').textContent).toBe(errorMessage); - }); - -}); diff --git a/code/horizon/horizon/static/angular/workflow/workflow.js b/code/horizon/horizon/static/angular/workflow/workflow.js deleted file mode 100644 index f33d478c..00000000 --- a/code/horizon/horizon/static/angular/workflow/workflow.js +++ /dev/null @@ -1,101 +0,0 @@ -(function () { - 'use strict'; - - /** - * @ngdoc overview - * @name hz.framework.workflow - * @description - * - * # hz.framework.workflow - * - * This module provides utility function service `workflow` to allow - * decorating a workflow object. A user (developer) friendly workflow - * specification object can be shaped into a format that is friendly to - * {@link hz.widget.wizard `wizard`} by utilizing this service. - * - * The service provides a mechanism of decoupling general wizard UI component - * from business components. - * - * | Factories | - * |--------------------------------------------------------------------------| - * | {@link hz.framework.workflow.factory:workflow `workflow`} | - * - */ - - angular.module('hz.framework.workflow', []) - - /** - * @ngdoc factory - * @name hz.framework.workflow.factory:workflow - * @module hz.framework.workflow - * @kind function - * @description - * - * Decorate the workflow specification object with specified decorators. - * - * @param {Object} The input workflow specification object - * @param {Array} decorators A list a decorator functions. - * - * @returns {Object} The decorated workflow specification object, the same - * reference to the input spec object. - * - ```js - - angular.module('MyModule', []) - - .factory('myService', ['$q', 'workflow', function ($q, workflow) { - - // a workflow specification object: - var spec = { - steps: [ - { requireSomeServices: true }, - { }, - { requireSomeServices: true } - ] - }; - - // define some decorators - var decorators = [ - // a decorator - function (spec) { - var steps = spec.steps; - - angular.forEach(steps, function (step) { - if (step.requireSomeServices) { - step.checkReadiness = function () { - var d = $q.defer(); - - // checking if the service is available asynchronously . - setTimeout(function () { - d.resolve(); - }, 500); - - return d.promise; - }; - } - }); - }, - - // another decorator - function (spec) { - //... - } - ]; - - return workflow(spec, decorators); - }]); - ``` - */ - - .factory('workflow', [ - function () { - return function (spec, decorators) { - angular.forEach(decorators, function (decorator) { - decorator(spec); - }); - return spec; - }; - } - ]); - -})(); diff --git a/code/horizon/horizon/static/angular/workflow/workflow.spec.js b/code/horizon/horizon/static/angular/workflow/workflow.spec.js deleted file mode 100644 index c408bd5e..00000000 --- a/code/horizon/horizon/static/angular/workflow/workflow.spec.js +++ /dev/null @@ -1,59 +0,0 @@ -(function () { - 'use strict'; - - describe('hz.framework.workflow module', function () { - it('should have been defined', function () { - expect(angular.module('hz.framework.workflow')).toBeDefined(); - }); - }); - - describe('workflow factory', function () { - - var workflow, - spec, - decorators = [ - function (spec) { - angular.forEach(spec.steps, function (step) { - if (step.requireSomeServices) { - step.checkReadiness = function () {}; - } - }); - } - ]; - - beforeEach(module('hz.framework.workflow')); - - beforeEach(inject(function ($injector) { - workflow = $injector.get('workflow'); - spec = { - steps: [ - { requireSomeServices: true }, - { }, - { requireSomeServices: true } - ] - }; - })); - - it('workflow is defined', function () { - expect(workflow).toBeDefined(); - }); - - it('workflow is a function', function () { - expect(angular.isFunction(workflow)).toBe(true); - }); - - it('can be decorated', function () { - workflow(spec, decorators); - var steps = spec.steps; - - expect(steps[0].checkReadiness).toBeDefined(); - expect(angular.isFunction(steps[0].checkReadiness)).toBe(true); - - expect(steps[1].checkReadiness).not.toBeDefined(); - - expect(steps[2].checkReadiness).toBeDefined(); - expect(angular.isFunction(steps[2].checkReadiness)).toBe(true); - }); - }); - -})(); diff --git a/code/horizon/horizon/static/horizon/js/angular/controllers/dummy.js b/code/horizon/horizon/static/horizon/js/angular/controllers/dummy.js deleted file mode 100644 index 0c930665..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/controllers/dummy.js +++ /dev/null @@ -1,5 +0,0 @@ -(function () { - 'use strict'; - angular.module('hz') - .controller('DummyCtrl', function () {}); -}()); diff --git a/code/horizon/horizon/static/horizon/js/angular/controllers/modal-form-update-metadata-ctrl.js b/code/horizon/horizon/static/horizon/js/angular/controllers/modal-form-update-metadata-ctrl.js deleted file mode 100644 index 39c6f95f..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/controllers/modal-form-update-metadata-ctrl.js +++ /dev/null @@ -1,23 +0,0 @@ -(function () { - 'use strict'; - angular.module('hz') - .controller('hzModalFormUpdateMetadataCtrl', [ - '$scope', '$window', - function ($scope, $window) { - $scope.tree = null; - $scope.available = $window.available_metadata.namespaces; - $scope.existing = $window.existing_metadata; - - $scope.saveMetadata = function () { - var metadata = []; - angular.forEach($scope.tree.getExisting(), function (value, key) { - metadata.push({ - key: key, - value: value - }); - }); - $scope.metadata = JSON.stringify(metadata); - }; - } - ]); -}()); \ No newline at end of file diff --git a/code/horizon/horizon/static/horizon/js/angular/controllers/namespace-controller.js b/code/horizon/horizon/static/horizon/js/angular/controllers/namespace-controller.js deleted file mode 100644 index 29d9bed3..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/controllers/namespace-controller.js +++ /dev/null @@ -1,12 +0,0 @@ -(function () { - 'use strict'; - angular.module('hz') - .controller('hzNamespaceResourceTypeFormController', function($scope, $window) { - $scope.resource_types = $window.resource_types; - - $scope.saveResourceTypes = function () { - $scope.resource_types = JSON.stringify($scope.resource_types); - $scope.namespace = namespace; - }; - }); -}()); \ No newline at end of file diff --git a/code/horizon/horizon/static/horizon/js/angular/directives/forms.js b/code/horizon/horizon/static/horizon/js/angular/directives/forms.js deleted file mode 100644 index a6ef2b52..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/directives/forms.js +++ /dev/null @@ -1,21 +0,0 @@ -(function () { - 'use strict'; - angular.module('hz') - .directive('notBlank', function () { - return { - require: 'ngModel', - link: function (scope, elm, attrs, ctrl) { - ctrl.$parsers.unshift(function (viewValue) { - if (viewValue.length) { - // it is valid - ctrl.$setValidity('notBlank', true); - return viewValue; - } - // it is invalid, return undefined (no model update) - ctrl.$setValidity('notBlank', false); - return undefined; - }); - } - }; - }); -}()); \ No newline at end of file diff --git a/code/horizon/horizon/static/horizon/js/angular/directives/serialConsole.js b/code/horizon/horizon/static/horizon/js/angular/directives/serialConsole.js deleted file mode 100644 index e50282f2..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/directives/serialConsole.js +++ /dev/null @@ -1,95 +0,0 @@ -/* -Copyright 2014, Rackspace, US, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -/*global Terminal,Blob,FileReader,gettext,interpolate */ -(function() { - 'use strict'; - - angular.module('serialConsoleApp', []) - .constant('protocols', ['binary', 'base64']) - .constant('states', [gettext('Connecting'), gettext('Open'), gettext('Closing'), gettext('Closed')]) - - /** - * @ngdoc directive - * @ngname serialConsole - * - * @description - * The serial-console element creates a terminal based on the widely-used term.js. - * The "connection" attribute is input to a WebSocket object, which connects - * to a server. In Horizon, this directive is used to connect to nova-serialproxy, - * opening a serial console to any instance. Each key the user types is transmitted - * to the instance, and each character the instance reponds with is displayed. - */ - .directive('serialConsole', function(protocols, states) { - return { - scope: true, - template: '

    {{statusMessage()}}', - restrict: 'E', - link: function postLink(scope, element, attrs) { - - var connection = scope.$eval(attrs.connection); - var term = new Terminal(); - var socket = new WebSocket(connection, protocols); - - socket.onerror = function() { - scope.$apply(scope.status); - }; - socket.onopen = function() { - scope.$apply(scope.status); - // initialize by "hitting enter" - socket.send(String.fromCharCode(13)); - }; - socket.onclose = function() { - scope.$apply(scope.status); - }; - - // turn the angular jQlite element into a raw DOM element so we can - // attach the Terminal to it - var termElement = angular.element(element)[0]; - term.open(termElement.ownerDocument.getElementById('terminalNode')); - - term.on('data', function(data) { - socket.send(data); - }); - - socket.onmessage = function(e) { - if (e.data instanceof Blob) { - var f = new FileReader(); - f.onload = function() { - term.write(f.result); - }; - f.readAsText(e.data); - } else { - term.write(e.data); - } - }; - - scope.status = function() { - return states[socket.readyState]; - }; - - scope.statusMessage = function() { - return interpolate(gettext('Status: %s'), [scope.status()]); - }; - - scope.$on('$destroy', function() { - socket.close(); - }); - - } - }; - }); -}()); \ No newline at end of file diff --git a/code/horizon/horizon/static/horizon/js/angular/filters/filters.js b/code/horizon/horizon/static/horizon/js/angular/filters/filters.js deleted file mode 100644 index 3159f0b4..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/filters/filters.js +++ /dev/null @@ -1,168 +0,0 @@ -/* - * (c) Copyright 2015 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -(function () { - 'use strict'; - - /** - * @ngdoc overview - * @name hz.filters - * @description - * hz.filters provides common filters to be used within Horizon. - * - */ - angular.module('hz.filters', []) - - /** - * @ngdoc filter - * @name yesno - * @description - * Evaluates given input as boolean and returns translation - * of 'Yes' and 'No' for true/false respectively. - */ - .filter('yesno', function() { - return function(input) { - return (input ? gettext("Yes") : gettext("No")); - }; - }) - - /** - * @ngdoc filter - * @name gb - * @description - * Expects numeric value and suffixes translated 'GB' with spacing. - * Returns empty string if input is not a number or is null. - */ - .filter('gb', function() { - return function(input) { - if (isNaN(input) || null === input) { - return ''; - } else { - return interpolate(gettext("%s GB"), [input.toString()]); - } - }; - }) - - /** - * @ngdoc filter - * @name mb - * @description - * Expects numeric value and suffixes translated 'MB' with spacing. - * Returns empty string if input is not a number or is null. - */ - .filter('mb', function() { - return function(input) { - if (isNaN(input) || null === input) { - return ''; - } else { - return interpolate(gettext("%s MB"), [input.toString()]); - } - }; - }) - - /** - * @ngdoc filter - * @name title - * @description - * Capitalizes leading characters of individual words. - */ - .filter('title', function() { - return function(input) { - if (typeof input !== 'string') { - return input; - } - return input.replace(/(?:^|\s)\S/g, function(a) { - return a.toUpperCase(); - }); - }; - }) - - /** - * @ngdoc filter - * @name noUnderscore - * @description - * Replaces all underscores with spaces. - */ - .filter('noUnderscore', function() { - return function(input) { - if (typeof input !== 'string') { - return input; - } - return input.replace(/_/g, ' '); - }; - }) - - /** - * @ngdoc filter - * @name decode - * @description - * Returns values based on key and given mapping. If key doesn't exist - * in given mapping, return key. This is useful when translations for - * codes are present. - */ - .filter('decode', function() { - return function(input, mapping) { - var val = mapping[input]; - return angular.isDefined(val) ? val : input; - }; - }) - - /** - * @ngdoc filter - * @name bytes - * @description - * Returns a human-readable approximation of the input of bytes, - * converted to a useful unit of measure. Uses 1024-based notation. - */ - .filter('bytes', function() { - return function(input) { - var kb = 1024; - var mb = kb*1024; - var gb = mb*1024; - var tb = gb*1024; - if (isNaN(input) || null === input || input < 0) { - return ''; - } else if (input >= tb) { - return interpolate(gettext("%s TB"), [Number(input/tb).toFixed(2)]); - } else if (input >= gb) { - return interpolate(gettext("%s GB"), [Number(input/gb).toFixed(2)]); - } else if (input >= mb) { - return interpolate(gettext("%s MB"), [Number(input/mb).toFixed(2)]); - } else if (input >= kb) { - return interpolate(gettext("%s KB"), [Number(input/kb).toFixed(2)]); - } else { - return interpolate(gettext("%s bytes"), [Math.floor(input)]); - } - }; - }) - - /** - * @ngdoc filter - * @name itemCount - * @description - * Displays translated count in table footer. - * Takes only finite numbers. - */ - .filter('itemCount', function() { - return function(input) { - var isNumeric = (input !== null && isFinite(input)); - var number = isNumeric ? Math.round(input): 0; - var count = (number > 0) ? number: 0; - var format = ngettext('Displaying %s item', 'Displaying %s items', count); - return interpolate(format, [count]); - }; - }); - -}()); diff --git a/code/horizon/horizon/static/horizon/js/angular/filters/filters.spec.js b/code/horizon/horizon/static/horizon/js/angular/filters/filters.spec.js deleted file mode 100644 index 72fabfa8..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/filters/filters.spec.js +++ /dev/null @@ -1,147 +0,0 @@ -describe('hz.filters', function () { - 'use strict'; - - beforeEach(module('hz.filters')); - - describe('yesno', function() { - - it('returns Yes for true', inject(function(yesnoFilter) { - expect(yesnoFilter(true)).toBe('Yes'); - })); - - it('returns No for false', inject(function(yesnoFilter) { - expect(yesnoFilter(false)).toBe('No'); - })); - - it('returns No for null', inject(function(yesnoFilter) { - expect(yesnoFilter(null)).toBe('No'); - })); - - }); - - describe('gb', function() { - - it('returns given numeric value properly', inject(function(gbFilter) { - expect(gbFilter(12)).toBe('12 GB'); - expect(gbFilter(-12)).toBe('-12 GB'); - expect(gbFilter(12.12)).toBe('12.12 GB'); - })); - - it('returns empty string for non-numeric', inject(function(gbFilter) { - expect(gbFilter('humbug')).toBe(''); - })); - - it('returns empty string for null', inject(function(gbFilter) { - expect(gbFilter(null)).toBe(''); - })); - - }); - - describe('mb', function() { - - it('returns given numeric value properly', inject(function(mbFilter) { - expect(mbFilter(12)).toBe('12 MB'); - expect(mbFilter(-12)).toBe('-12 MB'); - expect(mbFilter(12.12)).toBe('12.12 MB'); - })); - - it('returns empty string for non-numeric', inject(function(mbFilter) { - expect(mbFilter('humbug')).toBe(''); - })); - - it('returns empty string for null', inject(function(mbFilter) { - expect(mbFilter(null)).toBe(''); - })); - - }); - - describe('title', function() { - - it('capitalizes as expected', inject(function(titleFilter) { - expect(titleFilter('title')).toBe('Title'); - expect(titleFilter('we have several words')).toBe('We Have Several Words'); - })); - - }); - - describe('noUnderscore', function() { - - it('replaces all underscores with spaces', inject(function(noUnderscoreFilter) { - expect(noUnderscoreFilter('_this_is___a_lot____of_underscores__')).toBe(' this is a lot of underscores '); - })); - - it('returns falsy input', inject(function(noUnderscoreFilter) { - expect(noUnderscoreFilter(null)).toBe(null); - expect(noUnderscoreFilter(false)).toBe(false); - expect(noUnderscoreFilter('')).toBe(''); - })); - - }); - - describe("decode", function() { - - it("Returns value when key is present", inject(function(decodeFilter) { - expect(decodeFilter('PRESENT', {'PRESENT': 'Here'})).toBe('Here'); - })); - - it("Returns value when key is present and value is falsy", inject(function(decodeFilter) { - expect(decodeFilter('PRESENT', {'PRESENT': false})).toBe(false); - })); - - it("Returns input when key is not present", inject(function(decodeFilter) { - expect(decodeFilter('NOT_PRESENT', {'PRESENT': 'Here'})).toBe('NOT_PRESENT'); - })); - - }); - - describe('bytes', function() { - - it('returns TB values', inject(function(bytesFilter) { - expect(bytesFilter(1099511627776)).toBe('1.00 TB'); - })); - - it('returns GB values', inject(function(bytesFilter) { - expect(bytesFilter(1073741824)).toBe('1.00 GB'); - })); - - it('returns MB values', inject(function(bytesFilter) { - expect(bytesFilter(1048576)).toBe('1.00 MB'); - })); - - it('returns KB values', inject(function(bytesFilter) { - expect(bytesFilter(1024)).toBe('1.00 KB'); - })); - - it('returns byte values', inject(function(bytesFilter) { - expect(bytesFilter(0)).toBe('0 bytes'); - expect(bytesFilter(1)).toBe('1 bytes'); - expect(bytesFilter(1023)).toBe('1023 bytes'); - })); - - }); - - describe('itemCount', function() { - - it('should return translated text with item count', - inject(function(itemCountFilter) { - expect(itemCountFilter(null)).toBe('Displaying 0 items'); - expect(itemCountFilter(undefined)).toBe('Displaying 0 items'); - expect(itemCountFilter(true)).toBe('Displaying 1 item'); - expect(itemCountFilter(false)).toBe('Displaying 0 items'); - expect(itemCountFilter('a')).toBe('Displaying 0 items'); - expect(itemCountFilter('0')).toBe('Displaying 0 items'); - expect(itemCountFilter('1')).toBe('Displaying 1 item'); - expect(itemCountFilter('1e1')).toBe('Displaying 10 items'); - expect(itemCountFilter('1b1')).toBe('Displaying 0 items'); - expect(itemCountFilter(0)).toBe('Displaying 0 items'); - expect(itemCountFilter(1)).toBe('Displaying 1 item'); - expect(itemCountFilter(1.2)).toBe('Displaying 1 item'); - expect(itemCountFilter(1.6)).toBe('Displaying 2 items'); - expect(itemCountFilter(-1)).toBe('Displaying 0 items'); - expect(itemCountFilter(-1.2)).toBe('Displaying 0 items'); - }) - ); - - }); - -}); diff --git a/code/horizon/horizon/static/horizon/js/angular/horizon.conf.js b/code/horizon/horizon/static/horizon/js/angular/horizon.conf.js deleted file mode 100644 index 1fa60361..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/horizon.conf.js +++ /dev/null @@ -1,45 +0,0 @@ -/*global angular*/ -(function () { - 'use strict'; - angular.module('hz.conf', []) - .constant('hzConfig', { - // Placeholders; updated by Django. - debug: null, // - static_url: null, - ajax: { - queue_limit: null - }, - - // Config options which may be overridden. - spinner_options: { - inline: { - lines: 10, - length: 5, - width: 2, - radius: 3, - color: '#000', - speed: 0.8, - trail: 50, - zIndex: 100 - }, - modal: { - lines: 10, - length: 15, - width: 4, - radius: 10, - color: '#000', - speed: 0.8, - trail: 50 - }, - line_chart: { - lines: 10, - length: 15, - width: 4, - radius: 11, - color: '#000', - speed: 0.8, - trail: 50 - } - } - }); -}()); diff --git a/code/horizon/horizon/static/horizon/js/angular/horizon.js b/code/horizon/horizon/static/horizon/js/angular/horizon.js deleted file mode 100644 index 95eb3d96..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/horizon.js +++ /dev/null @@ -1,54 +0,0 @@ -/*global angularModuleExtension*/ -(function () { - 'use strict'; - - var horizon_dependencies = ['hz.conf', 'hz.utils', 'hz.api', 'ngCookies', 'hz.widgets', 'hz.filters']; - var dependencies = horizon_dependencies.concat(angularModuleExtension); - angular.module('hz', dependencies) - .config(['$interpolateProvider', '$httpProvider', - function ($interpolateProvider, $httpProvider) { - - // Replacing the default angular symbol - // allow us to mix angular with django templates - $interpolateProvider.startSymbol('{$'); - $interpolateProvider.endSymbol('$}'); - - // Http global settings for ease of use - $httpProvider.defaults.xsrfHeaderName = 'X-CSRFToken'; - $httpProvider.defaults.xsrfCookieName = 'csrftoken'; - $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest'; - $httpProvider.defaults.headers.common['Content-Type'] = 'application/json;charset=utf-8'; - - // Global http error handler - // if user is not authorized, log user out - // this can happen when session expires - $httpProvider.interceptors.push(function($q) { - return { - responseError: function(error) { - if (error.status === 401){ - window.location.replace('/auth/logout'); - } - return $q.reject(error); - } - }; - }); - }]) - .run(['hzConfig', 'hzUtils', '$cookieStore', '$http', '$cookies', - function (hzConfig, hzUtils, $cookieStore, $http, $cookies) { - $http.defaults.headers.post['X-CSRFToken'] = $cookies.csrftoken; - //expose the configuration for horizon legacy variable - horizon.conf = hzConfig; - horizon.utils = hzUtils; - angular.extend(horizon.cookies = {}, $cookieStore); - horizon.cookies.put = function (key, value) { - //cookies are updated at the end of current $eval, so for the horizon - //namespace we need to wrap it in a $apply function. - angular.element('body').scope().$apply(function () { - $cookieStore.put(key, value); - }); - }; - horizon.cookies.getRaw = function (key) { - return $cookies[key]; - }; - }]); -}()); diff --git a/code/horizon/horizon/static/horizon/js/angular/hz.api.module.js b/code/horizon/horizon/static/horizon/js/angular/hz.api.module.js deleted file mode 100644 index 6aa9b3e6..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/hz.api.module.js +++ /dev/null @@ -1,20 +0,0 @@ -/* -Copyright 2014, Rackspace, US, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -/*global angular*/ -(function () { - 'use strict'; - angular.module('hz.api', ['hz.api.service']); -}()); \ No newline at end of file diff --git a/code/horizon/horizon/static/horizon/js/angular/services/horizon.utils.js b/code/horizon/horizon/static/horizon/js/angular/services/horizon.utils.js deleted file mode 100644 index ccafc368..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/services/horizon.utils.js +++ /dev/null @@ -1,66 +0,0 @@ -/*global angular*/ -(function () { - 'use strict'; - function utils(hzConfig, $log, $rootScope, $compile) { - return { - /* - Use the log levels of http://docs.angularjs.org/api/ng.$log - default to log level. - */ - log: function (msg, lvl) { - if (hzConfig.debug) { - ($log[lvl] || $log.log)(msg); - } - }, - capitalize: function (string) { - return string.charAt(0).toUpperCase() + string.slice(1); - }, - /* - Adds commas to any integer or numbers within a string for human display. - - EG: - horizon.utils.humanizeNumbers(1234); -> "1,234" - horizon.utils.humanizeNumbers("My Total: 1234"); -> "My Total: 1,234" - */ - humanizeNumbers: function (number) { - return number.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ","); - }, - - /* - Truncate a string at the desired length. Optionally append an ellipsis - to the end of the string. - - EG: - horizon.utils.truncate("String that is too long.", 18, true); -> - "String that is too…" - */ - truncate: function (string, size, includeEllipsis) { - if (string.length > size) { - if (includeEllipsis) { - return string.substring(0, (size - 3)) + "…"; - } - - return string.substring(0, size); - } - - return string; - }, - loadAngular: function (element) { - try { - $compile(element)($rootScope); - $rootScope.$apply(); - } catch (err) {} - /* - Compilation fails when it could not find a directive, - fails silently on this, it is an angular behaviour. - */ - - }, - - }; - } - angular.module('hz.utils.hzUtils', ['hz.conf']) - .service('hzUtils', ['hzConfig', '$log', '$rootScope', '$compile', utils]); - - angular.module('hz.utils', ['hz.utils.hzUtils']); -}()); \ No newline at end of file diff --git a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.cinder.js b/code/horizon/horizon/static/horizon/js/angular/services/hz.api.cinder.js deleted file mode 100644 index db232d45..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.cinder.js +++ /dev/null @@ -1,83 +0,0 @@ -/* -Copyright 2015 IBM Corp. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -(function () { - 'use strict'; - - /** - * @ngdoc service - * @name hz.api.cinderAPI - * @description Provides direct access to Cinder APIs. - */ - function CinderAPI(apiService) { - - // Volumes - - /** - * @name hz.api.cinderAPI.getVolumes - * @description - * Get a list of volumes. - * - * The listing result is an object with property "items." Each item is - * a volume. - * - * @param {Object} params - * Query parameters. Optional. - * - * @param {string} param.search_opts - * Filters to pass through the API. - * For example, "status": "available" will show all available volumes. - */ - this.getVolumes = function(params) { - var config = (params) ? {'params': params} : {}; - return apiService.get('/api/cinder/volumes/', config) - .error(function () { - horizon.alert('error', gettext('Unable to retrieve volumes.')); - }); - }; - - // Volume Snapshots - - /** - * @name hz.api.cinderAPI.getVolumeSnapshots - * @description - * Get a list of volume snapshots. - * - * The listing result is an object with property "items." Each item is - * a volume snapshot. - * - * @param {Object} params - * Query parameters. Optional. - * - * @param {string} param.search_opts - * Filters to pass through the API. - * For example, "status": "available" will show all available volume - * snapshots. - */ - this.getVolumeSnapshots = function(params) { - var config = (params) ? {'params': params} : {}; - return apiService.get('/api/cinder/volumesnapshots/', config) - .error(function () { - horizon.alert('error', - gettext('Unable to retrieve volume snapshots.')); - }); - }; - } - - // Register it with the API module so that anybody using the - // API module will have access to the Cinder APIs. - angular.module('hz.api') - .service('cinderAPI', ['apiService', CinderAPI]); -}()); diff --git a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.config.js b/code/horizon/horizon/static/horizon/js/angular/services/hz.api.config.js deleted file mode 100644 index e7315ef7..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.config.js +++ /dev/null @@ -1,313 +0,0 @@ -/* - * Copyright 2015 IBM Corp - * (c) Copyright 2015 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -(function () { - 'use strict'; - - /** - * @ngdoc service - * @name hz.api.configAPI - * @description Provides access to dashboard configuration. - */ - function ConfigAPI(apiService) { - - /** - * @name hz.api.configAPI.getUserDefaults - * @description - * Get the default user configuration settings. - * - * Returns an object with user configuration settings. - */ - this.getUserDefaults = function() { - return apiService.get('/api/config/user/') - .success(function(data) { - // store config in localStorage - // should be call only when defaults are needed - // or when user wants to reset it - localStorage.user_config = angular.toJson(data); - }) - .error(function () { - horizon.alert('error', gettext('Unable to retrieve user configuration.')); - }); - }; - - /** - * @name hz.api.configAPI.getAdminDefaults - * @description - * Get the default admin configuration settings. - * - * Returns an object with admin configuration settings. - */ - this.getAdminDefaults = function(params) { - return apiService.get('/api/config/admin/') - .success(function(data) { - // store this in localStorage - // should be call once each page load - localStorage.admin_config = angular.toJson(data); - }) - .error(function () { - horizon.alert('error', gettext('Unable to retrieve admin configuration.')); - }); - }; - - } - - // Register it with the API module so that anybody using the - // API module will have access to the Config APIs. - angular.module('hz.api') - .service('configAPI', ['apiService', ConfigAPI]); - - /** - * @ngdoc service - * @name hz.api.settingsService - * @description - * Provides utilities to the cached settings data. This helps - * with asynchronous data loading. - * - * The cache in current horizon (Kilo non-single page app) only has a - * lifetime of the current page. The cache is reloaded every time you change - * panels. It also happens when you change the region selector at the top - * of the page, and when you log back in. - * - * So, at least for now, this seems to be a reliable way that will - * make only a single request to get user information for a - * particular page or modal. Making this a service allows it to be injected - * and used transparently where needed without making every single use of it - * pass it through as an argument. - */ - function settingsService($q, apiService) { - - var service = {}; - - /** - * @name hz.api.configAPI.getSettings - * @description - * Gets all the allowed settings - * - * Returns an object with settings. - */ - service.getSettings = function (suppressError) { - - function onError() { - var message = gettext('Unable to retrieve settings.'); - if (!suppressError && horizon.alert) { - horizon.alert('error', message); - } - - return message; - } - - // The below ensures that errors are handled like other - // service errors (for better or worse), but when successful - // unwraps the success result data for direct consumption. - return apiService.get('/api/settings/', {cache: true}) - .error(onError) - .then(function (response) { - return response.data; - }); - }; - - /** - * @name hz.api.settingsService.getSetting - * @description - * This retrieves a specific setting. - * - * If the setting isn't found, it will return undefined unless a default - * is specified. In that case, the default will be returned. - * - * @param {string} setting The path to the setting to get. - * - * local_settings.py allows you to create settings such as: - * - * OPENSTACK_HYPERVISOR_FEATURES = { - * 'can_set_mount_point': True, - * 'can_set_password': False, - * } - * - * To access a specific setting, use a simplified path where a . (dot) - * separates elements in the path. So in the above example, the paths - * would be: - * - * OPENSTACK_HYPERVISOR_FEATURES.can_set_mount_point - * OPENSTACK_HYPERVISOR_FEATURES.can_set_password - * - * @param {object=} defaultSetting If the requested setting does not exist, - * the defaultSetting will be returned. This is optional. - * - * @example - * - * Using the OPENSTACK_HYPERVISOR_FEATURES mentioned above, the following - * would call doSomething and pass the setting value into doSomething. - * - ```js - settingsService.getSetting('OPENSTACK_HYPERVISOR_FEATURES.can_set_mount_point') - .then(doSomething); - ``` - */ - service.getSetting = function (path, defaultSetting) { - var deferred = $q.defer(), - pathElements = path.split("."), - settingAtRequestedPath; - - function onSettingsLoaded(settings) { - // This recursively traverses the object hierarchy until either all the - // path elements are traversed or until the next element in the path - // does not have the requested child object. - settingAtRequestedPath = pathElements.reduce( - function (setting, nextPathElement) { - return setting ? setting[nextPathElement] : undefined; - }, settings); - - if (typeof settingAtRequestedPath === "undefined" && - (typeof defaultSetting !== "undefined")) { - settingAtRequestedPath = defaultSetting; - } - - deferred.resolve(settingAtRequestedPath); - } - - function onSettingsFailure(message) { - deferred.reject(message); - } - - service.getSettings() - .then(onSettingsLoaded, onSettingsFailure); - - return deferred.promise; - }; - - /** - * @name hz.api.settingsService.ifEnabled - * @description - * Checks if the desired setting is enabled. This returns a promise. - * If the setting is enabled, the promise will be resolved. - * If it is not enabled, the promise will be rejected. Use it like you - * would normal promises. - * - * @param {string} setting The path to the setting to check. - * local_settings.py allows you to create settings such as: - * - * OPENSTACK_HYPERVISOR_FEATURES = { - * 'can_set_mount_point': True, - * 'can_set_password': False, - * } - * - * To access a specific setting, use a simplified path where a . (dot) - * separates elements in the path. So in the above example, the paths - * would be: - * - * OPENSTACK_HYPERVISOR_FEATURES.can_set_mount_point - * OPENSTACK_HYPERVISOR_FEATURES.can_set_password - * - * @param (object=} expected Used to determine if the setting is - * enabled. The actual setting will be evaluated against the expected - * value using angular.equals(). If they are equal, then it will be - * considered enabled. This is optional and defaults to True. - * - * @param {object=} defaultSetting If the requested setting does not exist, - * the defaultSetting will be used for evaluation. This is optional. If - * not specified and the setting is not specified, then the setting will - * not be considered to be enabled. - * - * @example - * Simple true / false example: - * - * Using the OPENSTACK_HYPERVISOR_FEATURES mentioned above, the following - * would call the "setMountPoint" function only if - * OPENSTACK_HYPERVISOR_FEATURES.can_set_mount_point is set to true. - * - ```js - settingsService.ifEnabled('OPENSTACK_HYPERVISOR_FEATURES.can_set_mount_point') - .then(setMountPoint); - ``` - * - * Evaluating other types of settings: - * - * local_settings.py allows you optionally set the enabled OpenStack - * Service API versions with the following setting: - * - * OPENSTACK_API_VERSIONS = { - * "data-processing": 1.1, - * "identity": 3, - * "volume": 2, - * } - * - * The above is a nested object structure. The simplified path to the - * volume service version is OPENSTACK_API_VERSIONS.volume - * - * It is not uncommon for different OpenStack deployments to have - * different versions of the service enabled for various reasons. - * - * So, now, assume that if version 2 of the volume service (Cinder) is - * enabled that you want to do something. If it isn't, then you will do - * something else. - * - * Assume doSomethingIfVersion2 is a function you want to call if version 2 - * is enabled. - * - * Assume doSomethingElse is a function that does something else if - * version 2 is not enabled (optional) - * - ```js - settingsService.ifEnabled('OPENSTACK_API_VERSIONS.volume', 2) - .then(doSomethingIfVersion2, doSomethingElse); - ``` - * - * Now assume that if nothing is set in local_settings, that you want to - * treat the result as if version 1 is enabled (default when nothing set). - * - ```js - settingsService.ifEnabled('OPENSTACK_API_VERSIONS.volume', 2, 1) - .then(doSomethingIfVersion2, doSomethingElse); - ``` - */ - service.ifEnabled = function (setting, expected, defaultSetting) { - var deferred = $q.defer(); - - // If expected is not defined, we default to expecting the setting - // to be 'true' in order for it to be considered enabled. - expected = (typeof expected === "undefined") ? true : expected; - - function onSettingLoaded(setting) { - if (angular.equals(expected, setting)) { - deferred.resolve(); - } else { - deferred.reject(interpolate( - gettext('Setting is not enabled: %(setting)s'), - {setting: setting}, - true)); - } - - deferred.resolve(setting); - } - - function onSettingFailure(message) { - deferred.reject(message); - } - - service.getSetting(setting, defaultSetting) - .then(onSettingLoaded, onSettingFailure); - - return deferred.promise; - }; - - return service; - } - - angular.module('hz.api') - .factory('settingsService', ['$q', 'apiService', settingsService]); - -}()); diff --git a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.config.spec.js b/code/horizon/horizon/static/horizon/js/angular/services/hz.api.config.spec.js deleted file mode 100644 index 7a439766..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.config.spec.js +++ /dev/null @@ -1,253 +0,0 @@ -/* - * (c) Copyright 2015 Hewlett-Packard Development Company, L.P. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -/*global angular,describe,it,expect,inject,module,beforeEach,afterEach*/ -(function () { - 'use strict'; - - describe('settingsService', function () { - var settingsService, - $httpBackend, - responseMockOpts = {succeed: true}, - testData = { - isTrue: true, - isFalse: false, - versions: {one: 1, two: 2}, - deep: {nest: { foo: 'bar' } }, - isNull: null - }; - - beforeEach(module('hz.api')); - beforeEach(inject(function (_$httpBackend_, _settingsService_) { - responseMockOpts.succeed = true; - settingsService = _settingsService_; - $httpBackend = _$httpBackend_; - $httpBackend.whenGET('/api/settings/').respond( - function () { - return responseMockOpts.succeed ? - [200, testData, {}] : [500, 'Fail', {}]; - }); - $httpBackend.expectGET('/api/settings/'); - })); - - afterEach(function () { - $httpBackend.verifyNoOutstandingExpectation(); - $httpBackend.verifyNoOutstandingRequest(); - }); - - describe('getSettings', function () { - - it('should return all settings', function () { - settingsService.getSettings().then( - function (actual) { - expect(actual).toEqual(testData); - } - ); - $httpBackend.flush(); - }); - - it('should fail when error response', function () { - responseMockOpts.succeed = false; - settingsService.getSettings().then( - function (actual) { - fail('Should not have succeeded: ' + angular.toJson(actual)); - }, - function (actual) { - expect(actual).toBeDefined(); - } - ); - $httpBackend.flush(); - }); - - }); - - describe('getSetting', function () { - - it('nested deep object is found', function () { - settingsService.getSetting('deep.nest.foo') - .then(function (actual) { - expect(actual).toEqual('bar'); - }); - $httpBackend.flush(); - }); - - it("is undefined when doesn't exist", function () { - settingsService.getSetting('will.not.exist') - .then(function (actual) { - expect(actual).toBeUndefined(); - }); - $httpBackend.flush(); - }); - - it("default is returned when doesn't exist", function () { - var actual; - settingsService.getSetting('will.not.exist', 'hello') - .then(function (actual) { - expect(actual).toEqual('hello'); - }); - $httpBackend.flush(); - }); - - it('should return true', function () { - settingsService.getSetting('isTrue') - .then(function (actual) { - expect(actual).toEqual(true); - }); - $httpBackend.flush(); - }); - - it('should fail when error response', function () { - responseMockOpts.succeed = false; - settingsService.getSetting('isTrue').then( - function (actual) { - fail('Should not have succeeded: ' + angular.toJson(actual)); - }, - function (actual) { - expect(actual).toBeDefined(); - } - ); - $httpBackend.flush(); - }); - - }); - - describe('ifEnabled', function () { - - var expectedResult = {}; - - var enabled = function () { - expectedResult.enabled = true; - }; - - var notEnabled = function () { - expectedResult.enabled = false; - }; - - beforeEach(inject(function () { - expectedResult = {enabled: null}; - })); - - function meetsExpectations(expected) { - $httpBackend.flush(); - expect(expectedResult.enabled).toBe(expected); - } - - it('should fail when error response', function () { - responseMockOpts.succeed = false; - settingsService.ifEnabled('isTrue').then( - function (actual) { - fail('Should not have succeeded: ' + angular.toJson(actual)); - }, - function (actual) { - expect(actual).toBeDefined(); - } - ); - $httpBackend.flush(); - }); - - it('boolean is enabled when true', function () { - settingsService.ifEnabled('isTrue').then(enabled, notEnabled); - meetsExpectations(true); - }); - - it('boolean is enabled when true expected', function () { - settingsService.ifEnabled('isTrue', true).then(enabled, notEnabled); - meetsExpectations(true); - }); - - it('boolean is not enabled when false expected', function () { - settingsService.ifEnabled('isTrue', false).then(enabled, notEnabled); - meetsExpectations(false); - }); - - it('boolean is not enabled when false', function () { - settingsService.ifEnabled('isFalse').then(enabled, notEnabled); - meetsExpectations(false); - }); - - it('boolean is enabled when false expected', function () { - settingsService.ifEnabled('isFalse', false).then(enabled, notEnabled); - meetsExpectations(true); - }); - - it('nested object is enabled when expected', function () { - settingsService.ifEnabled('versions.one', 1).then(enabled, notEnabled); - meetsExpectations(true); - }); - - it('nested object is not enabled', function () { - settingsService.ifEnabled('versions.two', 1).then(enabled, notEnabled); - meetsExpectations(false); - }); - - it('nested object is not enabled when not found', function () { - settingsService.ifEnabled('no-exist.two', 1).then(enabled, notEnabled); - meetsExpectations(false); - }); - - it('nested deep object is enabled when expected', function () { - settingsService.ifEnabled('deep.nest.foo', 'bar').then(enabled, notEnabled); - meetsExpectations(true); - }); - - it('nested deep object is not enabled when not expected', function () { - settingsService.ifEnabled('deep.nest.foo', 'wrong').then(enabled, notEnabled); - meetsExpectations(false); - }); - - it('null is not enabled', function () { - settingsService.ifEnabled('isNull').then(enabled, notEnabled); - meetsExpectations(false); - }); - - it('null is enabled when expected', function () { - settingsService.ifEnabled('isNull', null).then(enabled, notEnabled); - meetsExpectations(true); - }); - - it('true is enabled when not found and true default', function () { - settingsService.ifEnabled('nonExistent', true, true).then(enabled, notEnabled); - meetsExpectations(true); - }); - - it('true is not enabled when not found and false default', function () { - settingsService.ifEnabled('nonExistent', true, false).then(enabled, notEnabled); - meetsExpectations(false); - }); - - it('true is not enabled when not found and no default', function () { - settingsService.ifEnabled('nonExistent', true).then(enabled, notEnabled); - meetsExpectations(false); - }); - - it('false is enabled when not found and expected w/ default', function () { - settingsService.ifEnabled('nonExistent', false, false).then(enabled, notEnabled); - meetsExpectations(true); - }); - - it('bar is enabled when expected not found and bar default', function () { - settingsService.ifEnabled('nonExistent', 'bar', 'bar').then(enabled, notEnabled); - meetsExpectations(true); - }); - - it('bar is not enabled when expected not found and not default', function () { - settingsService.ifEnabled('nonExistent', 'bar', 'foo').then(enabled, notEnabled); - meetsExpectations(false); - }); - }); - - }); - -})(); diff --git a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.glance.js b/code/horizon/horizon/static/horizon/js/angular/services/hz.api.glance.js deleted file mode 100644 index fd0cbc23..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.glance.js +++ /dev/null @@ -1,156 +0,0 @@ -/* -Copyright 2015, Hewlett-Packard Development Company, L.P. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -(function () { - 'use strict'; - - /** - * @ngdoc service - * @name hz.api.glanceAPI - * @description Provides direct pass through to Glance with NO abstraction. - */ - function GlanceAPI(apiService) { - - // Images - - /** - * @name hz.api.glanceAPI.getImage - * @description - * Get a single image by ID - * @param {string} id - * Specifies the id of the image to request. - */ - this.getImage = function(id) { - return apiService.get('/api/glance/images/' + id) - .error(function () { - horizon.alert('error', gettext('Unable to retrieve image.')); - }); - }; - - - /** - * @name hz.api.glanceAPI.getImages - * @description - * Get a list of images. - * - * The listing result is an object with property "items". Each item is - * an image. - * - * @param {Object} params - * Query parameters. Optional. - * - * @param {boolean} params.paginate - * True to paginate automatically. - * - * @param {string} params.marker - * Specifies the image of the last-seen image. - * - * The typical pattern of limit and marker is to make an - * initial limited request and then to use the last - * image from the response as the marker parameter - * in a subsequent limited request. With paginate, limit - * is automatically set. - * - * @param {string} params.sort_dir - * The sort direction ('asc' or 'desc'). - * - * @param {string} params.sort_key - * The field to sort on (for example, 'created_at'). - * Default is created_at. - * - * @param {string} params.other - * Any additional request parameters will be passed through the API as - * filters. For example "name" : "fedora" would filter on the fedora name. - */ - this.getImages = function(params) { - var config = (params) ? { 'params' : params} : {}; - return apiService.get('/api/glance/images/', config) - .error(function () { - horizon.alert('error', gettext('Unable to retrieve images.')); - }); - }; - - // Metadata Definitions - Namespaces - - /** - * @name hz.api.glanceAPI.getNamespaces - * @description - * Get a list of metadata definition namespaces. - * - * http://docs.openstack.org/developer/glance/metadefs-concepts.html - * - * The listing result is an object with property "items". Each item is - * an namespace. - * - * @description - * Get a list of namespaces. - * - * The listing result is an object with property "items". Each item is - * a namespace. - * - * @param {Object} params - * Query parameters. Optional. - * - * @param {string} params.resource_type - * Namespace resource type. - * - * @param {boolean} params.paginate - * True to paginate automatically. - * - * @param {string} params.marker - * Specifies the namespace of the last-seen namespace. - * - * The typical pattern of limit and marker is to make an - * initial limited request and then to use the last - * namespace from the response as the marker parameter - * in a subsequent limited request. With paginate, limit - * is automatically set. - * - * @param {string} params.sort_dir - * The sort direction ('asc' or 'desc'). - * - * @param {string} params.sort_key - * The field to sort on (for example, 'created_at'). - * Default is namespace. - * - * @param {string} params.other - * Any additional request parameters will be passed through the API as - * filters. - * - * @param {boolean} suppressError - * If passed in, this will not show the default error handling - * (horizon alert). The glance API may not have metadata definitions - * enabled. - */ - this.getNamespaces = function(params, suppressError) { - var config = (params) ? {'params' : params} : {}; - config.cache = true; - - var promise = apiService.get('/api/glance/metadefs/namespaces/', config); - - return suppressError ? promise : promise.error(function() { - horizon.alert('error', gettext('Unable to retrieve namespaces.')); - }); - }; - - } - - // Register it with the API module so that anybody using the - // API module will have access to the Glance APIs. - - angular.module('hz.api') - .service('glanceAPI', ['apiService', GlanceAPI]); - -}()); diff --git a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.keystone.js b/code/horizon/horizon/static/horizon/js/angular/services/hz.api.keystone.js deleted file mode 100644 index be51f3ec..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.keystone.js +++ /dev/null @@ -1,437 +0,0 @@ -/* -Copyright 2014, Rackspace, US, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -(function () { - 'use strict'; - function KeystoneAPI(apiService) { - // Users - this.getUsers = function(params) { - var config = (params) ? {'params': params} : {}; - return apiService.get('/api/keystone/users/', config) - .error(function () { - horizon.alert('error', gettext('Unable to retrieve users')); - }); - }; - - this.createUser = function(newUser) { - return apiService.post('/api/keystone/users/', newUser) - .error(function () { - horizon.alert('error', gettext('Unable to create the user.')); - }); - }; - - this.deleteUsers = function(user_ids) { - return apiService.delete('/api/keystone/users/', user_ids) - .error(function () { - horizon.alert('error', gettext('Unable to delete the users.')); - }); - }; - - /** - * @name hz.api.keystoneApi.getCurrentUserSession - * @description - * Gets the current User Session Information - * @example - * { - * "available_services_regions": [ - * "RegionOne" - * ], - * "domain_id": null, - * "domain_name": null, - * "enabled": true, - * "id": "2138efda19264c64b69551c6b08054c9", - * "is_superuser": true, - * "project_id": "53fafe441399439a852d3bd81c22caf6", - * "project_name": "demo", - * "roles": [ - * { - * "name": "admin" - * } - * ], - * "services_region": "RegionOne", - * "user_domain_id": "default", - * "user_domain_name": "Default", - * "username": "admin" - * } - */ - this.getCurrentUserSession = function(config) { - return apiService.get('/api/keystone/user-session/', config) - .error(function () { - horizon.alert('error', - gettext('Unable to retrieve the current user session.')); - }); - }; - - this.getUser = function(user_id) { - return apiService.get('/api/keystone/users/' + user_id) - .error(function () { - horizon.alert('error', gettext('Unable to retrieve the user')); - }); - }; - - this.editUser = function(updatedUser) { - var url = '/api/keystone/users/' + updatedUser.id; - return apiService.patch(url, updatedUser) - .error(function () { - horizon.alert('error', gettext('Unable to edit the user.')); - }); - }; - - this.deleteUser = function(user_id) { - return apiService.delete('/api/keystone/users/' + user_id) - .error(function () { - horizon.alert('error', gettext('Unable to delete the user.')); - }); - }; - - // Roles - this.getRoles = function() { - return apiService.get('/api/keystone/roles/') - .error(function () { - horizon.alert('error', gettext('Unable to retrieve role')); - }); - }; - - this.createRole = function(newRole) { - return apiService.post('/api/keystone/roles/', newRole) - .error(function () { - horizon.alert('error', gettext('Unable to create the role.')); - }); - }; - - this.deleteRoles = function(role_ids) { - return apiService.delete('/api/keystone/roles/', role_ids) - .error(function () { - horizon.alert('error', gettext('Unable to delete the roles.')); - }); - }; - - this.getRole = function(role_id) { - return apiService.get('/api/keystone/roles/' + role_id) - .error(function () { - horizon.alert('error', gettext('Unable to retrieve the role')); - }); - }; - - this.editRole = function(updatedRole) { - var url = '/api/keystone/roles/' + updatedRole.id; - return apiService.patch(url, updatedRole) - .error(function () { - horizon.alert('error', gettext('Unable to edit the role.')); - }); - }; - - this.deleteRole = function(role_id) { - return apiService.delete('/api/keystone/roles/' + role_id) - .error(function () { - horizon.alert('error', gettext('Unable to delete the role.')); - }); - }; - - // Domains - this.getDomains = function() { - return apiService.get('/api/keystone/domains/') - .error(function () { - horizon.alert('error', gettext('Unable to retrieve domains')); - }); - }; - - this.createDomain = function(newDomain) { - return apiService.post('/api/keystone/domains/', newDomain) - .error(function () { - horizon.alert('error', gettext('Unable to create the domain.')); - }); - }; - - this.deleteDomains = function(domain_ids) { - return apiService.delete('/api/keystone/domains/', domain_ids) - .error(function () { - horizon.alert('error', gettext('Unable to delete the domains.')); - }); - }; - - this.getDomain = function(domain_id) { - return apiService.get('/api/keystone/domains/' + domain_id) - .error(function () { - horizon.alert('error', gettext('Unable to retrieve the domain')); - }); - }; - - this.editDomain = function(updatedDomain) { - var url = '/api/keystone/domains/' + updatedDomain.id; - return apiService.patch(url, updatedDomain) - .error(function () { - horizon.alert('error', gettext('Unable to edit the domain.')); - }); - }; - - this.deleteDomain = function(domain_id) { - return apiService.delete('/api/keystone/domains/' + domain_id) - .error(function () { - horizon.alert('error', gettext('Unable to delete the domain.')); - }); - }; - - // Projects - this.getProjects = function(params) { - var config = (params) ? {'params': params} : {}; - return apiService.get('/api/keystone/projects/', config) - .error(function () { - horizon.alert('error', gettext('Unable to retrieve projects')); - }); - }; - - this.createProject = function(newProject) { - return apiService.post('/api/keystone/projects/', newProject) - .error(function () { - horizon.alert('error', gettext('Unable to create the project.')); - }); - }; - - this.deleteProjects = function(project_ids) { - return apiService.delete('/api/keystone/projects/', project_ids) - .error(function () { - horizon.alert('error', gettext('Unable to delete the projects.')); - }); - }; - - this.getProject = function(project_id) { - return apiService.get('/api/keystone/projects/' + project_id) - .error(function () { - horizon.alert('error', gettext('Unable to retrieve the project')); - }); - }; - - this.editProject = function(updatedProject) { - var url = '/api/keystone/projects/' + updatedProject.id; - return apiService.patch(url, updatedProject) - .error(function () { - horizon.alert('error', gettext('Unable to edit the project.')); - }); - }; - - this.deleteProject = function(project_id) { - return apiService.delete('/api/keystone/projects/' + project_id) - .error(function () { - horizon.alert('error', gettext('Unable to delete the project.')); - }); - }; - - this.grantRole = function(project_id, role_id, user_id) { - return apiService.delete('/api/keystone/projects/' + project_id + '/' + - role_id + '/' + user_id) - .error(function () { - horizon.alert('error', gettext('Unable to grant the role.')); - }); - }; - - /** - * @name hz.api.keyStoneAPI.serviceCatalog - * @description - * Returns the service catalog. - * @param {Object} config - * See $http config object parameters. - */ - this.serviceCatalog = function(config) { - return apiService.get('/api/keystone/svc-catalog/', config) - .error(function () { - horizon.alert('error', gettext('Unable to fetch the service catalog.')); - }); - }; - } - - angular.module('hz.api') - .service('keystoneAPI', ['apiService', KeystoneAPI]); - - /** - * @ngdoc service - * @name hz.api.userSession - * @description - * Provides cached access to the user session. The cache may be reset - * at any time by accessing the cache and calling removeAll, which means - * that the next call to any function in this service will retrieve fresh - * results after the cache is cleared. This allows programmatic refresh of - * the cache. - * - * The cache in current horizon (Kilo non-single page app) only has a - * lifetime of the current page. The cache is reloaded every time you change - * panels. It also happens when you change the region selector at the top - * of the page, and when you log back in. - * - * So, at least for now, this seems to be a reliable way that will - * make only a single request to get user information for a - * particular page or modal. Making this a service allows it to be injected - * and used transparently where needed without making every single use of it - * pass it through as an argument. - */ - function userSession($cacheFactory, keystoneAPI) { - - var service = {}; - - service.cache = $cacheFactory('hz.api.userSession', {capacity: 1}); - - service.get = function () { - return keystoneAPI.getCurrentUserSession({cache: service.cache}) - .then(function (response) { - return response.data; - } - ); - }; - - return service; - } - - angular.module('hz.api') - .factory('userSession', ['$cacheFactory', 'keystoneAPI', userSession]); - - /** - * @ngdoc service - * @name hz.api.serviceCatalog - * @description - * Provides cached access to the Service Catalog with utilities to help - * with asynchronous data loading. The cache may be reset at any time - * by accessing the cache and calling removeAll. The next call to any - * function will retrieve fresh results. - * - * The cache in current horizon (Kilo non-single page app) only has a - * lifetime of the current page. The cache is reloaded every time you change - * panels. It also happens when you change the region selector at the top - * of the page, and when you log back in. - * - * So, at least for now, this seems to be a reliable way that will - * make only a single request to get user information for a - * particular page or modal. Making this a service allows it to be injected - * and used transparently where needed without making every single use of it - * pass it through as an argument. - */ - function serviceCatalog($cacheFactory, $q, keystoneAPI, userSession) { - - var service = {}; - service.cache = $cacheFactory('hz.api.serviceCatalog', {capacity: 1}); - - /** - * @name hz.api.serviceCatalog.get - * @description - * Returns the service catalog. This is cached. - * - * @example - * - ```js - serviceCatalog.get() - .then(doSomething, doSomethingElse); - ``` - */ - service.get = function() { - return keystoneAPI.serviceCatalog({cache: service.cache}) - .then(function(response){ - return response.data; - } - ); - }; - - /** - * @name hz.api.serviceCatalog.ifTypeEnabled - * @description - * Checks if the desired service is enabled. If it is enabled, use the - * promise returned to execute the desired function. If it is not enabled, - * The promise will be rejected. - * - * @param {string} desiredType The type of service desired. - * - * @example - * Assume if the network service is enabled, you want to get networks, - * if it isn't, then you will do something else. - * Assume getNetworks is a function that hits Neutron. - * Assume doSomethingElse is a function that does something else if - * the network service is not enabled (optional) - * - ```js - serviceCatalog.ifTypeEnabled('network') - .then(getNetworks, doSomethingElse); - ``` - */ - service.ifTypeEnabled = function (desiredType) { - var deferred = $q.defer(); - - $q.all( - { - session: userSession.get(), - catalog: service.get() - } - ).then( - onDataLoaded, - onDataFailure - ); - - function onDataLoaded(d) { - if (typeHasEndpointsInRegion(d.catalog, - desiredType, - d.session.services_region)) { - deferred.resolve(); - } else { - deferred.reject(interpolate( - gettext('Service type is not enabled: %(desiredType)s'), - {desiredType: desiredType}, - true)); - } - } - - function onDataFailure() { - deferred.reject(gettext('Cannot get service catalog from keystone.')); - } - - return deferred.promise; - }; - - function typeHasEndpointsInRegion(catalog, desiredType, desiredRegion) { - var matchingSvcs = catalog.filter(function (svc) { - return svc.type === desiredType; - }); - - // Ignore region for identity. Identity service endpoint - // should not change for different regions. - if (desiredType === 'identity' && matchingSvcs.length > 0) { - return true; - } else { - return matchingSvcs.some(function (svc) { - return svc.endpoints.some(function (endpoint) { - return getEndpointRegion(endpoint) === desiredRegion; - }); - }); - } - } - - /* - * In Keystone V3, region has been deprecated in favor of - * region_id. - * - * This method provides a way to get region that works for - * both Keystone V2 and V3. - */ - function getEndpointRegion(endpoint) { - return endpoint.region_id || endpoint.region; - } - - return service; - } - - angular.module('hz.api') - .factory('serviceCatalog', ['$cacheFactory', - '$q', - 'keystoneAPI', - 'userSession', - serviceCatalog]); - -}()); diff --git a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.neutron.js b/code/horizon/horizon/static/horizon/js/angular/services/hz.api.neutron.js deleted file mode 100644 index 5756cd9d..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.neutron.js +++ /dev/null @@ -1,200 +0,0 @@ -/** - * Copyright 2015 IBM Corp. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ -(function () { - 'use strict'; - - /** - * @ngdoc service - * @name hz.api.NeutronAPI - * @description Provides access to Neutron APIs. - */ - function NeutronAPI(apiService) { - - // Networks - - /** - * @name hz.api.neturonAPI.getNetworks - * @description - * Get a list of networks for a tenant. - * - * The listing result is an object with property "items". Each item is - * a network. - */ - this.getNetworks = function() { - return apiService.get('/api/neutron/networks/') - .error(function () { - horizon.alert('error', gettext('Unable to retrieve networks.')); - }); - }; - - /** - * @name hz.api.neutronAPI.createNetwork - * @description - * Create a new network. - * @returns The new network object on success. - * - * @param {Object} newNetwork - * The network to create. Required. - * - * Example new network object - * { - * "name": "myNewNetwork", - * "admin_state_up": true, - * "net_profile_id" : "asdsarafssdaser", - * "shared": true, - * "tenant_id": "4fd44f30292945e481c7b8a0c8908869 - * } - * - * Description of properties on the network object - * - * @property {string} newNetwork.name - * The name of the new network. Optional. - * - * @property {boolean} newNetwork.admin_state_up - * The administrative state of the network, which is up (true) or - * down (false). Optional. - * - * @property {string} newNetwork.net_profile_id - * The network profile id. Optional. - * - * @property {boolean} newNetwork.shared - * Indicates whether this network is shared across all tenants. - * By default, only adminstative users can change this value. Optional. - * - * @property {string} newNetwork.tenant_id - * The UUID of the tenant that will own the network. This tenant can - * be different from the tenant that makes the create network request. - * However, only administative users can specify a tenant ID other than - * their own. You cannot change this value through authorization - * policies. Optional. - * - */ - this.createNetwork = function(newNetwork) { - return apiService.post('/api/neutron/networks/', newNetwork) - .error(function () { - horizon.alert('error', gettext('Unable to create the network.')); - }); - }; - - // Subnets - - /** - * @name hz.api.neutronAPI.getSubnets - * @description - * Get a list of subnets for a network. - * - * The listing result is an object with property "items". Each item is - * a subnet. - * - * @param {string} network_id - * The network id to retrieve subnets for. Required. - */ - this.getSubnets = function(network_id) { - return apiService.get('/api/neutron/subnets/', network_id) - .error(function () { - horizon.alert('error', gettext('Unable to retrieve subnets.')); - }); - }; - - /** - * @name hz.api.neutronAPI.createSubnet - * @description - * Create a Subnet for given Network. - * @returns The JSON representation of Subnet on success. - * - * @param {Object} newSubnet - * The subnet to create. - * - * Example new subnet object - * { - * "network_id": "d32019d3-bc6e-4319-9c1d-6722fc136a22", - * "ip_version": 4, - * "cidr": "192.168.199.0/24", - * "name": "mySubnet", - * "tenant_id": "4fd44f30292945e481c7b8a0c8908869, - * "allocation_pools": [ - * { - * "start": "192.168.199.2", - * "end": "192.168.199.254" - * } - * ], - * "gateway_ip": "192.168.199.1", - * "id": "abce", - * "enable_dhcp": true, - * } - * - * Description of properties on the subnet object - * @property {string} newSubnet.network_id - * The id of the attached network. Required. - * - * @property {number} newSubnet.ip_version - * The IP version, which is 4 or 6. Required. - * - * @property {string} newSubnet.cidr - * The CIDR. Required. - * - * @property {string} newSubnet.name - * The name of the new subnet. Optional. - * - * @property {string} newSubnet.tenant_id - * The ID of the tenant who owns the network. Only administrative users - * can specify a tenant ID other than their own. Optional. - * - * @property {string|Array} newSubnet.allocation_pools - * The start and end addresses for the allocation pools. Optional. - * - * @property {string} newSubnet.gateway_ip - * The gateway IP address. Optional. - * - * @property {string} newSubnet.id - * The ID of the subnet. Optional. - * - * @property {boolean} newSubnet.enable_dhcp - * Set to true if DHCP is enabled and false if DHCP is disabled. Optional. - * - */ - this.createSubnet = function(newSubnet) { - return apiService.post('/api/neutron/subnets/', newSubnet) - .error(function () { - horizon.alert('error', gettext('Unable to create the subnet.')); - }); - }; - - // Ports - - /** - * @name hz.api.neutronAPI.getPorts - * @description - * Get a list of ports for a network. - * - * The listing result is an object with property "items". Each item is - * a port. - * - * @param {string} network_id - * The network id to retrieve ports for. Required. - */ - this.getPorts = function(network_id) { - return apiService.get('/api/neutron/ports/', network_id) - .error(function () { - horizon.alert('error', gettext('Unable to retrieve ports.')); - }); - }; - - } - - angular.module('hz.api') - .service('neutronAPI', ['apiService', NeutronAPI]); -}()); diff --git a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.nova.js b/code/horizon/horizon/static/horizon/js/angular/services/hz.api.nova.js deleted file mode 100644 index 47d9c760..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.nova.js +++ /dev/null @@ -1,346 +0,0 @@ -/* -Copyright 2014, Rackspace, US, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -/*global angular,horizon*/ -(function () { - 'use strict'; - - /** - * @ngdoc service - * @name hz.api.novaAPI - * @description Provides access to Nova APIs. - */ - function NovaAPI(apiService) { - - // Keypairs - - /** - * @name hz.api.novaAPI.getKeypairs - * @description - * Get a list of keypairs. - * - * The listing result is an object with property "items". Each item is - * a keypair. - */ - this.getKeypairs = function() { - return apiService.get('/api/nova/keypairs/') - .error(function () { - horizon.alert('error', gettext('Unable to retrieve keypairs.')); - }); - }; - - /** - * @name hz.api.novaAPI.createKeypair - * @description - * Create a new keypair. This returns the new keypair object on success. - * - * @param {Object} newKeypair - * The keypair to create. - * - * @param {string} newKeypair.name - * The name of the new keypair. Required. - * - * @param {string} newKeypair.public_key - * The public key. Optional. - */ - this.createKeypair = function(newKeypair) { - return apiService.post('/api/nova/keypairs/', newKeypair) - .error(function () { - if (angular.isDefined(newKeypair.public_key)) { - horizon.alert('error', gettext('Unable to import the keypair.')); - } else { - horizon.alert('error', gettext('Unable to create the keypair.')); - } - }); - }; - - // Availability Zones - - /** - * @name hz.api.novaAPI.getAvailabilityZones - * @description - * Get a list of Availability Zones. - * - * The listing result is an object with property "items". Each item is - * an availability zone. - */ - this.getAvailabilityZones = function() { - return apiService.get('/api/nova/availzones/') - .error(function () { - horizon.alert('error', - gettext('Unable to retrieve availability zones.')); - }); - }; - - // Limits - - /** - * @name hz.api.novaAPI.getLimits - * @description - * Returns current limits. - * - * @example - * The following is an example response: - * { - * "maxImageMeta": 128, - * "maxPersonality": 5, - * "maxPersonalitySize": 10240, - * "maxSecurityGroupRules": 20, - * "maxSecurityGroups": 10, - * "maxServerGroupMembers": 10, - * "maxServerGroups": 10, - * "maxServerMeta": 128, - * "maxTotalCores": 20, - * "maxTotalFloatingIps": 10, - * "maxTotalInstances": 10, - * "maxTotalKeypairs": 100, - * "maxTotalRAMSize": 51200, - * "totalCoresUsed": 1, - * "totalFloatingIpsUsed": 0, - * "totalInstancesUsed": 1, - * "totalRAMUsed": 512, - * "totalSecurityGroupsUsed": 1, - * "totalServerGroupsUsed": 0 - * } - */ - this.getLimits = function() { - return apiService.get('/api/nova/limits/') - .error(function () { - horizon.alert('error', gettext('Unable to retrieve limits.')); - }); - }; - - // Servers - - /** - * @name hz.api.novaAPI.createServer - * @description - * Create a server using the parameters supplied in the - * newServer. The required parameters: - * - * "name", "source_id", "flavor_id", "key_name", "user_data" - * All strings - * "security_groups" - * An array of one or more objects with a "name" attribute. - * - * Other parameters are accepted as per the underlying novaclient: - * "block_device_mapping", "block_device_mapping_v2", "nics", "meta", - * "availability_zone", "instance_count", "admin_pass", "disk_config", - * "config_drive" - * - * This returns the new server object on success. - */ - this.createServer = function(newServer) { - return apiService.post('/api/nova/servers/', newServer) - .error(function () { - horizon.alert('error', gettext('Unable to create the server.')); - }); - }; - - /** - * @name hz.api.novaAPI.getServer - * @description - * Get a single server by ID - * @param {string} id - * Specifies the id of the server to request. - */ - this.getServer = function(id) { - return apiService.get('/api/nova/servers/' + id) - .error(function () { - horizon.alert('error', gettext('Unable to retrieve server.')); - }); - }; - - /** - * @name hz.api.novaAPI.getExtensions - * @description - * Returns a list of enabled extensions. - * - * The listing result is an object with property "items". Each item is - * an extension. - * @example - * The following is an example response: - * - * { - * "items": [ - * { - * "alias": "NMN", - * "description": "Multiple network support.", - * "links": [], - * "name": "Multinic", - * "namespace": "http://docs.openstack.org/compute/ext/multinic/api/v1.1", - * "updated": "2011-06-09T00:00:00Z" - * } - * ] - * } - */ - this.getExtensions = function(config) { - return apiService.get('/api/nova/extensions/', config) - .error(function () { - horizon.alert('error', gettext('Unable to retrieve extensions.')); - }); - }; - - /** - * @name hz.api.novaAPI.getFlavors - * @description - * Returns a list of flavors. - * - * The listing result is an object with property "items". Each item is - * a flavor. - * - * @param {boolean} isPublic (optional) - * True if public flavors should be returned. If not specified, the API - * will return public flavors by default for Admins and only project - * flavors for non-admins. - * @param {boolean} getExtras (optional) - * Also retrieve the extra specs. This is expensive (one extra underlying - * call per flavor). - */ - this.getFlavors = function(isPublic, getExtras) { - var config = {'params': {}}; - if (isPublic) { config.params.is_public = 'true'; } - if (getExtras) { config.params.get_extras = 'true'; } - return apiService.get('/api/nova/flavors/', config) - .success(function (data) { - // The colon character ':' in the flavor data causes problems when used - // in Angular $parse() statements. Since these values are used as keys - // to lookup data (and may end up in a $parse()) provide "user-friendly" - // attributes - if ( data && data.items ) { - data.items.map(function(item) { - if ( item.hasOwnProperty('OS-FLV-EXT-DATA:ephemeral')) { - item.ephemeral = item['OS-FLV-EXT-DATA:ephemeral']; - } - if ( item.hasOwnProperty('OS-FLV-DISABLED:disabled')) { - item.disabled = item['OS-FLV-DISABLED:disabled']; - } - if ( item.hasOwnProperty('os-flavor-access:is_public')) { - item.is_public = item['os-flavor-access:is_public']; - } - }); - } - }) - .error(function () { - horizon.alert('error', gettext('Unable to retrieve flavors.')); - }); - }; - - /** - * @name hz.api.novaAPI.getFlavor - * @description - * Get a single flavor by ID. - * @param {string} id - * Specifies the id of the flavor to request. - * @param {boolean} getExtras (optional) - * Also retrieve the extra specs for the flavor. - */ - this.getFlavor = function(id, getExtras) { - var config = {'params': {}}; - if (getExtras) { config.params.get_extras = 'true'; } - return apiService.get('/api/nova/flavors/' + id, config) - .error(function () { - horizon.alert('error', gettext('Unable to retrieve flavor.')); - }); - }; - - /** - * @name hz.api.novaAPI.getFlavorExtraSpecs - * @description - * Get a single flavor's extra specs by ID. - * @param {string} id - * Specifies the id of the flavor to request the extra specs. - */ - this.getFlavorExtraSpecs = function(id) { - return apiService.get('/api/nova/flavors/' + id + '/extra-specs') - .error(function () { - horizon.alert('error', gettext('Unable to retrieve flavor extra specs.')); - }); - }; - } - - angular.module('hz.api') - .service('novaAPI', ['apiService', NovaAPI]); - - /** - * @ngdoc service - * @name hz.api.novaExtensions - * @description - * Provides cached access to Nova Extensions with utilities to help - * with asynchronous data loading. The cache may be reset at any time - * by accessing the cache and calling removeAll. The next call to any - * function will retrieve fresh results. - * - * The enabled extensions do not change often, so using cached data will - * speed up results. Even on a local devstack in informal testing, - * this saved between 30 - 100 ms per request. - */ - function NovaExtensions($cacheFactory, $q, novaAPI) { - var service = {}; - service.cache = $cacheFactory('hz.api.novaExtensions', {capacity: 1}); - - service.get = function () { - return novaAPI.getExtensions({cache: service.cache}) - .then(function (data) { - return data.data.items; - }); - }; - - service.ifNameEnabled = function(desired) { - var deferred = $q.defer(); - - service.get().then(onDataLoaded, onDataFailure); - - function onDataLoaded(extensions) { - if (enabled(extensions, 'name', desired)) { - deferred.resolve(); - } else { - deferred.reject(interpolate( - gettext('Extension is not enabled: %(extension)s'), - {extension: desired}, - true)); - } - } - - function onDataFailure() { - deferred.reject(gettext('Cannot get nova extension list.')); - } - - return deferred.promise; - }; - - // This is an alias to support the extension directive default interface - service.ifEnabled = service.ifNameEnabled; - - function enabled(resources, key, desired) { - if(resources) { - return resources.some(function (resource) { - return resource[key] === desired; - }); - } else { - return false; - } - } - - return service; - } - - angular.module('hz.api') - .factory('novaExtensions', ['$cacheFactory', - '$q', - 'novaAPI', - NovaExtensions]); - -}()); diff --git a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.policy.js b/code/horizon/horizon/static/horizon/js/angular/services/hz.api.policy.js deleted file mode 100644 index 1bb68213..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.policy.js +++ /dev/null @@ -1,73 +0,0 @@ -/* -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -(function() { - 'use strict'; - - /** - * @ngdoc service - * @name hz.api.policyAPI - * @description Provides a direct pass through to the policy engine in - * Horizon. - */ - function PolicyService(apiService) { - - /** - * @name hz.api.policyAPI.check - * @description - * Check the passed in policy rule list to determine if the user has - * permission to perform the actions specified by the rules. The service - * APIs will ultimately reject actions that are not permitted. This is used - * for Role Based Access Control in the UI only. The required parameter - * should have the following structure: - * - * { - * "rules": [ - * [ "compute", "compute:get_all" ], - * ], - * "target": { - * "project_id": "1" - * } - * } - * - * where "rules" is a list of rules (1 or greater in length) policy rules - * which are composed of a - * * service name -- maps the policy rule to a service - * * rule -- the policy rule to check - * and "target" key and value is optional. In some cases, policy rules - * require specific details about the object that is to be acted on. - * If added, it is merely a dictionary of keys and values. - * - * - * The following is the response if the check passes: - * { - * "allowed": true - * } - * - * The following is the response if the check fails: - * { - * "allowed": false - * } - */ - this.check = function (policy_rules) { - return apiService.post('/api/policy/', policy_rules) - .error(function() { - horizon.alert('warning', gettext('Policy check failed.')); - horizon.autoDismissAlerts(); - }); - }; - } - - angular.module('hz.api') - .service('policyAPI', ['apiService', PolicyService]); -}()); diff --git a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.security-group.js b/code/horizon/horizon/static/horizon/js/angular/services/hz.api.security-group.js deleted file mode 100644 index 62856d08..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.security-group.js +++ /dev/null @@ -1,75 +0,0 @@ -/* -Copyright 2015, Hewlett-Packard Development Company, L.P. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -(function () { - 'use strict'; - - /** - * @ngdoc service - * @name hz.api.SecurityGroup - * @description Provides access to Security Groups - */ - function SecurityGroup(apiService) { - - /** - * @name hz.api.SecurityGroup.list - * @description - * Get a list of security groups. - * - * The listing result is an object with property "items". Each item is - * an image. - * - * @example - * The following is an example response: - * { - * "items": [ - * { - * "description": "Default security group", - * "id": "4a4c9dd4-ffa0-454a-beaa-23e8fa569062", - * "name": "default", - * "security_group_rules": [ - * { - * "direction": "ingress", - * "ethertype": "IPv4", - * "id": "22961412-fba1-4d0d-8eb8-d4460c921346", - * "port_range_max": null, - * "port_range_min": null, - * "protocol": null, - * "remote_group_id": "4a4c9dd4-ffa0-454a-beaa-23e8fa569062", - * "remote_ip_prefix": null, - * "security_group_id": "4a4c9dd4-ffa0-454a-beaa-23e8fa569062", - * "tenant_id": "3f867827f7eb45d4aa1d1395237f426b" - * } - * ], - * "tenant_id": "3f867827f7eb45d4aa1d1395237f426b" - * } - * ] - * } - */ - this.query = function() { - return apiService.get('/api/network/securitygroups/') - .error(function () { - horizon.alert('error', gettext('Unable to retrieve security groups.')); - }); - }; - } - - // Register it with the API module so that anybody using the - // API module will have access to the Security Group APIs. - - angular.module('hz.api') - .service('securityGroup', ['apiService', SecurityGroup]); - -}()); diff --git a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.service.js b/code/horizon/horizon/static/horizon/js/angular/services/hz.api.service.js deleted file mode 100644 index b3fb4736..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.service.js +++ /dev/null @@ -1,60 +0,0 @@ -/* -Copyright 2014, Rackspace, US, Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ -/*global angular*/ -(function () { - 'use strict'; - function ApiService($http, $log) { - - var httpCall = function (method, url, data, config) { - if (!angular.isDefined(config)) { - config = {}; - } - // url and method are always provided - config.method = method; - config.url = url; - if (angular.isDefined(data)) { - config.data = data; - } - - // - // TODO: need discussion with Richard for this change. - // The reason for this change is to get a promise object compatible - // to $q.defer().promise. - // - return $http(config); - }; - - this.get = function(url, config) { - return httpCall('GET', url, undefined, config); - }; - - this.post = function(url, data, config) { - return httpCall('POST', url, data, config); - }; - - this.patch = function(url, data, config) { - return httpCall('PATCH', url, data, config); - }; - - // NOTE the deviation from $http.delete which does not have the data param - this.delete = function (url, data, config) { - return httpCall('DELETE', url, data, config); - }; - } - - angular.module('hz.api.service', []) - .service('apiService', ['$http', '$log', ApiService]); -}()); diff --git a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.service.spec.js b/code/horizon/horizon/static/horizon/js/angular/services/hz.api.service.spec.js deleted file mode 100644 index aaff6532..00000000 --- a/code/horizon/horizon/static/horizon/js/angular/services/hz.api.service.spec.js +++ /dev/null @@ -1,47 +0,0 @@ -/*global angular,describe,it,expect,inject,module,beforeEach,afterEach*/ -(function () { - 'use strict'; - - describe('hz.api.service module', function() { - it('should have been defined', function () { - expect(angular.module('hz.api.service')).toBeDefined(); - }); - }); - - describe('api service', function () { - var api, $httpBackend; - - beforeEach(module('hz.api.service')); - beforeEach(inject(function ($injector, apiService) { - api = apiService; - $httpBackend = $injector.get('$httpBackend'); - })); - - afterEach(function() { - $httpBackend.verifyNoOutstandingExpectation(); - }); - - it('should be defined', function () { - expect(!!api).toBe(true); - }); - - it('should call success on a good response', function () { - var called = {}; - $httpBackend.when('GET', '/good').respond({status: 'good'}); - $httpBackend.expectGET('/good'); - api.get('/good').success(function (data) {called.data = data;}); - $httpBackend.flush(); - expect(called.data.status).toBe('good'); - }); - - it('should call error on a bad response', function () { - var called = {}; - $httpBackend.when('GET', '/bad').respond(500, ''); - $httpBackend.expectGET('/bad'); - api.get('/bad').error(function () {called.called = true;}); - $httpBackend.flush(); - expect(called.called).toBe(true); - }); - - }); -}()); \ No newline at end of file diff --git a/code/horizon/horizon/static/horizon/js/horizon.accordion_nav.js b/code/horizon/horizon/static/horizon/js/horizon.accordion_nav.js deleted file mode 100644 index ee718b80..00000000 --- a/code/horizon/horizon/static/horizon/js/horizon.accordion_nav.js +++ /dev/null @@ -1,81 +0,0 @@ -horizon.addInitFunction(function() { - var allPanelGroupBodies = $('.nav_accordion > dd > div > ul'); - - // mark the active panel group - var activePanel = $('.nav_accordion > dd > div > ul > li > a.active'); - activePanel.closest('div').find('h4').addClass('active'); - - // dashboard click - $('.nav_accordion > dt').click(function() { - var myDashHeader = $(this); - var myDashWasActive = myDashHeader.hasClass("active"); - - // mark the active dashboard - var allDashboardHeaders = $('.nav_accordion > dt'); - allDashboardHeaders.removeClass("active"); - - // collapse all dashboard contents - var allDashboardBodies = $('.nav_accordion > dd'); - allDashboardBodies.slideUp(); - - // if the current dashboard was active, leave it collapsed - if(!myDashWasActive) { - myDashHeader.addClass("active"); - - // expand the active dashboard body - var myDashBody = myDashHeader.next(); - myDashBody.slideDown(); - - var activeDashPanel = myDashBody.find("div > ul > li > a.active"); - // if the active panel is not in the expanded dashboard - if (activeDashPanel.length === 0) { - // expand the active panel group - var activePanel = myDashBody.find("div:first > ul"); - activePanel.removeClass('hidden').slideDown(); - activePanel.closest('div').find("h4").addClass("active"); - - // collapse the inactive panel groups - var nonActivePanels = myDashBody.find("div:not(:first) > ul"); - nonActivePanels.slideUp(); - } - // the expanded dashboard contains the active panel - else - { - // collapse the inactive panel groups - activeDashPanel.closest('div').find("h4").addClass("active"); - activeDashPanel.closest('ul').removeClass('hidden').slideDown(); - allPanelGroupBodies.each(function(index, value) { - var activePanels = $(value).find('li > a.active'); - if(activePanels.length === 0) { - $(this).slideUp(); - } - }); - } - } - return false; - }); - - // panel group click - $('.nav_accordion > dd > div > h4').click(function() { - var myPanelGroupHeader = $(this); - myPanelGroupWasActive = myPanelGroupHeader.hasClass("active"); - - // collapse all panel groups - var allPanelGroupHeaders = $('.nav_accordion > dd > div > h4'); - allPanelGroupHeaders.removeClass("active"); - allPanelGroupBodies.slideUp(); - - // expand the selected panel group if not already active - if(!myPanelGroupWasActive) { - myPanelGroupHeader.addClass("active"); - myPanelGroupHeader.closest('div').find('ul').removeClass('hidden') - .slideDown(); - } - }); - - // panel selection - $('.nav_accordion > dd > div > ul > li > a').click(function() { - horizon.modals.modal_spinner(gettext("Loading")); - }); - -}); diff --git a/code/horizon/horizon/static/horizon/js/horizon.communication.js b/code/horizon/horizon/static/horizon/js/horizon.communication.js deleted file mode 100644 index f1116d1e..00000000 --- a/code/horizon/horizon/static/horizon/js/horizon.communication.js +++ /dev/null @@ -1,51 +0,0 @@ -/* Queued ajax handling for Horizon. - * - * Note: The number of concurrent AJAX connections hanlded in the queue - * can be configured by setting an "ajax_queue_limit" key in - * HORIZON_CONFIG to the desired number (or None to disable queue - * limiting). - */ -horizon.ajax = { - // This will be our jQuery queue container. - _queue: [], - _active: [], - get_messages: function (request) { - return request.getResponseHeader("X-Horizon-Messages"); - }, - // Function to add a new call to the queue. - queue: function(opts) { - var complete = opts.complete, - active = horizon.ajax._active; - - opts.complete = function () { - var index = $.inArray(request, active); - if (index > -1) { - active.splice(index, 1); - } - horizon.ajax.next(); - if (complete) { - complete.apply(this, arguments); - } - }; - - function request() { - return $.ajax(opts); - } - - // Queue the request - horizon.ajax._queue.push(request); - - // Start up the queue handler in case it's stopped. - horizon.ajax.next(); - }, - next: function () { - var queue = horizon.ajax._queue, - limit = horizon.conf.ajax.queue_limit, - request; - if (queue.length && (!limit || horizon.ajax._active.length < limit)) { - request = queue.pop(); - horizon.ajax._active.push(request); - return request(); - } - } -}; diff --git a/code/horizon/horizon/static/horizon/js/horizon.d3barchart.js b/code/horizon/horizon/static/horizon/js/horizon.d3barchart.js deleted file mode 100644 index 5c30028f..00000000 --- a/code/horizon/horizon/static/horizon/js/horizon.d3barchart.js +++ /dev/null @@ -1,729 +0,0 @@ -/* - Used for animating and displaying bar information using - D3js rect. - - Usage: - In order to have single bars that work with this, you need to have a - DOM structure like this in your Django template: - - Example: -
    -
    -
    -
    - - The available data- attributes are: - data-tooltip-free, data-tooltip-used, data-tooltip-average OPTIONAL - Html content of tooltips that will be displayed over this areas. - - - data-used="integer" REQUIRED - 1. Integer - Integer representing the percent used. - 2. Array - Array of following structure: - [ - {"tooltip_used": "Popup html 1", "used_instances": "5"}, - {"tooltip_used": "Popup html 2", "used_instances": "15"},.... - ] - - used_instances: Integer representing the percent used. - tooltip_used: Html that will be displayed in tooltip window over - this area. - - data-settings="JSON" - Json with variety of settings described below. - - used-label-placement='string' OPTIONAL - String determining where the floating label stating number of percent - will be placed. So far only left is supported. - - width="integer" OPTIONAL - Integer in pixels. Determines the total width of the bar. Handy when - we use a used_label, so the bar is not a 100% of the container. - - average="integer" OPTIONAL - Integer representing the average usage in percent of given - single-bar. - - auto-scale-selector OPTIONAL - Jquery selector of bar elements that have Integer - used attribute. It then takes maximum of these - values as 100% of the linear scale of the colors. - So the array representing linear scale interval is set - automatically.This then maps to color-scale-range. - (arrays must have the same structure) - - color-scale-range OPTIONAL - Array representing linear scale interval that is set manually. - E.g "[0,10]". This then maps to color-scale-range. - (arrays must have the same structure) - - color-scale-range OPTIONAL - Array representing linear scale of colors. - E.g '["#000060", "#99FFFF"]' - - orientation OPTIONAL - String representing orientation of the bar.Can be "horizontal" - or "vertical". Default is horizontal. - -*/ - -horizon.d3_bar_chart = { - /** - * A class representing the bar chart - * @param chart_module A context of horizon.d3_line_chart module. - * @param html_element A html_element containing the chart. - * @param settings An object containing settings of the chart. - */ - BarChart: function(chart_module, html_element, settings, data){ - var self = this; - self.chart_module = chart_module; - self.html_element = html_element; - self.jquery_element = $(self.html_element); - - /************************************************************************/ - /*********************** Initialization methods *************************/ - /************************************************************************/ - /** - * Initialize the object. - */ - self.init = function(settings, data) { - var self = this; - self.data = {}; - - self.data.max_value = self.jquery_element.data('max-value'); - if (!self.max_value){ - // Default mas value is 100, representing 100 percent - self.max_value = 100; - } - - // Chart data - self.data.used = self.jquery_element.data('used'); - self.data.average = self.jquery_element.data('average'); - - // Tooltips data - self.data.tooltip_average = self.jquery_element.data('tooltip-average'); - self.data.tooltip_free = self.jquery_element.data('tooltip-free'); - self.data.tooltip_used = self.jquery_element.data('tooltip-used'); - - if (data !== undefined){ - if (data.used !== undefined){ - self.data.used = data.used; - } - if (data.average !== undefined){ - self.data.average = data.average; - } - if (data.tooltip_average !== undefined){ - self.data.tooltip_average = data.tooltip_average; - } - if (data.tooltip_free !== undefined){ - self.data.tooltip_free = data.tooltip_free; - } - if (data.tooltip_used !== undefined){ - self.data.tooltip_used = data.tooltip_used; - } - } - - // Percentage count - if ($.isArray(self.data.used)){ - self.data.percentage_average = 0; // No average for Multi-bar chart - self.data.percentage_used = Array(); - self.data.tooltip_used_contents = Array(); - for (var i = 0; i < self.data.used.length; ++i) { - if (!isNaN(self.max_value) && !isNaN(self.data.used[i].used_instances)) { - var used = Math.round((self.data.used[i].used_instances / self.max_value) * 100); - - self.data.percentage_used.push(used); - // for multi-bar chart, tooltip is in the data - self.data.tooltip_used_contents.push(self.data.used[i].tooltip_used); - } else { // If NaN self.data.percentage_used is 0 - - } - } - } - else { - if (!isNaN(self.max_value) && !isNaN(self.data.used)) { - self.data.percentage_used = Math.round((self.data.used / self.max_value) * 100); - } else { // If NaN self.data.percentage_used is 0 - self.data.percentage_used = 0; - } - - if (!isNaN(self.max_value) && !isNaN(self.data.average)) { - self.data.percentage_average = ((self.data.average / self.max_value) * 100); - } else { - self.data.percentage_average = 0; - } - } - - // Load initial settings. - self.init_settings(settings); - }; - - /** - * Initialize settings of the chart with default values, then applies - * defined settings of the chart. Settings are obtained either from JSON - * of the html attribute data-settings, or from init of the charts. The - * highest priority settings are obtained directly from the JSON data - * obtained from the server. - * @param settings An object containing settings of the chart. - */ - self.init_settings = function(settings) { - var self = this; - - self.data.settings = {}; - - // Placement of the used label - self.data.settings.used_label_placement = undefined; - // Orientation of the Bar chart - self.data.settings.orientation = 'horizontal'; - - // Color scales - self.data.settings.color_scale_domain = [0,100]; - self.data.settings.color_scale_range = ['#000000', '#0000FF']; - - // Width and height of bar - self.data.settings.width = self.jquery_element.data('width'); - self.data.settings.height = self.jquery_element.data('height'); - - /* Applying settings. The later application rewrites the previous - therefore it has bigger priority. */ - - // Settings defined in the init method of the chart - if (settings){ - self.apply_settings(settings); - } - - // Settings defined in the html data-settings attribute - if (self.jquery_element.data('settings')){ - var inline_settings = self.jquery_element.data('settings'); - self.apply_settings(inline_settings); - } - }; - - /** - * Applies passed settings to the chart object. Allowed settings are - * listed in this method. - * @param settings An object containing settings of the chart. - */ - self.apply_settings = function(settings){ - var self = this; - var allowed_settings = ['orientation', 'used_label_placement', - 'color_scale_domain', 'color_scale_range', - 'width', 'height']; - - $.each(allowed_settings, function(index, setting_name) { - if (settings[setting_name] !== undefined){ - self.data.settings[setting_name] = settings[setting_name]; - } - }); - }; - - /************************************************************************/ - /****************************** Initialization **************************/ - /************************************************************************/ - // Init the object - self.init(settings, data); - - /************************************************************************/ - /****************************** Methods *********************************/ - /************************************************************************/ - /** - * Obtains the actual chart data and renders the chart again. - */ - self.refresh = function(){ - var self = this; - // Clear the chart before rendering it - self.jquery_element.empty(); - self.render(); - }; - - /** - * Renders the chart into html element given in initializer. - */ - self.render = function() { - var self = this; - - // Initialize wrapper - var wrapper = new self.chart_module.Wrapper(self.chart_module, self.html_element, self.data); - - // Initialize Tool-tips - var tooltip_average = (new self.chart_module.TooltipComponent(wrapper)).render(self.data.tooltip_average); - var tooltip_free = (new self.chart_module.TooltipComponent(wrapper)).render(self.data.tooltip_free); - var tooltip_used = (new self.chart_module.TooltipComponent(wrapper)).render(self.data.tooltip_used); - - // Append Unused resources Bar - (new self.chart_module.UnusedComponent(wrapper)).render(tooltip_free); - - if (wrapper.used_multi()){ - // If UsedComponent is shown as multiple values in one chart - for (var i = 0; i < wrapper.percentage_used.length; ++i) { - // FIXME write proper iterator - wrapper.used_multi_iterator = i; - - /* Use general tool-tip, content of tool-tip will be changed by inner - used components on their hover. HTML content is taken from JSON sent - from the server. */ - tooltip_used = (new self.chart_module.TooltipComponent(wrapper)).render(''); - - // Append used so it will be shown as multiple values in one chart - (new self.chart_module.UsedComponent(wrapper)).render(tooltip_used); - - // Compute total value as a start point for next Used bar - wrapper.total_used_perc += wrapper.percentage_used_value(); - wrapper.total_used_value_in_pixels = (wrapper.w / 100) * wrapper.total_used_perc; - } - - } else { - // Used is show as one value it the chart - (new self.chart_module.UsedComponent(wrapper)).render(tooltip_used); - // Append average value to Bar - (new self.chart_module.AverageComponent(wrapper)).render(tooltip_average); - } - }; - }, - /** - * Chart wrapper class renders the main svg element and encapsulate - * the chart data. - * @param chart_module Chart module name - * @param html_element HTML element where the chart will be rendered - * @param chart_module Data + settings of the chart - */ - Wrapper: function(chart_module, html_element, data){ - var self = this; - self.html_element = html_element; - self.jquery_element = $(html_element); - - // Bar HTML element - self.bar_html = d3.select(html_element); - // Bar layout for bar chart - self.bar = self.bar_html.append('svg:svg') - .attr('class', 'chart') - .style('background-color', 'white'); - - // Get correct size of chart and the wrapper. - chart_module.get_size(self.html_element); - - self.data = data; - // Floating label of used bar placement - self.used_label_placement = data.settings.used_label_placement; - - // Width and height of the chart itself - if (data.settings.width !== undefined){ - self.w = parseFloat(data.settings.width); - } else { - self.w = parseFloat(self.jquery_element.width()); - } - if (data.settings.height !== undefined) { - self.h = parseFloat(data.settings.height); - } else { - self.h = parseFloat(self.jquery_element.height()); - } - - /* Start coordinations of the chart and size of the chart wrapper. - Chart can have other elements next to it, so it doesn't have to - start at 0. - */ - self.chart_start_x = 0; - if (self.data.settings.orientation === 'vertical'){ - if (self.used_label_placement === 'left'){ - self.chart_start_x = 44; - } - self.chart_wrapper_w = self.w + self.chart_start_x; - } else { - self.chart_wrapper_w = self.w; - } - self.chart_wrapper_h = self.h; - - // Basic settigns of the chart - self.lvl_curve = 3; - self.bkgrnd = '#F2F2F2'; - self.frgrnd = 'grey'; - self.color_scale_max = 25; - - // Percentage used - self.percentage_used = data.percentage_used; - self.total_used_perc = 0; // incremented in render method - self.total_used_value_in_pixels = 0; // incremented in render method - self.used_value_in_pixels = 0; // set in UsedComponent - self.average_value_in_pixels = 0; // set in AverageComponent - - - // Percentage average - self.percentage_average = data.percentage_average; - self.tooltip_used_contents = data.tooltip_used_contents; - - // Set scales for multi bar chart - self.usage_color = d3.scale.linear() - .domain(data.settings.color_scale_domain) - .range(data.settings.color_scale_range); - - // Border of the chart - self.border_width = 1; - - // Return true if it renders multiple used percentage in one chart - self.used_multi = function (){ - return ($.isArray(self.percentage_used)); - }; - - // Deals with percentage if there should be multiple in one chart - self.used_multi_iterator = 0; - self.percentage_used_value = function(){ - if (self.used_multi()){ - return self.percentage_used[self.used_multi_iterator]; - } else { - return self.percentage_used; - } - }; - - // Deals with html tooltips if there should be multiple in one chart - self.tooltip_used_value = function (){ - if (self.used_multi()){ - return self.tooltip_used_contents[self.used_multi_iterator]; - } else { - return ''; - } - }; - - // Return true if it chart is oriented horizontally - self.horizontal_orientation = function (){ - return (self.data.settings.orientation === 'horizontal'); - }; - }, - /** - * Component rendering part of chart showing 'used', optional labels - * and optional tool-tip element. - * the chart data. - * @param wrapper Wrapper object - */ - UsedComponent: function(wrapper){ - var self = this; - self.wrapper = wrapper; - - // FIXME(lsmola) would be good to abstract all attributes and resolve orientation inside - if (self.wrapper.horizontal_orientation()){ - // Horizontal Bars - self.wrapper.used_value_in_pixels = (self.wrapper.w / 100) * self.wrapper.percentage_used_value(); - - self.y = 0; - self.x = self.wrapper.total_used_value_in_pixels; - self.width = 0; - self.height = self.wrapper.h; - self.trasition_attr = 'width'; - self.trasition_value = self.wrapper.used_value_in_pixels; - } else { - // Vertical Bars - self.wrapper.used_value_in_pixels = (self.wrapper.h / 100) * self.wrapper.percentage_used_value(); - - self.y = self.wrapper.h; - self.x = self.wrapper.chart_start_x; - self.width = self.wrapper.w - self.wrapper.border_width; - self.height = self.wrapper.used_value_in_pixels; - self.trasition_attr = 'y'; - self.trasition_value = self.wrapper.h - self.wrapper.used_value_in_pixels; - } - - self.render = function(tooltip){ - self.wrapper.bar.append('rect') - .attr('class', 'used_component') - .attr('y', self.y) - .attr('x', self.x) - .attr('width', self.width) - .attr('height', self.height) - .style('fill', self.wrapper.usage_color(self.wrapper.percentage_used_value())) - .style('stroke', '#bebebe') - .style('stroke-width', 0) - .attr('d', self.wrapper.percentage_used_value()) - .attr('tooltip-used', self.wrapper.tooltip_used_value()) - .on('mouseover', function(d){ - if ($(this).attr('tooltip-used')){ - tooltip.html($(this).attr('tooltip-used')); - } - tooltip.style('visibility', 'visible'); - }) - .on('mousemove', function(d){ - var eventX = event.offsetX || event.layerX; - var eventY = event.offsetY || event.layerY; - tooltip - .style('top', (eventY - 10) + 'px') - .style('left',(eventX + 10) + 'px'); - }) - .on('mouseout', function(d){ - tooltip.style('visibility', 'hidden'); - }) - .transition() - .duration(500) - .attr(self.trasition_attr, self.trasition_value); - - if (self.wrapper.used_label_placement === 'left') { - // Now it works only for vertical bar chart placed left form the chart - var label_placement_y = self.wrapper.h - self.wrapper.used_value_in_pixels; - - // Make sure the placement will be visible with border values - if (label_placement_y <= 6){ - label_placement_y = 6; - } else if (label_placement_y >= (self.wrapper.h - 6)){ - label_placement_y = self.wrapper.h - 6; - } - - // Append label text - self.wrapper.bar.append('text') - .attr('class', 'used_component_label') - .text(self.wrapper.percentage_used_value() + '%') - .attr('y', label_placement_y) - .attr('x', 0) - .attr('dominant-baseline', 'middle') - .attr('font-size', 12) - .transition() - .duration(500) - .attr('x', function() { - if (self.wrapper.percentage_used_value() > 99){ - // If there are two digits, label have to be farther to the bar chart - return 0; - } - else if (self.wrapper.percentage_used_value() > 9){ - // If there are two digits, label have to be farther to the bar chart - return 4; - } - else { - // If there is only one digit, label can be closer to the bar chart - return 8; - } - }); - - // Append little triangle pointing to text - var poly = [{'x':self.wrapper.chart_start_x - 8, 'y':label_placement_y}, - {'x':self.wrapper.chart_start_x - 3,'y':label_placement_y + 2}, - {'x':self.wrapper.chart_start_x - 3,'y':label_placement_y - 2} - ]; - - self.wrapper.bar.selectAll('polygon') - .data([poly]) - .enter() - .append('polygon') - .attr('points',function(d) { - return d.map(function(d) { - return [d.x,d.y].join(','); - }).join(' '); - }) - .attr('stroke','black') - .attr('stroke-width', 2); - } - }; - }, - /** - * Component rendering part of chart showing 'average' and optional - * tool-tip element. - * the chart data. - * @param wrapper Wrapper object - */ - AverageComponent: function(wrapper){ - var self = this; - self.wrapper = wrapper; - - // FIXME would be good to abstract all attributes and resolve orientation inside - if (wrapper.horizontal_orientation()){ - // Horizontal Bars - self.wrapper.average_value_in_pixels = (self.wrapper.w / 100) * self.wrapper.percentage_average; - - self.y = 1; - self.x = self.wrapper.average_value_in_pixels; - self.width = 0; - self.height = self.wrapper.h; - } else { // Vertical Bars - self.wrapper.average_value_in_pixels = (self.wrapper.h / 100) * (100 - self.wrapper.percentage_average); - - self.y = self.wrapper.average_value_in_pixels; - self.x = self.wrapper.chart_start_x; - self.width = self.wrapper.w - self.wrapper.border_width; - self.height = 0; - } - - self.render = function(tooltip){ - if (self.wrapper.percentage_average > 0) { - // Only show average when it is bigger than 0 - // A dashed line, so it's pretty - self.wrapper.bar.append('line') - .attr('class', 'average_component') - .attr('y1', self.y) - .attr('x1', self.x) - .attr('class', 'average') - .attr('y2', self.y + self.height) - .attr('x2', self.x + self.width) - .style('stroke', 'black') - .style('stroke-width', 3) - .style('stroke-dasharray', ('6, 2')) - .on('mouseover', function(){tooltip.style('visibility', 'visible');}) - .on('mousemove', function(){ - var eventX = event.offsetX || event.layerX; - var eventY = event.offsetY || event.layerY; - tooltip - .style('top',(eventY - 10) + 'px') - .style('left',(eventX + 10) + 'px'); - }) - .on('mouseout', function(){tooltip.style('visibility', 'hidden');}); - - // A normal line, so it shows popup even in spaces, it's also bigger so - // it's easier to show popup - self.wrapper.bar.append('line') - .attr('class', 'average_component') - .attr('y1', self.y) - .attr('x1', self.x) - .attr('class', 'average') - .attr('y2', self.y + self.height) - .attr('x2', self.x + self.width) - .style('stroke', 'transparent') - .style('stroke-width', 5) - .on('mouseover', function(){tooltip.style('visibility', 'visible');}) - .on('mousemove', function(){ - var eventX = event.offsetX || event.layerX; - var eventY = event.offsetY || event.layerY; - tooltip - .style('top',(eventY - 10) + 'px') - .style('left',(eventX + 10) + 'px'); - }) - .on('mouseout', function(){tooltip.style('visibility', 'hidden');}); - } - }; - }, - /** - * Component rendering part of chart showing 'unused' and optional - * tool-tip element. - * the chart data. - * @param wrapper Wrapper object - */ - UnusedComponent: function(wrapper){ - var self = this; - self.wrapper = wrapper; - - self.render = function(tooltip_free){ - self.wrapper.bar.append('rect') - .attr('class', 'unused_component') - .attr('y', 0) - .attr('x', self.wrapper.chart_start_x) - .attr('width', self.wrapper.w) - .attr('height', self.wrapper.h) - .attr('rx', self.wrapper.lvl_curve) - .attr('ry', self.wrapper.lvl_curve) - .style('fill', self.wrapper.bkgrnd) - - .on('mouseover', function(d){ - tooltip_free.style('visibility', 'visible'); - }) - .on('mousemove', function(d){ - var eventX = event.offsetX || event.layerX; - var eventY = event.offsetY || event.layerY; - tooltip_free - .style('top',(eventY - 10) + 'px') - .style('left',(eventX + 10) + 'px'); - }) - .on('mouseout', function(d){tooltip_free.style('visibility', 'hidden');}); - - self.wrapper.bar.append('rect') - .attr('class', 'unused_component_border') - .attr('x', self.wrapper.chart_start_x) - .attr('y', 0) - .attr('height', self.wrapper.h) - .attr('width', self.wrapper.w - self.wrapper.border_width) // a space for right border line - .style('stroke', '#bebebe') - .style('fill', 'none') - .style('stroke-width', 1); - }; - }, - /** - * Component rendering tool-tip HTML code. - * the chart data. - * @param wrapper Wrapper object - * @return HTML code of tool-tip - */ - TooltipComponent: function(wrapper){ - var self = this; - self.wrapper = wrapper; - self.tooltip_html = self.wrapper.bar_html.append('div'); - - self.render = function(html_content){ - var display = 'none'; - if (html_content){ - // Display only when there is some HTML content - display = 'block'; - } - - return self.tooltip_html - .attr('class', 'tooltip_detail') - .style('position', 'absolute') - .style('z-index', '10') - .style('visibility', 'hidden') - .style('display', display) - .html(html_content); - }; - }, - /** - * Function for initializing of the charts. - * @param selector JQuery selector of charts we want to initialize. - * @param settings An object containing settings of the chart. - * @param data An object containing data of the chart. - */ - init: function(selector, settings, data) { - var self = this; - self.bars = $(selector); - - self.bars.each(function() { - self.refresh(this, settings, data); - }); - }, - /** - * Function for creating chart objects, saving them for later reuse - * and calling their refresh method. - * @param html_element HTML element where the chart will be rendered. - * @param settings An object containing settings of the chart. - * @param data An object containing data of the chart. - */ - refresh: function(html_element, settings, data){ - var chart = new this.BarChart(this, html_element, settings, data); - // FIXME save chart objects somewhere so I can use them again when - // e.g. I am switching tabs, or if I want to update them - // via web sockets - // this.charts.add_or_update(chart) - chart.refresh(); - }, - /** - * Function for computing size of the chart from the surrounding HTML. - * @param html_element HTML element where the chart will be rendered. - */ - get_size: function(html_element){ - /* The height will be determined by css or window size, - I have to hide everything inside that could mess with - the size, so it is fully determined by outer CSS. */ - var jquery_element = $(html_element); - jquery_element.css('height', ''); - jquery_element.css('width', ''); - var svg = jquery_element.find('svg'); - svg.hide(); - - // Width an height of the chart will be taken from chart wrapper, - // that can be styled by css. - var width = jquery_element.width(); - - // Set either the minimal height defined by CSS. - var height = jquery_element.height(); - - /* Setting new sizes. It is important when resizing a window.*/ - jquery_element.css('height', height); - jquery_element.css('width', width); - svg.show(); - svg.css('height', height); - svg.css('width', width); - } -}; - - -horizon.addInitFunction(function () { - horizon.d3_bar_chart.init('div[data-chart-type="bar_chart"]', {}, {}); -}); diff --git a/code/horizon/horizon/static/horizon/js/horizon.d3linechart.js b/code/horizon/horizon/static/horizon/js/horizon.d3linechart.js deleted file mode 100644 index ef12a1d9..00000000 --- a/code/horizon/horizon/static/horizon/js/horizon.d3linechart.js +++ /dev/null @@ -1,779 +0,0 @@ -/* - Draw line chart in d3. - - To use, a div is required with the data attributes - data-chart-type="line_chart", data-url. - - data-chart-type - REQUIRED(string) must be "line_chart" so chart gets initialized - data-url - REQUIRED(string) url for the json data for the chart - data-form-selector - Optional(string) JQuery selector of Forms that controls this chart - data-legend-selector - Optional(string) JQuery selector of div element that will display legend - data-smoother-selector - Optional(string) JQuery selector of TODO(lsmola) - data-slider-selector - Optional(string) JQuery selector of TODO(lsmola) - - - If used in popup, initialization must be made manually e.g.: - - if (typeof horizon.d3_line_chart !== 'undefined') { - horizon.d3_line_chart.init("div[data-chart-type='line_chart']"); - } - - - Example: -
    -
    -
    -
    - - - The data format example: - Url has to return JSON in format: - { - "series": [ - { - "name": "instance-00000005", - "data": [ - {"y": 171, "x": "2013-08-21T11:22:25"}, - {"y": 171, "x": "2013-08-21T11:22:25"} - ] - }, { - "name": "instance-00000005", - "data": [ - {"y": 171, "x": "2013-08-21T11:22:25"}, - {"y": 171, "x": "2013-08-21T11:22:25"} - ] - } - ], - "settings": {} - } - - Example of line-bar chart sparkline: - -
    -
    -
    -
    -
    -
    -
    -
    -
    -
    - - { - "series": [ - { - "name": "instance-00000005", - "data": [ - {"y": 171, "x": "2013-08-21T11:22:25"}, - {"y": 171, "x": "2013-08-21T11:22:25"} - ] - }, { - "name": "instance-00000005", - "data": [ - {"y": 171, "x": "2013-08-21T11:22:25"}, - {"y": 171, "x": "2013-08-21T11:22:25"} - ] - } - ], - "settings": { - 'renderer': 'StaticAxes', - 'yMin': 0, - 'yMax': 100, - 'higlight_last_point': True, - "auto_size": False, 'auto_resize': False, - "axes_x" : False, "axes_y" : False, - 'bar_chart_settings': { - 'orientation': 'vertical', - 'used_label_placement': 'left', - 'width': 30, - 'color_scale_domain': [0, 80, 80, 100], - 'color_scale_range': ['#00FE00', '#00FF00', '#FE0000', '#FF0000'], - 'average_color_scale_domain': [0, 100], - 'average_color_scale_range': ['#0000FF', '#0000FF'] - } - }, - "stats": { - 'average': 20, - 'used': 30, - 'tooltip_average': tooltip_average - } - } - - - The control Forms: - There are currently 2 form elements that can be connected to charts and act - as controls. Elements listen for change event and refresh the chart on change event. - Chart can be connected to multiple forms via selector, all for data will be sent on - change. - Form can be connected to multiple charts, all charts will be refreshed when form - element changes. - The firsts rendering of the chart takes data from the connected Forms. - - 1. Selectbox - The data attribute 'data-line-chart-command="select_box_change' needs to be defined on - select element. - - Example: -
    - -
    - -
    - -
    -
    -
    - - 2. Date picker - The data attribute 'data-line-chart-command="date_picker_change"' needs to be defined on - input element. - - Example: -
    -
    - -
    - -
    -
    -
    - - */ - -Rickshaw.namespace('Rickshaw.Graph.Renderer.StaticAxes'); -Rickshaw.Graph.Renderer.StaticAxes = Rickshaw.Class.create( Rickshaw.Graph.Renderer.Line, { - name: 'StaticAxes', - defaults: function($super) { - return Rickshaw.extend( $super(), { - xMin: undefined, - xMax: undefined, - yMin: undefined, - yMax: undefined - }); - }, - domain: function($super) { - var ret = $super(); - var xMin, xMax; - // If y axis wants to have static range, not based on data - if (this.yMin !== undefined && this.yMax !== undefined){ - ret.y = [this.yMin, this.yMax]; - } - // If x axis wants to have static range, not based on data - if (this.xMin !== undefined && this.xMax !== undefined){ - xMin = d3.time.format.utc('%Y-%m-%dT%H:%M:%S').parse(this.xMin); - xMin = xMin.getTime() / 1000; - xMax = d3.time.format.utc('%Y-%m-%dT%H:%M:%S').parse(this.xMax); - xMax = xMax.getTime() / 1000; - - ret.x = [xMin, xMax]; - } - return ret; - } -}); - -horizon.d3_line_chart = { - /** - * A class representing the line chart - * @param chart_module A context of horizon.d3_line_chart module. - * @param html_element A html_element containing the chart. - * @param settings An object containing settings of the chart. - */ - LineChart: function(chart_module, html_element, settings){ - var self = this; - var jquery_element = $(html_element); - - self.chart_module = chart_module; - self.html_element = html_element; - self.jquery_element = jquery_element; - - /************************************************************************/ - /*********************** Initialization methods *************************/ - /************************************************************************/ - /** - * Initialize object - */ - self.init = function() { - var self = this; - /* TODO(lsmola) make more configurable init from more sources */ - self.legend_element = $(jquery_element.data('legend-selector')).get(0); - self.slider_element = $(jquery_element.data('slider-selector')).get(0); - - self.url = jquery_element.data('url'); - self.url_parameters = jquery_element.data('url_parameters'); - - self.final_url = self.url; - if (jquery_element.data('form-selector')){ - $(jquery_element.data('form-selector')).each(function(){ - // Add serialized data from all connected forms to url. - if (self.final_url.indexOf('?') > -1){ - self.final_url += '&' + $(this).serialize(); - } else { - self.final_url += '?' + $(this).serialize(); - } - }); - } - - self.data = []; - self.color = d3.scale.category10(); - - // Self aggregation and statistic attrs - self.stats = {}; - self.stats.average = 0; - self.stats.last_value = 0; - - // Load initial settings. - self.init_settings(settings); - // Get correct size of chart and the wrapper. - self.get_size(); - }; - /** - * Initialize settings of the chart with default values, then applies - * defined settings of the chart. Settings are obtained either from JSON - * of the html attribute data-settings, or from init of the charts. The - * highest priority settings are obtained directly from the JSON data - * obtained from the server. - * @param settings An object containing settings of the chart. - */ - self.init_settings = function(settings) { - var self = this; - - self.settings = {}; - self.settings.renderer = 'line'; - self.settings.auto_size = true; - self.settings.axes_x = true; - self.settings.axes_y = true; - self.settings.axes_y_label = true; - self.settings.interpolation = 'linear'; - // Static y axes values - self.settings.yMin = undefined; - self.settings.yMax = undefined; - // Static x axes values - self.settings.xMin = undefined; - self.settings.xMax = undefined; - // Show last point as dot - self.settings.higlight_last_point = false; - - // Composed charts wrapper - self.settings.composed_chart_selector = '.overview_chart'; - // Bar chart component - self.settings.bar_chart_selector = 'div[data-chart-type="overview_bar_chart"]'; - self.settings.bar_chart_settings = undefined; - - // allowed: verbose - self.hover_formatter = 'verbose'; - - /* - Applying settings. The later application rewrites the previous - therefore it has bigger priority. - */ - - // Settings defined in the init method of the chart - if (settings){ - self.apply_settings(settings); - } - - // Settings defined in the html data-settings attribute - if (self.jquery_element.data('settings')){ - var inline_settings = self.jquery_element.data('settings'); - self.apply_settings(inline_settings); - } - }; - - /** - * Applies passed settings to the chart object. Allowed settings are - * listed in this method. - * @param settings An object containing settings of the chart. - */ - self.apply_settings = function(settings){ - var self = this; - - var allowed_settings = ['renderer', 'auto_size', 'axes_x', 'axes_y', - 'interpolation', 'yMin', 'yMax', 'xMin', 'xMax', 'bar_chart_settings', - 'bar_chart_selector', 'composed_chart_selector', - 'higlight_last_point', 'axes_y_label']; - - jQuery.each(allowed_settings, function(index, setting_name) { - if (settings[setting_name] !== undefined){ - self.settings[setting_name] = settings[setting_name]; - } - }); - }; - - /** - * Computes size of the chart from surrounding divs. When - * settings.auto_size is on, it stretches the chart to bottom of - * the screen. - */ - self.get_size = function(){ - /* - The height will be determined by css or window size, - I have to hide everything inside that could mess with - the size, so it is fully determined by outer CSS. - */ - $(self.html_element).css('height', ''); - $(self.html_element).css('width', ''); - var svg = $(self.html_element).find('svg'); - svg.hide(); - - /* - Width an height of the chart will be taken from chart wrapper, - that can be styled by css. - */ - self.width = jquery_element.width(); - - // Set either the minimal height defined by CSS. - self.height = jquery_element.height(); - /* - Or stretch it to the remaining height of the window if there - is a place. + some space on the bottom, lets say 30px. - */ - if (self.settings.auto_size) { - var auto_height = $(window).height() - jquery_element.offset().top - 30; - if (auto_height > self.height) { - self.height = auto_height; - } - } - - /* Setting new sizes. It is important when resizing a window.*/ - $(self.html_element).css('height', self.height); - $(self.html_element).css('width', self.width); - svg.show(); - svg.css('height', self.height); - svg.css('width', self.width); - }; - - /************************************************************************/ - /****************************** Initialization **************************/ - /************************************************************************/ - // Init of the object - self.init(); - - /************************************************************************/ - /****************************** Methods *********************************/ - /************************************************************************/ - /** - * Obtains the actual chart data and renders the chart again. - */ - self.refresh = function (){ - var self = this; - - self.start_loading(); - horizon.ajax.queue({ - url: self.final_url, - success: function (data, textStatus, jqXHR) { - // Clearing the old chart data. - self.jquery_element.empty(); - $(self.legend_element).empty(); - - self.series = data.series; - self.stats = data.stats; - // The highest priority settings are sent with the data. - self.apply_settings(data.settings); - - if (self.series.length <= 0) { - $(self.html_element).html(gettext('No data available.')); - $(self.legend_element).empty(); - // Setting a fix height breaks things when legend is getting - // bigger. - $(self.legend_element).css('height', ''); - } else { - self.render(); - } - }, - error: function (jqXHR, textStatus, errorThrown) { - $(self.html_element).html(gettext('No data available.')); - $(self.legend_element).empty(); - // Setting a fix height breaks things when legend is getting - // bigger. - $(self.legend_element).css('height', ''); - // FIXME add proper fail message - horizon.alert('error', gettext('An error occurred. Please try again later.')); - }, - complete: function (jqXHR, textStatus) { - self.finish_loading(); - } - }); - }; - - /** - * Renders the chart using Rickshaw library. - */ - self.render = function(){ - var self = this; - var last_point, last_point_color; - - $.map(self.series, function (serie) { - serie.color = last_point_color = self.color(serie.name); - $.map(serie.data, function (statistic) { - // need to parse each date - statistic.x = d3.time.format.utc('%Y-%m-%dT%H:%M:%S').parse(statistic.x); - statistic.x = statistic.x.getTime() / 1000; - last_point = statistic; - last_point.color = serie.color; - }); - }); - - var renderer = self.settings.renderer; - if (renderer === 'StaticAxes'){ - renderer = Rickshaw.Graph.Renderer.StaticAxes; - } - - // clean the old graph the messy way - // TODO(lsmola) clena when the Rickshaw issue is gone - // https://github.com/shutterstock/rickshaw/issues/432 - self.jquery_element.empty(); - - var $newGraph = self.jquery_element.clone(); - self.jquery_element.replaceWith($newGraph); - self.jquery_element = $newGraph; - self.html_element = self.jquery_element[0]; - - // instantiate our graph! - var graph = new Rickshaw.Graph({ - element: self.html_element, - width: self.width, - height: self.height, - renderer: renderer, - series: self.series, - yMin: self.settings.yMin, - yMax: self.settings.yMax, - xMin: self.settings.xMin, - xMax: self.settings.xMax, - interpolation: self.settings.interpolation - }); - - /* - TODO(lsmola) add JQuery UI slider to make this work - if (self.slider_element) { - var slider = new Rickshaw.Graph.RangeSlider({ - graph: graph, - element: $(self.slider_element) - }); - } - */ - graph.render(); - - if (self.hover_formatter === 'verbose'){ - var hoverDetail = new Rickshaw.Graph.HoverDetail({ - graph: graph, - formatter: function(series, x, y) { - if(y % 1 === 0) { - y = parseInt(y); - } else { - y = parseFloat(y).toFixed(2); - } - - var d = new Date(x * 1000); - // Convert datetime to YYYY-MM-DD HH:MM:SS GMT - var datetime_string = d.getUTCFullYear() + "-" + - ("00" + (d.getUTCMonth() + 1)).slice(-2) + "-" + - ("00" + d.getUTCDate()).slice(-2) + " " + - ("00" + d.getUTCHours()).slice(-2) + ":" + - ("00" + d.getUTCMinutes()).slice(-2) + ":" + - ("00" + d.getUTCSeconds()).slice(-2) + " GMT"; - - var date = '' + datetime_string + ''; - var swatch = ''; - return swatch + series.name + ': ' + y + ' ' + series.unit + '
    ' + date; - } - }); - } - - if (self.legend_element) { - var legend = new Rickshaw.Graph.Legend({ - graph: graph, - element: self.legend_element - }); - - var shelving = new Rickshaw.Graph.Behavior.Series.Toggle({ - graph: graph, - legend: legend - }); - - var order = new Rickshaw.Graph.Behavior.Series.Order({ - graph: graph, - legend: legend - }); - - var highlighter = new Rickshaw.Graph.Behavior.Series.Highlight({ - graph: graph, - legend: legend - }); - } - if (self.settings.axes_x) { - var axes_x = new Rickshaw.Graph.Axis.Time({ - graph: graph - }); - axes_x.render(); - } - if (self.settings.axes_y) { - var axes_y_settings = { - graph: graph - }; - if (!self.settings.axes_y_label){ - // hiding label of Y axis if setting is set to false - axes_y_settings.tickFormat = (function (d) { return ''; }); - } - var axes_y = new Rickshaw.Graph.Axis.Y(axes_y_settings); - axes_y.render(); - } - - /* - Setting a fix height breaks things when chart is refreshed and - legend is getting bigger. - */ - $(self.legend_element).css('height', ''); - - // Render bar chart - if (self.stats !== undefined){ - var composed_chart = self.jquery_element.parents(self.settings.composed_chart_selector).first(); - var bar_chart_html = composed_chart.find(self.settings.bar_chart_selector).get(0); - - horizon.d3_bar_chart.refresh(bar_chart_html, - self.settings.bar_chart_settings, - self.stats); - } - - // Render ending dot to last point - if (self.settings.higlight_last_point){ - if (last_point !== undefined && last_point_color !== undefined){ - graph.vis.append('circle') - .attr('class', 'used_component') - .attr('cy', graph.y(last_point.y)) - .attr('cx', graph.x(last_point.x)) - .attr('r', 2) - .style('fill', last_point_color) - .style('stroke', last_point_color) - .style('stroke-width', 2); - } - } - }; - - /** - * Shows chart loader with backdrop. Backdrop is computed to hide - * the canvas with chart. Loader is computed to be placed in the center. - * Hides also a block with legend. - */ - self.start_loading = function () { - var self = this; - - /* Find and remove backdrops and spinners that could be already there.*/ - $(self.html_element).find('.modal-backdrop').remove(); - $(self.html_element).find('.spinner_wrapper').remove(); - - // Display the backdrop that will be over the chart. - self.backdrop = $(''); - self.backdrop.css('width', self.width).css('height', self.height); - $(self.html_element).append(self.backdrop); - - // Hide the legend. - $(self.legend_element).empty().addClass('disabled'); - - // Show the spinner. - self.spinner = $('
    '); - $(self.html_element).append(self.spinner); - /* - TODO(lsmola) a loader for in-line tables spark-lines has to be - prepared, the parameters of loader could be sent in settings. - */ - self.spinner.spin(horizon.conf.spinner_options.line_chart); - - // Center the spinner considering the size of the spinner. - var radius = horizon.conf.spinner_options.line_chart.radius; - var length = horizon.conf.spinner_options.line_chart.length; - var spinner_size = radius + length; - var top = (self.height / 2) - spinner_size / 2; - var left = (self.width / 2) - spinner_size / 2; - self.spinner.css('top', top).css('left', left); - }; - - /** - * Hides the loader and backdrop so the chart will become visible. - * Shows also the block with legend. - */ - self.finish_loading = function () { - var self = this; - // Showing the legend. - $(self.legend_element).removeClass('disabled'); - }; - }, - - /** - * Function for initializing of the charts. - * If settings['auto_resize'] is true, the chart will be refreshed when - * the size of the window is changed. This option made only sense when - * the size of the chart and its wrapper is not static. - * @param selector JQuery selector of charts we want to initialize. - * @param settings An object containing settings of the chart. - */ - init: function(selector, settings) { - var self = this; - $(selector).each(function() { - self.refresh(this, settings); - }); - - if (settings !== undefined && settings.auto_resize) { - /* - I want to refresh chart on resize of the window, but only - at the end of the resize. Nice code from mr. Google. - */ - var rtime = new Date(1, 1, 2000, 12, 0, 0); - var timeout = false; - var delta = 400; - $(window).resize(function() { - rtime = new Date(); - if (timeout === false) { - timeout = true; - setTimeout(resizeend, delta); - } - }); - - var resizeend = function() { - if (new Date() - rtime < delta) { - setTimeout(resizeend, delta); - } else { - timeout = false; - $(selector).each(function() { - self.refresh(this, settings); - }); - } - }; - } - - self.bind_commands(selector, settings); - }, - - /** - * Function for creating chart objects, saving them for later reuse - * and calling their refresh method. - * @param html_element HTML element where the chart will be rendered. - * @param settings An object containing settings of the chart. - */ - refresh: function(html_element, settings){ - var chart = new this.LineChart(this, html_element, settings); - /* - FIXME save chart objects somewhere so I can use them again when - e.g. I am switching tabs, or if I want to update them - via web sockets - this.charts.add_or_update(chart) - */ - chart.refresh(); - }, - - /** - * Function for binding controlling commands to the chart. Like changing - * timespan or various parameters we want to show in the chart. The - * charts will be refreshed immediately after the form element connected - * to them is changed. - * @param selector JQuery selector of charts we are initializing. - * @param settings An object containing settings of the chart. - */ - bind_commands: function (selector, settings){ - // connecting controls of the charts - var select_box_selector = 'select[data-line-chart-command="select_box_change"]'; - var datepicker_selector = 'input[data-line-chart-command="date_picker_change"]'; - var self = this; - - /** - * Connecting forms to charts it controls. Each chart contains - * JQuery selector data-form-selector, which defines by which - * html Forms is a particular chart controlled. This information - * has to be projected to forms. So when form input is changed, - * all connected charts are refreshed. - */ - connect_forms_to_charts = function(){ - $(selector).each(function() { - var chart = $(this); - $(chart.data('form-selector')).each(function(){ - var form = $(this); - // each form is building a jquery selector for all charts it affects - var chart_identifier = 'div[data-form-selector="' + chart.data('form-selector') + '"]'; - if (!form.data('charts_selector')){ - form.data('charts_selector', chart_identifier); - } else { - form.data('charts_selector', form.data('charts_selector') + ', ' + chart_identifier); - } - }); - }); - }; - - /** - * A helper function for delegating form events to charts, causing their - * refreshing. - * @param selector JQuery selector of charts we are initializing. - * @param event_name Event name we want to delegate. - * @param settings An object containing settings of the chart. - */ - delegate_event_and_refresh_charts = function(selector, event_name, settings) { - $('form').delegate(selector, event_name, function() { - /* - Registering 'any event' on form element by delegating. This way it - can be easily overridden / enhanced when some special functionality - needs to be added. Like input element showing/hiding another element - on some condition will be defined directly on element and can block - this default behavior. - */ - var invoker = $(this); - var form = invoker.parents('form').first(); - - $(form.data('charts_selector')).each(function(){ - // refresh the chart connected to changed form - self.refresh(this, settings); - }); - }); - }; - - /** - * A helper function for catching change event of form selectboxes - * connected to charts. - */ - bind_select_box_change = function(settings) { - delegate_event_and_refresh_charts(select_box_selector, 'change', settings); - }; - - /** - * A helper function for catching changeDate event of form datepickers - * connected to charts. - */ - bind_datepicker_change = function(settings) { - var now = new Date(); - - $(datepicker_selector).each(function() { - var el = $(this); - el.datepicker({format: 'yyyy-mm-dd', - setDate: new Date(), - showButtonPanel: true}); - }); - delegate_event_and_refresh_charts(datepicker_selector, 'changeDate', settings); - }; - - connect_forms_to_charts(); - bind_select_box_change(settings); - bind_datepicker_change(settings); - } -}; - -/* Init the graphs */ -horizon.addInitFunction(function () { - horizon.d3_line_chart.init('div[data-chart-type="line_chart"]', {}); -}); diff --git a/code/horizon/horizon/static/horizon/js/horizon.d3piechart.js b/code/horizon/horizon/static/horizon/js/horizon.d3piechart.js deleted file mode 100644 index 15e1b57c..00000000 --- a/code/horizon/horizon/static/horizon/js/horizon.d3piechart.js +++ /dev/null @@ -1,275 +0,0 @@ -/* - Draw pie charts in d3. - - To use, a div is required with the class .d3_pie_chart_usage or - .d3_pie_chart_distribution, and a data-used attribute in the div - that stores the data used to fill the chart. - - Example (usage): -
    -
    - - Example (distribution): -
    -
    -*/ - -// Pie chart dimensions -var WIDTH = 100; -var HEIGHT = 100; -var RADIUS = 45; - -// Colors -var BKGRND = "#F2F2F2"; -var FRGRND = "#006CCF"; -var FULL = "#D0342B"; -var NEARLY_FULL = "#FFA500"; -var STROKE_USAGE = "#CCCCCC"; -var STROKE_DISTRIBUTION = "#609ED2"; -var BLUE_SHADES = [ - "#609ED2", - "#BFD8ED", - "#EFF5FB", - "#2D6997", - "#1F4A6F", - "#122A40", - "#428BCA", - "#90BAE0", - "#DFEBF6" -]; - - -function create_vis(chart) { - return d3.select(chart).append("svg:svg") - .attr("class", "chart") - .attr("width", WIDTH) - .attr("height", HEIGHT) - .attr("viewBox", "0 0 " + WIDTH + " " + HEIGHT ) - .append("g") - .attr("transform", - "translate(" + (WIDTH / 2) + "," + (HEIGHT / 2) + ")"); -} - -function create_arc() { - return d3.svg.arc() - .outerRadius(RADIUS) - .innerRadius(0); -} - -function create_pie(param) { - return d3.layout.pie() - .sort(null) - .value(function(d){ return d[param]; }); -} - - -horizon.d3_pie_chart_usage = { - init: function() { - var self = this; - - // Pie Charts - var pie_chart_data = $(".d3_pie_chart_usage"); - self.chart = d3.selectAll(".d3_pie_chart_usage"); - - for (var i = 0; i < pie_chart_data.length; i++) { - var used = Math.min(parseInt($(pie_chart_data[i]).data("used")), 100); - self.data = [{"percentage":used}, {"percentage":100 - used}]; - self.pieChart(i); - } - }, - // Draw a pie chart - pieChart: function(i) { - var self = this; - var vis = create_vis(self.chart[0][i]); - var arc = create_arc(); - var pie = create_pie("percentage"); - - // Draw an empty pie chart - vis.selectAll(".arc") - .data(pie([{"percentage":10}])) - .enter() - .append("path") - .attr("class","arc") - .attr("d", arc) - .style("fill", BKGRND) - .style("stroke", STROKE_USAGE) - .style("stroke-width", 1); - - // Animate filling the pie chart - var animate = function(data) { - vis.selectAll(".arc") - .data(pie(data)) - .enter() - .append("path") - .attr("class","arc") - .attr("d", arc) - .style("fill", function(){ - if (self.data[0].percentage >= 100) { - return FULL; - } else if (self.data[0].percentage >= 80) { - return NEARLY_FULL; - } else { - return FRGRND; - } - }) - .style("stroke", STROKE_USAGE) - .style("stroke-width", function() { - if (self.data[0].percentage <= 0 || self.data[0].percentage >= 100) { - return 0; - } else { - return 1; - } - }) - .transition() - .duration(500) - .attrTween("d", function(start) { - start.endAngle = start.startAngle = 0; - var end = { - startAngle: 0, - endAngle: 2 * Math.PI * (100 - start.value) / 100 - }; - var tween = d3.interpolate(start, end); - return function(t) { return arc(tween(t)); }; - }); - }; - - animate(self.data); - } -}; - - -horizon.d3_pie_chart_distribution = { - colors: BLUE_SHADES, - - init: function() { - var self = this; - var pie_chart_data = $(".d3_pie_chart_distribution"); - self.chart = d3.selectAll(".d3_pie_chart_distribution"); - - for (var i = 0; i < pie_chart_data.length; i++) { - var parts = $(pie_chart_data[i]).data("used").split("|"); - self.data = []; - self.keys = []; - for (var j = 0; j < parts.length; j++) { - var key_value = parts[j].split("="); - var d = { - key: key_value[0], - value: key_value[1] - }; - self.data.push(d); - self.keys.push(key_value[0]); - } - self.pieChart(i); - } - }, - // Draw a pie chart - pieChart: function(i) { - var self = this; - var vis = create_vis(self.chart[0][i]); - var arc = create_arc(); - var pie = create_pie("value"); - - var total = 0; - for (var j = 0; j < self.data.length; j++) { - total = total + parseInt(self.data[j].value); - } - - var initial_data = []; - if (total === 0) { - initial_data = [{"value": 1}]; - } - - // Draw an empty pie chart - vis.selectAll(".arc") - .data(pie(initial_data)) - .enter() - .append("path") - .attr("class","arc") - .attr("d", arc) - .style("fill", BKGRND) - .style("stroke", STROKE_DISTRIBUTION) - .style("stroke-width", 1); - - // Animate filling the pie chart - var animate = function(data) { - vis.selectAll(".arc") - .data(pie(data)) - .enter() - .append("path") - .attr("class","arc") - .attr("d", arc) - .style("fill", function(d) { - return self.colors[self.data.indexOf(d.data)]; - }) - .style("stroke", STROKE_DISTRIBUTION) - .style("stroke-width", 1) - .transition() - .duration(500) - .attrTween("d", function(start) { - start.endAngle = start.startAngle; - var end = jQuery.extend({}, start); - end.endAngle = end.startAngle + 2 * Math.PI / total * end.value; - var tween = d3.interpolate(start, end); - return function(t) { return arc(tween(t)); }; - }); - }; - - if (total !== 0) { - animate(self.data); - } - - // Add a legend - var legend = d3.select(self.chart[0][i]) - .append("svg") - .attr("class", "legend") - .attr("width", WIDTH * 2) - .attr("height", self.data.length * 18 + 20) - .selectAll("g") - .data(self.keys) - .enter() - .append("g") - .attr("transform", function(d, i) { - return "translate(0," + i * 20 + ")"; - }); - - legend.append("rect") - .attr("width", 18) - .attr("height", 18) - .style("fill", function(d) { - var item; - for (var i = 0; i < self.data.length; i++) { - if (self.data[i].key == d) { - item = self.data[i]; - break; - } - } - return self.colors[self.data.indexOf(item)]; - }); - - legend.append("text") - .attr("x", 24) - .attr("y", 9) - .attr("dy", ".35em") - .text(function(d) { - if (total === 0) { - return d + " 0%"; - } - var value = 0; - for (var j = 0; j < self.data.length; j++) { - if (self.data[j].key == d) { - value = self.data[j].value; - break; - } - } - return d + " " + Math.round(value/total * 100) + "%"; - }); - } -}; - - -horizon.addInitFunction(function () { - horizon.d3_pie_chart_usage.init(); - horizon.d3_pie_chart_distribution.init(); -}); diff --git a/code/horizon/horizon/static/horizon/js/horizon.firewalls.js b/code/horizon/horizon/static/horizon/js/horizon.firewalls.js deleted file mode 100644 index 5daa032d..00000000 --- a/code/horizon/horizon/static/horizon/js/horizon.firewalls.js +++ /dev/null @@ -1,265 +0,0 @@ -horizon.firewalls = { - user_decided_length: false, - rules_selected: [], - rules_available: [], - routers_selected: [], - routers_available: [], - - getConsoleLog: function(via_user_submit) { - var form_element = $("#tail_length"), - data; - - if (!via_user_submit) { - via_user_submit = false; - } - - if(this.user_decided_length) { - data = $(form_element).serialize(); - } else { - data = "length=35"; - } - - $.ajax({ - url: $(form_element).attr('action'), - data: data, - method: 'get', - success: function(response_body) { - $('pre.logs').text(response_body); - }, - error: function(response) { - if(via_user_submit) { - horizon.clearErrorMessages(); - horizon.alert('error', gettext('There was a problem communicating with the server, please try again.')); - } - } - }); - }, - - /* - * Gets the html select element associated with a given - * rule id for rule_id. - **/ - get_rule_element: function(rule_id) { - return $('li > label[for^="id_rule_' + rule_id + '"]'); - }, - - /* - * Initializes an associative array of lists of the current - * rules. - **/ - init_rule_list: function() { - horizon.firewalls.rules_selected = []; - horizon.firewalls.rules_available = []; - $(this.get_rule_element("")).each(function(){ - var $this = $(this); - var $input = $this.children("input"); - var rule_property = { - name:$this.text().replace(/^\s+/,""), - id:$input.attr("id"), - value:$input.attr("value") - }; - if($input.is(':checked')) { - horizon.firewalls.rules_selected.push(rule_property); - } else { - horizon.firewalls.rules_available.push(rule_property); - } - }); - }, - - /* - * Generates the HTML structure for a rule that will be displayed - * as a list item in the rule list. - **/ - generate_rule_element: function(name, id, value) { - var $li = $('
  • '); - $li.attr('name', value).html(name + '(' + value + ')'); - return $li; - }, - - /* - * Generates the HTML structure for the Rule List. - **/ - generate_rulelist_html: function() { - var self = this; - var updateForm = function() { - var lists = $("#ruleListId li").attr('data-index',100); - var active_rules = $("#selected_rule > li").map(function(){ - return $(this).attr("name"); - }); - $("#ruleListId input:checkbox").removeAttr('checked'); - active_rules.each(function(index, value){ - $("#ruleListId input:checkbox[value=" + value + "]") - .prop('checked', true) - .parents("li").attr('data-index',index); - }); - $("#ruleListId ul").html( - lists.sort(function(a,b){ - if( $(a).data("index") < $(b).data("index")) { return -1; } - if( $(a).data("index") > $(b).data("index")) { return 1; } - return 0; - }) - ); - }; - $("#ruleListSortContainer").show(); - $("#ruleListIdContainer").hide(); - self.init_rule_list(); - // Make sure we don't duplicate the rules in the list - $("#available_rule").empty(); - $.each(self.rules_available, function(index, value){ - $("#available_rule").append(self.generate_rule_element(value.name, value.id, value.value)); - }); - // Make sure we don't duplicate the rules in the list - $("#selected_rule").empty(); - $.each(self.rules_selected, function(index, value){ - $("#selected_rule").append(self.generate_rule_element(value.name, value.id, value.value)); - }); - $(".rulelist > li > a.btn").click(function(e){ - var $this = $(this); - e.preventDefault(); - e.stopPropagation(); - if($this.parents("ul#available_rule").length > 0) { - $this.parent().appendTo($("#selected_rule")); - } else if ($this.parents("ul#selected_rule").length > 0) { - $this.parent().appendTo($("#available_rule")); - } - updateForm(); - }); - if ($("#ruleListId > div.form-group.error").length > 0) { - var errortext = $("#ruleListId > div.form-group.error").find("span.help-block").text(); - $("#selected_rule_h4").before($('
    ').html(errortext)); - } - $(".rulelist").sortable({ - connectWith: "ul.rulelist", - placeholder: "ui-state-highlight", - distance: 5, - start:function(e,info){ - $("#selected_rule").addClass("dragging"); - }, - stop:function(e,info){ - $("#selected_rule").removeClass("dragging"); - updateForm(); - } - }).disableSelection(); - }, - - /* - * Gets the html select element associated with a given - * router id for router_id. - **/ - get_router_element: function(router_id) { - return $('li > label[for^="id_router_' + router_id + '"]'); - }, - - /* - * Initializes an associative array of lists of the current - * routers. - **/ - init_router_list: function() { - horizon.firewalls.routers_selected = []; - horizon.firewalls.routers_available = []; - $(this.get_router_element("")).each(function(){ - var $this = $(this); - var $input = $this.children("input"); - var router_property = { - name:$this.text().replace(/^\s+/,""), - id:$input.attr("id"), - value:$input.attr("value") - }; - if($input.is(':checked')) { - horizon.firewalls.routers_selected.push(router_property); - } else { - horizon.firewalls.routers_available.push(router_property); - } - }); - }, - - /* - * Generates the HTML structure for a router that will be displayed - * as a list item in the router list. - **/ - generate_router_element: function(name, id, value) { - var $li = $('
  • '); - $li.attr('name', value).html(name + '(' + value + ')'); - return $li; - }, - - /* - * Generates the HTML structure for the router List. - **/ - generate_routerlist_html: function() { - var self = this; - var updateForm = function() { - var lists = $("#routerListId li").attr('data-index',100); - var active_routers = $("#selected_router > li").map(function(){ - return $(this).attr("name"); - }); - $("#routerListId input:checkbox").removeAttr('checked'); - active_routers.each(function(index, value){ - $("#routerListId input:checkbox[value=" + value + "]") - .prop('checked', true) - .parents("li").attr('data-index',index); - }); - $("#routerListId ul").html( - lists.sort(function(a,b){ - if( $(a).data("index") < $(b).data("index")) { return -1; } - if( $(a).data("index") > $(b).data("index")) { return 1; } - return 0; - }) - ); - }; - $("#routerListSortContainer").show(); - $("#routerListIdContainer").hide(); - self.init_router_list(); - // Make sure we don't duplicate the routers in the list - $("#available_router").empty(); - $.each(self.routers_available, function(index, value){ - $("#available_router").append(self.generate_router_element(value.name, value.id, value.value)); - }); - // Make sure we don't duplicate the routers in the list - $("#selected_router").empty(); - $.each(self.routers_selected, function(index, value){ - $("#selected_router").append(self.generate_router_element(value.name, value.id, value.value)); - }); - $(".routerlist > li > a.btn").click(function(e){ - var $this = $(this); - e.preventDefault(); - e.stopPropagation(); - if($this.parents("ul#available_router").length > 0) { - $this.parent().appendTo($("#selected_router")); - } else if ($this.parents("ul#selected_router").length > 0) { - $this.parent().appendTo($("#available_router")); - } - updateForm(); - }); - if ($("#routerListId > div.form-group.error").length > 0) { - var errortext = $("#routerListId > div.form-group.error").find("span.help-block").text(); - $("#selected_router_h4").before($('
    ').html(errortext)); - } - $(".routerlist").sortable({ - connectWith: "ul.routerlist", - placeholder: "ui-state-highlight", - distance: 5, - start:function(e,info){ - $("#selected_router").addClass("dragging"); - }, - stop:function(e,info){ - $("#selected_router").removeClass("dragging"); - updateForm(); - } - }).disableSelection(); - }, - - workflow_init: function(modal) { - // Initialise the drag and drop rule list - horizon.firewalls.generate_rulelist_html(); - horizon.firewalls.generate_routerlist_html(); - } -}; - -horizon.addInitFunction(horizon.firewalls.init = function () { - $(document).on('submit', '#tail_length', function (evt) { - horizon.firewalls.user_decided_length = true; - horizon.firewalls.getConsoleLog(true); - evt.preventDefault(); - }); -}); diff --git a/code/horizon/horizon/static/horizon/js/horizon.forms.js b/code/horizon/horizon/static/horizon/js/horizon.forms.js deleted file mode 100644 index cb485f88..00000000 --- a/code/horizon/horizon/static/horizon/js/horizon.forms.js +++ /dev/null @@ -1,381 +0,0 @@ -/* Namespace for core functionality related to Forms. */ -horizon.forms = { - handle_snapshot_source: function() { - $("div.table_wrapper, #modal_wrapper").on("change", "select#id_snapshot_source", function(evt) { - var $option = $(this).find("option:selected"); - var $form = $(this).closest('form'); - var $volName = $form.find('input#id_name'); - if ($volName.val() === "") { - $volName.val($option.data("name")); - } - var $volSize = $form.find('input#id_size'); - var volSize = parseInt($volSize.val(), 10) || -1; - var dataSize = parseInt($option.data("size"), 10) || -1; - if (volSize < dataSize) { - $volSize.val(dataSize); - } - }); - }, - - handle_volume_source: function() { - $("div.table_wrapper, #modal_wrapper").on("change", "select#id_volume_source", function(evt) { - var $option = $(this).find("option:selected"); - var $form = $(this).closest('form'); - var $volName = $form.find('input#id_name'); - if ($volName.val() === "") { - $volName.val($option.data("name")); - } - var $volSize = $form.find('input#id_size'); - var volSize = parseInt($volSize.val(), 10) || -1; - var dataSize = parseInt($option.data("size"), 10) || -1; - if (volSize < dataSize) { - $volSize.val(dataSize); - } - }); - }, - - handle_image_source: function() { - $("div.table_wrapper, #modal_wrapper").on("change", "select#id_image_source", function(evt) { - var $option = $(this).find("option:selected"); - var $form = $(this).closest('form'); - var $volName = $form.find('input#id_name'); - if ($volName.val() === "") { - $volName.val($option.data("name")); - } - var $volSize = $form.find('input#id_size'); - var volSize = parseInt($volSize.val(), 10) || -1; - var dataSize = parseInt($option.data("size"), 10) || -1; - var minDiskSize = parseInt($option.data("min_disk"), 10) || -1; - var defaultVolSize = dataSize; - if (minDiskSize > defaultVolSize) { - defaultVolSize = minDiskSize; - } - if (volSize < defaultVolSize) { - $volSize.val(defaultVolSize); - } - }); - }, - - /** - * In the container's upload object form, copy the selected file name in the - * object name field if the field is empty. The filename string is stored in - * the input as an attribute "filename". The value is used as comparison to - * compare with the value of the new filename string. - */ - handle_object_upload_source: function() { - $("div.table_wrapper, #modal_wrapper").on("change", "input#id_object_file", function(evt) { - if (typeof($(this).attr("filename")) === 'undefined') { - $(this).attr("filename", ""); - } - var $form = $(this).closest("form"); - var $obj_name = $form.find("input#id_name"); - var $fullPath = $(this).val(); - var $startIndex = ($fullPath.indexOf('\\') >= 0 ? $fullPath.lastIndexOf('\\') : $fullPath.lastIndexOf('/')); - var $filename = $fullPath.substring($startIndex); - - if ($filename.indexOf('\\') === 0 || $filename.indexOf('/') === 0) { - $filename = $filename.substring(1); - } - - if (typeof($obj_name.val()) === 'undefined' || $obj_name.val().length < 1 || $(this).attr("filename").localeCompare($obj_name.val()) === 0) { - $obj_name.val($filename); - $(this).attr("filename", $filename); - $obj_name.trigger('input'); - } - }); - }, - - datepicker: function() { - var startDate = $('input#id_start').datepicker({ language: horizon.datepickerLocale }) - .on('changeDate', function(ev) { - if (ev.dates[0].valueOf() > endDate.dates[0].valueOf()) { - var newDate = new Date(ev.dates[0]); - newDate.setDate(newDate.getDate() + 1); - endDate.setDate(newDate); - $('input#id_end')[0].focus(); - } - startDate.hide(); - endDate.setStartDate(ev.dates[0]); - endDate.update(); - }).data('datepicker'); - - var endDate = $('input#id_end').datepicker({ - language: horizon.datepickerLocale, - startDate: startDate ? startDate.dates[0] : null - }).on('changeDate', function(ev) { - endDate.hide(); - }).data('datepicker'); - - $("input#id_start").mousedown(function(){ - endDate.hide(); - }); - - $("input#id_end").mousedown(function(){ - startDate.hide(); - }); - } -}; - -horizon.forms.prevent_multiple_submission = function (el) { - // Disable multiple submissions when launching a form. - var $form = $(el).find("form"); - $form.submit(function () { - var button = $(this).find('[type="submit"]'); - if (button.hasClass('btn-primary') && !button.hasClass('always-enabled')){ - $(this).submit(function () { - return false; - }); - button.removeClass('primary').addClass('disabled'); - button.attr('disabled', 'disabled'); - } - return true; - }); -}; - -horizon.forms.add_password_fields_reveal_buttons = function (el) { - var _change_input_type = function ($input, type) { - /* - * In a perfect world, this function would just do: - * - * $input.attr('type', type); - * - * however, Microsoft Internet Explorer exists and we have to support it. - */ - - var $new_input = $input.clone(); - - $new_input.attr('type', type); - $input.replaceWith($new_input); - return $new_input; - }; - - - $(el).find('input[type="password"]').each(function (i, input) { - var $input = $(input); - - $input.closest('div').addClass("has-feedback"); - $('').addClass( - "form-control-feedback fa fa-eye password-icon" - ).insertAfter($input).click(function () { - var $icon = $(this); - - if ($input.attr('type') === 'password') { - $icon.removeClass('fa-eye'); - $icon.addClass('fa-eye-slash'); - $input = _change_input_type($input, 'text'); - } else { - $icon.removeClass('fa-eye-slash'); - $icon.addClass('fa-eye'); - $input = _change_input_type($input, 'password'); - } - }); - }); -}; - -horizon.forms.init_examples = function (el) { - var $el = $(el); - - // FIXME(gabriel): These should be moved into the forms themselves as help text, etc. - - // Update/create image form. - $el.find("#create_image_form input#id_copy_from").attr("placeholder", "http://example.com/image.iso"); - - // Table search box. - $el.find(".table_search input").attr("placeholder", gettext("Filter")); -}; - -horizon.addInitFunction(horizon.forms.init = function () { - horizon.forms.prevent_multiple_submission($('body')); - horizon.modals.addModalInitFunction(horizon.forms.prevent_multiple_submission); - - horizon.forms.init_examples($("body")); - horizon.modals.addModalInitFunction(horizon.forms.init_examples); - - horizon.forms.handle_snapshot_source(); - horizon.forms.handle_volume_source(); - horizon.forms.handle_image_source(); - horizon.forms.handle_object_upload_source(); - horizon.forms.datepicker(); - - if (!horizon.conf.disable_password_reveal) { - horizon.forms.add_password_fields_reveal_buttons($("body")); - horizon.modals.addModalInitFunction( - horizon.forms.add_password_fields_reveal_buttons); - } - - // Bind event handlers to confirm dangerous actions. - // Stops angular form buttons from triggering this event - $("body").on("click", "form button:not([ng-click]).btn-danger", function (evt) { - horizon.datatables.confirm(this); - evt.preventDefault(); - }); - - /* Switchable Fields (See Horizon's Forms docs for more information) */ - - // Single reference - var $document = $(document); - - // Bind handler for swapping labels on "switchable" select fields. - $document.on("change", 'select.switchable', function (evt) { - var $fieldset = $(evt.target).closest('fieldset'), - $switchables = $fieldset.find('select.switchable'); - - $switchables.each(function (index, switchable) { - var $switchable = $(switchable), - slug = $switchable.data('slug'), - visible = $switchable.is(':visible'), - val = $switchable.val(); - - function handle_switched_field(index, input){ - var $input = $(input), - data = $input.data(slug + "-" + val); - - if (typeof data === "undefined" || !visible) { - $input.closest('.form-group').hide(); - } else { - $('label[for=' + $input.attr('id') + ']').html(data); - $input.closest('.form-group').show(); - } - } - - $fieldset.find('.switched[data-switch-on*="' + slug + '"]').each(handle_switched_field); - $fieldset.siblings().find('.switched[data-switch-on*="' + slug + '"]').each(handle_switched_field); - }); - }); - - // Fire off the change event to trigger the proper initial values. - $('select.switchable').trigger('change'); - // Queue up the for new modals, too. - horizon.modals.addModalInitFunction(function (modal) { - $(modal).find('select.switchable').trigger('change'); - }); - - // Bind handler for swapping labels on "switchable" checkbox input fields. - $document.on("change", 'input.switchable', function (evt) { - var $fieldset = $(evt.target).closest('fieldset'), - $switchables = $fieldset.find('input.switchable'); - - $switchables.each(function (index, switchable) { - var $switchable = $(switchable), - visible = $switchable.is(':visible'), - slug = $switchable.data('slug'), - checked = $switchable.prop('checked'), - hide_tab = $switchable.data('hide-tab'), - hide_on = $switchable.data('hideOnChecked'); - - // If checkbox is hidden then do not apply any further logic - if (!visible) return; - - // If the checkbox has hide-tab attribute then hide/show the tab - if (hide_tab) { - var $btnfinal = $('.button-final'); - if(checked == hide_on) { - // If the checkbox is not checked then hide the tab - $('*[data-target="#'+ hide_tab +'"]').parent().hide(); - $('.button-next').hide(); - $btnfinal.show(); - $btnfinal.data('show-on-tab', $fieldset.prop('id')); - } else if (!$('*[data-target="#'+ hide_tab +'"]').parent().is(':visible')) { - // If the checkbox is checked and the tab is currently hidden then show the tab again - $('*[data-target="#'+ hide_tab +'"]').parent().show(); - $btnfinal.hide(); - $('.button-next').show(); - $btnfinal.removeData('show-on-tab'); - } - } - - function handle_switched_field(index, input){ - var $input = $(input); - - if (checked != hide_on) { - $input.closest('.form-group').show(); - // Add the required class to form group to show a (*) next to label - if ($input.data('is-required')) { - $input.closest('.form-group').addClass("required"); - } - } else { - $input.closest('.form-group').hide(); - if ($input.data('is-required')) { - $input.closest('.form-group').removeClass("required"); - } - } - } - - $fieldset.find('.switched[data-switch-on*="' + slug + '"]').each(handle_switched_field); - $fieldset.siblings().find('.switched[data-switch-on*="' + slug + '"]').each(handle_switched_field); - }); - }); - - // Fire off the change event to trigger the proper initial values. - $('input.switchable').trigger('change'); - // Queue up the for new modals, too. - horizon.modals.addModalInitFunction(function (modal) { - $(modal).find('input.switchable').trigger('change'); - }); - - $document.on('shown.bs.tab', function(evt) { - var $fieldset = $('fieldset.active'); - var $btnfinal = $('.button-final'); - if ($btnfinal.data('show-on-tab')) { - if ($fieldset.prop('id') == $btnfinal.data('show-on-tab')) { - $('.button-next').hide(); - $btnfinal.show(); - } else { - $btnfinal.hide(); - $('.button-next').show(); - } - } - }); - - // Handle field toggles for the Create Volume source type field - function update_volume_source_displayed_fields (field) { - var $this = $(field), - base_type = $this.val(); - - $this.find("option").each(function () { - if (this.value !== base_type) { - $("#id_" + this.value).closest(".form-group").hide(); - } else { - $("#id_" + this.value).closest(".form-group").show(); - } - }); - } - - $document.on('change', '#id_volume_source_type', function (evt) { - update_volume_source_displayed_fields(this); - }); - - $('#id_volume_source_type').change(); - horizon.modals.addModalInitFunction(function (modal) { - $(modal).find("#id_volume_source_type").change(); - }); - - /* Help tooltips */ - - // Apply standard handler for everything but checkboxes. - $document.tooltip({ - selector: "div.form-group .help-icon", - placement: function (tip, input) { - // Position to the right unless this is a "split" for in which case put - // the tooltip below so it doesn't block the next field. - return $(input).closest("form[class*='split']").length ? "bottom" : 'right'; - }, - title: function () { - return $(this).closest('div.form-group').children('.help-block').text(); - } - }); - // Hide the tooltip upon interaction with the field for select boxes. - // We use mousedown and keydown since those "open" the select dropdown. - $document.on('mousedown keydown', '.form-group select', function (evt) { - $(this).tooltip('hide'); - }); - // Hide the tooltip after escape button pressed - $document.on('keydown.esc_btn', function (evt) { - if (evt.keyCode === 27) { - $('.tooltip').hide(); - } - }); - - // Hide the help text for js-capable browsers - $('p.help-block').hide(); -}); diff --git a/code/horizon/horizon/static/horizon/js/horizon.formset_table.js b/code/horizon/horizon/static/horizon/js/horizon.formset_table.js deleted file mode 100644 index 239d9d2f..00000000 --- a/code/horizon/horizon/static/horizon/js/horizon.formset_table.js +++ /dev/null @@ -1,87 +0,0 @@ -horizon.formset_table = (function () { - 'use strict'; - - var module = {}; - - - // go through the whole table and fix the numbering of rows - module.reenumerate_rows = function (table, prefix) { - var count = 0; - var input_name_re = new RegExp('^' + prefix + '-(\\d+|__prefix__)-'); - var input_id_re = new RegExp('^id_' + prefix + '-(\\d+|__prefix__)-'); - - table.find('tbody tr').each(function () { - $(this).find('input').each(function () { - var input = $(this); - input.attr('name', input.attr('name').replace( - input_name_re, prefix + '-' + count + '-')); - input.attr('id', input.attr('id').replace( - input_id_re, 'id_' + prefix + '-' + count + '-')); - }); - count += 1; - }); - $('#id_' + prefix + '-TOTAL_FORMS').val(count); - }; - - // mark a row as deleted and hide it - module.delete_row = function (e) { - $(this).closest('tr').hide(); - $(this).prev('input[name$="-DELETE"]').attr('checked', true); - }; - - // replace the "Delete" checkboxes with × for deleting rows - module.replace_delete = function (where) { - where.find('input[name$="-DELETE"]').hide().after( - $('×').click(module.delete_row) - ); - }; - - // add more empty rows in the flavors table - module.add_row = function (table, prefix, empty_row_html) { - var new_row = $(empty_row_html); - module.replace_delete(new_row); - table.find('tbody').append(new_row); - module.reenumerate_rows(table, prefix); - }; - - // prepare all the javascript for formset table - module.init = function (prefix, empty_row_html, add_label) { - - var table = $('table#' + prefix); - - module.replace_delete(table); - - // if there are extra empty rows, add the button for new rows - if (add_label) { - var button = $('' + - add_label + ''); - table.find('tfoot td').append(button); - button.click(function () { - module.add_row(table, prefix, empty_row_html); - }); - } - - // if the formset is not empty and has no errors, - // delete the empty extra rows from the end - var initial_forms = +$('#id_' + prefix + '-INITIAL_FORMS').val(); - var total_forms = +$('#id_' + prefix + '-TOTAL_FORMS').val(); - - if (table.find('tbody tr').length > 1 && - table.find('tbody td.error').length === 0 && - total_forms > initial_forms) { - table.find('tbody tr').each(function (index) { - if (index >= initial_forms) { - $(this).remove(); - } - }); - module.reenumerate_rows(table, prefix); - $('#id_' + prefix + '-INITIAL_FORMS').val( - $('#id_' + prefix + '-TOTAL_FORMS').val()); - } - - // enable tooltips - table.find('td.error[title]').tooltip(); - }; - - return module; -} ()); diff --git a/code/horizon/horizon/static/horizon/js/horizon.heattop.js b/code/horizon/horizon/static/horizon/js/horizon.heattop.js deleted file mode 100644 index e7fcfe11..00000000 --- a/code/horizon/horizon/static/horizon/js/horizon.heattop.js +++ /dev/null @@ -1,283 +0,0 @@ -/** - * - * HeatTop JS Framework - * Dependencies: jQuery 1.7.1 or later, d3 v3 or later - * Date: June 2013 - * Description: JS Framework that subclasses the D3 Force Directed Graph library to create - * Heat-specific objects and relationships with the purpose of displaying - * Stacks, Resources, and related Properties in a Resource Topology Graph. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. You may obtain - * a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations - * under the License. - */ - -var container = "#heat_resource_topology"; - -function update(){ - node = node.data(nodes, function(d) { return d.name; }); - link = link.data(links); - - var nodeEnter = node.enter().append("g") - .attr("class", "node") - .attr("node_name", function(d) { return d.name; }) - .attr("node_id", function(d) { return d.instance; }) - .call(force.drag); - - nodeEnter.append("image") - .attr("xlink:href", function(d) { return d.image; }) - .attr("id", function(d){ return "image_"+ d.name; }) - .attr("x", function(d) { return d.image_x; }) - .attr("y", function(d) { return d.image_y; }) - .attr("width", function(d) { return d.image_size; }) - .attr("height", function(d) { return d.image_size; }); - node.exit().remove(); - - link.enter().insert("svg:line", "g.node") - .attr("class", "link") - .style("stroke-width", function(d) { return Math.sqrt(d.value); }); - link.exit().remove(); - //Setup click action for all nodes - node.on("mouseover", function(d) { - $("#info_box").html(d.info_box); - current_info = d.name; - }); - node.on("mouseout", function(d) { - $("#info_box").html(''); - }); - - force.start(); -} - -function tick() { - link.attr("x1", function(d) { return d.source.x; }) - .attr("y1", function(d) { return d.source.y; }) - .attr("x2", function(d) { return d.target.x; }) - .attr("y2", function(d) { return d.target.y; }); - - node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; }); -} - -function set_in_progress(stack, nodes) { - if (stack.in_progress === true) { in_progress = true; } - for (var i = 0; i < nodes.length; i++) { - var d = nodes[i]; - if (d.in_progress === true){ in_progress = true; return false; } - } -} - -function findNode(name) { - for (var i = 0; i < nodes.length; i++) { - if (nodes[i].name === name){ return nodes[i]; } - } -} - -function findNodeIndex(name) { - for (var i = 0; i < nodes.length; i++) { - if (nodes[i].name === name){ return i; } - } -} - -function addNode (node) { - nodes.push(node); - needs_update = true; -} - -function removeNode (name) { - var i = 0; - var n = findNode(name); - while (i < links.length) { - if (links[i].source === n || links[i].target === n) { - links.splice(i, 1); - } else { - i++; - } - } - nodes.splice(findNodeIndex(name),1); - needs_update = true; -} - -function remove_nodes(old_nodes, new_nodes){ - //Check for removed nodes - for (var i=0;i label[for^="id_network_' + network_id + '"]'); - }, - - /* - * Initializes an associative array of lists of the current - * networks. - **/ - init_network_list: function () { - horizon.instances.networks_selected = []; - horizon.instances.networks_available = []; - $(this.get_network_element("")).each(function () { - var $this = $(this); - var $input = $this.children("input"); - var name = horizon.escape_html($this.text().replace(/^\s+/, "")); - var network_property = { - "name": name, - "id": $input.attr("id"), - "value": $input.attr("value") - }; - if ($input.is(":checked")) { - horizon.instances.networks_selected.push(network_property); - } else { - horizon.instances.networks_available.push(network_property); - } - }); - }, - - /* - * Generates the HTML structure for a network that will be displayed - * as a list item in the network list. - **/ - generate_network_element: function(name, id, value) { - var $li = $('
  • '); - $li.attr('name', value).html(name + '(' + value + ')'); - return $li; - }, - - /* - * Generates the HTML structure for the Network List. - **/ - generate_networklist_html: function() { - var self = this; - var available_network = $("#available_network"); - var selected_network = $("#selected_network"); - var updateForm = function() { - var networkListId = $("#networkListId"); - var lists = networkListId.find("li").attr('data-index',100); - var active_networks = $("#selected_network > li").map(function(){ - return $(this).attr("name"); - }); - networkListId.find("input:checkbox").removeAttr('checked'); - active_networks.each(function(index, value){ - networkListId.find("input:checkbox[value=" + value + "]") - .prop('checked', true) - .parents("li").attr('data-index',index); - }); - networkListId.find("ul").html( - lists.sort(function(a,b){ - if( $(a).data("index") < $(b).data("index")) { return -1; } - if( $(a).data("index") > $(b).data("index")) { return 1; } - return 0; - }) - ); - }; - $("#networkListSortContainer").show(); - $("#networkListIdContainer").hide(); - self.init_network_list(); - // Make sure we don't duplicate the networks in the list - available_network.empty(); - $.each(self.networks_available, function(index, value){ - available_network.append(self.generate_network_element(value.name, value.id, value.value)); - }); - // Make sure we don't duplicate the networks in the list - selected_network.empty(); - $.each(self.networks_selected, function(index, value){ - selected_network.append(self.generate_network_element(value.name, value.id, value.value)); - }); - // $(".networklist > li").click(function(){ - // $(this).toggleClass("ui-selected"); - // }); - $(".networklist > li > a.btn").click(function(e){ - var $this = $(this); - e.preventDefault(); - e.stopPropagation(); - if($this.parents("ul#available_network").length > 0) { - $this.parent().appendTo(selected_network); - } else if ($this.parents("ul#selected_network").length > 0) { - $this.parent().appendTo(available_network); - } - updateForm(); - }); - if ($("#networkListId > div.form-group.error").length > 0) { - var errortext = $("#networkListId > div.form-group.error span.help-block").text(); - $("#selected_network_label").before($('
    ').html(errortext)); - } - $(".networklist").sortable({ - connectWith: "ul.networklist", - placeholder: "ui-state-highlight", - distance: 5, - start:function(e,info){ - selected_network.addClass("dragging"); - }, - stop:function(e,info){ - selected_network.removeClass("dragging"); - updateForm(); - } - }).disableSelection(); - }, - - workflow_init: function(modal) { - // Initialise the drag and drop network list - horizon.instances.generate_networklist_html(); - } -}; - -horizon.addInitFunction(horizon.instances.init = function () { - var $document = $(document); - - $document.on('submit', '#tail_length', function (evt) { - horizon.instances.user_decided_length = true; - horizon.instances.getConsoleLog(true); - evt.preventDefault(); - }); - - /* Launch instance workflow */ - - // Handle field toggles for the Launch Instance source type field - function update_launch_source_displayed_fields (field) { - var $this = $(field); - var base_type = $this.val(); - var elements_list; - - $this.closest(".form-group").nextAll().hide(); - - switch(base_type) { - case "image_id": - elements_list = "#id_image_id"; - break; - case "instance_snapshot_id": - elements_list = "#id_instance_snapshot_id"; - break; - case "volume_id": - elements_list = "#id_volume_id, #id_device_name, #id_delete_on_terminate"; - break; - case "volume_image_id": - elements_list = "#id_image_id, #id_volume_size, #id_device_name, #id_delete_on_terminate"; - break; - case "volume_snapshot_id": - elements_list = "#id_volume_snapshot_id, #id_device_name, #id_delete_on_terminate"; - break; - } - var elements_list_group = $(elements_list).closest(".form-group"); - elements_list_group.addClass("required"); - // marking all the fields in 'elements_list' as mandatory except '#id_device_name' - $("#id_device_name").closest(".form-group").removeClass("required"); - // showing all the fields in 'elements_list' - elements_list_group.show(); - } - - $document.on('change', '.workflow #id_source_type', function (evt) { - update_launch_source_displayed_fields(this); - }); - - $('.workflow #id_source_type').change(); - horizon.modals.addModalInitFunction(function (modal) { - $(modal).find("#id_source_type").change(); - }); - - /* - Update the device size value to reflect minimum allowed - for selected image and flavor - */ - function update_device_size() { - var volume_size = horizon.Quota.getSelectedFlavor().disk; - var image = horizon.Quota.getSelectedImage(); - var size_field = $("#id_volume_size"); - - if (image !== undefined && image.min_disk > volume_size) { - volume_size = image.min_disk; - } - if (image !== undefined && image.size > volume_size) { - volume_size = image.size; - } - - // If the user has manually changed the volume size, do not override - // unless user-defined value is too small. - if (horizon.instances.user_volume_size) { - var user_value = size_field.val(); - if (user_value > volume_size) { - volume_size = user_value; - } - } - - // Make sure the new value is >= the minimum allowed (1GB) - if (volume_size < 1) { - volume_size = 1; - } - - size_field.val(volume_size); - } - - $document.on('change', '.workflow #id_flavor', function (evt) { - update_device_size(); - }); - - $document.on('change', '.workflow #id_image_id', function (evt) { - update_device_size(); - }); - - $document.on('input', '.workflow #id_volume_size', function (evt) { - horizon.instances.user_volume_size = true; - // We only need to listen for the first user input to this field, - // so remove the listener after the first time it gets called. - $document.off('input', '.workflow #id_volume_size'); - }); - - horizon.instances.decrypt_password = function(encrypted_password, private_key) { - var crypt = new JSEncrypt(); - crypt.setKey(private_key); - return crypt.decrypt(encrypted_password); - }; - - $document.on('change', '#id_private_key_file', function (evt) { - var file = evt.target.files[0]; - var reader = new FileReader(); - if (file) { - reader.onloadend = function(event) { - $("#id_private_key").val(event.target.result); - }; - reader.onerror = function(event) { - horizon.clearErrorMessages(); - horizon.alert('error', gettext('Could not read the file')); - }; - reader.readAsText(file); - } - else { - horizon.clearErrorMessages(); - horizon.alert('error', gettext('Could not decrypt the password')); - } - }); - /* - The font-family is changed because with the default policy the major I - and minor the l cannot be distinguished. - */ - $document.on('show.bs.modal', '#password_instance_modal', function (evt) { - $("#id_decrypted_password").css({ - "font-family": "monospace", - "cursor": "text" - }); - $("#id_encrypted_password").css("cursor","text"); - $("#id_keypair_name").css("cursor","text"); - }); - - $document.on('click', '#decryptpassword_button', function (evt) { - encrypted_password = $("#id_encrypted_password").val(); - private_key = $('#id_private_key').val(); - if (!private_key) { - evt.preventDefault(); - $(this).closest('.modal').modal('hide'); - } - else { - if (private_key.length > 0) { - evt.preventDefault(); - decrypted_password = horizon.instances.decrypt_password(encrypted_password, private_key); - if (decrypted_password === false || decrypted_password === null) { - horizon.clearErrorMessages(); - horizon.alert('error', gettext('Could not decrypt the password')); - } - else { - $("#id_decrypted_password").val(decrypted_password); - $("#decryptpassword_button").hide(); - } - } - } - }); -}); diff --git a/code/horizon/horizon/static/horizon/js/horizon.js b/code/horizon/horizon/static/horizon/js/horizon.js deleted file mode 100644 index ae6a8fe3..00000000 --- a/code/horizon/horizon/static/horizon/js/horizon.js +++ /dev/null @@ -1,45 +0,0 @@ -/* This is the base Horizon JavaScript object. There is only ever one of these - * loaded (referenced as horizon with a lower-case h) which happens immediately - * after the definition below. - * - * Scripts that are dependent on functionality defined in the Horizon object - * must be included after this script in templates/base.html. - */ -var Horizon = function () { - var horizon = {}, - initFunctions = []; - - /* Use the addInitFunction() function to add initialization code which must - * be called on DOM ready. This is useful for adding things like event - * handlers or any other initialization functions which should precede user - * interaction but rely on DOM readiness. - */ - horizon.addInitFunction = function (fn) { - initFunctions.push(fn); - }; - - /* Call all initialization functions and clear the queue. */ - horizon.init = function () { - for (var i = 0; i < initFunctions.length; i += 1) { - initFunctions[i](); - } - - // Prevent multiple executions, just in case. - initFunctions = []; - }; - - /* An utility function for escaping HTML to avoid XSS. */ - horizon.escape_html = function (text) { - return text.replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, ''') - .replace(/\//g, '/'); - }; - - return horizon; -}; - -// Create the one and only horizon object. -var horizon = new Horizon(); // jshint ignore:line diff --git a/code/horizon/horizon/static/horizon/js/horizon.membership.js b/code/horizon/horizon/static/horizon/js/horizon.membership.js deleted file mode 100644 index 45656e17..00000000 --- a/code/horizon/horizon/static/horizon/js/horizon.membership.js +++ /dev/null @@ -1,495 +0,0 @@ -/* Namespace for core functionality related to Membership Workflow Step. */ -horizon.membership = { - - current_membership: [], - data: [], - roles: [], - has_roles: [], - default_role_id: [], - - /* Parses the form field selector's ID to get either the - * role or user id (i.e. returns "id12345" when - * passed the selector with id: "id_group_id12345"). - **/ - get_field_id: function(id_string) { - return id_string.slice(id_string.lastIndexOf("_") + 1); - }, - - /* - * Gets the html select element associated with a given - * role id. - **/ - get_role_element: function(step_slug, role_id) { - return $('select[id^="id_' + step_slug + '_role_' + role_id + '"]'); - }, - - /* - * Gets the html ul element associated with a given - * data id. I.e., the member's row. - **/ - get_member_element: function(step_slug, data_id) { - return $('li[data-' + step_slug + '-id$=' + data_id + ']').parent(); - }, - - /* - * Initializes all of the horizon.membership lists with - * data parsed from the hidden form fields, as well as the - * default role id. - **/ - init_properties: function(step_slug) { - horizon.membership.has_roles[step_slug] = $("." + step_slug + "_membership").data('show-roles') !== "False"; - horizon.membership.default_role_id[step_slug] = $('#id_default_' + step_slug + '_role').attr('value'); - horizon.membership.init_data_list(step_slug); - horizon.membership.init_role_list(step_slug); - horizon.membership.init_current_membership(step_slug); - }, - - /* - * Initializes an associative array mapping data ids to display names. - **/ - init_data_list: function(step_slug) { - horizon.membership.data[step_slug] = []; - angular.forEach($(this.get_role_element(step_slug, "")).find("option"), function (option) { - horizon.membership.data[step_slug][option.value] = option.text; - }); - }, - - /* - * Initializes an associative array mapping role ids to role names. - **/ - init_role_list: function(step_slug) { - horizon.membership.roles[step_slug] = []; - angular.forEach($('label[for^="id_' + step_slug + '_role_"]'), function(role) { - var id = horizon.membership.get_field_id($(role).attr('for')); - horizon.membership.roles[step_slug][id] = $(role).text(); - }); - }, - - /* - * Initializes an associative array of lists of the current - * members for each available role. - **/ - init_current_membership: function(step_slug) { - horizon.membership.current_membership[step_slug] = []; - var members_list = []; - var role_name, role_id, selected_members; - angular.forEach(this.get_role_element(step_slug, ''), function(value, key) { - role_id = horizon.membership.get_field_id($(value).attr('id')); - role_name = $('label[for="id_' + step_slug + '_role_' + role_id + '"]').text(); - - // get the array of members who are selected in this list - selected_members = $(value).find("option:selected"); - // extract the member names and add them to the dictionary of lists - members_list = []; - if (selected_members) { - angular.forEach(selected_members, function(member) { - members_list.push(member.value); - }); - } - horizon.membership.current_membership[step_slug][role_id] = members_list; - }); - }, - - /* - * Returns the ids of roles the data is member of. - **/ - get_member_roles: function(step_slug, data_id) { - var roles = []; - for (var role in horizon.membership.current_membership[step_slug]) { - if ($.inArray(data_id, horizon.membership.current_membership[step_slug][role]) !== -1) { - roles.push(role); - } - } - return roles; - }, - - /* - * Updates the selected values on the role_list's form field, as - * well as the current_membership dictionary's list. - **/ - update_role_lists: function(step_slug, role_id, new_list) { - this.get_role_element(step_slug, role_id).val(new_list); - horizon.membership.current_membership[step_slug][role_id] = new_list; - }, - - /* - * Helper function for remove_member_from_role. - **/ - remove_member: function(step_slug, data_id, role_id, role_list) { - var index = role_list.indexOf(data_id); - if (index >= 0) { - // remove member from list - role_list.splice(index, 1); - horizon.membership.update_role_lists(step_slug, role_id, role_list); - } - }, - - /* - * Searches through the role lists and removes a given member - * from the lists. - **/ - remove_member_from_role: function(step_slug, data_id, role_id) { - var role, membership = horizon.membership.current_membership[step_slug]; - if (role_id) { - horizon.membership.remove_member( - step_slug, data_id, role_id, membership[role_id] - ); - } - else { - // search for membership in role lists - for (role in membership) { - if (membership.hasOwnProperty(role)) { - horizon.membership.remove_member( - step_slug, data_id, role, membership[role] - ); - } - } - } - }, - - /* - * Adds a member to a given role list. - **/ - add_member_to_role: function(step_slug, data_id, role_id) { - var role_list = horizon.membership.current_membership[step_slug][role_id]; - role_list.push(data_id); - horizon.membership.update_role_lists(step_slug, role_id, role_list); - }, - - update_member_role_dropdown: function(step_slug, data_id, role_ids, member_el) { - if (typeof(role_ids) === 'undefined') { - role_ids = horizon.membership.get_member_roles(step_slug, data_id); - } - if (typeof(member_el) === 'undefined') { - member_el = horizon.membership.get_member_element(step_slug, data_id); - } - - var $dropdown = member_el.find("li.member").siblings('.dropdown'); - var $role_items = $dropdown.children('.role_dropdown').children('li'); - - $role_items.each(function (idx, el) { - if ($.inArray(($(el).data('role-id')), role_ids) !== -1) { - $(el).addClass('selected'); - } else { - $(el).removeClass('selected'); - } - }); - - // set the selection back to default role - var $roles_display = $dropdown.children('.dropdown-toggle').children('.roles_display'); - var roles_to_display = []; - for (var i = 0; i < role_ids.length; i++) { - if (i === 2) { - roles_to_display.push('...'); - break; - } - roles_to_display.push(horizon.membership.roles[step_slug][role_ids[i]]); - } - text = roles_to_display.join(', '); - if (text.length === 0) { - text = gettext('No roles'); - } - $roles_display.text(text); - }, - - /* - * Generates the HTML structure for a member that will be displayed - * as a list item in the member list. - **/ - generate_member_element: function(step_slug, display_name, data_id, role_ids, text) { - var roles = [], - that = this, - membership_roles = that.roles[step_slug], - r; - - for (r in membership_roles) { - if (membership_roles.hasOwnProperty(r)){ - roles.push({ - role_id: r, - role_name: membership_roles[r] - }); - } - } - - var template = horizon.templates.compiled_templates["#membership_template"], - params = { - data_id: "id_" + step_slug + "_" + data_id, - step_slug: step_slug, - default_role: that.roles[that.default_role_id[step_slug]], - display_name: display_name, - text: text, - roles: roles, - roles_label: gettext("Roles") - }, - member_el = $(template.render(params)); - this.update_member_role_dropdown(step_slug, params.data_id, role_ids, member_el); - return $(member_el); - }, - - /* - * Generates the HTML structure for the membership UI. - **/ - generate_html: function(step_slug) { - var data_id, data = horizon.membership.data[step_slug]; - for (data_id in data) { - if(data.hasOwnProperty(data_id)){ - var display_name = data[data_id]; - var role_ids = this.get_member_roles(step_slug, data_id); - if (role_ids.length > 0) { - $("." + step_slug + "_members").append(this.generate_member_element(step_slug, display_name, data_id, role_ids, "-")); - } - else { - $(".available_" + step_slug).append(this.generate_member_element(step_slug, display_name, data_id, role_ids, "+")); - } - } - } - horizon.membership.detect_no_results(step_slug); - }, - - /* - * Triggers on click of link to add/remove membership association. - **/ - update_membership: function(step_slug) { - $(".available_" + step_slug + ", ." + step_slug + "_members").on('click', ".btn-group a[href='#add_remove']", function (evt) { - evt.preventDefault(); - var available = $(".available_" + step_slug).has($(this)).length; - var data_id = horizon.membership.get_field_id($(this).parent().siblings().attr('data-' + step_slug + '-id')); - var member_el = $(this).parent().parent(); - - if (available) { - var default_role = horizon.membership.default_role_id[step_slug]; - $(this).text("-"); - $("." + step_slug + "_members").append(member_el); - horizon.membership.add_member_to_role(step_slug, data_id, default_role); - - if (horizon.membership.has_roles[step_slug]) { - $(this).parent().siblings(".role_options").show(); - horizon.membership.update_member_role_dropdown(step_slug, data_id, [default_role], member_el); - } - } - else { - $(this).text("+"); - $(this).parent().siblings(".role_options").hide(); - $(".available_" + step_slug).append(member_el); - horizon.membership.remove_member_from_role(step_slug, data_id); - } - - // update lists - horizon.membership.list_filtering(step_slug); - horizon.membership.detect_no_results(step_slug); - - // remove input filters - $("input." + step_slug + "_filter").val(""); - }); - }, - - /* - * Detects whether each list has members and if it does not - * displays a message to the user. - **/ - detect_no_results: function (step_slug) { - $('.' + step_slug + '_filterable').each( function () { - var css_class = $(this).find('ul').attr('class'); - // Example value: members step_slug_members - // Pick the class name that contains the step_slug - var filter = $.grep(css_class.split(' '), function(val){ return val.indexOf(step_slug) !== -1; })[0]; - - if (!$('.' + filter).children('ul').length) { - $('#no_' + filter).show(); - $("input[id='" + filter + "']").attr('disabled', 'disabled'); - } - else { - $('#no_' + filter).hide(); - $("input[id='" + filter + "']").removeAttr('disabled'); - } - }); - }, - - /* - * Triggers on selection of new role for a member. - **/ - select_member_role: function(step_slug) { - $(".available_" + step_slug + ", ." + step_slug + "_members").on('click', '.role_dropdown li', function (evt) { - evt.preventDefault(); - evt.stopPropagation(); - - // get the newly selected role and the member's name - var new_role_id = $(this).attr("data-role-id"); - var id_str = $(this).parent().parent().siblings(".member").attr("data-" + step_slug + "-id"); - var data_id = horizon.membership.get_field_id(id_str); - // update role lists - if ($(this).hasClass('selected')) { - $(this).removeClass('selected'); - horizon.membership.remove_member_from_role(step_slug, data_id, new_role_id); - } else { - $(this).addClass('selected'); - horizon.membership.add_member_to_role(step_slug, data_id, new_role_id); - } - horizon.membership.update_member_role_dropdown(step_slug, data_id); - }); - }, - - /* - * Triggers on the addition of a new member via the inline object creation field. - **/ - add_new_member: function(step_slug) { - $("select[id='id_new_" + step_slug + "']").on('change', function (evt) { - // add the member to the visible list - var display_name = $(this).find("option").text(); - var data_id = $(this).find("option").attr("value"); - var default_role_id = horizon.membership.default_role_id[step_slug]; - $("." + step_slug + "_members").append(horizon.membership.generate_member_element(step_slug, display_name, data_id, [default_role_id], "-")); - - // add the member to the hidden role lists and the data list - horizon.membership.data[step_slug][data_id] = display_name; - $("select[multiple='multiple']").append(""); - horizon.membership.add_member_to_role(step_slug, data_id, default_role_id); - - // remove option from hidden select - $(this).text(""); - - // reset lists and input filters - horizon.membership.list_filtering(step_slug); - horizon.membership.detect_no_results(step_slug); - $("input.filter").val(""); - - // fix styling - $("." + step_slug + "_members .btn-group").removeClass('last_stripe'); - $("." + step_slug + "_members .btn-group:last").addClass('last_stripe'); - }); - }, - - /* - * Style the inline object creation button, hide the associated field. - **/ - add_new_member_styling: function(step_slug) { - var add_member_el = $("label[for='id_new_" + step_slug + "']").parent(); - $(add_member_el).find("select").hide(); - $("#add_" + step_slug).append($(add_member_el)); - $(add_member_el).addClass("add_" + step_slug); - $(add_member_el).find("label, .input").addClass("add_" + step_slug + "_btn"); - }, - - /* - * Fixes the striping of the fake table upon modification of the lists. - **/ - fix_stripes: function(step_slug) { - $('.fake_' + step_slug + '_table').each( function () { - var filter = "." + $(this).attr('id'); - var visible = " .btn-group:visible"; - var even = " .btn-group:visible:even"; - var last = " .btn-group:visible:last"; - - // fix striping of rows - $(filter + visible).removeClass('dark_stripe'); - $(filter + visible).addClass('light_stripe'); - $(filter + even).removeClass('light_stripe'); - $(filter + even).addClass('dark_stripe'); - - // fix bottom border of new last element - $(filter + visible).removeClass('last_stripe'); - $(filter + last).addClass('last_stripe'); - }); - }, - - /* - * Sets up filtering for each list of data. - **/ - list_filtering: function (step_slug) { - // remove previous lists' quicksearch events - $('input.' + step_slug + '_filter').unbind(); - - // set up quicksearch to filter on input - $('.' + step_slug + '_filterable').each(function () { - var css_class = $(this).children().children('ul').attr('class'); - // Example value: members step_slug_members - // Pick the class name that contains the step_slug - var filter = $.grep(css_class.split(' '), function(val){ return val.indexOf(step_slug) !== -1; })[0]; - - var input = $("input[id='" + filter +"']"); - input.quicksearch('ul.' + filter + ' ul li span.display_name', { - 'delay': 200, - 'loader': 'span.loading', - 'show': function () { - $(this).parent().parent().show(); - if (filter === "available_" + step_slug) { - $(this).parent('.dropdown-toggle').hide(); - } - }, - 'hide': function () { - $(this).parent().parent().hide(); - }, - 'noResults': 'ul#no_' + filter, - 'onAfter': function () { - horizon.membership.fix_stripes(step_slug); - }, - 'prepareQuery': function (val) { - return new RegExp(val, "i"); - }, - 'testQuery': function (query, txt, span) { - if ($(input).attr('id') === filter) { - $(input).prev().removeAttr('disabled'); - return query.test($(span).text()); - } else { - return true; - } - } - }); - }); - }, - - /* - * Calls set-up functions upon loading the workflow. - **/ - workflow_init: function(modal, step_slug, step_id) { - $(modal).find('form').each( function () { - var $form = $(this); - - // Do nothing if this isn't a membership modal - if ($form.find('div.' + step_slug + '_membership').length === 0) { - return; // continue - } - - // call the initialization functions - horizon.membership.init_properties(step_slug); - horizon.membership.generate_html(step_slug); - horizon.membership.update_membership(step_slug); - horizon.membership.select_member_role(step_slug); - horizon.membership.add_new_member(step_slug); - - - // initially hide role dropdowns for available member list - $form.find(".available_" + step_slug + " .role_options").hide(); - - // hide the dropdown for members too if we don't need to show it - if (!horizon.membership.has_roles[step_slug]) { - $form.find("." + step_slug + "_members .role_options").hide(); - } - - // unfocus filter fields - if (step_id.indexOf('update') === 0) { - $form.find("#" + step_id + " input").blur(); - } - - // prevent filter inputs from submitting form on 'enter' - $form.find('.' + step_slug + '_membership').keydown(function(event){ - if(event.keyCode === 13) { - event.preventDefault(); - return false; - } - }); - - // add filtering + styling to the inline obj creation btn - horizon.membership.add_new_member_styling(step_slug); - horizon.membership.list_filtering(step_slug); - horizon.membership.detect_no_results(step_slug); - - // fix initial striping of rows - $form.find('.fake_' + step_slug + '_table').each( function () { - var filter = "." + $(this).attr('id'); - $(filter + ' .btn-group:even').addClass('dark_stripe'); - $(filter + ' .btn-group:last').addClass('last_stripe'); - }); - }); - } -}; diff --git a/code/horizon/horizon/static/horizon/js/horizon.messages.js b/code/horizon/horizon/static/horizon/js/horizon.messages.js deleted file mode 100644 index 99f78693..00000000 --- a/code/horizon/horizon/static/horizon/js/horizon.messages.js +++ /dev/null @@ -1,81 +0,0 @@ -horizon.alert = function (type, message, extra_tags) { - safe = false; - // Check if the message is tagged as safe. - if (typeof(extra_tags) !== "undefined" && $.inArray('safe', extra_tags.split(' ')) !== -1) { - safe = true; - } - - var type_display = { - 'danger': gettext("Danger: "), - 'warning': gettext("Warning: "), - 'info': gettext("Notice: "), - 'success': gettext("Success: "), - 'error': gettext("Error: ") - }[type]; - - // the "error" type needs to be rewritten as "danger" for correct styling - if (type === 'error') { - type = 'danger'; - } - - var template = horizon.templates.compiled_templates["#alert_message_template"], - params = { - "type": type, - "type_display": type_display, - "message": message, - "safe": safe - }; - return $(template.render(params)).hide().prependTo("#main_content .messages").fadeIn(100); -}; - -horizon.clearErrorMessages = function() { - $('#main_content .messages .alert.alert-danger').remove(); -}; - -horizon.clearSuccessMessages = function() { - $('#main_content .messages .alert.alert-success').remove(); -}; - -horizon.clearAllMessages = function() { - horizon.clearErrorMessages(); - horizon.clearSuccessMessages(); -}; - -horizon.autoDismissAlerts = function() { - var $alerts = $('#main_content .messages .alert'); - - $alerts.each(function(index, alert) { - var $alert = $(this), - types = $alert.attr('class').split(' '), - intersection = $.grep(types, function (value) { - return $.inArray(value, horizon.conf.auto_fade_alerts.types) !== -1; - }); - // Check if alert should auto-fade - if (intersection.length > 0) { - setTimeout(function() { - $alert.fadeOut(horizon.conf.auto_fade_alerts.fade_duration); - }, horizon.conf.auto_fade_alerts.delay); - } - }); -}; - -horizon.addInitFunction(function () { - // Bind AJAX message handling. - $(document).ajaxComplete(function(event, request, settings){ - var message_array = $.parseJSON(horizon.ajax.get_messages(request)); - $(message_array).each(function (index, item) { - horizon.alert(item[0], item[1], item[2]); - }); - }); - - // Dismiss alert messages when moving on to a new type of action. - $('a.ajax-modal').click(function() { - horizon.clearAllMessages(); - }); - - // Bind dismiss(x) handlers for alert messages. - $(".alert").alert(); - - // Hide alerts automatically if attribute data-dismiss-auto is set to true. - horizon.autoDismissAlerts(); -}); diff --git a/code/horizon/horizon/static/horizon/js/horizon.modals.js b/code/horizon/horizon/static/horizon/js/horizon.modals.js deleted file mode 100644 index 6f6be810..00000000 --- a/code/horizon/horizon/static/horizon/js/horizon.modals.js +++ /dev/null @@ -1,386 +0,0 @@ -/* Namespace for core functionality related to modal dialogs. - * - * Modals in Horizon are treated as a "stack", e.g new ones are added to the - * top of the stack, and they are always removed in a last-in-first-out - * order. This allows for things like swapping between modals as part of a - * workflow, for confirmations, etc. - * - * When a new modal is loaded into the DOM, it fires a "new_modal" event which - * event handlers can listen for. However, for consistency, it is better to - * add methods which should be run on instantiation of any new modal to be - * applied via the horizon.modals.addModalInitFunction method. - */ -horizon.modals = { - // Storage for our current jqXHR object. - _request: null, - spinner: null, - _init_functions: [] -}; - -horizon.modals.addModalInitFunction = function (f) { - horizon.modals._init_functions.push(f); -}; - -horizon.modals.initModal = function (modal) { - $(horizon.modals._init_functions).each(function (index, f) { - f(modal); - }); -}; - -/* Creates a modal dialog from the client-side template. */ -horizon.modals.create = function (title, body, confirm, cancel) { - if (!cancel) { - cancel = gettext("Cancel"); - } - var template = horizon.templates.compiled_templates["#modal_template"], - params = { - title: title, body: body, confirm: confirm, cancel: cancel, - modal_backdrop: horizon.modals.MODAL_BACKDROP - }; - return $(template.render(params)).appendTo("#modal_wrapper"); -}; - -horizon.modals.success = function (data, textStatus, jqXHR) { - var modal; - $('#modal_wrapper').append(data); - modal = $('.modal:last'); - modal.modal(); - $(modal).trigger("new_modal", modal); - return modal; -}; - -horizon.modals.modal_spinner = function (text) { - // Adds a spinner with the desired text in a modal window. - var template = horizon.templates.compiled_templates["#spinner-modal"]; - horizon.modals.spinner = $(template.render({text: text})); - horizon.modals.spinner.appendTo("#modal_wrapper"); - horizon.modals.spinner.modal({backdrop: 'static'}); - horizon.modals.spinner.find(".modal-body").spin(horizon.conf.spinner_options.modal); -}; - -horizon.modals.init_wizard = function () { - // If workflow is in wizard mode, initialize wizard. - var _max_visited_step = 0; - var _validate_steps = function (start, end) { - var $form = $('.workflow > form'), - response = {}; - - if (typeof end === 'undefined') { - end = start; - } - - // Clear old errors. - $form.find('td.actions div.alert-danger').remove(); - $form.find('.form-group.error').each(function () { - var $group = $(this); - $group.removeClass('error'); - $group.find('span.help-block.error').remove(); - }); - - // Send the data for validation. - $.ajax({ - type: 'POST', - url: $form.attr('action'), - headers: { - 'X-Horizon-Validate-Step-Start': start, - 'X-Horizon-Validate-Step-End': end - }, - data: $form.serialize(), - dataType: 'json', - async: false, - success: function (data) { response = data; } - }); - - // Handle errors. - if (response.has_errors) { - var first_field = true; - - $.each(response.errors, function (step_slug, step_errors) { - var step_id = response.workflow_slug + '__' + step_slug, - $fieldset = $form.find('#' + step_id); - $.each(step_errors, function (field, errors) { - var $field; - if (field === '__all__') { - // Add global errors. - $.each(errors, function (index, error) { - $fieldset.find('td.actions').prepend( - '
    ' + - error + '
    '); - }); - $fieldset.find('input, select, textarea').first().focus(); - return; - } - // Add field errors. - $field = $fieldset.find('[name="' + field + '"]'); - $field.closest('.form-group').addClass('error'); - $.each(errors, function (index, error) { - $field.before( - '' + - error + ''); - }); - // Focus the first invalid field. - if (first_field) { - $field.focus(); - first_field = false; - } - }); - }); - - return false; - } - }; - - $('.workflow.wizard').bootstrapWizard({ - tabClass: 'wizard-tabs', - nextSelector: '.button-next', - previousSelector: '.button-previous', - onTabShow: function (tab, navigation, index) { - var $navs = navigation.find('li'); - var total = $navs.length; - var current = index; - var $footer = $('.modal-footer'); - _max_visited_step = Math.max(_max_visited_step, current); - if (current + 1 >= total) { - $footer.find('.button-next').hide(); - $footer.find('.button-final').show(); - } else { - $footer.find('.button-next').show(); - $footer.find('.button-final').hide(); - } - $navs.each(function(i) { - $this = $(this); - if (i <= _max_visited_step) { - $this.addClass('done'); - } else { - $this.removeClass('done'); - } - }); - }, - onNext: function ($tab, $nav, index) { - return _validate_steps(index - 1); - }, - onTabClick: function ($tab, $nav, current, index) { - // Validate if moving forward, but move backwards without validation - return (index <= current || - _validate_steps(current, index - 1) !== false); - } - }); -}; - - -horizon.addInitFunction(horizon.modals.init = function() { - - var $document = $(document); - - // Bind handler for initializing new modals. - $('#modal_wrapper').on('new_modal', function (evt, modal) { - horizon.modals.initModal(modal); - }); - - // Bind "cancel" button handler. - $document.on('click', '.modal .cancel', function (evt) { - $(this).closest('.modal').modal('hide'); - evt.preventDefault(); - }); - - // AJAX form submissions from modals. Makes validation happen in-modal. - $document.on('submit', '.modal form', function (evt) { - var $form = $(this), - form = this, - $button = $form.find(".modal-footer .btn-primary"), - update_field_id = $form.attr("data-add-to-field"), - headers = {}, - modalFileUpload = $form.attr("enctype") === "multipart/form-data", - formData, ajaxOpts, featureFileList, featureFormData; - - if (modalFileUpload) { - featureFileList = $("").get(0).files !== undefined; - featureFormData = window.FormData !== undefined; - - if (!featureFileList || !featureFormData) { - // Test whether browser supports HTML5 FileList and FormData interfaces, - // which make XHR file upload possible. If not, it doesn't - // support setting custom headers in AJAX requests either, so - // modal forms won't work in them (namely, IE9). - return; - } else { - formData = new window.FormData(form); - } - } else { - formData = $form.serialize(); - } - evt.preventDefault(); - - // Prevent duplicate form POSTs - $button.prop("disabled", true); - - if (update_field_id) { - headers["X-Horizon-Add-To-Field"] = update_field_id; - } - - ajaxOpts = { - type: "POST", - url: $form.attr('action'), - headers: headers, - data: formData, - beforeSend: function () { - $("#modal_wrapper .modal").last().modal("hide"); - $('.ajax-modal, .dropdown-toggle').attr('disabled', true); - horizon.modals.modal_spinner(gettext("Working")); - }, - complete: function () { - horizon.modals.spinner.modal('hide'); - $("#modal_wrapper .modal").last().modal("show"); - $button.prop("disabled", false); - }, - success: function (data, textStatus, jqXHR) { - var redirect_header = jqXHR.getResponseHeader("X-Horizon-Location"), - add_to_field_header = jqXHR.getResponseHeader("X-Horizon-Add-To-Field"), - json_data, field_to_update; - if (redirect_header === null) { - $('.ajax-modal, .dropdown-toggle').removeAttr("disabled"); - } - $form.closest(".modal").modal("hide"); - if (redirect_header) { - location.href = redirect_header; - } - else if (add_to_field_header) { - json_data = $.parseJSON(data); - field_to_update = $("#" + add_to_field_header); - field_to_update.append(""); - field_to_update.change(); - field_to_update.val(json_data[0]); - } else { - horizon.modals.success(data, textStatus, jqXHR); - } - }, - error: function (jqXHR, status, errorThrown) { - if (jqXHR.getResponseHeader('logout')) { - location.href = jqXHR.getResponseHeader("X-Horizon-Location"); - } else { - $('.ajax-modal, .dropdown-toggle').removeAttr("disabled"); - $form.closest(".modal").modal("hide"); - horizon.alert("danger", gettext("There was an error submitting the form. Please try again.")); - } - } - }; - - if (modalFileUpload) { - ajaxOpts.contentType = false; // tell jQuery not to process the data - ajaxOpts.processData = false; // tell jQuery not to set contentType - } - $.ajax(ajaxOpts); - }); - - // Position modal so it's in-view even when scrolled down. - $document.on('show.bs.modal', '.modal', function (evt) { - // Filter out indirect triggers of "show" from (for example) tabs. - if ($(evt.target).hasClass("modal")) { - var scrollShift = $('body').scrollTop() || $('html').scrollTop(), - $this = $(this), - topVal = $this.css('top'); - $this.css('top', scrollShift + parseInt(topVal, 10)); - } - // avoid closing the modal when escape is pressed on a select input - $("select", evt.target).keyup(function (e) { - if (e.keyCode === 27) { - // remove the focus on the select, so double escape close the modal - e.target.blur(); - e.stopPropagation(); - } - }); - }); - - // Focus the first usable form field in the modal for accessibility. - horizon.modals.addModalInitFunction(function (modal) { - $(modal).find(":text, select, textarea").filter(":visible:first").focus(); - }); - - horizon.modals.addModalInitFunction(function(modal) { - horizon.datatables.validate_button($(modal).find(".table_wrapper > form")); - }); - horizon.modals.addModalInitFunction(horizon.utils.loadAngular); - - // Load modals for ajax-modal links. - $document.on('click', '.ajax-modal', function (evt) { - var $this = $(this); - - // If there's an existing modal request open, cancel it out. - if (horizon.modals._request && typeof(horizon.modals._request.abort) !== undefined) { - horizon.modals._request.abort(); - } - - horizon.modals._request = $.ajax($this.attr('href'), { - beforeSend: function () { - horizon.modals.modal_spinner(gettext("Loading")); - }, - complete: function () { - // Clear the global storage; - horizon.modals._request = null; - horizon.modals.spinner.modal('hide'); - }, - error: function(jqXHR, status, errorThrown) { - if (jqXHR.status === 401){ - var redir_url = jqXHR.getResponseHeader("X-Horizon-Location"); - if (redir_url){ - location.href = redir_url; - } else { - location.reload(true); - } - } - else { - if (!horizon.ajax.get_messages(jqXHR)) { - // Generic error handler. Really generic. - horizon.alert("danger", gettext("An error occurred. Please try again later.")); - } - } - }, - success: function (data, textStatus, jqXHR) { - var update_field_id = $this.attr('data-add-to-field'), - modal, - form; - modal = horizon.modals.success(data, textStatus, jqXHR); - if (update_field_id) { - form = modal.find("form"); - if (form.length) { - form.attr("data-add-to-field", update_field_id); - } - } - } - }); - evt.preventDefault(); - }); - - - /* Manage the modal "stack" */ - - // After a modal has been shown, hide any other modals that are already in - // the stack. Only one modal can be visible at the same time. - $document.on("show.bs.modal", ".modal", function () { - var modal_stack = $("#modal_wrapper .modal"); - modal_stack.splice(modal_stack.length - 1, 1); - modal_stack.modal("hide"); - }); - - // After a modal has been fully hidden, remove it to avoid confusion. - // Note: the modal should only be removed if it is the "top" of the stack of - // modals, e.g. it's the one currently being interacted with and isn't just - // temporarily being hidden. - $document.on('hidden.bs.modal', '.modal', function () { - var $this = $(this), - modal_stack = $("#modal_wrapper .modal"); - if ($this[0] === modal_stack.last()[0] || $this.hasClass("loading")) { - $this.remove(); - if (!$this.hasClass("loading")) { - $("#modal_wrapper .modal").last().modal("show"); - } - } - }); - - // Make modals draggable - $document.on("show.bs.modal", ".modal", function () { - $(".modal-content").draggable({ - handle: ".modal-header" - }); - }); -}); diff --git a/code/horizon/horizon/static/horizon/js/horizon.networktopology.js b/code/horizon/horizon/static/horizon/js/horizon.networktopology.js deleted file mode 100644 index a6bf3acb..00000000 --- a/code/horizon/horizon/static/horizon/js/horizon.networktopology.js +++ /dev/null @@ -1,659 +0,0 @@ -/* Namespace for core functionality related to Network Topology. */ - -horizon.network_topology = { - model: null, - fa_globe_glyph: '\uf0ac', - fa_globe_glyph_width: 15, - svg:'#topology_canvas', - svg_container:'#topologyCanvasContainer', - post_messages:'#topologyMessages', - network_tmpl:{ - small:'#topology_template > .network_container_small', - normal:'#topology_template > .network_container_normal' - }, - router_tmpl: { - small:'#topology_template > .router_small', - normal:'#topology_template > .router_normal' - }, - instance_tmpl: { - small:'#topology_template > .instance_small', - normal:'#topology_template > .instance_normal' - }, - balloon_tmpl : null, - balloon_device_tmpl : null, - balloon_port_tmpl : null, - network_index: {}, - balloon_id:null, - reload_duration: 10000, - draw_mode:'normal', - network_height : 0, - previous_message : null, - element_properties:{ - normal:{ - network_width:270, - network_min_height:500, - top_margin:80, - default_height:50, - margin:20, - device_x:98.5, - device_width:90, - port_margin:16, - port_height:6, - port_width:82, - port_text_margin:{x:6,y:-4}, - texts_bg_y:32, - type_y:46, - balloon_margin:{x:12,y:-12} - }, - small :{ - network_width:100, - network_min_height:400, - top_margin:50, - default_height:20, - margin:30, - device_x:47.5, - device_width:20, - port_margin:5, - port_height:3, - port_width:32.5, - port_text_margin:{x:0,y:0}, - texts_bg_y:0, - type_y:0, - balloon_margin:{x:12,y:-30} - }, - cidr_margin:5, - device_name_max_size:9, - device_name_suffix:'..' - }, - init:function() { - var self = this; - $(self.svg_container).spin(horizon.conf.spinner_options.modal); - if($('#networktopology').length === 0) { - return; - } - self.color = d3.scale.category10(); - self.balloon_tmpl = Hogan.compile($('#balloon_container').html()); - self.balloon_device_tmpl = Hogan.compile($('#balloon_device').html()); - self.balloon_port_tmpl = Hogan.compile($('#balloon_port').html()); - - $(document) - .on('click', 'a.closeTopologyBalloon', function(e) { - e.preventDefault(); - self.delete_balloon(); - }) - .on('click', '.topologyBalloon', function(e) { - e.stopPropagation(); - }) - .on('click', 'a.vnc_window', function(e) { - e.preventDefault(); - var vnc_window = window.open($(this).attr('href'), vnc_window, 'width=760,height=560'); - self.delete_balloon(); - }) - .click(function(){ - self.delete_balloon(); - }); - - $('.toggleView > .btn').click(function(){ - self.draw_mode = $(this).data('value'); - $('g.network').remove(); - horizon.cookies.put('ntp_draw_mode',self.draw_mode); - self.data_convert(); - }); - - $(window) - .on('message',function(e){ - var message = $.parseJSON(e.originalEvent.data); - if (self.previous_message !== message.message) { - horizon.alert(message.type, message.message); - horizon.autoDismissAlerts(); - self.previous_message = message.message; - self.delete_post_message(message.iframe_id); - self.load_network_info(); - setTimeout(function() { - self.previous_message = null; - },10000); - } - }); - - self.load_network_info(); - }, - load_network_info:function(){ - var self = this; - if($('#networktopology').length === 0) { - return; - } - $.getJSON($('#networktopology').data('networktopology') + '?' + $.now(), - function(data) { - self.model = data; - self.data_convert(); - setTimeout(function(){ - self.load_network_info(); - }, self.reload_duration); - } - ); - }, - select_draw_mode:function() { - var self = this; - var draw_mode = horizon.cookies.get('ntp_draw_mode'); - if (draw_mode && (draw_mode === 'normal' || draw_mode === 'small')) { - self.draw_mode = draw_mode; - } else { - if (self.model.networks.length * - self.element_properties.normal.network_width > $('#topologyCanvas').width()) { - self.draw_mode = 'small'; - } else { - self.draw_mode = 'normal'; - } - horizon.cookies.put('ntp_draw_mode',self.draw_mode); - } - $('.toggleView > .btn').each(function(){ - var $this = $(this); - if($this.data('value') === self.draw_mode) { - $this.addClass('active'); - } else { - $this.removeClass('active'); - } - }); - }, - data_convert:function() { - var self = this; - var model = self.model; - $.each(model.networks, function(index, network) { - self.network_index[network.id] = index; - }); - self.select_draw_mode(); - var element_properties = self.element_properties[self.draw_mode]; - self.network_height = element_properties.top_margin; - $.each([ - {model:model.routers, type:'router'}, - {model:model.servers, type:'instance'} - ], function(index, devices) { - var type = devices.type; - var model = devices.model; - $.each(model, function(index, device) { - device.type = type; - device.ports = self.select_port(device.id); - var hasports = (device.ports.length <= 0) ? false : true; - device.parent_network = (hasports) ? - self.select_main_port(device.ports).network_id : self.model.networks[0].id; - var height = element_properties.port_margin*(device.ports.length - 1); - device.height = - (self.draw_mode === 'normal' && height > element_properties.default_height) ? height : - element_properties.default_height; - device.pos_y = self.network_height; - device.port_height = - (self.draw_mode === 'small' && height > device.height) ? 1 : - element_properties.port_height; - device.port_margin = - (self.draw_mode === 'small' && height > device.height) ? - device.height/device.ports.length : - element_properties.port_margin; - self.network_height += device.height + element_properties.margin; - }); - }); - $.each(model.networks, function(index, network) { - network.devices = []; - $.each([model.routers, model.servers],function(index, devices) { - $.each(devices,function(index, device) { - if(network.id === device.parent_network) { - network.devices.push(device); - } - }); - }); - }); - self.network_height += element_properties.top_margin; - self.network_height = (self.network_height > element_properties.network_min_height) ? - self.network_height : element_properties.network_min_height; - self.draw_topology(); - }, - draw_topology:function() { - var self = this; - $(self.svg_container).spin(false); - $(self.svg_container).removeClass('noinfo'); - if (self.model.networks.length <= 0) { - $('g.network').remove(); - $(self.svg_container).addClass('noinfo'); - return; - } - var svg = d3.select(self.svg); - var element_properties = self.element_properties[self.draw_mode]; - svg - .attr('width',self.model.networks.length*element_properties.network_width) - .attr('height',self.network_height); - - var network = svg.selectAll('g.network') - .data(self.model.networks); - - var network_enter = network.enter() - .append('g') - .attr('class','network') - .each(function(d,i){ - this.appendChild(d3.select(self.network_tmpl[self.draw_mode]).node().cloneNode(true)); - var $this = d3.select(this).select('.network-rect'); - if (d.url) { - $this - .on('mouseover',function(){ - $this.transition().style('fill', function() { - return d3.rgb(self.get_network_color(d.id)).brighter(0.5); - }); - }) - .on('mouseout',function(){ - $this.transition().style('fill', function() { - return self.get_network_color(d.id); - }); - }) - .on('click',function(){ - window.location.href = d.url; - }); - } else { - $this.classed('nourl', true); - } - }); - - network - .attr('id',function(d) { return 'id_' + d.id; }) - .attr('transform',function(d,i){ - return 'translate(' + element_properties.network_width * i + ',' + 0 + ')'; - }) - .select('.network-rect') - .attr('height', function(d) { return self.network_height; }) - .style('fill', function(d) { return self.get_network_color(d.id); }); - network - .select('.network-name') - .attr('x', function(d) { return self.network_height/2; }) - .text(function(d) { return d.name; }); - network - .select('.network-cidr') - .attr('x', function(d) { - var padding = isExternalNetwork(d) ? self.fa_globe_glyph_width : 0; - return self.network_height - self.element_properties.cidr_margin - - padding; - }) - .text(function(d) { - var cidr = $.map(d.subnets,function(n, i){ - return n.cidr; - }); - return cidr.join(', '); - }); - function isExternalNetwork(d) { - return d['router:external']; - } - network - .select('.network-type') - .text(function(d) { - return isExternalNetwork(d) ? self.fa_globe_glyph : ''; - }) - .attr('x', function(d) { - return self.network_height - self.element_properties.cidr_margin; - }); - - $('[data-toggle="tooltip"]').tooltip({container: 'body'}); - - network.exit().remove(); - - var device = network.selectAll('g.device') - .data(function(d) { return d.devices; }); - - var device_enter = device.enter() - .append("g") - .attr('class','device') - .each(function(d,i){ - var device_template = self[d.type + '_tmpl'][self.draw_mode]; - this.appendChild(d3.select(device_template).node().cloneNode(true)); - }); - - device_enter - .on('mouseenter',function(d){ - var $this = $(this); - self.show_balloon(d,$this); - }) - .on('click',function(){ - d3.event.stopPropagation(); - }); - - device - .attr('id',function(d) { return 'id_' + d.id; }) - .attr('transform',function(d,i){ - return 'translate(' + element_properties.device_x + ',' + d.pos_y + ')'; - }) - .select('.frame') - .attr('height',function(d) { return d.height; }); - device - .select('.texts_bg') - .attr('y',function(d) { - return element_properties.texts_bg_y + d.height - element_properties.default_height; - }); - device - .select('.type') - .attr('y',function(d) { - return element_properties.type_y + d.height - element_properties.default_height; - }); - device - .select('.name') - .text(function(d) { return self.string_truncate(d.name); }); - device.each(function(d) { - if (d.status === 'BUILD') { - d3.select(this).classed('loading',true); - } else if (d.task === 'deleting') { - d3.select(this).classed('loading',true); - if ('bl_' + d.id === self.balloon_id) { - self.delete_balloon(); - } - } else { - d3.select(this).classed('loading',false); - if ('bl_' + d.id === self.balloon_id) { - var $this = $(this); - self.show_balloon(d,$this); - } - } - }); - - device.exit().each(function(d){ - if ('bl_' + d.id === self.balloon_id) { - self.delete_balloon(); - } - }).remove(); - - var port = device.select('g.ports') - .selectAll('g.port') - .data(function(d) { return d.ports; }); - - var port_enter = port.enter() - .append('g') - .attr('class','port') - .attr('id',function(d) { return 'id_' + d.id; }); - - port_enter - .append('line') - .attr('class','port_line'); - - port_enter - .append('text') - .attr('class','port_text'); - - device.select('g.ports').each(function(d,i){ - this._portdata = {}; - this._portdata.ports_length = d.ports.length; - this._portdata.parent_network = d.parent_network; - this._portdata.device_height = d.height; - this._portdata.port_height = d.port_height; - this._portdata.port_margin = d.port_margin; - this._portdata.left = 0; - this._portdata.right = 0; - $(this).mouseenter(function(e){ - e.stopPropagation(); - }); - }); - - port.each(function(d,i){ - var index_diff = self.get_network_index(this.parentNode._portdata.parent_network) - - self.get_network_index(d.network_id); - this._index_diff = index_diff = (index_diff >= 0)? ++index_diff : index_diff; - this._direction = (this._index_diff < 0)? 'right' : 'left'; - this._index = this.parentNode._portdata[this._direction] ++; - - }); - - port.attr('transform',function(d,i){ - var x = (this._direction === 'left') ? 0 : element_properties.device_width; - var ports_length = this.parentNode._portdata[this._direction]; - var distance = this.parentNode._portdata.port_margin; - var y = (this.parentNode._portdata.device_height - - (ports_length -1)*distance)/2 + this._index*distance; - return 'translate(' + x + ',' + y + ')'; - }); - - port - .select('.port_line') - .attr('stroke-width',function(d,i) { - return this.parentNode.parentNode._portdata.port_height; - }) - .attr('stroke', function(d, i) { - return self.get_network_color(d.network_id); - }) - .attr('x1',0).attr('y1',0).attr('y2',0) - .attr('x2',function(d,i) { - var parent = this.parentNode; - var width = (Math.abs(parent._index_diff) - 1)*element_properties.network_width + - element_properties.port_width; - return (parent._direction === 'left') ? -1*width : width; - }); - - port - .select('.port_text') - .attr('x',function(d) { - var parent = this.parentNode; - if (parent._direction === 'left') { - d3.select(this).classed('left',true); - return element_properties.port_text_margin.x*-1; - } else { - d3.select(this).classed('left',false); - return element_properties.port_text_margin.x; - } - }) - .attr('y',function(d) { - return element_properties.port_text_margin.y; - }) - .text(function(d) { - var ip_label = []; - $.each(d.fixed_ips, function() { - ip_label.push(this.ip_address); - }); - return ip_label.join(','); - }); - - port.exit().remove(); - }, - get_network_color: function(network_id) { - return this.color(this.get_network_index(network_id)); - }, - get_network_index: function(network_id) { - return this.network_index[network_id]; - }, - select_port: function(device_id){ - return $.map(this.model.ports,function(port, index){ - if (port.device_id === device_id) { - return port; - } - }); - }, - select_main_port: function(ports){ - var _self = this; - var main_port_index = 0; - var MAX_INT = 4294967295; - var min_port_length = MAX_INT; - $.each(ports, function(index, port){ - var port_length = _self.sum_port_length(port.network_id, ports); - if(port_length < min_port_length){ - min_port_length = port_length; - main_port_index = index; - } - }); - return ports[main_port_index]; - }, - sum_port_length: function(network_id, ports){ - var self = this; - var sum_port_length = 0; - var base_index = self.get_network_index(network_id); - $.each(ports, function(index, port){ - sum_port_length += base_index - self.get_network_index(port.network_id); - }); - return sum_port_length; - }, - string_truncate: function(string) { - var self = this; - var str = string; - var max_size = self.element_properties.device_name_max_size; - var suffix = self.element_properties.device_name_suffix; - var bytes = 0; - for (var i = 0; i < str.length; i++) { - bytes += str.charCodeAt(i) <= 255 ? 1 : 2; - if (bytes > max_size) { - str = str.substr(0, i) + suffix; - break; - } - } - return str; - }, - delete_device: function(type, device_id) { - var self = this; - var message = {id:device_id}; - self.post_message(device_id,type,message); - }, - delete_port: function(router_id, port_id) { - var self = this; - var message = {id:port_id}; - self.post_message(port_id, 'router/' + router_id + '/', message); - }, - show_balloon:function(d,element) { - var self = this; - var element_properties = self.element_properties[self.draw_mode]; - if (self.balloon_id) { - self.delete_balloon(); - } - var balloon_tmpl = self.balloon_tmpl; - var device_tmpl = self.balloon_device_tmpl; - var port_tmpl = self.balloon_port_tmpl; - var balloon_id = 'bl_' + d.id; - var ports = []; - $.each(d.ports,function(i, port){ - var object = {}; - object.id = port.id; - object.router_id = port.device_id; - object.url = port.url; - object.port_status = port.status; - object.port_status_css = (port.status === "ACTIVE")? 'active' : 'down'; - var ip_address = ''; - try { - ip_address = port.fixed_ips[0].ip_address; - }catch(e){ - ip_address = gettext('None'); - } - var device_owner = ''; - try { - device_owner = port.device_owner.replace('network:',''); - }catch(e){ - device_owner = gettext('None'); - } - object.ip_address = ip_address; - object.device_owner = device_owner; - object.is_interface = (device_owner === 'router_interface'); - ports.push(object); - }); - var html_data = { - balloon_id:balloon_id, - id:d.id, - url:d.url, - name:d.name, - type:d.type, - delete_label: gettext("Delete"), - status:d.status, - status_class:(d.status === "ACTIVE")? 'active' : 'down', - status_label: gettext("STATUS"), - id_label: gettext("ID"), - interfaces_label: gettext("Interfaces"), - delete_interface_label: gettext("Delete Interface"), - open_console_label: gettext("Open Console"), - view_details_label: gettext("View Details") - }; - if (d.type === 'router') { - html_data.delete_label = gettext("Delete Router"); - html_data.view_details_label = gettext("View Router Details"); - html_data.port = ports; - html_data.add_interface_url = d.url + 'addinterface'; - html_data.add_interface_label = gettext("Add Interface"); - html = balloon_tmpl.render(html_data,{ - table1:device_tmpl, - table2:(ports.length > 0) ? port_tmpl : null - }); - } else if (d.type === 'instance') { - html_data.delete_label = gettext("Terminate Instance"); - html_data.view_details_label = gettext("View Instance Details"); - html_data.console_id = d.id; - html_data.console = d.console; - html = balloon_tmpl.render(html_data,{ - table1:device_tmpl - }); - } else { - return; - } - $(self.svg_container).append(html); - var device_position = element.find('.frame'); - var x = device_position.position().left + - element_properties.device_width + - element_properties.balloon_margin.x; - var y = device_position.position().top + - element_properties.balloon_margin.y; - $('#' + balloon_id).css({ - 'left': x + 'px', - 'top': y + 'px' - }) - .show(); - var $balloon = $('#' + balloon_id); - if ($balloon.offset().left + $balloon.outerWidth() > $(window).outerWidth()) { - $balloon - .css({ - 'left': 0 + 'px' - }) - .css({ - 'left': (device_position.position().left - $balloon.outerWidth() - - element_properties.balloon_margin.x + 'px') - }) - .addClass('leftPosition'); - } - $balloon.find('.delete-device').click(function(e){ - var $this = $(this); - action_string = html_data.delete_label; - name_string = " \"" + html_data.name + "\""; - name_string = interpolate(gettext("You have selected %s. "), [name_string]); - title = interpolate(gettext("Confirm %s"), [action_string]); - body = name_string + gettext("Please confirm your selection. "); - modal = horizon.modals.create(title, body, action_string); - modal.modal(); - modal.find('.btn-primary').click(function (evt) { - $this.prop('disabled', true); - d3.select('#id_' + $this.data('device-id')).classed('loading',true); - self.delete_device($this.data('type'),$this.data('device-id')); - modal.modal('hide'); - }); - - }); - $balloon.find('.delete-port').click(function(e){ - var $this = $(this); - action_string = html_data.delete_interface_label; - name_string = " \"" + $this.data('port-id') + "\""; - name_string = interpolate(gettext("You have selected %s. "), [name_string]); - title = interpolate(gettext("Confirm %s"), [action_string]); - body = name_string + gettext("Please confirm your selection. "); - modal = horizon.modals.create(title, body, action_string); - modal.modal(); - modal.find('.btn-primary').click(function (evt) { - self.delete_port($this.data('router-id'),$this.data('port-id')); - modal.modal('hide'); - }); - }); - self.balloon_id = balloon_id; - }, - delete_balloon:function() { - var self = this; - if(self.balloon_id) { - $('#' + self.balloon_id).remove(); - self.balloon_id = null; - } - }, - post_message: function(id,url,message) { - var self = this; - var iframe_id = 'ifr_' + id; - var iframe = $('