
This patch renames the remaining kimchi-named files in wok. No code changes, only renames. --- contrib/kimchid-upstart.conf.debian | 34 --- contrib/kimchid-upstart.conf.fedora | 33 --- contrib/kimchid.service.fedora | 13 - contrib/kimchid.sysvinit | 104 ------- contrib/wokd-upstart.conf.debian | 34 +++ contrib/wokd-upstart.conf.fedora | 33 +++ contrib/wokd.service.fedora | 13 + contrib/wokd.sysvinit | 104 +++++++ docs/kimchid.8 | 156 ----------- docs/wokd.8 | 156 +++++++++++ src/kimchi.conf.in | 65 ----- src/kimchid.in | 99 ------- src/nginx/kimchi.conf.in | 76 ----- src/nginx/wok.conf.in | 76 +++++ src/wok.conf.in | 65 +++++ src/wokd.in | 99 +++++++ ui/js/src/kimchi.cookie.js | 40 --- ui/js/src/kimchi.grid.js | 528 ----------------------------------- ui/js/src/kimchi.lang.js | 50 ---- ui/js/src/kimchi.login.js | 72 ----- ui/js/src/kimchi.main.js | 366 ------------------------ ui/js/src/kimchi.message.js | 116 -------- ui/js/src/kimchi.object.js | 85 ------ ui/js/src/kimchi.popable.js | 34 --- ui/js/src/kimchi.string.js | 45 --- ui/js/src/kimchi.substitute.js | 45 --- ui/js/src/kimchi.topic.js | 48 ---- ui/js/src/kimchi.user.js | 43 --- ui/js/src/kimchi.window.js | 70 ----- ui/js/src/wok.cookie.js | 40 +++ ui/js/src/wok.grid.js | 528 +++++++++++++++++++++++++++++++++++ ui/js/src/wok.lang.js | 50 ++++ ui/js/src/wok.login.js | 72 +++++ ui/js/src/wok.main.js | 366 ++++++++++++++++++++++++ ui/js/src/wok.message.js | 116 ++++++++ ui/js/src/wok.object.js | 85 ++++++ ui/js/src/wok.popable.js | 34 +++ ui/js/src/wok.string.js | 45 +++ ui/js/src/wok.substitute.js | 45 +++ ui/js/src/wok.topic.js | 48 ++++ ui/js/src/wok.user.js | 43 +++ ui/js/src/wok.window.js | 70 +++++ ui/pages/kimchi-ui.html.tmpl | 141 ---------- ui/pages/wok-ui.html.tmpl | 141 ++++++++++ 44 files changed, 2263 insertions(+), 2263 deletions(-) delete mode 100644 contrib/kimchid-upstart.conf.debian delete mode 100644 contrib/kimchid-upstart.conf.fedora delete mode 100644 contrib/kimchid.service.fedora delete mode 100644 contrib/kimchid.sysvinit create mode 100644 contrib/wokd-upstart.conf.debian create mode 100644 contrib/wokd-upstart.conf.fedora create mode 100644 contrib/wokd.service.fedora create mode 100644 contrib/wokd.sysvinit delete mode 100644 docs/kimchid.8 create mode 100644 docs/wokd.8 delete mode 100644 src/kimchi.conf.in delete mode 100644 src/kimchid.in delete mode 100644 src/nginx/kimchi.conf.in create mode 100644 src/nginx/wok.conf.in create mode 100644 src/wok.conf.in create mode 100644 src/wokd.in delete mode 100644 ui/js/src/kimchi.cookie.js delete mode 100644 ui/js/src/kimchi.grid.js delete mode 100644 ui/js/src/kimchi.lang.js delete mode 100644 ui/js/src/kimchi.login.js delete mode 100644 ui/js/src/kimchi.main.js delete mode 100644 ui/js/src/kimchi.message.js delete mode 100644 ui/js/src/kimchi.object.js delete mode 100644 ui/js/src/kimchi.popable.js delete mode 100644 ui/js/src/kimchi.string.js delete mode 100644 ui/js/src/kimchi.substitute.js delete mode 100644 ui/js/src/kimchi.topic.js delete mode 100644 ui/js/src/kimchi.user.js delete mode 100644 ui/js/src/kimchi.window.js create mode 100644 ui/js/src/wok.cookie.js create mode 100644 ui/js/src/wok.grid.js create mode 100644 ui/js/src/wok.lang.js create mode 100644 ui/js/src/wok.login.js create mode 100644 ui/js/src/wok.main.js create mode 100644 ui/js/src/wok.message.js create mode 100644 ui/js/src/wok.object.js create mode 100644 ui/js/src/wok.popable.js create mode 100644 ui/js/src/wok.string.js create mode 100644 ui/js/src/wok.substitute.js create mode 100644 ui/js/src/wok.topic.js create mode 100644 ui/js/src/wok.user.js create mode 100644 ui/js/src/wok.window.js delete mode 100644 ui/pages/kimchi-ui.html.tmpl create mode 100644 ui/pages/wok-ui.html.tmpl diff --git a/contrib/kimchid-upstart.conf.debian b/contrib/kimchid-upstart.conf.debian deleted file mode 100644 index a58d3c3..0000000 --- a/contrib/kimchid-upstart.conf.debian +++ /dev/null @@ -1,34 +0,0 @@ -# -# kimchid - Kimchi Web Server -# -# Copyright IBM, Corp. 2013 -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -# - -description "Kimchi Web Server" - -start on started libvirt-bin -stop on stopped libvirt-bin - -respawn -respawn limit 5 30 - -pre-start script - status libvirt-bin | grep -q "start/running" && exit 0 - start libvirt-bin || exit 1 -end script - -exec /usr/bin/kimchid diff --git a/contrib/kimchid-upstart.conf.fedora b/contrib/kimchid-upstart.conf.fedora deleted file mode 100644 index 53e8a39..0000000 --- a/contrib/kimchid-upstart.conf.fedora +++ /dev/null @@ -1,33 +0,0 @@ -# -# kimchid - Kimchi Web Server -# -# Copyright IBM, Corp. 2013 -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -# - -description "Kimchi Web Server" - -start on stopped rc RUNLEVEL=[2345] - -respawn -respawn limit 5 30 - -pre-start script - service libvirtd status | grep -q "start/running" && exit 0 - service libvirtd start || exit 1 -end script - -exec /usr/bin/kimchid diff --git a/contrib/kimchid.service.fedora b/contrib/kimchid.service.fedora deleted file mode 100644 index 7abe49b..0000000 --- a/contrib/kimchid.service.fedora +++ /dev/null @@ -1,13 +0,0 @@ -[Unit] -Description=Kimchi server -Requires=libvirtd.service -After=libvirtd.service - -[Service] -Type=simple -ExecStart=/usr/bin/kimchid -ExecStop=/bin/kill -TERM $MAINPID -EnvironmentFile=/etc/kimchi/kimchi.conf - -[Install] -WantedBy=multi-user.target diff --git a/contrib/kimchid.sysvinit b/contrib/kimchid.sysvinit deleted file mode 100644 index 023b34c..0000000 --- a/contrib/kimchid.sysvinit +++ /dev/null @@ -1,104 +0,0 @@ -#! /bin/sh -# -# kimchid Kimchi Web Server -# -# Copyright IBM, Corp. 2013 -# -# Author: Aline Manera <alinefm@br.ibm.com> -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -# -### BEGIN INIT INFO -# Provides: kimchid -# Required-Start: libvirtd -# Required-Stop: -# Default-Start: 3 5 -# Default-Stop: 0 1 2 6 -# Description: Start the kimchid daemon -### END INIT INFO - -. /etc/rc.status - -# Shell functions sourced from /etc/rc.status: -# rc_check check and set local and overall rc status -# rc_status check and set local and overall rc status -# rc_status -v ditto but be verbose in local rc status -# rc_status -v -r ditto and clear the local rc status -# rc_failed set local and overall rc status to failed -# rc_reset clear local rc status (overall remains) -# rc_exit exit appropriate to overall rc status - -# First reset status of this service -rc_reset - -case "$1" in - start) - echo -n "Starting kimchid daemon" - ## Start daemon with startproc(8). If this fails - ## the echo return value is set appropriate. - - startproc -f /usr/bin/kimchid > /dev/null 2>&1 - - # Remember status and be verbose - rc_status -v - ;; - stop) - echo -n "Shutting down kimchid daemon" - ## Stop daemon with killproc(8) and if this fails - ## set echo the echo return value. - - killproc -TERM /usr/bin/kimchid - - # Remember status and be verbose - rc_status -v - ;; - try-restart) - ## Stop the service and if this succeeds (i.e. the - ## service was running before), start it again. - $0 status >/dev/null && $0 restart - - # Remember status and be quiet - rc_status - ;; - restart) - ## Stop the service and regardless of whether it was - ## running or not, start it again. - $0 stop - $0 start - - # Remember status and be quiet - rc_status - ;; - status) - echo -n "Checking for service kimchid " - ## Check status with checkproc(8), if process is running - ## checkproc will return with exit status 0. - - # Status has a slightly different for the status command: - # 0 - service running - # 1 - service dead, but /var/run/ pid file exists - # 2 - service dead, but /var/lock/ lock file exists - # 3 - service not running - - checkproc /usr/bin/kimchid - - rc_status -v - ;; - *) - echo "Usage: $0 {start|stop|status|try-restart|restart}" - exit 1 - ;; -esac -rc_exit diff --git a/contrib/wokd-upstart.conf.debian b/contrib/wokd-upstart.conf.debian new file mode 100644 index 0000000..a58d3c3 --- /dev/null +++ b/contrib/wokd-upstart.conf.debian @@ -0,0 +1,34 @@ +# +# kimchid - Kimchi Web Server +# +# Copyright IBM, Corp. 2013 +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# + +description "Kimchi Web Server" + +start on started libvirt-bin +stop on stopped libvirt-bin + +respawn +respawn limit 5 30 + +pre-start script + status libvirt-bin | grep -q "start/running" && exit 0 + start libvirt-bin || exit 1 +end script + +exec /usr/bin/kimchid diff --git a/contrib/wokd-upstart.conf.fedora b/contrib/wokd-upstart.conf.fedora new file mode 100644 index 0000000..53e8a39 --- /dev/null +++ b/contrib/wokd-upstart.conf.fedora @@ -0,0 +1,33 @@ +# +# kimchid - Kimchi Web Server +# +# Copyright IBM, Corp. 2013 +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# + +description "Kimchi Web Server" + +start on stopped rc RUNLEVEL=[2345] + +respawn +respawn limit 5 30 + +pre-start script + service libvirtd status | grep -q "start/running" && exit 0 + service libvirtd start || exit 1 +end script + +exec /usr/bin/kimchid diff --git a/contrib/wokd.service.fedora b/contrib/wokd.service.fedora new file mode 100644 index 0000000..7abe49b --- /dev/null +++ b/contrib/wokd.service.fedora @@ -0,0 +1,13 @@ +[Unit] +Description=Kimchi server +Requires=libvirtd.service +After=libvirtd.service + +[Service] +Type=simple +ExecStart=/usr/bin/kimchid +ExecStop=/bin/kill -TERM $MAINPID +EnvironmentFile=/etc/kimchi/kimchi.conf + +[Install] +WantedBy=multi-user.target diff --git a/contrib/wokd.sysvinit b/contrib/wokd.sysvinit new file mode 100644 index 0000000..023b34c --- /dev/null +++ b/contrib/wokd.sysvinit @@ -0,0 +1,104 @@ +#! /bin/sh +# +# kimchid Kimchi Web Server +# +# Copyright IBM, Corp. 2013 +# +# Author: Aline Manera <alinefm@br.ibm.com> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +# +### BEGIN INIT INFO +# Provides: kimchid +# Required-Start: libvirtd +# Required-Stop: +# Default-Start: 3 5 +# Default-Stop: 0 1 2 6 +# Description: Start the kimchid daemon +### END INIT INFO + +. /etc/rc.status + +# Shell functions sourced from /etc/rc.status: +# rc_check check and set local and overall rc status +# rc_status check and set local and overall rc status +# rc_status -v ditto but be verbose in local rc status +# rc_status -v -r ditto and clear the local rc status +# rc_failed set local and overall rc status to failed +# rc_reset clear local rc status (overall remains) +# rc_exit exit appropriate to overall rc status + +# First reset status of this service +rc_reset + +case "$1" in + start) + echo -n "Starting kimchid daemon" + ## Start daemon with startproc(8). If this fails + ## the echo return value is set appropriate. + + startproc -f /usr/bin/kimchid > /dev/null 2>&1 + + # Remember status and be verbose + rc_status -v + ;; + stop) + echo -n "Shutting down kimchid daemon" + ## Stop daemon with killproc(8) and if this fails + ## set echo the echo return value. + + killproc -TERM /usr/bin/kimchid + + # Remember status and be verbose + rc_status -v + ;; + try-restart) + ## Stop the service and if this succeeds (i.e. the + ## service was running before), start it again. + $0 status >/dev/null && $0 restart + + # Remember status and be quiet + rc_status + ;; + restart) + ## Stop the service and regardless of whether it was + ## running or not, start it again. + $0 stop + $0 start + + # Remember status and be quiet + rc_status + ;; + status) + echo -n "Checking for service kimchid " + ## Check status with checkproc(8), if process is running + ## checkproc will return with exit status 0. + + # Status has a slightly different for the status command: + # 0 - service running + # 1 - service dead, but /var/run/ pid file exists + # 2 - service dead, but /var/lock/ lock file exists + # 3 - service not running + + checkproc /usr/bin/kimchid + + rc_status -v + ;; + *) + echo "Usage: $0 {start|stop|status|try-restart|restart}" + exit 1 + ;; +esac +rc_exit diff --git a/docs/kimchid.8 b/docs/kimchid.8 deleted file mode 100644 index f5fa90a..0000000 --- a/docs/kimchid.8 +++ /dev/null @@ -1,156 +0,0 @@ -.TH KIMCHI 8 "February 05, 2015" "Version 1.4.0" "Kimchi Manual" -.SH NAME -Kimchi \- HTML5 based management tool for KVM -.SH SYNOPSIS -.B kimchid -[\fB-h\fP|\fB--help\fP] [\fB--host\fP \fIhost\fP] [\fB--port\fP \fIport\fP] -[\fB--ssl-port\fP \fIssl_port\fP] [\fB--cherrypy_port\fP \fIcherrypy_port\fP] -[\fB--log-level\fP \fIlog_level\fP] [\fB--access-log\fP \fIaccess_log\fP] -[\fB--error-log\fP \fIerror_log\fP] [\fB--environment\fP \fIenvironment\fP] -[\fB--federation\fP \fIfederation\fP] [\fB--test\fP] -.SH DESCRIPTION -\fBKimchi\fP is an HTML5 based management tool for KVM. It is designed to make -it as easy as possible to get started with KVM and create your first guest. -\fBkimchid\fP launches the daemon on the hypervisor host which manages KVM guests through -libvirt. The management interface is accessed over the web using a browser that -supports HTML5. -.SH OPTIONS -The following options are supported: -.TP -\fB-h\fP , \fB--help\fP -Show this help message and exit. -.TP -\fB--host\fP \fIhost\fP -Specify the hostname or IP to listen on. -.TP -\fB--port\fP \fIport\fP -Specify the HTTP port (default \fI8000\fP). -.TP -\fB--ssl-port\fP \fIssl_port\fP -Specify the HTTPS port (default \fI8001\fP). -.TP -\fB--cherrypy_port\fP \fIcherrypy_port\fP -Specify the Cherrypy server port (default \fI8010\fP). -.TP -\fB--log-level\fP [\fIdebug\fP | \fIinfo\fP | \fIwarning\fP | \fIerror\fP | \fIcritical\fP] -Specify the log level (default \fIdebug\fP). -.TP -\fB--access-log\fP \fIaccess_log\fP -Specify the access log location where kimchi should create the access log file. -.TP -\fB--environment\fP [\fIdevelopment\fP | \fIproduction\fP] -Specify the running environment of kimchi server. Check cherrypy documentation for more details (default \fIproduction\fP). -.TP -\fB--federation\fP [\fIon\fP | \fIoff\fP] -Register and discover Kimchi peers in the same network using OpenSLP. Check -below the \fBFEDERATION\fP section for more details (default \fIoff\fP). -.TP -\fB--test\fP -Run kimchi on a mock version that does not affect the system. For testing proposals. -.SH FEDERATION -Federation feature is a mechanism to discover Kimchi peers in the same network. -It uses OpenSLP tool (http://www.openslp.org/) to register and find the Kimchi -servers. - -By default this feature is disabled on Kimchi as it is not critical for KVM -virtualization and requires additional software installation. - -To enable it, do the following: - -1. Install OpenSLP server package - -2. OpenSLP uses port 427 (UDP) and port 427 (TCP) so make sure to open those - ports in your firewall configuration - - For system using firewalld, do: - sudo firewall-cmd --permanent --add-port=427/udp - sudo firewall-cmd --permanent --add-port=427/tcp - sudo firewall-cmd --reload - - For openSUSE systems, do: - sudo /sbin/SuSEfirewall2 open EXT TCP 427 - sudo /sbin/SuSEfirewall2 open EXT UDP 427 - - For system using iptables, do: - sudo iptables -A INPUT -p tcp --dport 427 -j ACCEPT - sudo iptables -A INPUT -p udp --dport 427 -j ACCEPT - -3. In addition to the OpenSLP ports, you also need to allow multicast in the - firewall configuration - - For system using firewalld, do: - sudo firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -s <subnet> -j ACCEPT - - For openSUSE systems, do: - Add the subnet to the trusted networks listed on FW_TRUSTED_NETS in - /etc/sysconfig/SuSEfirewall2 file. - Make sure to restart /sbin/SuSEfirewall2 after modifying /etc/sysconfig/SuSEfirewall2 - - For system using iptables, do: - sudo iptables -A INPUT -s <subnet> -j ACCEPT - -4. Start slpd service and make sure it is up while running Kimchi - sudo service slpd start - -5. Enable federation on Kimchi by editing the /etc/kimchi/kimchi.conf file: - - federation = on - -6. Then start Kimchi service - sudo service kimchid start - -The Kimchi server will be registered on OpenSLP on server starting up and will -be found by other Kimchi peers (with federation feature enabled) in the same -network. -.SH LICENCE -.br -Kimchi is distributed pursuant to the terms of two different licenses. -The user interface (located in ui/ in this distribution) is governed by -the Apache License version 2.0. - -The code under ui/spice-html5 is imported from spice-html5 project -(http://cgit.freedesktop.org/spice/spice-html5) and the code under ui/libs which is -imported from JQuery UI (http://jqueryui.com) - -The rest of this distribution is governed by the GNU Lesser General Public -License version 3. - -See COPYING.LGPL and COPYING.ASL2. -.SH BUGS -Current bugs can be found here : https://github.com/kimchi-project/kimchi/issues -.br -If you find any, please open an issue : https://github.com/kimchi-project/kimchi/issues/new -.SH AUTHOR -\fBAdam King\fP <rak@linux.vnet.ibm.com>, -\fBAdam Litke\fP <agl@linux.vnet.ibm.com>, -\fBAdriano Botega\fP <abotega@linux.vnet.ibm.com>, -\fBAlexandre Tanaka Hirata\fP <hirata@linux.vnet.ibm.com>, -\fBAline Manera\fP <alinefm@br.ibm.com>, -\fBapporc\fP <appleorchard2000@gmail.com>, -\fBAnthony Liguori\fP <aliguori@us.ibm.com>, -\fBBing Bu Cao\fP <mars@linux.vnet.ibm.com>, -\fBChristy Perez\fP <christy@linux.vnet.ibm.com>, -\fBCole Robinson\fP <crobinso@redhat.com>, -\fBCrístian Viana\fP <vianac@linux.vnet.ibm.com>, -\fBDaniel H Barboza\fP <danielhb@linux.vnet.ibm.com>, -\fBEduardo Elias Ferreira\fP <edusf@linux.vnet.ibm.com>, -\fBEli Qiao(Li Yong Qiao)\fP <taget@linux.vnet.ibm.com>, -\fBHongliang Wang\fP <hlwang@linux.vnet.ibm.com>, -\fBLeonardo Garcia\fP <lagarcia@br.ibm.com>, -\fBLise Noble\fP <lwnoble@us.ibm.com>, -\fBMalcolm Yu\fP <minghaoyusombie@gmail.com>, -\fBMark Wu\fP <wudxw@linux.vnet.ibm.com>, -\fBMei Na Zhou\fP <zhoumein@linux.vnet.ibm.com>, -\fBPaulo Vital\fP <pvital@linux.vnet.ibm.com>, -\fBPradeep K Surisetty\fP <psuriset@linux.vnet.ibm.com>, -\fBRamon Medeiros\fP <ramonn@linux.vnet.ibm.com>, -\fBRodrigo Trujilo\fP <rodrigo.trujillo@linux.vnet.ibm.com>, -\fBRoyce Lv\fP <lvroyce@linux.vnet.ibm.com>, -\fBShaoHe Feng\fP <shaohef@linux.vnet.ibm.com>, -\fBShu Ming\fP <shuming@linux.vnet.ibm.com>, -\fBToby Allsopp\fP <toby@MI6.GEN.NZ>, -\fBTony Breeds\fP <tonyb@au1.ibm.com>, -\fBXin BJ Ding\fP <xinding@cn.ibm.com>, -\fBYu Xin Huo\fP <huoyuxin@linux.vnet.ibm.com>, -\fBZhou Zheng Sheng\fP <zhshzhou@linux.vnet.ibm.com>, -.SH SEE ALSO diff --git a/docs/wokd.8 b/docs/wokd.8 new file mode 100644 index 0000000..f5fa90a --- /dev/null +++ b/docs/wokd.8 @@ -0,0 +1,156 @@ +.TH KIMCHI 8 "February 05, 2015" "Version 1.4.0" "Kimchi Manual" +.SH NAME +Kimchi \- HTML5 based management tool for KVM +.SH SYNOPSIS +.B kimchid +[\fB-h\fP|\fB--help\fP] [\fB--host\fP \fIhost\fP] [\fB--port\fP \fIport\fP] +[\fB--ssl-port\fP \fIssl_port\fP] [\fB--cherrypy_port\fP \fIcherrypy_port\fP] +[\fB--log-level\fP \fIlog_level\fP] [\fB--access-log\fP \fIaccess_log\fP] +[\fB--error-log\fP \fIerror_log\fP] [\fB--environment\fP \fIenvironment\fP] +[\fB--federation\fP \fIfederation\fP] [\fB--test\fP] +.SH DESCRIPTION +\fBKimchi\fP is an HTML5 based management tool for KVM. It is designed to make +it as easy as possible to get started with KVM and create your first guest. +\fBkimchid\fP launches the daemon on the hypervisor host which manages KVM guests through +libvirt. The management interface is accessed over the web using a browser that +supports HTML5. +.SH OPTIONS +The following options are supported: +.TP +\fB-h\fP , \fB--help\fP +Show this help message and exit. +.TP +\fB--host\fP \fIhost\fP +Specify the hostname or IP to listen on. +.TP +\fB--port\fP \fIport\fP +Specify the HTTP port (default \fI8000\fP). +.TP +\fB--ssl-port\fP \fIssl_port\fP +Specify the HTTPS port (default \fI8001\fP). +.TP +\fB--cherrypy_port\fP \fIcherrypy_port\fP +Specify the Cherrypy server port (default \fI8010\fP). +.TP +\fB--log-level\fP [\fIdebug\fP | \fIinfo\fP | \fIwarning\fP | \fIerror\fP | \fIcritical\fP] +Specify the log level (default \fIdebug\fP). +.TP +\fB--access-log\fP \fIaccess_log\fP +Specify the access log location where kimchi should create the access log file. +.TP +\fB--environment\fP [\fIdevelopment\fP | \fIproduction\fP] +Specify the running environment of kimchi server. Check cherrypy documentation for more details (default \fIproduction\fP). +.TP +\fB--federation\fP [\fIon\fP | \fIoff\fP] +Register and discover Kimchi peers in the same network using OpenSLP. Check +below the \fBFEDERATION\fP section for more details (default \fIoff\fP). +.TP +\fB--test\fP +Run kimchi on a mock version that does not affect the system. For testing proposals. +.SH FEDERATION +Federation feature is a mechanism to discover Kimchi peers in the same network. +It uses OpenSLP tool (http://www.openslp.org/) to register and find the Kimchi +servers. + +By default this feature is disabled on Kimchi as it is not critical for KVM +virtualization and requires additional software installation. + +To enable it, do the following: + +1. Install OpenSLP server package + +2. OpenSLP uses port 427 (UDP) and port 427 (TCP) so make sure to open those + ports in your firewall configuration + + For system using firewalld, do: + sudo firewall-cmd --permanent --add-port=427/udp + sudo firewall-cmd --permanent --add-port=427/tcp + sudo firewall-cmd --reload + + For openSUSE systems, do: + sudo /sbin/SuSEfirewall2 open EXT TCP 427 + sudo /sbin/SuSEfirewall2 open EXT UDP 427 + + For system using iptables, do: + sudo iptables -A INPUT -p tcp --dport 427 -j ACCEPT + sudo iptables -A INPUT -p udp --dport 427 -j ACCEPT + +3. In addition to the OpenSLP ports, you also need to allow multicast in the + firewall configuration + + For system using firewalld, do: + sudo firewall-cmd --direct --add-rule ipv4 filter INPUT 0 -s <subnet> -j ACCEPT + + For openSUSE systems, do: + Add the subnet to the trusted networks listed on FW_TRUSTED_NETS in + /etc/sysconfig/SuSEfirewall2 file. + Make sure to restart /sbin/SuSEfirewall2 after modifying /etc/sysconfig/SuSEfirewall2 + + For system using iptables, do: + sudo iptables -A INPUT -s <subnet> -j ACCEPT + +4. Start slpd service and make sure it is up while running Kimchi + sudo service slpd start + +5. Enable federation on Kimchi by editing the /etc/kimchi/kimchi.conf file: + + federation = on + +6. Then start Kimchi service + sudo service kimchid start + +The Kimchi server will be registered on OpenSLP on server starting up and will +be found by other Kimchi peers (with federation feature enabled) in the same +network. +.SH LICENCE +.br +Kimchi is distributed pursuant to the terms of two different licenses. +The user interface (located in ui/ in this distribution) is governed by +the Apache License version 2.0. + +The code under ui/spice-html5 is imported from spice-html5 project +(http://cgit.freedesktop.org/spice/spice-html5) and the code under ui/libs which is +imported from JQuery UI (http://jqueryui.com) + +The rest of this distribution is governed by the GNU Lesser General Public +License version 3. + +See COPYING.LGPL and COPYING.ASL2. +.SH BUGS +Current bugs can be found here : https://github.com/kimchi-project/kimchi/issues +.br +If you find any, please open an issue : https://github.com/kimchi-project/kimchi/issues/new +.SH AUTHOR +\fBAdam King\fP <rak@linux.vnet.ibm.com>, +\fBAdam Litke\fP <agl@linux.vnet.ibm.com>, +\fBAdriano Botega\fP <abotega@linux.vnet.ibm.com>, +\fBAlexandre Tanaka Hirata\fP <hirata@linux.vnet.ibm.com>, +\fBAline Manera\fP <alinefm@br.ibm.com>, +\fBapporc\fP <appleorchard2000@gmail.com>, +\fBAnthony Liguori\fP <aliguori@us.ibm.com>, +\fBBing Bu Cao\fP <mars@linux.vnet.ibm.com>, +\fBChristy Perez\fP <christy@linux.vnet.ibm.com>, +\fBCole Robinson\fP <crobinso@redhat.com>, +\fBCrístian Viana\fP <vianac@linux.vnet.ibm.com>, +\fBDaniel H Barboza\fP <danielhb@linux.vnet.ibm.com>, +\fBEduardo Elias Ferreira\fP <edusf@linux.vnet.ibm.com>, +\fBEli Qiao(Li Yong Qiao)\fP <taget@linux.vnet.ibm.com>, +\fBHongliang Wang\fP <hlwang@linux.vnet.ibm.com>, +\fBLeonardo Garcia\fP <lagarcia@br.ibm.com>, +\fBLise Noble\fP <lwnoble@us.ibm.com>, +\fBMalcolm Yu\fP <minghaoyusombie@gmail.com>, +\fBMark Wu\fP <wudxw@linux.vnet.ibm.com>, +\fBMei Na Zhou\fP <zhoumein@linux.vnet.ibm.com>, +\fBPaulo Vital\fP <pvital@linux.vnet.ibm.com>, +\fBPradeep K Surisetty\fP <psuriset@linux.vnet.ibm.com>, +\fBRamon Medeiros\fP <ramonn@linux.vnet.ibm.com>, +\fBRodrigo Trujilo\fP <rodrigo.trujillo@linux.vnet.ibm.com>, +\fBRoyce Lv\fP <lvroyce@linux.vnet.ibm.com>, +\fBShaoHe Feng\fP <shaohef@linux.vnet.ibm.com>, +\fBShu Ming\fP <shuming@linux.vnet.ibm.com>, +\fBToby Allsopp\fP <toby@MI6.GEN.NZ>, +\fBTony Breeds\fP <tonyb@au1.ibm.com>, +\fBXin BJ Ding\fP <xinding@cn.ibm.com>, +\fBYu Xin Huo\fP <huoyuxin@linux.vnet.ibm.com>, +\fBZhou Zheng Sheng\fP <zhshzhou@linux.vnet.ibm.com>, +.SH SEE ALSO diff --git a/src/kimchi.conf.in b/src/kimchi.conf.in deleted file mode 100644 index cd141f5..0000000 --- a/src/kimchi.conf.in +++ /dev/null @@ -1,65 +0,0 @@ -# -# Configuration file for Kimchi Web Server -# - -[server] -# Hostname or IP address to listen on -#host = 0.0.0.0 - -# Port to listen on -#port = 8000 - -# If present, start an SSL-enabled server on the given port -#ssl_port = 8001 - -# Cherrypy server port -#cherrypy_port = 8010 - -# The full path to an SSL Certificate in PEM format. If left unspecified, -# Kimchi will generate a self-signed certificate automatically. -#ssl_cert = - -# The corresponding private key in PEM format for the SSL Certificate supplied -# above. If left blank, Kimchi will generate a self-signed certificate. -#ssl_key = - -# Running environment of the server -#environment = production - -# Federation feature: register Kimchi server on openSLP and discover peers -# in the same network. Check README-federation for more details. -#federation = off - -# Max request body size in KB, default value is 4GB -#max_body_size = 4 * 1024 * 1024 - -# Automatically create ISO pool on server start up -#create_iso_pool = true - -[logging] -# Log directory -#log_dir = @localstatedir@/log/kimchi - -# Logging level: debug, info, warning, error or critical -#log_level = debug - -[display] -# Port for websocket proxy to listen on -#display_proxy_port = 64667 - -[authentication] -# Authentication method, available option: pam, ldap. -# method = pam - -# If specified method to ldap, following fields need to be specified. -# ldap server domain name used to authenticate. -# ldap_server = "localhost" - -# Search tree base in ldap -# ldap_search_base = "ou=People, dc=kimchi, dc=org" - -# User id filter -# ldap_search_filter = "uid=%(username)s" - -# User IDs regarded as kimchi admin -# ldap_admin_id = "foo@foo.com, bar@bar.com" diff --git a/src/kimchid.in b/src/kimchid.in deleted file mode 100644 index 4ea7a42..0000000 --- a/src/kimchid.in +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python2 -# -# Project Kimchi -# -# Copyright IBM, Corp. 2013-2015 -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, -# MA 02110-1301 USA - -import os -import sys -sys.path.insert(1, '@pythondir@') - -from optparse import OptionParser - -import kimchi.server -import kimchi.config as config - - -if not config.paths.installed: - sys.path.append(config.paths.prefix) - -ACCESS_LOG = "kimchi-access.log" -ERROR_LOG = "kimchi-error.log" - - -def main(options): - # Script must run as root or with sudo. - if not os.geteuid() == 0: - sys.exit("\nMust be root to run this script. Exiting ...\n") - - host = config.config.get("server", "host") - port = config.config.get("server", "port") - ssl_port = config.config.get("server", "ssl_port") - cherrypy_port = config.config.get("server", "cherrypy_port") - runningEnv = config.config.get("server", "environment") - federation = config.config.get("server", "federation") - isopool = config.config.get("server", "create_iso_pool") - logDir = config.config.get("logging", "log_dir") - logLevel = config.config.get("logging", "log_level") - - parser = OptionParser() - parser.add_option('--host', type="string", default=host, - help="Hostname to listen on") - parser.add_option('--port', type="int", default=port, - help="Port to listen on (default %s)" % port) - parser.add_option('--ssl-port', type="int", default=ssl_port, - help="Port to enable SSL (default %s)" % ssl_port) - parser.add_option('--cherrypy_port', type="int", default=cherrypy_port, - help="Cherrypy server port (default %s)" % cherrypy_port) - parser.add_option('--log-level', default=logLevel, - help="Logging level") - parser.add_option('--access-log', - default=os.path.join(logDir, ACCESS_LOG), - help="Access log file") - parser.add_option('--error-log', - default=os.path.join(logDir, ERROR_LOG), - help="Error log file") - parser.add_option('--environment', default=runningEnv, - help="Running environment of kimchi server") - parser.add_option('--federation', default=federation, - help="Register and discover Kimchi peers in the same " - "network using openSLP. Check README-federation for" - " more details.") - parser.add_option('--create_iso_pool', default=isopool, - help="Automatically create ISO pool on server start up.") - parser.add_option('--test', action='store_true', - help="Run server in mock model") - (options, args) = parser.parse_args() - - # Update config.config with the command line values - # So the whole application will have access to accurate values - for sec in config.config.sections(): - for item in config.config.options(sec): - if hasattr(options, item): - config.config.set(sec, item, str(getattr(options, item))) - - # Add non-option arguments - setattr(options, 'ssl_cert', config.config.get('server', 'ssl_cert')) - setattr(options, 'ssl_key', config.config.get('server', 'ssl_key')) - setattr(options, 'max_body_size', - config.config.get('server', 'max_body_size')) - - kimchi.server.main(options) - -if __name__ == '__main__': - sys.exit(main(sys.argv[1:])) diff --git a/src/nginx/kimchi.conf.in b/src/nginx/kimchi.conf.in deleted file mode 100644 index 3ecbde4..0000000 --- a/src/nginx/kimchi.conf.in +++ /dev/null @@ -1,76 +0,0 @@ -# Project Kimchi -# -# Copyright IBM, Corp. 2014-2015 -# -# This library is free software; you can redistribute it and/or -# modify it under the terms of the GNU Lesser General Public -# License as published by the Free Software Foundation; either -# version 2.1 of the License, or (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -# Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public -# License along with this library; if not, write to the Free Software -# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA -# 02110-1301 USA - -# This is a template file to be used to generate a nginx -# proxy config file at kimchid script. - -user ${user}; -worker_processes 1; - -error_log /var/log/nginx/error.log; - -events { - worker_connections 1024; -} - -http { - - log_format main '$remote_addr - $remote_user [$time_local] "$request" ' - '$status $body_bytes_sent "$http_referer" ' - '"$http_user_agent" "$http_x_forwarded_for"'; - - access_log /var/log/nginx/access.log main; - sendfile on; - - client_max_body_size ${max_body_size}k; - - # Timeout set to 10 minutes to avoid the 504 Gateway Timeout - # when Kimchi is processing a request. - proxy_connect_timeout 600; - proxy_send_timeout 600; - proxy_read_timeout 600; - send_timeout 600; - - server { - listen ${proxy_ssl_port} ssl; - - ssl_certificate ${cert_pem}; - ssl_certificate_key ${cert_key}; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers ECDH@STRENGTH:DH@STRENGTH:HIGH:!RC4:!MD5:!DES:!aNULL:!eNULL; - - add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;"; - add_header X-Frame-Options DENY; - add_header X-Content-Type-Options nosniff; - add_header X-XSS-Protection "1; mode=block"; - - location / { - proxy_pass http://127.0.0.1:${kimchid_port}; - proxy_set_header Host $host; - proxy_set_header X-Real-IP $remote_addr; - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_redirect http://127.0.0.1:${kimchid_port}/ https://$host:${proxy_ssl_port}/; - } - } - - server { - listen ${proxy_port}; - rewrite ^/(.*)$ https://$host:${proxy_ssl_port}/$1 redirect; - } -} diff --git a/src/nginx/wok.conf.in b/src/nginx/wok.conf.in new file mode 100644 index 0000000..3ecbde4 --- /dev/null +++ b/src/nginx/wok.conf.in @@ -0,0 +1,76 @@ +# Project Kimchi +# +# Copyright IBM, Corp. 2014-2015 +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +# 02110-1301 USA + +# This is a template file to be used to generate a nginx +# proxy config file at kimchid script. + +user ${user}; +worker_processes 1; + +error_log /var/log/nginx/error.log; + +events { + worker_connections 1024; +} + +http { + + log_format main '$remote_addr - $remote_user [$time_local] "$request" ' + '$status $body_bytes_sent "$http_referer" ' + '"$http_user_agent" "$http_x_forwarded_for"'; + + access_log /var/log/nginx/access.log main; + sendfile on; + + client_max_body_size ${max_body_size}k; + + # Timeout set to 10 minutes to avoid the 504 Gateway Timeout + # when Kimchi is processing a request. + proxy_connect_timeout 600; + proxy_send_timeout 600; + proxy_read_timeout 600; + send_timeout 600; + + server { + listen ${proxy_ssl_port} ssl; + + ssl_certificate ${cert_pem}; + ssl_certificate_key ${cert_key}; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers ECDH@STRENGTH:DH@STRENGTH:HIGH:!RC4:!MD5:!DES:!aNULL:!eNULL; + + add_header Strict-Transport-Security "max-age=31536000; includeSubdomains;"; + add_header X-Frame-Options DENY; + add_header X-Content-Type-Options nosniff; + add_header X-XSS-Protection "1; mode=block"; + + location / { + proxy_pass http://127.0.0.1:${kimchid_port}; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_redirect http://127.0.0.1:${kimchid_port}/ https://$host:${proxy_ssl_port}/; + } + } + + server { + listen ${proxy_port}; + rewrite ^/(.*)$ https://$host:${proxy_ssl_port}/$1 redirect; + } +} diff --git a/src/wok.conf.in b/src/wok.conf.in new file mode 100644 index 0000000..cd141f5 --- /dev/null +++ b/src/wok.conf.in @@ -0,0 +1,65 @@ +# +# Configuration file for Kimchi Web Server +# + +[server] +# Hostname or IP address to listen on +#host = 0.0.0.0 + +# Port to listen on +#port = 8000 + +# If present, start an SSL-enabled server on the given port +#ssl_port = 8001 + +# Cherrypy server port +#cherrypy_port = 8010 + +# The full path to an SSL Certificate in PEM format. If left unspecified, +# Kimchi will generate a self-signed certificate automatically. +#ssl_cert = + +# The corresponding private key in PEM format for the SSL Certificate supplied +# above. If left blank, Kimchi will generate a self-signed certificate. +#ssl_key = + +# Running environment of the server +#environment = production + +# Federation feature: register Kimchi server on openSLP and discover peers +# in the same network. Check README-federation for more details. +#federation = off + +# Max request body size in KB, default value is 4GB +#max_body_size = 4 * 1024 * 1024 + +# Automatically create ISO pool on server start up +#create_iso_pool = true + +[logging] +# Log directory +#log_dir = @localstatedir@/log/kimchi + +# Logging level: debug, info, warning, error or critical +#log_level = debug + +[display] +# Port for websocket proxy to listen on +#display_proxy_port = 64667 + +[authentication] +# Authentication method, available option: pam, ldap. +# method = pam + +# If specified method to ldap, following fields need to be specified. +# ldap server domain name used to authenticate. +# ldap_server = "localhost" + +# Search tree base in ldap +# ldap_search_base = "ou=People, dc=kimchi, dc=org" + +# User id filter +# ldap_search_filter = "uid=%(username)s" + +# User IDs regarded as kimchi admin +# ldap_admin_id = "foo@foo.com, bar@bar.com" diff --git a/src/wokd.in b/src/wokd.in new file mode 100644 index 0000000..4ea7a42 --- /dev/null +++ b/src/wokd.in @@ -0,0 +1,99 @@ +#!/usr/bin/env python2 +# +# Project Kimchi +# +# Copyright IBM, Corp. 2013-2015 +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, +# MA 02110-1301 USA + +import os +import sys +sys.path.insert(1, '@pythondir@') + +from optparse import OptionParser + +import kimchi.server +import kimchi.config as config + + +if not config.paths.installed: + sys.path.append(config.paths.prefix) + +ACCESS_LOG = "kimchi-access.log" +ERROR_LOG = "kimchi-error.log" + + +def main(options): + # Script must run as root or with sudo. + if not os.geteuid() == 0: + sys.exit("\nMust be root to run this script. Exiting ...\n") + + host = config.config.get("server", "host") + port = config.config.get("server", "port") + ssl_port = config.config.get("server", "ssl_port") + cherrypy_port = config.config.get("server", "cherrypy_port") + runningEnv = config.config.get("server", "environment") + federation = config.config.get("server", "federation") + isopool = config.config.get("server", "create_iso_pool") + logDir = config.config.get("logging", "log_dir") + logLevel = config.config.get("logging", "log_level") + + parser = OptionParser() + parser.add_option('--host', type="string", default=host, + help="Hostname to listen on") + parser.add_option('--port', type="int", default=port, + help="Port to listen on (default %s)" % port) + parser.add_option('--ssl-port', type="int", default=ssl_port, + help="Port to enable SSL (default %s)" % ssl_port) + parser.add_option('--cherrypy_port', type="int", default=cherrypy_port, + help="Cherrypy server port (default %s)" % cherrypy_port) + parser.add_option('--log-level', default=logLevel, + help="Logging level") + parser.add_option('--access-log', + default=os.path.join(logDir, ACCESS_LOG), + help="Access log file") + parser.add_option('--error-log', + default=os.path.join(logDir, ERROR_LOG), + help="Error log file") + parser.add_option('--environment', default=runningEnv, + help="Running environment of kimchi server") + parser.add_option('--federation', default=federation, + help="Register and discover Kimchi peers in the same " + "network using openSLP. Check README-federation for" + " more details.") + parser.add_option('--create_iso_pool', default=isopool, + help="Automatically create ISO pool on server start up.") + parser.add_option('--test', action='store_true', + help="Run server in mock model") + (options, args) = parser.parse_args() + + # Update config.config with the command line values + # So the whole application will have access to accurate values + for sec in config.config.sections(): + for item in config.config.options(sec): + if hasattr(options, item): + config.config.set(sec, item, str(getattr(options, item))) + + # Add non-option arguments + setattr(options, 'ssl_cert', config.config.get('server', 'ssl_cert')) + setattr(options, 'ssl_key', config.config.get('server', 'ssl_key')) + setattr(options, 'max_body_size', + config.config.get('server', 'max_body_size')) + + kimchi.server.main(options) + +if __name__ == '__main__': + sys.exit(main(sys.argv[1:])) diff --git a/ui/js/src/kimchi.cookie.js b/ui/js/src/kimchi.cookie.js deleted file mode 100644 index f1b52db..0000000 --- a/ui/js/src/kimchi.cookie.js +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Project Kimchi - * - * Copyright IBM, Corp. 2013-2014 - * - * 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. - */ -kimchi.cookie = { - set: function(key, value, expireDays) { - value = encodeURIComponent(value); - value += '; secure' - if (expireDays) { - var expireDate = new Date(); - expireDate.setDate(expireDate.getDate() + expireDays); - value += '; expires=' + expireDate.toUTCString(); - } - document.cookie = key + '=' + value; - }, - - get: function(key) { - var cookieRe = new RegExp(';?\\\s*(' + key + ')=(\s*[^;]*);?', 'g'); - var match = cookieRe.exec(document.cookie); - return match ? decodeURIComponent(match[2]) : undefined; - }, - - remove: function(key) { - var utcString = new Date().toUTCString(); - document.cookie = key + '=; expires=' + utcString; - } -}; diff --git a/ui/js/src/kimchi.grid.js b/ui/js/src/kimchi.grid.js deleted file mode 100644 index 6fed753..0000000 --- a/ui/js/src/kimchi.grid.js +++ /dev/null @@ -1,528 +0,0 @@ -/* - * Project Kimchi - * - * Copyright IBM, Corp. 2013-2015 - * - * 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. - */ -kimchi.widget.Grid = function(opts) { - this.opts = $.extend({}, this.opts, opts); - this.createDOM(); - this.reload(); -}; - -kimchi.widget.Grid.prototype = (function() { - var htmlStr = [ - '<div id="{id}" class="grid">', - '<div class="grid-content">', - '<div class="grid-header">', - '<div class="grid-frozen-header-view">', - '<table class="grid-frozen-header-container">', - '</table>', - '</div>', - '<div class="grid-header-view">', - '<div class="grid-header-wrapper">', - '<table class="grid-header-container">', - '</table>', - '</div>', - '</div>', - '</div>', - '<div class="grid-body">', - '<div class="grid-frozen-body-view">', - '<div class="grid-frozen-body-wrapper">', - '<table class="grid-frozen-body-container">', - '</table>', - '</div>', - '</div>', - '<div class="grid-body-view">', - '<div class="grid-body-wrapper">', - '<table class="grid-body-container">', - '</table>', - '</div>', - '</div>', - '</div>', - '<div class="grid-resizer-leftmost hidden"></div>', - '<div class="grid-resizer hidden"></div>', - '</div>', - '<div class="grid-footer"></div>', - '<div class="grid-mask hidden">', - '<div class="grid-loading">', - '<div class="grid-loading-icon"></div>', - '<div class="grid-loading-text">', - '{loading}', - '</div>', - '</div>', - '</div>', - '<div class="grid-message hidden">', - '<div class="grid-message-text">', - '{message}', - '<button class="retry-button btn-small">', - '{buttonLabel}', - '</button>', - '</div>', - '<div class="detailed-title">', - '{detailedLabel}', - '</div>', - '<div class="detailed-text"></div>', - '</div>', - '</div>' - ].join(''); - - var CONTAINER_NORMAL = 0, CONTAINER_FROZEN = 1; - - var setupHeaders = function(header, body, fields) { - var colGroup = $('<colgroup></colgroup>').appendTo(header); - var headerHeader = $('<thead></thead>'); - var headerRow = $('<tr></tr>').appendTo(headerHeader); - $.each(fields || [], function(i, field) { - $('<col class="' + - field['class'] + - '"/>') - .appendTo(colGroup); - $('<th><div class="cell-text-wrapper">' + - field['label'] + - '</div></th>').appendTo(headerRow); - }); - headerHeader.appendTo(header); - - var totalWidth = 0; - $('col', colGroup).each(function(index, col) { - var width = $(col).width(); - totalWidth += width; - $(col).css('width', width + 'px'); - }); - $(body).append(colGroup.clone()); - return totalWidth; - }; - - var getValue = function(name, obj) { - var result=undefined; - if(!Array.isArray(name)) { - name=name.parseKey(); - } - if(name.length!=0) { - var tmpName=name.shift(); - if(obj[tmpName]!=undefined) { - result=obj[tmpName]; - } - if(name.length!=0) { - result=getValue(name,obj[tmpName]); - } - } - return(result); - }; - - var fillBody = function(container, fields) { - var data = this.data; - var tbody = ($('tbody', container).length && $('tbody', container)) - || $('<tbody></tbody>').appendTo(container); - tbody.empty(); - $.each(data, function(i, row) { - var rowNode = $('<tr></tr>').appendTo(tbody); - $.each(fields, function(fi, field) { - var value = getValue(field['name'], row); - $('<td><div class="cell-text-wrapper"' + - (field['makeTitle'] === true - ? ' title="' + value + '"' - : '' - ) + '>' + value.toString() + '</div></td>' - ).appendTo(rowNode); - }); - }); - }; - - var fixTableLayout = function(style) { - $.each([ - this.frozenHeaderContainer, - this.headerContainer, - this.frozenBodyContainer, - this.bodyContainer - ], function(i, tableNode) { - $(tableNode).css('table-layout', style || 'fixed'); - }); - }; - - var initResizing = function(event) { - var resizer = event.data.resizer; - var pageX = event.pageX; - var tailPos = $(this).width() + $(this).offset()['left']; - var atResizer = Math.abs(pageX - tailPos) <= 2; - var isResizing = !$(resizer).hasClass('hidden'); - $('body')[(atResizer || isResizing) - ? 'addClass' - : 'removeClass' - ]('resizing'); - }; - - var clearResizing = function(event) { - $(event.data.resizer).hasClass('hidden') && - $('body').removeClass('resizing'); - }; - - var stylingRow = function(row, className, add) { - var index = $(row).index() + 1; - $('tr', this.frozenBodyContainer) - .removeClass(className); - $('tr', this.bodyContainer) - .removeClass(className); - - if(add === false) { - return; - } - - $('tr:nth-child(' + index + ')', this.frozenBodyContainer) - .addClass(className); - $('tr:nth-child(' + index + ')', this.bodyContainer) - .addClass(className); - }; - - var setBodyListeners = function() { - if(this['opts']['rowSelection'] != 'disabled') { - $('tr', this.gridBody).on('mouseover', { - grid: this - }, function(event) { - if (! $(this).hasClass('no-hover')) - stylingRow.call(event.data.grid, this, 'hover'); - }); - - $('tr', this.gridBody).on('mouseout', { - grid: this - }, function(event) { - stylingRow.call(event.data.grid, this, 'hover', false); - }); - - $('tr', this.gridBody).on('click', { - grid: this - }, function(event) { - var grid = event.data.grid; - grid.selectedIndex = $(this).index(); - stylingRow.call(grid, this, 'selected'); - grid['opts']['onRowSelected'] && grid['opts']['onRowSelected'](); - }); - } - - $('.grid-body-view', this.domNode).on('scroll', { - grid: this - }, function(event) { - var grid = event.data.grid; - $('.grid-header .grid-header-view', grid.domNode) - .prop('scrollLeft', this.scrollLeft); - $('.grid-body .grid-frozen-body-view', grid.domNode) - .prop('scrollTop', this.scrollTop); - }); - }; - - var setData = function(data) { - this.data = data; - fillBody.call(this, this.frozenBodyContainer, this['opts']['frozenFields']); - fillBody.call(this, this.bodyContainer, this['opts']['fields']); - setBodyListeners.call(this); - }; - - var getSelected = function() { - return this.selectedIndex >= 0 - ? this.data[this.selectedIndex] - : null; - }; - - var startResizing = function(container, event) { - var grid = event.data.grid; - kimchi.widget.Grid.beingResized = grid; - if(!($('body').hasClass('resizing') - && $(grid.resizer).hasClass('hidden'))) { - return; - } - - grid.columnBeingResized = container; - var pageX = event.pageX; - var gridOffsetX = grid.domNode.offset()['left']; - var leftmostOffsetX = $(container).offset()['left'] - gridOffsetX; - var left = pageX - gridOffsetX; - var contentHeight = $('.grid-content', grid.domNode).height(); - $(grid.resizerLeftmost).css({ - left: leftmostOffsetX + 'px', - height: contentHeight + 'px' - }); - $(grid.resizer).css({ - left: left + 'px', - height: contentHeight + 'px' - }); - $(grid.resizerLeftmost).removeClass('hidden'); - $(grid.resizer).removeClass('hidden'); - event.preventDefault(); - }; - - var endResizing = function(event) { - var grid = kimchi.widget.Grid.beingResized; - if(!$('body').hasClass('resizing')) { - return; - } - $(grid.resizerLeftmost).addClass('hidden'); - $(grid.resizer).addClass('hidden'); - $('body').removeClass('resizing'); - var leftmostOffset = $(grid.columnBeingResized).offset()['left']; - var left = event.pageX; - if(leftmostOffset > left) { - return; - } - resizeColumnWidth.call( - grid, - $(grid.columnBeingResized).index(), - left - leftmostOffset - ); - fixTableLayout.call(grid); - grid.columnBeingResized = null; - kimchi.widget.Grid.beingResized = null; - }; - - var resizeColumnWidth = function(index, width) { - var width = Math.ceil(width); - var widthArray = []; - var totalWidth = 0; - var header = this.headerContainer; - var body = this.bodyContainer; - if(this.containerBeingResized === CONTAINER_FROZEN) { - header = this.frozenHeaderContainer; - body = this.frozenBodyContainer; - } - $('col', header).each(function(i, colNode) { - var w = index === i ? width : $(colNode).width(); - widthArray.push(w); - totalWidth += w; - }); - $.each([header, body], function(i, container) { - container.css({ - 'table-layout': 'fixed', - width: totalWidth + 'px' - }); - $('col:nth-child(' + (index + 1) + ')', container).css({ - width: width + 'px' - }); - }); - - if(this.containerBeingResized === CONTAINER_FROZEN) { - var headerView = $('.grid-header-view', this.domNode); - var bodyView = $('.grid-body-view', this.domNode); - $.each([headerView, bodyView], function(i, view) { - view.css({ - left: totalWidth + 'px' - }); - }); - } - }; - - var positionResizer = function(event) { - var grid = event.data.grid; - if($(grid.resizer).hasClass('hidden')) { - return; - } - - var pageX = event.pageX; - var gridOffsetX = $(grid.domNode).offset()['left']; - var leftMost = $(grid.resizerLeftmost).position()['left']; - var offsetX = pageX - gridOffsetX; - offsetX = offsetX >= leftMost ? offsetX : leftMost; - $(grid.resizer).css('left', offsetX + 'px'); - }; - - var showMessage = function(msg) { - $('.detailed-text', this.messageNode).text(msg); - $(this.messageNode).removeClass('hidden'); - }; - - var hideMessage = function() { - $(this.messageNode).addClass('hidden'); - }; - - var reload = function() { - var data = this['opts']['data']; - if(!data) { - return; - } - - $(this.messageNode).addClass('hidden'); - - if($.isArray(data)) { - return this.setData(data); - } - - if($.isFunction(data)) { - var loadData = data; - $(this.maskNode).removeClass('hidden'); - loadData($.proxy(function(data) { - this.setData(data); - $(this.maskNode).addClass('hidden'); - }, this)); - } - }; - - var destroy = function() { - $('body').off('mousemove.grid#' + this['opts']['id'], positionResizer); - $('body').off('mouseup.grid#' + this['opts']['id'], endResizing); - }; - - var createDOM = function() { - var containerID = this['opts']['container']; - var container = $('#' + containerID); - var gridID = this['opts']['id']; - var rowSelection = this['opts']['rowSelection'] || 'single'; - var domNode = $(kimchi.substitute(htmlStr, { - id: gridID, - loading: i18n['KCHGRD6001M'], - message: i18n['KCHGRD6002M'], - buttonLabel: i18n['KCHGRD6003M'], - detailedLabel: i18n['KCHGRD6004'] - })).appendTo(container); - this.domNode = domNode; - - var height = domNode.height(); - var width = domNode.width(); - - var title = this['opts']['title']; - var titleNode = null; - if(title) { - titleNode = $('<div class="grid-caption">' + title + '</div>') - .prependTo(domNode); - } - - var toolbarButtons = this['opts']['toolbarButtons']; - var toolbarNode = null; - if(toolbarButtons) { - toolbarNode = $('<div class="grid-toolbar"></div>'); - if(titleNode) { - titleNode.after(toolbarNode); - } - else { - toolbarNode.prependTo(domNode); - } - - $.each(toolbarButtons, function(i, button) { - var btnHTML = [ - '<button', - button['id'] ? (' id="' + button['id'] + '"') : '', - ' class="grid-toolbar-button', - button['class'] ? (' ' + button['class']) : '', - '"', - button['disabled'] === true ? ' disabled' : '', - '>', - button['label'], - '</button>' - ].join(''); - var btnNode = $(btnHTML).appendTo(toolbarNode); - button['onClick'] && - btnNode.on('click', button['onClick']); - }); - } - - var frozenHeaderContainer = $('.grid-frozen-header-container', domNode); - var frozenBodyContainer = $('.grid-frozen-body-container', domNode); - var frozenWidth = setupHeaders( - frozenHeaderContainer, - frozenBodyContainer, - this['opts']['frozenFields'] - ); - this.frozenHeaderContainer = frozenHeaderContainer; - this.frozenBodyContainer = frozenBodyContainer; - - var headerContainer = $('.grid-header-container', domNode); - var bodyContainer = $('.grid-body-container', domNode); - setupHeaders(headerContainer, bodyContainer, this['opts']['fields']); - this.headerContainer = headerContainer; - this.bodyContainer = bodyContainer; - - fixTableLayout.call(this, 'auto'); - - var gridContentNode = $('.grid-content', domNode); - var captionHeight = titleNode && $(titleNode).height() || 0; - var toolbarHeight = toolbarNode && $(toolbarNode).height() || 0; - gridContentNode.css('top', (captionHeight + toolbarHeight) + 'px'); - - var maskNode = $('.grid-mask', domNode); - maskNode.css('top', captionHeight + 'px'); - this.maskNode = maskNode; - - var messageNode = $('.grid-message', domNode); - messageNode.css('top', captionHeight + 'px'); - this.messageNode = messageNode; - - var headerView = $('.grid-header-view', domNode); - var bodyView = $('.grid-body-view', domNode); - headerView.css('left', (frozenWidth) + 'px'); - bodyView.css('left', (frozenWidth) + 'px'); - - var bodyWidth = width - frozenWidth; - headerContainer.css('width', bodyWidth + 'px'); - bodyContainer.css('width', bodyWidth + 'px'); - - fixTableLayout.call(this); - - var gridBody = $('.grid-body', domNode); - this.gridBody = gridBody; - this.resizerLeftmost = $('.grid-resizer-leftmost', domNode); - this.resizer = $('.grid-resizer', domNode); - var gridHeader = $('.grid-header', domNode); - $('th', gridHeader).on('mouseover mousemove', { - resizer: this.resizer - }, initResizing); - - $('th', gridHeader).on('mouseout', { - resizer: this.resizer - }, clearResizing); - - this.containerBeingResized = CONTAINER_NORMAL; - $('th', frozenHeaderContainer).on('mousedown', { - grid: this - }, function(event) { - event.data.grid.containerBeingResized = CONTAINER_FROZEN; - startResizing(this, event); - }); - $('th', headerContainer).on('mousedown', { - grid: this - }, function(event) { - event.data.grid.containerBeingResized = CONTAINER_NORMAL; - startResizing(this, event); - }); - - $('body').on('mousemove.grid#' + this['opts']['id'], { - grid: this - }, positionResizer); - $('body').on('mouseup.grid#' + this['opts']['id'], endResizing); - - var data = this['opts']['data']; - - $('.retry-button', domNode).on('click', { - grid: this - }, function(event) { - event.data.grid.reload(); - }); - }; - - return { - opts: { - container: null, - id: null, - rowSelection: 'single', - onRowSelected: null, - title: null, - toolbarButtons: null, - frozenFields: null, - fields: null - }, - createDOM: createDOM, - setData: setData, - getSelected: getSelected, - reload: reload, - destroy: destroy, - showMessage: showMessage - }; -})(); diff --git a/ui/js/src/kimchi.lang.js b/ui/js/src/kimchi.lang.js deleted file mode 100644 index 1d2de4e..0000000 --- a/ui/js/src/kimchi.lang.js +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Project Kimchi - * - * Copyright IBM, Corp. 2013-2014 - * - * 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. - */ -kimchi.lang = { - all: function() { - return { - 'en_US': 'English (US)', - 'zh_CN': '中文(简体)', - 'pt_BR': 'Português (Brasil)', - 'de_DE': 'Deutsch (Deutschland)', - 'es_ES': 'Español (España)', - 'fr_FR': 'Français (France)', - 'it_IT': 'Italiano (Italia)', - 'ja_JP': '日本語 (日本)', - 'ko_KR': '한국어 (대한민국)', - 'ru_RU': 'Русский (Россия)', - 'zh_TW': '中文(繁體)' - }; - }, - - /** - * Language is determined by the following sequence: - * 1) Cookie setting; or if not set -> - * 2) HTML DOM lang attribute; or if not set -> - * 3) DEFAULT (en_US). - */ - get: function() { - return kimchi.cookie.get('kimchiLang') || - $('html').prop('lang') || - 'en_US'; - }, - - set: function(lang) { - kimchi.cookie.set('kimchiLang', lang, 365); - } -}; diff --git a/ui/js/src/kimchi.login.js b/ui/js/src/kimchi.login.js deleted file mode 100644 index c737d26..0000000 --- a/ui/js/src/kimchi.login.js +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Project Kimchi - * - * Copyright IBM, Corp. 2014-2015 - * - * 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. - */ -kimchi.login_main = function() { - - var selectedLanguage = kimchi.lang.get(); - $('#userLang').val(selectedLanguage); - - $('#userLang').on('change', function() { - kimchi.lang.set($(this).val()); - location.reload(); - }); - - var query = window.location.search; - var error = /.*error=(.*?)(&|$)/g.exec(query); - if (error && error[1] == "sessionTimeout") { - $("#messSession").show(); - } - - var userNameBox = $('#username'); - var passwordBox = $('#password'); - var loginButton = $('#btn-login'); - - var login = function(event) { - $("#login").hide(); - $("#logging").show(); - - var userName = userNameBox.val(); - userName && kimchi.user.setUserName(userName); - var settings = { - username: userName, - password: passwordBox.val() - }; - - kimchi.login(settings, function(data) { - var query = window.location.search; - var next = /.*next=(.*?)(&|$)/g.exec(query); - if (next) { - var next_url = decodeURIComponent(next[1]); - } - else { - var lastPage = kimchi.cookie.get('lastPage'); - var next_url = lastPage ? lastPage.replace(/\"/g,'') : "/"; - } - kimchi.cookie.set('roles',JSON.stringify(data.roles)); - window.location.replace(window.location.pathname.replace(/\/+login.html/, '') + next_url) - }, function() { - $("#messUserPass").show(); - $("#messSession").hide(); - $("#logging").hide(); - $("#login").show(); - }); - - return false; - }; - - $('#btn-login').bind('click', login); -}; diff --git a/ui/js/src/kimchi.main.js b/ui/js/src/kimchi.main.js deleted file mode 100644 index 0d4ad43..0000000 --- a/ui/js/src/kimchi.main.js +++ /dev/null @@ -1,366 +0,0 @@ -/* - * Project Kimchi - * - * Copyright IBM, Corp. 2013-2015 - * - * 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. - */ -kimchi.tabMode = {}; - -kimchi.capabilities = undefined; -kimchi.getCapabilities(function(result) { - kimchi.capabilities = result; - - if(kimchi.capabilities.federation=="on") - $('#peers').removeClass('hide-content'); -}, function() { - kimchi.capabilities = {}; -}); - -kimchi.main = function() { - kimchi.isLoggingOut = false; - kimchi.popable(); - - var genTabs = function(tabs) { - var tabsHtml = []; - $(tabs).each(function(i, tab) { - var title = tab['title']; - var path = tab['path']; - var mode = tab['mode']; - if (mode != 'none') { - var helpPath = kimchi.checkHelpFile(path); - var disableHelp = (helpPath.length == 0 ? "disableHelp" : helpPath); - tabsHtml.push( - '<li>', - '<a class="item ', disableHelp,'" href="', path, '">', - title, - '</a>', - '<input id="helpPathId" name="helpPath" value="' + helpPath + '" type="hidden"/>', - '</li>' - ); - } - }); - return tabsHtml.join(''); - }; - - var parseTabs = function(xmlData) { - var tabs = []; - $(xmlData).find('tab').each(function() { - var $tab = $(this); - var titleKey = $tab.find('title').text(); - var title = i18n[titleKey] ? i18n[titleKey] : titleKey; - var path = $tab.find('path').text(); - var roles = kimchi.cookie.get('roles'); - if (roles) { - var role = JSON.parse(roles)[titleKey.toLowerCase()]; - var mode = $tab.find('[role="' + role + '"]').attr('mode'); - kimchi.tabMode[titleKey.toLowerCase()] = mode; - tabs.push({ - title: title, - path: path, - mode: mode - }); - } else { - document.location.href = 'login.html'; - } - }); - - return tabs; - }; - - var retrieveTabs = function(url) { - var tabs; - $.ajax({ - url : url, - async : false, - success : function(xmlData) { - tabs = parseTabs(xmlData); - } - }); - return tabs; - }; - - var tabConfigUrl = 'config/ui/tabs.xml'; - var pluginConfigUrl = 'plugins/{plugin}/ui/config/tab-ext.xml'; - var pluginI18nUrl = 'plugins/{plugin}/i18n.json'; - var DEFAULT_HASH; - var buildTabs = function(callback) { - var tabs = retrieveTabs(tabConfigUrl); - kimchi.listPlugins(function(plugins) { - $(plugins).each(function(i, p) { - var url = kimchi.substitute(pluginConfigUrl, { - plugin: p - }); - var i18nUrl = kimchi.substitute(pluginI18nUrl, { - plugin: p - }); - kimchi.getI18n(function(i18nObj){ $.extend(i18n, i18nObj)}, - function(i18nObj){ //i18n is not define by plugin - }, i18nUrl, true); - tabs.push.apply(tabs, retrieveTabs(url)); - }); - - var defaultTab = tabs[1] - - var defaultTabPath = defaultTab && defaultTab['path'] - // Remove file extension from 'defaultTabPath' - DEFAULT_HASH = defaultTabPath && - defaultTabPath.substring(0, defaultTabPath.lastIndexOf('.')) - - $('#nav-menu').append(genTabs(tabs)); - - callback && callback(); - }, function(data) { - kimchi.message.error(data.responseJSON.reason); - }, true); - }; - - var onLanguageChanged = function(lang) { - kimchi.lang.set(lang); - location.reload(); - }; - - /** - * Do the following setup: - * 1) Clear any timing events. - * 2) If the given URL is invalid (i.e., no corresponding href value in - * page tab list.), then clear location.href and inform the user; - * - * Or else: - * Move the page tab indicator to the right position; - * Load the page content via Ajax. - */ - var onKimchiRedirect = function(url) { - /* - * Find the corresponding tab node and animate the arrow indicator to - * point to the tab. If nothing found, inform user the URL is invalid - * and clear location.hash to jump to home page. - */ - var tab = $('#nav-menu a[href="' + url + '"]'); - if (tab.length === 0) { - location.hash = ''; - return; - } - - // Animate arrow indicator. - var left = $(tab).parent().position().left; - var width = $(tab).parent().width(); - $('.menu-arrow').stop().animate({ - left : left + width / 2 - 10 - }); - - // Update the visual style of tabs; focus the selected one. - $('#nav-menu a').removeClass('current'); - $(tab).addClass('current'); - $(tab).focus(); - // Disable Help button according to selected tab - if ($(tab).hasClass("disableHelp")) { - $('#btn-help').css('cursor', "not-allowed"); - $('#btn-help').off("click"); - } - else { - $('#btn-help').css('cursor', "pointer"); - $('#btn-help').on("click", kimchi.openHelp); - } - // Load page content. - loadPage(url); - }; - - /** - * Use Ajax to dynamically load a page without a page refreshing. Handle - * arrow cursor animation, DOM node focus, and page content rendering. - */ - var loadPage = function(url) { - // Get the page content through Ajax and render it. - url && $('#main').load(url, function(responseText, textStatus, jqXHR) { - if (jqXHR['status'] === 401 || jqXHR['status'] === 303) { - var isSessionTimeout = jqXHR['responseText'].indexOf("sessionTimeout")!=-1; - document.location.href= isSessionTimeout ? 'login.html?error=sessionTimeout' : 'login.html'; - return; - } - }); - }; - - /* - * Update page content. - * 1) If user types in the main page URL without hash, then we apply the - * default hash. e.g., http://kimchi.company.com:8000; - * 2) If user types a URL with hash, then we publish an "redirect" event - * to load the page, e.g., http://kimchi.company.com:8000/#templates. - */ - var updatePage = function() { - // Parse hash string. - var hashString = (location.hash && location.hash.substr(1)); - /* - * If hash string is empty, then apply the default one; - * or else, publish an "redirect" event to load the page. - */ - if (!hashString) { - location.hash = DEFAULT_HASH; - } - else { - kimchi.topic('redirect').publish(hashString + '.html'); - } - }; - - /** - * Register listeners including: - * 1) Kimchi redirect event - * 2) hashchange event - * 3) Tab list click event - * 4) Log-out button click event - * 5) About button click event - * 6) Help button click event - * 7) Peers button click event - */ - var searchingPeers = false; - var initListeners = function() { - kimchi.topic('languageChanged').subscribe(onLanguageChanged); - kimchi.topic('redirect').subscribe(onKimchiRedirect); - - /* - * If hash value is changed, then we know the user is intended to load - * another page. - */ - window.onhashchange = updatePage; - - /* - * Register click listener of tabs. Replace the default reloading page - * behavior of <a> with Ajax loading. - */ - $('#nav-menu').on('click', 'a.item', function(event) { - var href = $(this).attr('href'); - // Remove file extension from 'href' - location.hash = href.substring(0,href.lastIndexOf('.')) - /* - * We use the HTML file name for hash, like: guests for guests.html - * and templates for templates.html. - * Retrieve hash value from the given URL and update location's - * hash part. It has 2 effects: one is to publish Kimchi "redirect" - * event to trigger listener, the other is to put an entry into the - * browser's address history to make pages be bookmark-able. - */ - // Prevent <a> causing browser redirecting to other page. - event.preventDefault(); - }); - - // Perform logging out via Ajax request. - $('#btn-logout').on('click', function() { - kimchi.logout(function() { - kimchi.isLoggingOut = true; - document.location.href = "login.html"; - }, function(err) { - kimchi.message.error(err.responseJSON.reason); - }); - }); - - // Set handler for about button - $('#btn-about').on('click', function(event) { - kimchi.window.open({"content": $('#about-tmpl').html()}); - event.preventDefault(); - }); - - // Set handler for help button - $('#btn-help').on('click', kimchi.openHelp); - - // Set handler to peers drop down - $('#peers').on('click', function() { - - // Check if any request is in progress - if ($('.popover', '#peers').is(':visible') || searchingPeers == true) - return - - $('#search-peers').show(); - $('#no-peers').addClass('hide-content'); - $('a', '#peers').remove(); - - searchingPeers = true; - - kimchi.getPeers(function(data){ - $('#search-peers').hide(); - if (data.length == 0) - $('#no-peers').removeClass('hide-content'); - - for(var i=0; i<data.length; i++){ - $('.dropdown', '#peers').append("<a href='"+data[i]+"' target='_blank'>"+data[i]+"</a>"); - } - searchingPeers = false; - }); - }); - }; - - var initUI = function() { - $(document).bind('ajaxError', function(event, jqXHR, ajaxSettings, errorThrown) { - if (!ajaxSettings['kimchi']) { - return; - } - - if (jqXHR['status'] === 401) { - var isSessionTimeout = jqXHR['responseText'].indexOf("sessionTimeout")!=-1; - kimchi.user.showUser(false); - kimchi.previousAjax = ajaxSettings; - $(".empty-when-logged-off").empty(); - $(".remove-when-logged-off").remove(); - document.location.href= isSessionTimeout ? 'login.html?error=sessionTimeout' : 'login.html'; - return; - } - else if((jqXHR['status'] == 0) && ("error"==jqXHR.statusText) && !kimchi.isLoggingOut) { - kimchi.message.error(i18n['KCHAPI6007E'].replace("%1", jqXHR.state())); - } - if(ajaxSettings['originalError']) { - ajaxSettings['originalError'](jqXHR, jqXHR.statusText, errorThrown); - } - }); - - kimchi.user.showUser(true); - initListeners(); - updatePage(); - }; - - // Load i18n translation strings first and then render the page. - kimchi.getI18n( - function(i18nStrings){ //success - i18n = i18nStrings; - buildTabs(initUI); - }, - function(data){ //error - kimchi.message.error(data.responseJSON.reason); - }); -}; - - -kimchi.checkHelpFile = function(path) { - var lang = kimchi.lang.get(); - var url = "" - // Find help page path according to tab name - if (/^tabs/.test(path)) - url = path.replace("tabs", "help/" + lang); - else if (/^plugins/.test(path)) - url = path.slice(0, path.lastIndexOf('/')) + "help/" + lang + path.slice(path.lastIndexOf('/')); - // Checking if help page exist. - $.ajax({ - url: url, - async: false, - error: function() { url = ""; }, - success: function() { } - }); - return url; -}; - - -kimchi.openHelp = function(e) { - var tab = $('#nav-menu a.current'); - var url = $(tab).parent().find("input[name='helpPath']").val(); - window.open(url, "Kimchi Help"); - e.preventDefault(); -}; diff --git a/ui/js/src/kimchi.message.js b/ui/js/src/kimchi.message.js deleted file mode 100644 index 241626f..0000000 --- a/ui/js/src/kimchi.message.js +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Project Kimchi - * - * Copyright IBM, Corp. 2013-2014 - * - * 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. - */ -kimchi.message = function(msg, level, node) { - var container = node || $('#messageField'); - if ($(container).size() < 1) { - container = $('<div id="messageField"/>').appendTo(document.body); - } - var message = '<div class="message ' + (level || '') + '" style="display: none;">'; - if(!node) { - message += '<div class="close">X</div>'; - } - message += '<div class="content">' + msg + '</div>'; - message += '</div>'; - var $message = $(message); - $(container).append($message); - $message.fadeIn(100); - - setTimeout(function() { - $message.fadeOut(2000, function() { - $(this).remove(); - }); - }, 4000); - - $(container).on("click", ".close", function(e) { - $(this).parent().fadeOut(200, function() { - $(this).remove(); - }); - }); -}; - -/** - * A public function of confirm box. - * - * @param msg - * type:[object] - * @param msg.title - * The title of the confirm box. - * @param msg.content - * The main text of the confirm box. - * @param msg.confirm - * The text of the confirm button. - * @param msg.cancel - * the text of the cancel button. - * @param confirmCallback - * the callback function of click the confirm button. - * @param cancelCallback - * The callback function of click the cancel and X button. - */ -kimchi.confirm = function(settings, confirmCallback, cancelCallback) { - if ($('#confirmbox-container ').size() < 1) { - $(document.body).append('<div id="confirmbox-container" class="bgmask"></div>'); - } - var confirmboxHtml = '<div class="confirmbox">'; - confirmboxHtml += '<header>'; - confirmboxHtml += '<h4 class="title">' + (settings.title || '') + '</h4>'; - confirmboxHtml += '<div class="close cancel">X</div>'; - confirmboxHtml += '</header>'; - confirmboxHtml += '<div class="content">'; - confirmboxHtml += settings.content + '</div>'; - confirmboxHtml += '<footer>'; - confirmboxHtml += '<div class="btn-group">'; - confirmboxHtml += '<button id="button-confirm" class="btn-small"><span class="text">' + (settings.confirm || i18n['KCHAPI6004M']) + '</span></button>'; - confirmboxHtml += '<button id="button-cancel" class="btn-small cancel"><span class="text">' + (settings.cancel || i18n['KCHAPI6003M']) + '</span></button>'; - confirmboxHtml += '</div>'; - confirmboxHtml += '</footer>'; - confirmboxHtml += '</div>'; - var confirmboxNode = $(confirmboxHtml); - $('#confirmbox-container').append(confirmboxNode); - confirmboxNode.fadeIn(); - - $('#confirmbox-container').on("click", "#button-confirm", function(e) { - if (confirmCallback) { - confirmCallback(); - } - confirmboxNode.fadeOut(1, function() { - $('#confirmbox-container').remove(); - }); - }); - $('#confirmbox-container').on("click", ".cancel", function(e) { - if (cancelCallback) { - cancelCallback(); - } - confirmboxNode.fadeOut(1, function() { - $('#confirmbox-container').remove(); - }); - }); -}; - -kimchi.message.warn = function(msg, node) { - kimchi.message(msg, 'warn', node); -}; -kimchi.message.error = function(msg, node) { - kimchi.message(msg, 'error', node); -}; -kimchi.message.error.code = function(code) { - msg = code + ": " + i18n[code] - kimchi.message(msg, 'error'); -}; -kimchi.message.success = function(msg, node) { - kimchi.message(msg, 'success', node); -}; diff --git a/ui/js/src/kimchi.object.js b/ui/js/src/kimchi.object.js deleted file mode 100644 index 57ec8d7..0000000 --- a/ui/js/src/kimchi.object.js +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Project Kimchi - * - * Copyright IBM, Corp. 2014 - * - * 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. - */ - -Object.defineProperty(Object.prototype, "getDeepValue", { - value: function(key) { - var result=undefined; - try { - if(!Array.isArray(key)) { - key=key.parseKey(); - } - if(key.length!=0) { - var tmpName=key.shift(); - if(this[tmpName]!=undefined) { - result=this[tmpName]; - } - if(key.length!=0) { - result=result.getDeepValue(key); - } - } - } - catch (err) { - //do nothing - } - return(result); - } -}); - -Object.defineProperty(Object.prototype, "setDeepValue", { - value: function(key, val) { - var keys; - if(Array.isArray(key)) { - keys=key; - } - else { - keys=key.parseKey(); - } - if(keys.length!=0) { - var key=keys.shift(); - if(keys.length==0) { - if(this[key]==undefined) { - this[key]=val; - } - else if(Array.isArray(this[key])){ - this[key].push(val); - } - else { - var tmpArray=[] - tmpArray.push(this[key]); - tmpArray.push(val); - this[key]=tmpArray; - } - } - else { - if(this[key]==undefined) { - this[key]=new Object(); - this[key].setDeepValue(keys,val); - } - else if(Array.isArray(this[key])){ - var tmpO=new Object(); - this[key].push(tmpO); - tmpO.setDeepValue(keys,val); - } - else { - this[key].setDeepValue(keys,val); - } - } - } - return(this); - } -}); diff --git a/ui/js/src/kimchi.popable.js b/ui/js/src/kimchi.popable.js deleted file mode 100644 index fb57010..0000000 --- a/ui/js/src/kimchi.popable.js +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Project Kimchi - * - * Copyright IBM, Corp. 2013-2014 - * - * 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. - */ -kimchi.popable = function() { - $(document).click(function(e) { - $('.popable').each(function(i, n) { - n === e.target || $.contains(n, e.target) || - $('.popover', n).toggle(false); - }); - }); - $(document).on('click', '.popable', function(e) { - var popup = $('.popover', this)[0]; - $(popup).toggle(); - - // Scroll the popup menu into viewport if invisible. - !$(popup).is(':visible') || - kimchi.isElementInViewport(popup) || - popup.scrollIntoView(); - }); -}; diff --git a/ui/js/src/kimchi.string.js b/ui/js/src/kimchi.string.js deleted file mode 100644 index 252ae50..0000000 --- a/ui/js/src/kimchi.string.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Project Kimchi - * - * Copyright IBM, Corp. 2014 - * - * 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. - */ - -Object.defineProperty(String.prototype, "parseKey", { - value: function(parsedKey) { - try { - if (!Array.isArray(parsedKey)) { - parsedKey=[]; - } - } - catch (err) { - parsedKey=[]; - } - var openBracket=this.indexOf("["); - if (openBracket!=-1) { - var id=this.slice(0, openBracket); - parsedKey.push(id); - var closeBracket=this.lastIndexOf("]"); - if (closeBracket==-1) { - closeBracket=this.length; - } - var tmpName=this.slice(openBracket+1,closeBracket); - tmpName.parseKey(parsedKey); - } - else { - parsedKey.push(this); - } - return(parsedKey); - } -}); diff --git a/ui/js/src/kimchi.substitute.js b/ui/js/src/kimchi.substitute.js deleted file mode 100644 index 434d9d3..0000000 --- a/ui/js/src/kimchi.substitute.js +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Project Kimchi - * - * Copyright IBM, Corp. 2014 - * - * 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. - */ -kimchi.substitute = function(templateStr, data, tag) { - tag = tag || /\{([^\}]+)\}/g; - - var escapeHtml = function(html) { - return String(html) - .replace(/&/g, '&') - .replace(/</g, '<') - .replace(/>/g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); - }; - - return templateStr.replace(tag, function(matchResult, express) { - var propertyArray = express.split('!'); - var defaultValue = propertyArray[1] || ''; - propertyArray = propertyArray[0].split('.'); - var value = data, i = 0, l = propertyArray.length, property; - for (; i < l; i++) { - property = propertyArray[i]; - if (value) { - value = value[property]; - } else { - break; - } - } - return escapeHtml((value || value === 0) ? value : defaultValue); - }); -}; diff --git a/ui/js/src/kimchi.topic.js b/ui/js/src/kimchi.topic.js deleted file mode 100644 index fd62ffe..0000000 --- a/ui/js/src/kimchi.topic.js +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Project Kimchi - * - * Copyright IBM, Corp. 2013-2014 - * - * 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. - */ - -/** - * pub/sub - * Usage: - * Publish - kimchi.topic('eventname').publish(params); - * Subscribe - kimchi.topic('eventname').subscribe(listener); - * Unsubscribe - kimchi.topic('eventname').unsubscribe(listener); - */ -kimchi.topic = (function() { - - var topics = {}; - - return function( id ) { - var callbacks, - method, - topic = id && topics[ id ]; - - if ( !topic ) { - callbacks = jQuery.Callbacks(); - topic = { - publish: callbacks.fire, - subscribe: callbacks.add, - unsubscribe: callbacks.remove - }; - if ( id ) { - topics[ id ] = topic; - } - } - return topic; - }; -})(); diff --git a/ui/js/src/kimchi.user.js b/ui/js/src/kimchi.user.js deleted file mode 100644 index c036155..0000000 --- a/ui/js/src/kimchi.user.js +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Project Kimchi - * - * Copyright IBM, Corp. 2013-2014 - * - * 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. - */ -kimchi.user = (function() { - var getUserName = function() { - return kimchi.cookie.get('username'); - }; - - var setUserName = function(userName) { - kimchi.cookie.set('username', userName, 365); - }; - - var showUser = function(toShow) { - if (toShow) { - var userName = getUserName(); - userName && $('#user-name').text(userName); - $('#user').removeClass('not-logged-in'); - return; - } - - $('#user').addClass('not-logged-in'); - }; - - return { - getUserName: getUserName, - setUserName: setUserName, - showUser: showUser - }; -})(); diff --git a/ui/js/src/kimchi.window.js b/ui/js/src/kimchi.window.js deleted file mode 100644 index 3ac8699..0000000 --- a/ui/js/src/kimchi.window.js +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Project Kimchi - * - * Copyright IBM, Corp. 2013-2014 - * - * 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. - */ -kimchi.window = (function() { - var _windows = []; - var _listeners = {}; - var open = function(settings) { - var settings = jQuery.type(settings) === 'object' ? settings : { - url: settings - }; - - var windowID = settings['id'] || 'window-' + _windows.length; - - if ($('#' + windowID).length) { - $('#' + windowID).remove(); - } - - _windows.push(windowID); - _listeners[windowID] = settings['close']; - var windowNode = $('<div></div>', { - id: windowID, - 'class': settings['class'] ? settings['class'] + ' bgmask remove-when-logged-off' : 'bgmask remove-when-logged-off' - }); - - $(windowNode).css(settings['style'] || ''); - - $(windowNode).appendTo('body').on('click', '.window .close', function() { - kimchi.window.close(); - }); - - if (settings['url']) { - $(windowNode).load(settings['url']).fadeIn(100); - return; - } - - settings['content'] && $(windowNode).html(settings['content']); - }; - - var close = function() { - var windowID = _windows.pop(); - if(_listeners[windowID]) { - _listeners[windowID](); - _listeners[windowID] = null; - } - delete _listeners[windowID]; - - $('#' + windowID).fadeOut(100, function() { - $(this).remove(); - }); - }; - - return { - open: open, - close: close - }; -})(); diff --git a/ui/js/src/wok.cookie.js b/ui/js/src/wok.cookie.js new file mode 100644 index 0000000..f1b52db --- /dev/null +++ b/ui/js/src/wok.cookie.js @@ -0,0 +1,40 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2013-2014 + * + * 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. + */ +kimchi.cookie = { + set: function(key, value, expireDays) { + value = encodeURIComponent(value); + value += '; secure' + if (expireDays) { + var expireDate = new Date(); + expireDate.setDate(expireDate.getDate() + expireDays); + value += '; expires=' + expireDate.toUTCString(); + } + document.cookie = key + '=' + value; + }, + + get: function(key) { + var cookieRe = new RegExp(';?\\\s*(' + key + ')=(\s*[^;]*);?', 'g'); + var match = cookieRe.exec(document.cookie); + return match ? decodeURIComponent(match[2]) : undefined; + }, + + remove: function(key) { + var utcString = new Date().toUTCString(); + document.cookie = key + '=; expires=' + utcString; + } +}; diff --git a/ui/js/src/wok.grid.js b/ui/js/src/wok.grid.js new file mode 100644 index 0000000..6fed753 --- /dev/null +++ b/ui/js/src/wok.grid.js @@ -0,0 +1,528 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2013-2015 + * + * 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. + */ +kimchi.widget.Grid = function(opts) { + this.opts = $.extend({}, this.opts, opts); + this.createDOM(); + this.reload(); +}; + +kimchi.widget.Grid.prototype = (function() { + var htmlStr = [ + '<div id="{id}" class="grid">', + '<div class="grid-content">', + '<div class="grid-header">', + '<div class="grid-frozen-header-view">', + '<table class="grid-frozen-header-container">', + '</table>', + '</div>', + '<div class="grid-header-view">', + '<div class="grid-header-wrapper">', + '<table class="grid-header-container">', + '</table>', + '</div>', + '</div>', + '</div>', + '<div class="grid-body">', + '<div class="grid-frozen-body-view">', + '<div class="grid-frozen-body-wrapper">', + '<table class="grid-frozen-body-container">', + '</table>', + '</div>', + '</div>', + '<div class="grid-body-view">', + '<div class="grid-body-wrapper">', + '<table class="grid-body-container">', + '</table>', + '</div>', + '</div>', + '</div>', + '<div class="grid-resizer-leftmost hidden"></div>', + '<div class="grid-resizer hidden"></div>', + '</div>', + '<div class="grid-footer"></div>', + '<div class="grid-mask hidden">', + '<div class="grid-loading">', + '<div class="grid-loading-icon"></div>', + '<div class="grid-loading-text">', + '{loading}', + '</div>', + '</div>', + '</div>', + '<div class="grid-message hidden">', + '<div class="grid-message-text">', + '{message}', + '<button class="retry-button btn-small">', + '{buttonLabel}', + '</button>', + '</div>', + '<div class="detailed-title">', + '{detailedLabel}', + '</div>', + '<div class="detailed-text"></div>', + '</div>', + '</div>' + ].join(''); + + var CONTAINER_NORMAL = 0, CONTAINER_FROZEN = 1; + + var setupHeaders = function(header, body, fields) { + var colGroup = $('<colgroup></colgroup>').appendTo(header); + var headerHeader = $('<thead></thead>'); + var headerRow = $('<tr></tr>').appendTo(headerHeader); + $.each(fields || [], function(i, field) { + $('<col class="' + + field['class'] + + '"/>') + .appendTo(colGroup); + $('<th><div class="cell-text-wrapper">' + + field['label'] + + '</div></th>').appendTo(headerRow); + }); + headerHeader.appendTo(header); + + var totalWidth = 0; + $('col', colGroup).each(function(index, col) { + var width = $(col).width(); + totalWidth += width; + $(col).css('width', width + 'px'); + }); + $(body).append(colGroup.clone()); + return totalWidth; + }; + + var getValue = function(name, obj) { + var result=undefined; + if(!Array.isArray(name)) { + name=name.parseKey(); + } + if(name.length!=0) { + var tmpName=name.shift(); + if(obj[tmpName]!=undefined) { + result=obj[tmpName]; + } + if(name.length!=0) { + result=getValue(name,obj[tmpName]); + } + } + return(result); + }; + + var fillBody = function(container, fields) { + var data = this.data; + var tbody = ($('tbody', container).length && $('tbody', container)) + || $('<tbody></tbody>').appendTo(container); + tbody.empty(); + $.each(data, function(i, row) { + var rowNode = $('<tr></tr>').appendTo(tbody); + $.each(fields, function(fi, field) { + var value = getValue(field['name'], row); + $('<td><div class="cell-text-wrapper"' + + (field['makeTitle'] === true + ? ' title="' + value + '"' + : '' + ) + '>' + value.toString() + '</div></td>' + ).appendTo(rowNode); + }); + }); + }; + + var fixTableLayout = function(style) { + $.each([ + this.frozenHeaderContainer, + this.headerContainer, + this.frozenBodyContainer, + this.bodyContainer + ], function(i, tableNode) { + $(tableNode).css('table-layout', style || 'fixed'); + }); + }; + + var initResizing = function(event) { + var resizer = event.data.resizer; + var pageX = event.pageX; + var tailPos = $(this).width() + $(this).offset()['left']; + var atResizer = Math.abs(pageX - tailPos) <= 2; + var isResizing = !$(resizer).hasClass('hidden'); + $('body')[(atResizer || isResizing) + ? 'addClass' + : 'removeClass' + ]('resizing'); + }; + + var clearResizing = function(event) { + $(event.data.resizer).hasClass('hidden') && + $('body').removeClass('resizing'); + }; + + var stylingRow = function(row, className, add) { + var index = $(row).index() + 1; + $('tr', this.frozenBodyContainer) + .removeClass(className); + $('tr', this.bodyContainer) + .removeClass(className); + + if(add === false) { + return; + } + + $('tr:nth-child(' + index + ')', this.frozenBodyContainer) + .addClass(className); + $('tr:nth-child(' + index + ')', this.bodyContainer) + .addClass(className); + }; + + var setBodyListeners = function() { + if(this['opts']['rowSelection'] != 'disabled') { + $('tr', this.gridBody).on('mouseover', { + grid: this + }, function(event) { + if (! $(this).hasClass('no-hover')) + stylingRow.call(event.data.grid, this, 'hover'); + }); + + $('tr', this.gridBody).on('mouseout', { + grid: this + }, function(event) { + stylingRow.call(event.data.grid, this, 'hover', false); + }); + + $('tr', this.gridBody).on('click', { + grid: this + }, function(event) { + var grid = event.data.grid; + grid.selectedIndex = $(this).index(); + stylingRow.call(grid, this, 'selected'); + grid['opts']['onRowSelected'] && grid['opts']['onRowSelected'](); + }); + } + + $('.grid-body-view', this.domNode).on('scroll', { + grid: this + }, function(event) { + var grid = event.data.grid; + $('.grid-header .grid-header-view', grid.domNode) + .prop('scrollLeft', this.scrollLeft); + $('.grid-body .grid-frozen-body-view', grid.domNode) + .prop('scrollTop', this.scrollTop); + }); + }; + + var setData = function(data) { + this.data = data; + fillBody.call(this, this.frozenBodyContainer, this['opts']['frozenFields']); + fillBody.call(this, this.bodyContainer, this['opts']['fields']); + setBodyListeners.call(this); + }; + + var getSelected = function() { + return this.selectedIndex >= 0 + ? this.data[this.selectedIndex] + : null; + }; + + var startResizing = function(container, event) { + var grid = event.data.grid; + kimchi.widget.Grid.beingResized = grid; + if(!($('body').hasClass('resizing') + && $(grid.resizer).hasClass('hidden'))) { + return; + } + + grid.columnBeingResized = container; + var pageX = event.pageX; + var gridOffsetX = grid.domNode.offset()['left']; + var leftmostOffsetX = $(container).offset()['left'] - gridOffsetX; + var left = pageX - gridOffsetX; + var contentHeight = $('.grid-content', grid.domNode).height(); + $(grid.resizerLeftmost).css({ + left: leftmostOffsetX + 'px', + height: contentHeight + 'px' + }); + $(grid.resizer).css({ + left: left + 'px', + height: contentHeight + 'px' + }); + $(grid.resizerLeftmost).removeClass('hidden'); + $(grid.resizer).removeClass('hidden'); + event.preventDefault(); + }; + + var endResizing = function(event) { + var grid = kimchi.widget.Grid.beingResized; + if(!$('body').hasClass('resizing')) { + return; + } + $(grid.resizerLeftmost).addClass('hidden'); + $(grid.resizer).addClass('hidden'); + $('body').removeClass('resizing'); + var leftmostOffset = $(grid.columnBeingResized).offset()['left']; + var left = event.pageX; + if(leftmostOffset > left) { + return; + } + resizeColumnWidth.call( + grid, + $(grid.columnBeingResized).index(), + left - leftmostOffset + ); + fixTableLayout.call(grid); + grid.columnBeingResized = null; + kimchi.widget.Grid.beingResized = null; + }; + + var resizeColumnWidth = function(index, width) { + var width = Math.ceil(width); + var widthArray = []; + var totalWidth = 0; + var header = this.headerContainer; + var body = this.bodyContainer; + if(this.containerBeingResized === CONTAINER_FROZEN) { + header = this.frozenHeaderContainer; + body = this.frozenBodyContainer; + } + $('col', header).each(function(i, colNode) { + var w = index === i ? width : $(colNode).width(); + widthArray.push(w); + totalWidth += w; + }); + $.each([header, body], function(i, container) { + container.css({ + 'table-layout': 'fixed', + width: totalWidth + 'px' + }); + $('col:nth-child(' + (index + 1) + ')', container).css({ + width: width + 'px' + }); + }); + + if(this.containerBeingResized === CONTAINER_FROZEN) { + var headerView = $('.grid-header-view', this.domNode); + var bodyView = $('.grid-body-view', this.domNode); + $.each([headerView, bodyView], function(i, view) { + view.css({ + left: totalWidth + 'px' + }); + }); + } + }; + + var positionResizer = function(event) { + var grid = event.data.grid; + if($(grid.resizer).hasClass('hidden')) { + return; + } + + var pageX = event.pageX; + var gridOffsetX = $(grid.domNode).offset()['left']; + var leftMost = $(grid.resizerLeftmost).position()['left']; + var offsetX = pageX - gridOffsetX; + offsetX = offsetX >= leftMost ? offsetX : leftMost; + $(grid.resizer).css('left', offsetX + 'px'); + }; + + var showMessage = function(msg) { + $('.detailed-text', this.messageNode).text(msg); + $(this.messageNode).removeClass('hidden'); + }; + + var hideMessage = function() { + $(this.messageNode).addClass('hidden'); + }; + + var reload = function() { + var data = this['opts']['data']; + if(!data) { + return; + } + + $(this.messageNode).addClass('hidden'); + + if($.isArray(data)) { + return this.setData(data); + } + + if($.isFunction(data)) { + var loadData = data; + $(this.maskNode).removeClass('hidden'); + loadData($.proxy(function(data) { + this.setData(data); + $(this.maskNode).addClass('hidden'); + }, this)); + } + }; + + var destroy = function() { + $('body').off('mousemove.grid#' + this['opts']['id'], positionResizer); + $('body').off('mouseup.grid#' + this['opts']['id'], endResizing); + }; + + var createDOM = function() { + var containerID = this['opts']['container']; + var container = $('#' + containerID); + var gridID = this['opts']['id']; + var rowSelection = this['opts']['rowSelection'] || 'single'; + var domNode = $(kimchi.substitute(htmlStr, { + id: gridID, + loading: i18n['KCHGRD6001M'], + message: i18n['KCHGRD6002M'], + buttonLabel: i18n['KCHGRD6003M'], + detailedLabel: i18n['KCHGRD6004'] + })).appendTo(container); + this.domNode = domNode; + + var height = domNode.height(); + var width = domNode.width(); + + var title = this['opts']['title']; + var titleNode = null; + if(title) { + titleNode = $('<div class="grid-caption">' + title + '</div>') + .prependTo(domNode); + } + + var toolbarButtons = this['opts']['toolbarButtons']; + var toolbarNode = null; + if(toolbarButtons) { + toolbarNode = $('<div class="grid-toolbar"></div>'); + if(titleNode) { + titleNode.after(toolbarNode); + } + else { + toolbarNode.prependTo(domNode); + } + + $.each(toolbarButtons, function(i, button) { + var btnHTML = [ + '<button', + button['id'] ? (' id="' + button['id'] + '"') : '', + ' class="grid-toolbar-button', + button['class'] ? (' ' + button['class']) : '', + '"', + button['disabled'] === true ? ' disabled' : '', + '>', + button['label'], + '</button>' + ].join(''); + var btnNode = $(btnHTML).appendTo(toolbarNode); + button['onClick'] && + btnNode.on('click', button['onClick']); + }); + } + + var frozenHeaderContainer = $('.grid-frozen-header-container', domNode); + var frozenBodyContainer = $('.grid-frozen-body-container', domNode); + var frozenWidth = setupHeaders( + frozenHeaderContainer, + frozenBodyContainer, + this['opts']['frozenFields'] + ); + this.frozenHeaderContainer = frozenHeaderContainer; + this.frozenBodyContainer = frozenBodyContainer; + + var headerContainer = $('.grid-header-container', domNode); + var bodyContainer = $('.grid-body-container', domNode); + setupHeaders(headerContainer, bodyContainer, this['opts']['fields']); + this.headerContainer = headerContainer; + this.bodyContainer = bodyContainer; + + fixTableLayout.call(this, 'auto'); + + var gridContentNode = $('.grid-content', domNode); + var captionHeight = titleNode && $(titleNode).height() || 0; + var toolbarHeight = toolbarNode && $(toolbarNode).height() || 0; + gridContentNode.css('top', (captionHeight + toolbarHeight) + 'px'); + + var maskNode = $('.grid-mask', domNode); + maskNode.css('top', captionHeight + 'px'); + this.maskNode = maskNode; + + var messageNode = $('.grid-message', domNode); + messageNode.css('top', captionHeight + 'px'); + this.messageNode = messageNode; + + var headerView = $('.grid-header-view', domNode); + var bodyView = $('.grid-body-view', domNode); + headerView.css('left', (frozenWidth) + 'px'); + bodyView.css('left', (frozenWidth) + 'px'); + + var bodyWidth = width - frozenWidth; + headerContainer.css('width', bodyWidth + 'px'); + bodyContainer.css('width', bodyWidth + 'px'); + + fixTableLayout.call(this); + + var gridBody = $('.grid-body', domNode); + this.gridBody = gridBody; + this.resizerLeftmost = $('.grid-resizer-leftmost', domNode); + this.resizer = $('.grid-resizer', domNode); + var gridHeader = $('.grid-header', domNode); + $('th', gridHeader).on('mouseover mousemove', { + resizer: this.resizer + }, initResizing); + + $('th', gridHeader).on('mouseout', { + resizer: this.resizer + }, clearResizing); + + this.containerBeingResized = CONTAINER_NORMAL; + $('th', frozenHeaderContainer).on('mousedown', { + grid: this + }, function(event) { + event.data.grid.containerBeingResized = CONTAINER_FROZEN; + startResizing(this, event); + }); + $('th', headerContainer).on('mousedown', { + grid: this + }, function(event) { + event.data.grid.containerBeingResized = CONTAINER_NORMAL; + startResizing(this, event); + }); + + $('body').on('mousemove.grid#' + this['opts']['id'], { + grid: this + }, positionResizer); + $('body').on('mouseup.grid#' + this['opts']['id'], endResizing); + + var data = this['opts']['data']; + + $('.retry-button', domNode).on('click', { + grid: this + }, function(event) { + event.data.grid.reload(); + }); + }; + + return { + opts: { + container: null, + id: null, + rowSelection: 'single', + onRowSelected: null, + title: null, + toolbarButtons: null, + frozenFields: null, + fields: null + }, + createDOM: createDOM, + setData: setData, + getSelected: getSelected, + reload: reload, + destroy: destroy, + showMessage: showMessage + }; +})(); diff --git a/ui/js/src/wok.lang.js b/ui/js/src/wok.lang.js new file mode 100644 index 0000000..1d2de4e --- /dev/null +++ b/ui/js/src/wok.lang.js @@ -0,0 +1,50 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2013-2014 + * + * 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. + */ +kimchi.lang = { + all: function() { + return { + 'en_US': 'English (US)', + 'zh_CN': '中文(简体)', + 'pt_BR': 'Português (Brasil)', + 'de_DE': 'Deutsch (Deutschland)', + 'es_ES': 'Español (España)', + 'fr_FR': 'Français (France)', + 'it_IT': 'Italiano (Italia)', + 'ja_JP': '日本語 (日本)', + 'ko_KR': '한국어 (대한민국)', + 'ru_RU': 'Русский (Россия)', + 'zh_TW': '中文(繁體)' + }; + }, + + /** + * Language is determined by the following sequence: + * 1) Cookie setting; or if not set -> + * 2) HTML DOM lang attribute; or if not set -> + * 3) DEFAULT (en_US). + */ + get: function() { + return kimchi.cookie.get('kimchiLang') || + $('html').prop('lang') || + 'en_US'; + }, + + set: function(lang) { + kimchi.cookie.set('kimchiLang', lang, 365); + } +}; diff --git a/ui/js/src/wok.login.js b/ui/js/src/wok.login.js new file mode 100644 index 0000000..c737d26 --- /dev/null +++ b/ui/js/src/wok.login.js @@ -0,0 +1,72 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2014-2015 + * + * 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. + */ +kimchi.login_main = function() { + + var selectedLanguage = kimchi.lang.get(); + $('#userLang').val(selectedLanguage); + + $('#userLang').on('change', function() { + kimchi.lang.set($(this).val()); + location.reload(); + }); + + var query = window.location.search; + var error = /.*error=(.*?)(&|$)/g.exec(query); + if (error && error[1] == "sessionTimeout") { + $("#messSession").show(); + } + + var userNameBox = $('#username'); + var passwordBox = $('#password'); + var loginButton = $('#btn-login'); + + var login = function(event) { + $("#login").hide(); + $("#logging").show(); + + var userName = userNameBox.val(); + userName && kimchi.user.setUserName(userName); + var settings = { + username: userName, + password: passwordBox.val() + }; + + kimchi.login(settings, function(data) { + var query = window.location.search; + var next = /.*next=(.*?)(&|$)/g.exec(query); + if (next) { + var next_url = decodeURIComponent(next[1]); + } + else { + var lastPage = kimchi.cookie.get('lastPage'); + var next_url = lastPage ? lastPage.replace(/\"/g,'') : "/"; + } + kimchi.cookie.set('roles',JSON.stringify(data.roles)); + window.location.replace(window.location.pathname.replace(/\/+login.html/, '') + next_url) + }, function() { + $("#messUserPass").show(); + $("#messSession").hide(); + $("#logging").hide(); + $("#login").show(); + }); + + return false; + }; + + $('#btn-login').bind('click', login); +}; diff --git a/ui/js/src/wok.main.js b/ui/js/src/wok.main.js new file mode 100644 index 0000000..0d4ad43 --- /dev/null +++ b/ui/js/src/wok.main.js @@ -0,0 +1,366 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2013-2015 + * + * 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. + */ +kimchi.tabMode = {}; + +kimchi.capabilities = undefined; +kimchi.getCapabilities(function(result) { + kimchi.capabilities = result; + + if(kimchi.capabilities.federation=="on") + $('#peers').removeClass('hide-content'); +}, function() { + kimchi.capabilities = {}; +}); + +kimchi.main = function() { + kimchi.isLoggingOut = false; + kimchi.popable(); + + var genTabs = function(tabs) { + var tabsHtml = []; + $(tabs).each(function(i, tab) { + var title = tab['title']; + var path = tab['path']; + var mode = tab['mode']; + if (mode != 'none') { + var helpPath = kimchi.checkHelpFile(path); + var disableHelp = (helpPath.length == 0 ? "disableHelp" : helpPath); + tabsHtml.push( + '<li>', + '<a class="item ', disableHelp,'" href="', path, '">', + title, + '</a>', + '<input id="helpPathId" name="helpPath" value="' + helpPath + '" type="hidden"/>', + '</li>' + ); + } + }); + return tabsHtml.join(''); + }; + + var parseTabs = function(xmlData) { + var tabs = []; + $(xmlData).find('tab').each(function() { + var $tab = $(this); + var titleKey = $tab.find('title').text(); + var title = i18n[titleKey] ? i18n[titleKey] : titleKey; + var path = $tab.find('path').text(); + var roles = kimchi.cookie.get('roles'); + if (roles) { + var role = JSON.parse(roles)[titleKey.toLowerCase()]; + var mode = $tab.find('[role="' + role + '"]').attr('mode'); + kimchi.tabMode[titleKey.toLowerCase()] = mode; + tabs.push({ + title: title, + path: path, + mode: mode + }); + } else { + document.location.href = 'login.html'; + } + }); + + return tabs; + }; + + var retrieveTabs = function(url) { + var tabs; + $.ajax({ + url : url, + async : false, + success : function(xmlData) { + tabs = parseTabs(xmlData); + } + }); + return tabs; + }; + + var tabConfigUrl = 'config/ui/tabs.xml'; + var pluginConfigUrl = 'plugins/{plugin}/ui/config/tab-ext.xml'; + var pluginI18nUrl = 'plugins/{plugin}/i18n.json'; + var DEFAULT_HASH; + var buildTabs = function(callback) { + var tabs = retrieveTabs(tabConfigUrl); + kimchi.listPlugins(function(plugins) { + $(plugins).each(function(i, p) { + var url = kimchi.substitute(pluginConfigUrl, { + plugin: p + }); + var i18nUrl = kimchi.substitute(pluginI18nUrl, { + plugin: p + }); + kimchi.getI18n(function(i18nObj){ $.extend(i18n, i18nObj)}, + function(i18nObj){ //i18n is not define by plugin + }, i18nUrl, true); + tabs.push.apply(tabs, retrieveTabs(url)); + }); + + var defaultTab = tabs[1] + + var defaultTabPath = defaultTab && defaultTab['path'] + // Remove file extension from 'defaultTabPath' + DEFAULT_HASH = defaultTabPath && + defaultTabPath.substring(0, defaultTabPath.lastIndexOf('.')) + + $('#nav-menu').append(genTabs(tabs)); + + callback && callback(); + }, function(data) { + kimchi.message.error(data.responseJSON.reason); + }, true); + }; + + var onLanguageChanged = function(lang) { + kimchi.lang.set(lang); + location.reload(); + }; + + /** + * Do the following setup: + * 1) Clear any timing events. + * 2) If the given URL is invalid (i.e., no corresponding href value in + * page tab list.), then clear location.href and inform the user; + * + * Or else: + * Move the page tab indicator to the right position; + * Load the page content via Ajax. + */ + var onKimchiRedirect = function(url) { + /* + * Find the corresponding tab node and animate the arrow indicator to + * point to the tab. If nothing found, inform user the URL is invalid + * and clear location.hash to jump to home page. + */ + var tab = $('#nav-menu a[href="' + url + '"]'); + if (tab.length === 0) { + location.hash = ''; + return; + } + + // Animate arrow indicator. + var left = $(tab).parent().position().left; + var width = $(tab).parent().width(); + $('.menu-arrow').stop().animate({ + left : left + width / 2 - 10 + }); + + // Update the visual style of tabs; focus the selected one. + $('#nav-menu a').removeClass('current'); + $(tab).addClass('current'); + $(tab).focus(); + // Disable Help button according to selected tab + if ($(tab).hasClass("disableHelp")) { + $('#btn-help').css('cursor', "not-allowed"); + $('#btn-help').off("click"); + } + else { + $('#btn-help').css('cursor', "pointer"); + $('#btn-help').on("click", kimchi.openHelp); + } + // Load page content. + loadPage(url); + }; + + /** + * Use Ajax to dynamically load a page without a page refreshing. Handle + * arrow cursor animation, DOM node focus, and page content rendering. + */ + var loadPage = function(url) { + // Get the page content through Ajax and render it. + url && $('#main').load(url, function(responseText, textStatus, jqXHR) { + if (jqXHR['status'] === 401 || jqXHR['status'] === 303) { + var isSessionTimeout = jqXHR['responseText'].indexOf("sessionTimeout")!=-1; + document.location.href= isSessionTimeout ? 'login.html?error=sessionTimeout' : 'login.html'; + return; + } + }); + }; + + /* + * Update page content. + * 1) If user types in the main page URL without hash, then we apply the + * default hash. e.g., http://kimchi.company.com:8000; + * 2) If user types a URL with hash, then we publish an "redirect" event + * to load the page, e.g., http://kimchi.company.com:8000/#templates. + */ + var updatePage = function() { + // Parse hash string. + var hashString = (location.hash && location.hash.substr(1)); + /* + * If hash string is empty, then apply the default one; + * or else, publish an "redirect" event to load the page. + */ + if (!hashString) { + location.hash = DEFAULT_HASH; + } + else { + kimchi.topic('redirect').publish(hashString + '.html'); + } + }; + + /** + * Register listeners including: + * 1) Kimchi redirect event + * 2) hashchange event + * 3) Tab list click event + * 4) Log-out button click event + * 5) About button click event + * 6) Help button click event + * 7) Peers button click event + */ + var searchingPeers = false; + var initListeners = function() { + kimchi.topic('languageChanged').subscribe(onLanguageChanged); + kimchi.topic('redirect').subscribe(onKimchiRedirect); + + /* + * If hash value is changed, then we know the user is intended to load + * another page. + */ + window.onhashchange = updatePage; + + /* + * Register click listener of tabs. Replace the default reloading page + * behavior of <a> with Ajax loading. + */ + $('#nav-menu').on('click', 'a.item', function(event) { + var href = $(this).attr('href'); + // Remove file extension from 'href' + location.hash = href.substring(0,href.lastIndexOf('.')) + /* + * We use the HTML file name for hash, like: guests for guests.html + * and templates for templates.html. + * Retrieve hash value from the given URL and update location's + * hash part. It has 2 effects: one is to publish Kimchi "redirect" + * event to trigger listener, the other is to put an entry into the + * browser's address history to make pages be bookmark-able. + */ + // Prevent <a> causing browser redirecting to other page. + event.preventDefault(); + }); + + // Perform logging out via Ajax request. + $('#btn-logout').on('click', function() { + kimchi.logout(function() { + kimchi.isLoggingOut = true; + document.location.href = "login.html"; + }, function(err) { + kimchi.message.error(err.responseJSON.reason); + }); + }); + + // Set handler for about button + $('#btn-about').on('click', function(event) { + kimchi.window.open({"content": $('#about-tmpl').html()}); + event.preventDefault(); + }); + + // Set handler for help button + $('#btn-help').on('click', kimchi.openHelp); + + // Set handler to peers drop down + $('#peers').on('click', function() { + + // Check if any request is in progress + if ($('.popover', '#peers').is(':visible') || searchingPeers == true) + return + + $('#search-peers').show(); + $('#no-peers').addClass('hide-content'); + $('a', '#peers').remove(); + + searchingPeers = true; + + kimchi.getPeers(function(data){ + $('#search-peers').hide(); + if (data.length == 0) + $('#no-peers').removeClass('hide-content'); + + for(var i=0; i<data.length; i++){ + $('.dropdown', '#peers').append("<a href='"+data[i]+"' target='_blank'>"+data[i]+"</a>"); + } + searchingPeers = false; + }); + }); + }; + + var initUI = function() { + $(document).bind('ajaxError', function(event, jqXHR, ajaxSettings, errorThrown) { + if (!ajaxSettings['kimchi']) { + return; + } + + if (jqXHR['status'] === 401) { + var isSessionTimeout = jqXHR['responseText'].indexOf("sessionTimeout")!=-1; + kimchi.user.showUser(false); + kimchi.previousAjax = ajaxSettings; + $(".empty-when-logged-off").empty(); + $(".remove-when-logged-off").remove(); + document.location.href= isSessionTimeout ? 'login.html?error=sessionTimeout' : 'login.html'; + return; + } + else if((jqXHR['status'] == 0) && ("error"==jqXHR.statusText) && !kimchi.isLoggingOut) { + kimchi.message.error(i18n['KCHAPI6007E'].replace("%1", jqXHR.state())); + } + if(ajaxSettings['originalError']) { + ajaxSettings['originalError'](jqXHR, jqXHR.statusText, errorThrown); + } + }); + + kimchi.user.showUser(true); + initListeners(); + updatePage(); + }; + + // Load i18n translation strings first and then render the page. + kimchi.getI18n( + function(i18nStrings){ //success + i18n = i18nStrings; + buildTabs(initUI); + }, + function(data){ //error + kimchi.message.error(data.responseJSON.reason); + }); +}; + + +kimchi.checkHelpFile = function(path) { + var lang = kimchi.lang.get(); + var url = "" + // Find help page path according to tab name + if (/^tabs/.test(path)) + url = path.replace("tabs", "help/" + lang); + else if (/^plugins/.test(path)) + url = path.slice(0, path.lastIndexOf('/')) + "help/" + lang + path.slice(path.lastIndexOf('/')); + // Checking if help page exist. + $.ajax({ + url: url, + async: false, + error: function() { url = ""; }, + success: function() { } + }); + return url; +}; + + +kimchi.openHelp = function(e) { + var tab = $('#nav-menu a.current'); + var url = $(tab).parent().find("input[name='helpPath']").val(); + window.open(url, "Kimchi Help"); + e.preventDefault(); +}; diff --git a/ui/js/src/wok.message.js b/ui/js/src/wok.message.js new file mode 100644 index 0000000..241626f --- /dev/null +++ b/ui/js/src/wok.message.js @@ -0,0 +1,116 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2013-2014 + * + * 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. + */ +kimchi.message = function(msg, level, node) { + var container = node || $('#messageField'); + if ($(container).size() < 1) { + container = $('<div id="messageField"/>').appendTo(document.body); + } + var message = '<div class="message ' + (level || '') + '" style="display: none;">'; + if(!node) { + message += '<div class="close">X</div>'; + } + message += '<div class="content">' + msg + '</div>'; + message += '</div>'; + var $message = $(message); + $(container).append($message); + $message.fadeIn(100); + + setTimeout(function() { + $message.fadeOut(2000, function() { + $(this).remove(); + }); + }, 4000); + + $(container).on("click", ".close", function(e) { + $(this).parent().fadeOut(200, function() { + $(this).remove(); + }); + }); +}; + +/** + * A public function of confirm box. + * + * @param msg + * type:[object] + * @param msg.title + * The title of the confirm box. + * @param msg.content + * The main text of the confirm box. + * @param msg.confirm + * The text of the confirm button. + * @param msg.cancel + * the text of the cancel button. + * @param confirmCallback + * the callback function of click the confirm button. + * @param cancelCallback + * The callback function of click the cancel and X button. + */ +kimchi.confirm = function(settings, confirmCallback, cancelCallback) { + if ($('#confirmbox-container ').size() < 1) { + $(document.body).append('<div id="confirmbox-container" class="bgmask"></div>'); + } + var confirmboxHtml = '<div class="confirmbox">'; + confirmboxHtml += '<header>'; + confirmboxHtml += '<h4 class="title">' + (settings.title || '') + '</h4>'; + confirmboxHtml += '<div class="close cancel">X</div>'; + confirmboxHtml += '</header>'; + confirmboxHtml += '<div class="content">'; + confirmboxHtml += settings.content + '</div>'; + confirmboxHtml += '<footer>'; + confirmboxHtml += '<div class="btn-group">'; + confirmboxHtml += '<button id="button-confirm" class="btn-small"><span class="text">' + (settings.confirm || i18n['KCHAPI6004M']) + '</span></button>'; + confirmboxHtml += '<button id="button-cancel" class="btn-small cancel"><span class="text">' + (settings.cancel || i18n['KCHAPI6003M']) + '</span></button>'; + confirmboxHtml += '</div>'; + confirmboxHtml += '</footer>'; + confirmboxHtml += '</div>'; + var confirmboxNode = $(confirmboxHtml); + $('#confirmbox-container').append(confirmboxNode); + confirmboxNode.fadeIn(); + + $('#confirmbox-container').on("click", "#button-confirm", function(e) { + if (confirmCallback) { + confirmCallback(); + } + confirmboxNode.fadeOut(1, function() { + $('#confirmbox-container').remove(); + }); + }); + $('#confirmbox-container').on("click", ".cancel", function(e) { + if (cancelCallback) { + cancelCallback(); + } + confirmboxNode.fadeOut(1, function() { + $('#confirmbox-container').remove(); + }); + }); +}; + +kimchi.message.warn = function(msg, node) { + kimchi.message(msg, 'warn', node); +}; +kimchi.message.error = function(msg, node) { + kimchi.message(msg, 'error', node); +}; +kimchi.message.error.code = function(code) { + msg = code + ": " + i18n[code] + kimchi.message(msg, 'error'); +}; +kimchi.message.success = function(msg, node) { + kimchi.message(msg, 'success', node); +}; diff --git a/ui/js/src/wok.object.js b/ui/js/src/wok.object.js new file mode 100644 index 0000000..57ec8d7 --- /dev/null +++ b/ui/js/src/wok.object.js @@ -0,0 +1,85 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2014 + * + * 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. + */ + +Object.defineProperty(Object.prototype, "getDeepValue", { + value: function(key) { + var result=undefined; + try { + if(!Array.isArray(key)) { + key=key.parseKey(); + } + if(key.length!=0) { + var tmpName=key.shift(); + if(this[tmpName]!=undefined) { + result=this[tmpName]; + } + if(key.length!=0) { + result=result.getDeepValue(key); + } + } + } + catch (err) { + //do nothing + } + return(result); + } +}); + +Object.defineProperty(Object.prototype, "setDeepValue", { + value: function(key, val) { + var keys; + if(Array.isArray(key)) { + keys=key; + } + else { + keys=key.parseKey(); + } + if(keys.length!=0) { + var key=keys.shift(); + if(keys.length==0) { + if(this[key]==undefined) { + this[key]=val; + } + else if(Array.isArray(this[key])){ + this[key].push(val); + } + else { + var tmpArray=[] + tmpArray.push(this[key]); + tmpArray.push(val); + this[key]=tmpArray; + } + } + else { + if(this[key]==undefined) { + this[key]=new Object(); + this[key].setDeepValue(keys,val); + } + else if(Array.isArray(this[key])){ + var tmpO=new Object(); + this[key].push(tmpO); + tmpO.setDeepValue(keys,val); + } + else { + this[key].setDeepValue(keys,val); + } + } + } + return(this); + } +}); diff --git a/ui/js/src/wok.popable.js b/ui/js/src/wok.popable.js new file mode 100644 index 0000000..fb57010 --- /dev/null +++ b/ui/js/src/wok.popable.js @@ -0,0 +1,34 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2013-2014 + * + * 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. + */ +kimchi.popable = function() { + $(document).click(function(e) { + $('.popable').each(function(i, n) { + n === e.target || $.contains(n, e.target) || + $('.popover', n).toggle(false); + }); + }); + $(document).on('click', '.popable', function(e) { + var popup = $('.popover', this)[0]; + $(popup).toggle(); + + // Scroll the popup menu into viewport if invisible. + !$(popup).is(':visible') || + kimchi.isElementInViewport(popup) || + popup.scrollIntoView(); + }); +}; diff --git a/ui/js/src/wok.string.js b/ui/js/src/wok.string.js new file mode 100644 index 0000000..252ae50 --- /dev/null +++ b/ui/js/src/wok.string.js @@ -0,0 +1,45 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2014 + * + * 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. + */ + +Object.defineProperty(String.prototype, "parseKey", { + value: function(parsedKey) { + try { + if (!Array.isArray(parsedKey)) { + parsedKey=[]; + } + } + catch (err) { + parsedKey=[]; + } + var openBracket=this.indexOf("["); + if (openBracket!=-1) { + var id=this.slice(0, openBracket); + parsedKey.push(id); + var closeBracket=this.lastIndexOf("]"); + if (closeBracket==-1) { + closeBracket=this.length; + } + var tmpName=this.slice(openBracket+1,closeBracket); + tmpName.parseKey(parsedKey); + } + else { + parsedKey.push(this); + } + return(parsedKey); + } +}); diff --git a/ui/js/src/wok.substitute.js b/ui/js/src/wok.substitute.js new file mode 100644 index 0000000..434d9d3 --- /dev/null +++ b/ui/js/src/wok.substitute.js @@ -0,0 +1,45 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2014 + * + * 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. + */ +kimchi.substitute = function(templateStr, data, tag) { + tag = tag || /\{([^\}]+)\}/g; + + var escapeHtml = function(html) { + return String(html) + .replace(/&/g, '&') + .replace(/</g, '<') + .replace(/>/g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); + }; + + return templateStr.replace(tag, function(matchResult, express) { + var propertyArray = express.split('!'); + var defaultValue = propertyArray[1] || ''; + propertyArray = propertyArray[0].split('.'); + var value = data, i = 0, l = propertyArray.length, property; + for (; i < l; i++) { + property = propertyArray[i]; + if (value) { + value = value[property]; + } else { + break; + } + } + return escapeHtml((value || value === 0) ? value : defaultValue); + }); +}; diff --git a/ui/js/src/wok.topic.js b/ui/js/src/wok.topic.js new file mode 100644 index 0000000..fd62ffe --- /dev/null +++ b/ui/js/src/wok.topic.js @@ -0,0 +1,48 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2013-2014 + * + * 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. + */ + +/** + * pub/sub + * Usage: + * Publish - kimchi.topic('eventname').publish(params); + * Subscribe - kimchi.topic('eventname').subscribe(listener); + * Unsubscribe - kimchi.topic('eventname').unsubscribe(listener); + */ +kimchi.topic = (function() { + + var topics = {}; + + return function( id ) { + var callbacks, + method, + topic = id && topics[ id ]; + + if ( !topic ) { + callbacks = jQuery.Callbacks(); + topic = { + publish: callbacks.fire, + subscribe: callbacks.add, + unsubscribe: callbacks.remove + }; + if ( id ) { + topics[ id ] = topic; + } + } + return topic; + }; +})(); diff --git a/ui/js/src/wok.user.js b/ui/js/src/wok.user.js new file mode 100644 index 0000000..c036155 --- /dev/null +++ b/ui/js/src/wok.user.js @@ -0,0 +1,43 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2013-2014 + * + * 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. + */ +kimchi.user = (function() { + var getUserName = function() { + return kimchi.cookie.get('username'); + }; + + var setUserName = function(userName) { + kimchi.cookie.set('username', userName, 365); + }; + + var showUser = function(toShow) { + if (toShow) { + var userName = getUserName(); + userName && $('#user-name').text(userName); + $('#user').removeClass('not-logged-in'); + return; + } + + $('#user').addClass('not-logged-in'); + }; + + return { + getUserName: getUserName, + setUserName: setUserName, + showUser: showUser + }; +})(); diff --git a/ui/js/src/wok.window.js b/ui/js/src/wok.window.js new file mode 100644 index 0000000..3ac8699 --- /dev/null +++ b/ui/js/src/wok.window.js @@ -0,0 +1,70 @@ +/* + * Project Kimchi + * + * Copyright IBM, Corp. 2013-2014 + * + * 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. + */ +kimchi.window = (function() { + var _windows = []; + var _listeners = {}; + var open = function(settings) { + var settings = jQuery.type(settings) === 'object' ? settings : { + url: settings + }; + + var windowID = settings['id'] || 'window-' + _windows.length; + + if ($('#' + windowID).length) { + $('#' + windowID).remove(); + } + + _windows.push(windowID); + _listeners[windowID] = settings['close']; + var windowNode = $('<div></div>', { + id: windowID, + 'class': settings['class'] ? settings['class'] + ' bgmask remove-when-logged-off' : 'bgmask remove-when-logged-off' + }); + + $(windowNode).css(settings['style'] || ''); + + $(windowNode).appendTo('body').on('click', '.window .close', function() { + kimchi.window.close(); + }); + + if (settings['url']) { + $(windowNode).load(settings['url']).fadeIn(100); + return; + } + + settings['content'] && $(windowNode).html(settings['content']); + }; + + var close = function() { + var windowID = _windows.pop(); + if(_listeners[windowID]) { + _listeners[windowID](); + _listeners[windowID] = null; + } + delete _listeners[windowID]; + + $('#' + windowID).fadeOut(100, function() { + $(this).remove(); + }); + }; + + return { + open: open, + close: close + }; +})(); diff --git a/ui/pages/kimchi-ui.html.tmpl b/ui/pages/kimchi-ui.html.tmpl deleted file mode 100644 index 8da8acc..0000000 --- a/ui/pages/kimchi-ui.html.tmpl +++ /dev/null @@ -1,141 +0,0 @@ -#* - * Project Kimchi - * - * Copyright IBM, Corp. 2013-2015 - * - * 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. - *# -#unicode UTF-8 -#import gettext -#from kimchi.cachebust import href -#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) -#silent _ = t.gettext -#silent _t = t.gettext -#from kimchi.config import get_version -<!DOCTYPE html> -<html lang="$lang.lang[0]"> -<head> -<meta charset="UTF-8"> -<title>Kimchi</title> -<meta http-equiv="X-UA-Compatible" content="IE=edge"/> -<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> -<link rel="shortcut icon" href="images/logo.ico"> -<link rel="stylesheet" href="$href('libs/themes/base/jquery-ui.min.css')"> -<link rel="stylesheet" href="$href('css/theme-default.min.css')"> - -<script src="$href('libs/jquery-1.10.0.min.js')"></script> -<script src="$href('libs/jquery-ui.min.js')"></script> -<script src="$href('libs/jquery-ui-i18n.min.js')"></script> -<script src="$href('js/kimchi.min.js')"></script> - -<!-- This is used for detecting if the UI needs to be built --> -<style type="text/css"> -#buildme { - position: fixed; - background: rgba(0, 0, 0, 0.5); - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: 10000; -} - -#buildme div { - background-color: #FFB2C0; - border-style: solid; - border-color: #FF0000; - padding: 30px; - width: 75%; - margin-left: auto; - margin-right: auto; - margin-top: 50px; - -moz-border-radius: 15px; - border-radius: 15px; -} -</style> -</head> -<body onload="kimchi.main()"> -<div class="container"> -<header class="topbar"> - <h1 id="logo"><img alt="Project Kimchi" src="images/theme-default/logo-white.png"></h1> - <ul class="nav-top"> - <li> - <div id="peers" class="peers hide-content popable"> - <span>$_("Peers")</span> - <span class="arrow"></span> - <div class="dropdown popover right-side"> - <p id="search-peers">$_("Searching")...</p> - <p id="no-peers" class="hide-content">$_("No peers found.")</p> - </div> - </div> - </li> - <li> - <div id="user" class="popable"> - <span id="user-icon"></span> - <span id="user-name" class="empty-when-logged-off"></span> - <span class="arrow"></span> - <div class="action-panel popover right-side"> - <a id="btn-help" class="user-menu-item" href="javascript:void(0);">$_("Help")</a> - <br/> - <br/> - <a id="btn-about" class="user-menu-item" href="javascript:void(0);">$_("About")</a> - <br/> - <hr/> - <a id="btn-logout" class="user-menu-item" href="javascript: void(0);">$_("Log out")</a> - </div> - </div> - </li> - </ul> -</header> -<div class="content"> - <nav class="navbar"> - <ul id="nav-menu" class="nav-menu"> - <li class="menu-arrow"></li> - </ul> - </nav> - <div id="main"> - </div> -</div> -</div> - -<div id="buildme"> - <div><p>Oops! It looks like I am running from a source tree and you forgot to build! - Please run the following command from the kimchi directory and reload this page:</p> - <p><code>make</code></p> - </div> -</div> - -<script id="about-tmpl" type="kimchi/template"> - <div class="window about-window"> - <header> - <h1 class="title"><img alt="Kimchi logo" src="images/logo.ico"/> $_("About")</h1> - <div class="close">X</div> - </header> - <div class="content" align="center"> - <center> - <div> - <br/> - <br/> - <img src="images/theme-default/logo-plain.gif"/> - <br/> - <br/> - <h2>Kimchi</h2> - <p>$_("Version:") $get_version()</p> - </div> - </center> - </div> - </div> -</script> - -</body> -</html> diff --git a/ui/pages/wok-ui.html.tmpl b/ui/pages/wok-ui.html.tmpl new file mode 100644 index 0000000..8da8acc --- /dev/null +++ b/ui/pages/wok-ui.html.tmpl @@ -0,0 +1,141 @@ +#* + * Project Kimchi + * + * Copyright IBM, Corp. 2013-2015 + * + * 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. + *# +#unicode UTF-8 +#import gettext +#from kimchi.cachebust import href +#silent t = gettext.translation($lang.domain, $lang.localedir, languages=$lang.lang, fallback=True) +#silent _ = t.gettext +#silent _t = t.gettext +#from kimchi.config import get_version +<!DOCTYPE html> +<html lang="$lang.lang[0]"> +<head> +<meta charset="UTF-8"> +<title>Kimchi</title> +<meta http-equiv="X-UA-Compatible" content="IE=edge"/> +<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" /> +<link rel="shortcut icon" href="images/logo.ico"> +<link rel="stylesheet" href="$href('libs/themes/base/jquery-ui.min.css')"> +<link rel="stylesheet" href="$href('css/theme-default.min.css')"> + +<script src="$href('libs/jquery-1.10.0.min.js')"></script> +<script src="$href('libs/jquery-ui.min.js')"></script> +<script src="$href('libs/jquery-ui-i18n.min.js')"></script> +<script src="$href('js/kimchi.min.js')"></script> + +<!-- This is used for detecting if the UI needs to be built --> +<style type="text/css"> +#buildme { + position: fixed; + background: rgba(0, 0, 0, 0.5); + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 10000; +} + +#buildme div { + background-color: #FFB2C0; + border-style: solid; + border-color: #FF0000; + padding: 30px; + width: 75%; + margin-left: auto; + margin-right: auto; + margin-top: 50px; + -moz-border-radius: 15px; + border-radius: 15px; +} +</style> +</head> +<body onload="kimchi.main()"> +<div class="container"> +<header class="topbar"> + <h1 id="logo"><img alt="Project Kimchi" src="images/theme-default/logo-white.png"></h1> + <ul class="nav-top"> + <li> + <div id="peers" class="peers hide-content popable"> + <span>$_("Peers")</span> + <span class="arrow"></span> + <div class="dropdown popover right-side"> + <p id="search-peers">$_("Searching")...</p> + <p id="no-peers" class="hide-content">$_("No peers found.")</p> + </div> + </div> + </li> + <li> + <div id="user" class="popable"> + <span id="user-icon"></span> + <span id="user-name" class="empty-when-logged-off"></span> + <span class="arrow"></span> + <div class="action-panel popover right-side"> + <a id="btn-help" class="user-menu-item" href="javascript:void(0);">$_("Help")</a> + <br/> + <br/> + <a id="btn-about" class="user-menu-item" href="javascript:void(0);">$_("About")</a> + <br/> + <hr/> + <a id="btn-logout" class="user-menu-item" href="javascript: void(0);">$_("Log out")</a> + </div> + </div> + </li> + </ul> +</header> +<div class="content"> + <nav class="navbar"> + <ul id="nav-menu" class="nav-menu"> + <li class="menu-arrow"></li> + </ul> + </nav> + <div id="main"> + </div> +</div> +</div> + +<div id="buildme"> + <div><p>Oops! It looks like I am running from a source tree and you forgot to build! + Please run the following command from the kimchi directory and reload this page:</p> + <p><code>make</code></p> + </div> +</div> + +<script id="about-tmpl" type="kimchi/template"> + <div class="window about-window"> + <header> + <h1 class="title"><img alt="Kimchi logo" src="images/logo.ico"/> $_("About")</h1> + <div class="close">X</div> + </header> + <div class="content" align="center"> + <center> + <div> + <br/> + <br/> + <img src="images/theme-default/logo-plain.gif"/> + <br/> + <br/> + <h2>Kimchi</h2> + <p>$_("Version:") $get_version()</p> + </div> + </center> + </div> + </div> +</script> + +</body> +</html> -- 1.7.1