diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..039edd9 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,32 @@ +root = true + +[*] +end_of_line = lf +trim_trailing_whitespace = true +insert_final_newline = true + +[*.{js,py}] +charset = utf-8 + +[*.py] +indent_style = tab +tag_width = 4 +; max_line_length = 79 + +[*.html] +indent_style = space +indent_size = 2 + +[*.js] +indent_style = space +indent_size = 2 + +[*.css] +indent_style = space +indent_size = 2 + +[{.travis.yml}] +indent_style = space +indent_size = 2 + + diff --git a/README.rst b/README.rst index 06c756c..9af0ac5 100644 --- a/README.rst +++ b/README.rst @@ -2,19 +2,20 @@ :target: http://coalition.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status -.. |badge-size| image:: https://reposs.herokuapp.com/?path=https://github.com/MercenariesEngineering/coalition +.. |badge-tests| image:: https://travis-ci.org/MercenariesEngineering/coalition.svg?branch=master .. |badge-version| image:: https://badge.fury.io/gh/MercenariesEngineering%2Fcoalition.svg :target: https://badge.fury.io/gh/MercenariesEngineering%2Fcoalition +.. |badge-size| image:: https://reposs.herokuapp.com/?path=https://github.com/MercenariesEngineering/coalition + .. |badge-coverage| image:: https://coveralls.io/repos/github/MercenariesEngineering/coalition/badge.svg?branch=development :target: https://coveralls.io/github/MercenariesEngineering/coalition?branch=development -.. |badge-tests| image:: https://travis-ci.org/MercenariesEngineering/coalition.svg?branch=master |badge-doc| |badge-size| |badge-version| |badge-coverage| |badge-tests| -`Full online documentation is availlble on ReadTheDocs `_. +`Full online documentation is available on ReadTheDocs `_. Coalition ========= @@ -40,9 +41,6 @@ The server waits for incoming workers connections. Workers ask the server for a - **Unittests** of critical code parts; - **Source code** and **documentation** on `the development platform `_. -The current stable version are 3.8 and 3.10. - -The development version is |current-version|. - -.. |current-version| include:: version +The stable versions are 3.8 and 3.10. The current version is referenced in the file *version*, that is: +.. literalinclude:: ../../version diff --git a/db_sql.py b/db_sql.py index a9167b4..7d4ff97 100644 --- a/db_sql.py +++ b/db_sql.py @@ -113,9 +113,9 @@ def _getLdapPermission(self, action): if not hasattr(self, "ldap_user") or not self.ldap_user: # LDAP is not set up in configuration or ldapunsafeapi is set to True return "" if action == "addjob": - if self.permissions["ldaptemplateaddjobglobal"]: + if self.permissions["ldaptemplatecreatejobglobal"]: return "" - elif self.permissions["ldaptemplateaddjob"]: + elif self.permissions["ldaptemplatecreatejob"]: return "AND user='{user}'".format(user=self.ldap_user) else: raise LdapError("Action '{action}' is not permitted for user '{user}'".format(action=action, user=self.ldap_user)) @@ -207,7 +207,7 @@ def getAffinityMask (self, affinities): aff = self.listAffinities () mask = 0L cur = self.Conn.cursor () - for affinity in affinities.split (","): + for affinity in [a.strip() for a in affinities.split (",")]: if affinity != "": m = re.match(r"^#(\d+)$", affinity) if m: @@ -236,7 +236,7 @@ def getAffinityString (self, affinity_bits): self.AffinityBitsToName[affinity_bits] = result return result - def newJob(self, parent, title, command, dir, environment, state, paused, timeout, + def newJob(self, parent, title, command, dir, environment, state, paused, timeout, priority, affinity, user, url, progress_pattern, dependencies = None): ldap_perm = self._getLdapPermission("addjob") if ldap_perm is False: @@ -244,7 +244,7 @@ def newJob(self, parent, title, command, dir, environment, state, paused, timeou if ldap_perm != "": # User can add job owned by himself, force user value user = self.ldap_user cur = self.Conn.cursor() - self._execute(cur, + self._execute(cur, "SELECT h_depth, h_affinity, h_priority, h_paused, command " "FROM Jobs " "WHERE id = {parent} {ldap_perm}".format(parent=parent, ldap_perm=ldap_perm)) @@ -354,16 +354,22 @@ def getJobDependencies(self, id): rows = cur.fetchall() return [self._rowAsDict (cur, row) for row in rows] - def getCountJobsWhere(self, where_clause=''): + def getCountJobsWhere(self, where_clause='', inner_join_table=''): """Get the number of matching jobs.""" cur = self.Conn.cursor() - self._execute(cur, "SELECT COUNT(*) FROM Jobs WHERE {}".format(where_clause[0])) + if not inner_join_table: + self._execute(cur, "SELECT COUNT(DISTINCT Jobs.id) FROM Jobs WHERE {}".format(where_clause)) + else: + self._execute(cur, "SELECT COUNT(DISTINCT Jobs.id) FROM Jobs, {} WHERE {}".format(inner_join_table, where_clause)) return cur.fetchone()[0] - def getJobsWhere(self, where_clause='', index_min=0, index_max=1): + def getJobsWhere(self, where_clause='', inner_join_table='', index_min=0, index_max=1): """Get Jobs via a readonly SQL request.""" cur = self.Conn.cursor() - self._execute(cur, "SELECT * FROM Jobs WHERE {} LIMIT {},{}".format(where_clause, index_min, index_max)) + if not inner_join_table: + self._execute(cur, "SELECT DISTINCT Jobs.* FROM Jobs WHERE {} LIMIT {},{}".format(where_clause, index_min, index_max)) + else: + self._execute(cur, "SELECT DISTINCT Jobs.* FROM Jobs, {} WHERE {} LIMIT {},{}".format(inner_join_table, where_clause, index_min, index_max)) return [self._rowAsDict (cur, row) for row in cur.fetchall()] def getJobsUsers(self): @@ -396,12 +402,6 @@ def getJobsAffinities(self): self._execute(cur, "SELECT DISTINCT affinity FROM Jobs") return [self._rowAsDict (cur, row) for row in cur.fetchall()] - def getChildrenDependencyIds (self, id): - cur = self.Conn.cursor () - self._execute (cur, "SELECT job.id AS id, dep.dependency AS dependency FROM Dependencies AS dep " - "INNER JOIN Jobs AS job ON job.id = dep.job_id " - " WHERE job.parent = %d" % id) - def getChildrenDependencyIds(self, id): cur = self.Conn.cursor() self._execute(cur, """ @@ -426,20 +426,18 @@ def getWorker (self, hostname): worker['total_memory'] = info['total_memory'] except: pass - + self._execute (cur, "SELECT affinity FROM WorkerAffinities WHERE worker_name = '%s'" % ( hostname ) ) affinities = [] - - data = cur.fetchone() - - if data is None: - worker['affinity'] = "" - return worker for data in cur: + if data is None: + worker['affinity'] = "" + return worker affinities.append( self.getAffinityString( data[0] ) ) worker['affinity'] = "\n".join( affinities ) + worker['start_time'] = self.getWorkerStartTime(worker['name']) return worker def getWorkerStartTime(self, name): @@ -481,6 +479,19 @@ def getWorkers (self): workers.append (worker) return workers + def getWorkersWhere(self, where_clause='', inner_join_table='', index_min=0, index_max=1): + """Get WOrkers via readonly SQL requests.""" + workers = list() + cur = self.Conn.cursor() + if not inner_join_table: + self._execute(cur, "SELECT DISTINCT Workers.name FROM Workers WHERE {} LIMIT {},{}".format(where_clause, index_min, index_max)) + else: + self._execute(cur, "SELECT DISTINCT Workers.name FROM Workers, {} WHERE {} LIMIT {},{}".format(inner_join_table, where_clause, index_min, index_max)) + + for name in cur.fetchall(): + workers.append(self.getWorker(name)) + return workers + def getEvents (self, job, worker, howlong): cur = self.Conn.cursor() req = "SELECT * FROM Events WHERE start > %d" % (int(time.time())-howlong) diff --git a/doc/source/installation.rst b/doc/source/installation.rst index dd7e7ae..b6193bb 100644 --- a/doc/source/installation.rst +++ b/doc/source/installation.rst @@ -45,6 +45,7 @@ Using a `python virtual environment `_ is Logged as a priviledged user, in a shell prompt, run:: + apt-get install libsasl2-dev libldap2-dev libmysqlclient-dev cd /usr/local/bin git clone https://github.com/MercenariesEngineering/coalition.git cd coalition diff --git a/doc/source/python_api.rst b/doc/source/python_api.rst index 28e1847..f09f90e 100644 --- a/doc/source/python_api.rst +++ b/doc/source/python_api.rst @@ -1,6 +1,6 @@ Python API ========== -.. automodule:: coalition +.. automodule:: api.coalition :members: :show-inheritance: diff --git a/public_html/css/coalition.css b/public_html/css/coalition.css index ed4b54e..1619f70 100644 --- a/public_html/css/coalition.css +++ b/public_html/css/coalition.css @@ -1,3 +1,8 @@ +/*** + * Main coalition stylesheet + **/ + +/*** page style ***/ html, body { font-size: 90%; height: 100%; @@ -5,315 +10,385 @@ html, body { margin: 0; padding: 0; box-sizing: border-box; + overflow: hidden; } *, *:before, *:after { box-sizing: inherit; } -body { - text-decoration: none; +body { + text-decoration: none; color: ghostwhite; font-family: Arial, Helvetica, sans-serif; - font-weight: normal; + font-weight: normal; background-color: #b0b0b0; } -input, select, textarea { - width: 100%; - border: 0; - font-size: 0.7rem; - background-color: #555; - color: ghostwhite; +#content { + width: inherit; + overflow: hidden; } -.button select { - width: auto; +#main { + height: 0; + width: 100%; + background-color: #444444; } -#parents { - left: 1rem; - background-color: #b0b0b0; - padding: 0 1rem; - justify-content: flex-start; - color: #444; - font-size: 0.9rem; - border-top:1px solid #000000; - border-left:1px solid #000000; - border-right:1px solid #888888; - border-bottom:1px solid #888888; +/*** tables ***/ +table { + display: flex; + flex-direction: column; + border-collapse: collapse; + text-align: left; } -#parents a:link { - color: #222222; - text-decoration: none; - font-weight: bold; - margin: 0 0.5rem; +tr { + display: flex; + flex-direction: row; + line-height: 1.6rem; } -#jobs, #workers, #activities, #logs, #affinities -{ - flex-grow: 1; - height: 1rem; - /*border-top:1px solid #888888;*/ - /*border-left:1px solid #888888;*/ - /*border-right:1px solid #000000;*/ - /*border-bottom:1px solid #000000;*/ -} - -#workers, #logs, #activities -{ - /*top: 95px;*/ - /*bottom: 58px;*/ -} - -#affinities -{ - /*position: fixed;*/ - /*left: 10px;*/ - /*right: 10px;*/ - /*top: 65px;*/ - /*bottom: 58px;*/ - /*overflow: auto;*/ - /*border-top:1px solid #888888;*/ - /*border-left:1px solid #888888;*/ - /*border-right:1px solid #000000;*/ - /*border-bottom:1px solid #000000;*/ -} - -#logs { - color: white; +thead, tfoot { + position: sticky; + top: 0; + text-align: center; + background-color: #666666; + margin-right: 1rem; + z-index: 1; } -#jobsTable, -#workersTable, -#activitiesTable, -#affinitiesTable -{ - width:100%; - border-collapse: collapse; - text-align: left; +thead label { + cursor: pointer; } -#config-jobs-table { - display: flex; +thead>tr { + min-height: inherit; } -#jobsTable td a:link, #workersTable td a:link, #activitiesTable td a:link { - color: #DDDDDD; +tr>th { + display: flex; + flex-direction: column; + min-height: inherit; + padding: 0; } -#jobsTable thead { - min-height: 5rem; +tr>th .flex-row { + flex-wrap: nowrap; } -#jobsTable thead label { - cursor: pointer; +tbody { + height: 100%; + overflow-y: scroll; + word-break: keep-all; } -#jobsTable thead .headerCell .flex-row { - justify-content: center; +tbody tr { + justify-content: flex-start; } -table { - height: 100%; +th, td { + border-right: 1px dotted #444; + padding: 0; + overflow: hidden; + white-space: nowrap; +} + +td a { + color: #DDDDDD; +} + +.resizable { + width: 5px; + flex-shrink: 0; + cursor: col-resize; + z-index: 1; +} + +.resizable:hover { + background: gray; +} + +.flex-column { display: flex; flex-direction: column; + justify-content: flex-end; } -th, tr { +.flex-row { display: flex; flex-direction: row; + flex-wrap: wrap; } -th { - border-right: 1px dotted gray; +.flex-grow { + flex-grow: 1; +} + +.flex-wrap { + flex-wrap: wrap; +} + +.flex-nowrap { + flex-wrap: nowrap; +} + +.entry, .entry0, .entry1, .title, .entry0Selected, .entry1Selected { + font-size: 0.9rem; + color: #DDDDDD; +} + +.title a:link { + color: #EEEEEE; + text-decoration: none; +} + +.entry0 { background-color: #222222; +} + +.entry1 { + background-color: #303030; +} + +.entry0Selected { + background-color: #444466; } -thead { +.entry1Selected { + background-color: #555577; +} + +.FINISHED, .PAUSED, .ERROR, .TIMEOUT, .WAITING, .WORKING, .PENDING, .STARTING, .TERMINATED, .ACTIVEtrue, .ACTIVEfalse, .ACTIVE1, .ACTIVE0 { text-align: center; - overflow-y: scroll; + color: White; } -tfoot { - overflow-y: scroll; - min-height: 1.5rem; +.FINISHED, .TERMINATED { + background-color: #009000; } -tbody { - height: 100%; - overflow-y: scroll; - word-break: keep-all; +.PAUSED { + background-color: #000090; } -tbody tr { - justify-content: flex-start; +.PENDING, .STARTING { + background-color: #303060; } -tbody td { - border-right: 1px dotted #444; - height: 1.2rem; - overflow: hidden; - white-space: nowrap; +.ERROR, .TIMEOUT { + background-color: #900000; +} + +.WORKING { + background-color: #009090; +} + +.ACTIVEtrue, .active1 { + background-color: #009000; +} + +.ACTIVEfalse, .active0 { + background-color: #900000; +} + +#dragged { +} + +tr>th .flex-row.draggable { + flex-grow: 1; + overflow: hidden; +} + +img, +.dropzone { + -webkit-user-drag: none; +} + +.side-right, +.side-left { + width: 50%; +} + +div[draggable]:hover { + background: darkslategray; +} + +table .dropzone.side-left { + align-items: center; +} + +table .dropzone.side-right { + justify-content: flex-end; } +.dropzone-hover { + background: orange; +} + +.not-displayed { + display: none; +} +/*** jobs table proportions ***/ /* id */ #jobsTable th:nth-child(1), #jobsTable td:nth-child(1) { - width: 2%; + width: 10rem; } /* title */ #jobsTable th:nth-child(2), #jobsTable td:nth-child(2) { - width: 10%; + width: 20rem; } /* url */ #jobsTable th:nth-child(3), #jobsTable td:nth-child(3) { - width: 4%; + width: 5rem; } /* user */ #jobsTable th:nth-child(4), #jobsTable td:nth-child(4) { - width: 5%; + width: 12rem; } /* state */ - #jobsTable th:nth-child(5), #jobsTable td:nth-child(5) { - width: 6%; + width: 8rem; } /* priority */ #jobsTable th:nth-child(6), #jobsTable td:nth-child(6) { - width: 4%; + width: 5rem; } /* ok */ #jobsTable th:nth-child(7), #jobsTable td:nth-child(7) { - width: 2%; + width: 4rem; } /* wkr */ #jobsTable th:nth-child(8), #jobsTable td:nth-child(8) { - width: 2%; + width: 4rem; } /* err */ #jobsTable th:nth-child(9), #jobsTable td:nth-child(9) { - width: 3%; + width: 4rem; } /* total */ #jobsTable th:nth-child(10), #jobsTable td:nth-child(10) { - width: 3%; + width: 4rem; } /* progress */ #jobsTable th:nth-child(11), #jobsTable td:nth-child(11) { - width: 5%; + width: 12rem; } /* affinity */ #jobsTable th:nth-child(12), #jobsTable td:nth-child(12) { - width: 6%; + width: 12rem; } /* timeout */ #jobsTable th:nth-child(13), #jobsTable td:nth-child(13) { - width: 4%; + width: 3rem; } /* worker */ #jobsTable th:nth-child(14), #jobsTable td:nth-child(14) { - width: 7%; + width: 12rem; } /* start_time */ #jobsTable th:nth-child(15), #jobsTable td:nth-child(15) { - width: 6%; + width: 5rem; } /* duration */ #jobsTable th:nth-child(16), #jobsTable td:nth-child(16) { - width: 5%; + width: 12rem; } /* run */ #jobsTable th:nth-child(17), #jobsTable td:nth-child(17) { - width: 2%; + width: 4rem; } /* command */ #jobsTable th:nth-child(18), #jobsTable td:nth-child(18) { - width: 13%; + width: 30rem; } /* dir */ #jobsTable th:nth-child(19), #jobsTable td:nth-child(19) { - width: 3%; + width: 12rem; } /* dependencies */ #jobsTable th:nth-child(20), #jobsTable td:nth-child(20) { - width: 8%; + width: 12rem; } +/*** workers table proportions ***/ /* name */ #workersTable th:nth-child(1), #workersTable td:nth-child(1) { - width: 20%; + width: 20rem; } /* active */ #workersTable th:nth-child(2), #workersTable td:nth-child(2) { - width: 4%; + width: 4rem; + text-align: center; } /* state */ #workersTable th:nth-child(3), #workersTable td:nth-child(3) { - width: 8%; + width: 8rem; } /* affinity */ #workersTable th:nth-child(4), #workersTable td:nth-child(4) { - width: 10%; + width: 10rem; } /* ping_time */ #workersTable th:nth-child(5), #workersTable td:nth-child(5) { - width: 10%; + width: 10rem; } /* cpu */ #workersTable th:nth-child(6), #workersTable td:nth-child(6) { - width: 11%; + width: 11rem; } /* memory */ #workersTable th:nth-child(7), #workersTable td:nth-child(7) { - width: 11%; + width: 11rem; } /* last_jobs */ #workersTable th:nth-child(8), #workersTable td:nth-child(8) { - width: 5%; + width: 5rem; } /* finished */ #workersTable th:nth-child(9), #workersTable td:nth-child(9) { - width: 5%; + width: 5rem; } /* error */ #workersTable th:nth-child(10), #workersTable td:nth-child(10) { - width: 5%; + width: 5rem; } /* ip */ #workersTable th:nth-child(11), #workersTable td:nth-child(11) { - width: 11%; + width: 11rem; } +/*** activities table proportions ***/ /* start */ #activitiesTable th:nth-child(1), #activitiesTable td:nth-child(1) { width: 12%; @@ -344,6 +419,7 @@ tbody td { width: 12%; } +/*** affinities table proportions ***/ /* id */ #affinitiesTable th:nth-child(1), #affinitiesTable td:nth-child(1) { width: 5%; @@ -354,164 +430,115 @@ tbody td { width: 25%; } -#affinitiesTable -{ - border-collapse: collapse; - text-align: right; +/*** title **/ +#header { + justify-content: space-between; } -#affinitiesTable td -{ - /*font-size: 8pt; */ - font-size: 0.9rem; - text-align: center; - color: #FFFFFF; +#header>.flex-row:first-child { + justify-content: space-between; } -.entry, .entry0, .entry1, .title, .entry0Selected, .entry1Selected -{ - /*font-size: 8pt; */ - font-size: 0.9rem; - color: #DDDDDD; +#header > div:nth-child(1) > div.flex-column.flex-grow { + justify-content: flex-start; } -.title -{ - background-color: #666666; - color: #EEEEEE; - text-transform: capitalize; -} - -.title a:link -{ - color: #EEEEEE; - text-decoration: none; +#header > div:nth-child(1) > div.flex-column.flex-grow > div { + justify-content: space-between; } -.entry0 -{ - background-color: #222222; -} - -.entry1 -{ - background-color: #303030; +#maintitle { + justify-content: flex-start; + text-transform: lowercase; } -.entry0Selected -{ - background-color: #444466; +#maintitle a { + color: #444444; + font-size: 2rem; + font-weight: bolder; + text-decoration: none; } -.entry1Selected -{ - background-color: #555577; +#subtitle { + color: #444444; + font-size: small; + font-style: italic; } -.FINISHED, .PAUSED, .ERROR, .TIMEOUT, .WAITING, .WORKING, .PENDING, .STARTING, .TERMINATED, .ACTIVEtrue, .ACTIVEfalse, .ACTIVE1, .ACTIVE0 -{ - text-align: center; - color: White; +#subtitle a { + color: #444444; + font-weight: bold; + text-decoration: none; } -.FINISHED, .TERMINATED -{ - background-color: #009000; +#subtitle p { + margin: 0.1rem; } -.PAUSED -{ - background-color: #000090; +#header > div:nth-child(1) > div:nth-child(2) { + flex-grow: 1; } -.PENDING, .STARTING -{ - background-color: #303060; +#header > div:nth-child(1) > div:nth-child(2) > div { + justify-content: flex-end; } -.ERROR, .TIMEOUT -{ - background-color: #900000; +/*** menu ***/ +#menu-button { + padding: 0.5rem; + font-size: 2rem; + color: black; } -.WORKING -{ - background-color: #009090; +#menu-button:hover { + cursor: pointer; + color: lightgray; } -.ACTIVEtrue, .ACTIVE1 -{ - background-color: #009000; +#menu-content { + text-align: right; } -.ACTIVEfalse, .ACTIVE0 -{ - background-color: #900000; +#menu-content label { + display: flex; + justify-content: flex-end; } -.logs -{ - font-size: 0.9rem; - /*font-size: 8pt; */ +#menu { + display: flex; + flex-direction: column; + justify-content: flex-start; + background: #666666; + border-left: 1px solid #999; } -#main -{ - width: 100%; - /*overflow: auto;*/ - /*position: fixed;*/ - /*bottom: 5px;*/ - /*top: 60px;*/ - /*left: 5px;*/ - /*right: 5px;*/ - background-color: #444444; +#menu input { + width: auto; } -#header > div { - margin: 0 1rem; +/*** tools bar ***/ +.button select { + width: auto; } -#maintitle -{ - /*display: inline;*/ - /*font-family: Verdana;*/ - text-transform: lowercase; - /*margin-left: 5px;*/ +/*** node parent row ***/ +#parents { + background-color: #b0b0b0; + justify-content: flex-start; + color: #444; + flex-shrink: 0; } -#maintitle a -{ - color: #444444; - font-size: 2rem; - font-weight: bolder; +#parents a:link { + color: #222222; text-decoration: none; -} - -#subtitle { - color: #444444; - font-size: small; - font-style: italic; -} - -#subtitle a { - color: #444444; font-weight: bold; - text-decoration: none; -} - -#subtitle p { - margin: 0.1rem; + margin: 0 0.5rem; } -#tabs -{ +/*** tabs ***/ +#tabs { justify-content: flex-end; - /*position: fixed;*/ - /*top: 35;*/ - /*height: 21;*/ - /*display: table-row;*/ - /*z-index: 1000;*/ - /*border-spacing: 5;*/ } #tabs > .flex-row { @@ -546,305 +573,305 @@ tbody td { color: white; } - -#tabs button.activetab -{ - /*display: table-cell;*/ - /*padding-left : 10;*/ - /*padding-right : 10;*/ - /*padding: 0.5rem 1rem;*/ +#tabs button.activetab { background-color: #444; - /*color: White;*/ - /*height:21;*/ - /*vertical-align: middle;*/ - /*border-top-style: 1px solid black;*/ - /*border-top-style: solid;*/ - /*border-top-color: Black;*/ - /*border-top-width: 1;*/ - /*border-left-style: solid;*/ - /*border-left-color: Black;*/ - /*border-left-width: 1;*/ - /*border-right-style: solid;*/ - /*border-right-color: Black;*/ - /*border-right-width: 1;*/ - /*cursor: pointer;*/ -} - -#tags button.unactivetab -{ - background-color: #333333; - border-top: 1px solid black; - border-right: 1px solid black; - border-left: 1px solid black; -} - -#refreshtools label -{ - color: #444; } -.refreshbutton, .refreshing -{ - /*display: inline;*/ - /*background-color: #DDDDDD;*/ - /*cursor: pointer;*/ - /*border: 1px solid black;*/ - /*padding: 0.4rem 1rem;*/ - /*margin: 0.2rem;*/ - /*position: fixed;*/ - /*width: 100;*/ - /*right: 5px;*/ - /*text-align: center;*/ - /*font-weight: bold;*/ - /*height: 50;*/ -} - -.refreshing -{ - background-color: #00F000; -} - -#jobtools .button, -#jobtools .button label, -#jobtools .button select, -#workertools .button, -#logtools .button, -#activitiestools .button, -#affinitiestools .button -{ - cursor: pointer; +#jobs, +#workers, +#activities, +#logs, +#affinities { + display: flex; + flex-grow: 1; + overflow-x: scroll; +} + +/*** table configurator ***/ +#config-jobs-table { + display: flex; + flex-direction: column; + position: absolute; + right: 0; + top: 0; + background: white; + color: black; + opacity: 0.8; +} + +/*** jobs table ***/ +#jobsTable thead { + /*overflow-y: scroll;*/ + margin-right: 0; } +#jobsTable thead>tr>th>.flex-column { + justify-content: flex-start; + flex-grow: 1; +} + +#jobsTable thead>tr>th>.flex-column>.flex-row { + justify-content: flex-start; +} + +/*** workers table ***/ +#workersTable { + flex-grow: 1; +} + +/*** activities table ***/ +#activitiesTable { + flex-grow: 1; +} + +/*** affinities ***/ +#affinitiesTable { + border-collapse: collapse; + text-align: right; + flex-grow: 1; +} + +#affinitiesTable td { + font-size: 0.9rem; + text-align: center; + color: #FFFFFF; +} + +/*** tools ***/ #jobtools, #workertools, #logtools, #activitiestools, -#affinitiestools -{ - color: #dddddd; +#affinitiestools, +#workertoolstable, +#affinitytoolstable { + justify-content: flex-end; + flex-shrink: 0; +} + +#logout-button { + position: relative; + left: -100%; +} + +#logout-button input { + color: white; +} + +/*** tools table ***/ +#jobtoolstable .flex-column { + flex-grow: 1; justify-content: flex-end; } -.button -{ +#jobtoolstable .flex-column:last-of-type { + flex-grow: 0; +} + +#jobtoolstable>div:first-child { + justify-content: flex-end; +} + +#jobtoolstable input { + width: 75%; +} + +.width-50pc { + width: 50%; +} + +/*** elements ***/ +.button { color: ghostwhite; - padding: 0.1rem 1rem; - margin: 0.2rem 0.3rem; + margin: 0.1rem 0.2rem; + max-height: 1.7rem; background-color: #444; cursor: pointer; - border-radius: 0.4rem; + white-space: nowrap; border-top: 1px solid #777777; border-right: 1px solid #222222; border-bottom: 1px solid #222222; border-left: 1px solid #777777; - box-shadow: 1px 1px 1px #333; + box-shadow: 1px 1px 1px #333; + height: 1.9rem; + margin: 4px 6px; } .button img { + max-height: 1rem; margin: 0 0.3rem; + vertical-align: middle; } -button:hover -{ +button:hover { background-color: #666; color: white; } -.buttonSep -{ - /*display: inline;*/ - /*width: 10px;*/ -} - -/* Selection button */ -#b01 { - padding: 0.1rem 0.2rem 0.2rem 1rem; -} - -#toolstable input, -#workertoolstable textarea, +input, +select, +textarea, +input, tbody input { + cursor: pointer; + width: 100%; + border: 0; color: white; background-color: #222; + line-height: 1.6rem; } -#toolstable input:hover, -#workertoolstable textarea:hover, +input:hover, +select:hover, +textarea:hover, tbody input:hover { background-color: #333; } -#toolstable .flex-column { - align-items: flex-end; - flex-grow: 1; +.flex-row label { + flex-wrap: nowrap; + margin: 0.1rem 0.1rem; + justify-content: flex-end; + text-transform: capitalize; } -#toolstable label { - flex-wrap: nowrap; - width: 100%; +legend { + font-style: oblique; + margin: 0 0.2rem; } -#toolstable label span { +label span { margin: 0 0.5rem; } -#workertoolstable, #affinitytoolstable { - justify-content: flex-end; +.value-modified { + background-color: greenyellow; + color: darkmagenta } -.ttr1 -{ +.value-modified:hover{ + background-color: yellow; +} + +.value-different { + background-color: orange; + color: darkmagenta +} + +.value-different:hover { + background-color: yellow; +} + +input[type="range"] { + margin: 0; +} + +.ttr1 { width: 10%; font-size: small; color: White; text-align: right; } -.ttr2 -{ + +.ttr2 { width: 60%; } -.ttr3 -{ + +.ttr3 { width: 10%; font-size: small; color: White; text-align: right; } -.ttr4 -{ -} -.ttedit -{ -} - -#toolbuttons -{ -} - -.toolbutton -{ -} -.headerCell .flex-column { - justify-content: flex-start; - flex-grow: 1; -} - -.loadbar -{ +.loadbar { background-color: #009000; } -.loadlabel -{ - /*width: 100%;*/ +.loadlabel { text-align: center; - /*position: absolute;*/ - /*top: 1;*/ -} - -.load -{ - /*width: 100%;*/ - /*position: relative;*/ } -.membar -{ +.membar { height: inherit; background-color: #009000; } -.memlabel -{ - height: inherit; +.memlabel { + height: inherit; text-align: center; position: relative; top: -100%; } -.mem -{ - height: inherit; +.mem { + height: 100%; } -.progress -{ +.progress { height: inherit; } -.lprogressbar -{ +.lprogressbar { height: inherit; background-color: #009000; } -.gprogressbar -{ +.gprogressbar { background-color: #007000; } -.progresslabel -{ - height: inherit; +.progresslabel { + height: inherit; text-align: center; position: relative; top: -100%; } -.worker_affinities -{ +.worker_affinities { white-space: pre; + line-height: 1.2rem; } -#pagination { - /*display:inline;*/ -} - -.flex-column { - display: flex; - flex-direction: column; - justify-content: space-around; -} - -.flex-row { - display: flex; - flex-direction: row; - justify-content: space-between; - flex-wrap: wrap; +.tab-content { + width: inherit; + height: 100%; } -.flex-grow { - flex-grow: 1; +.tab-content>.flex-column { + overflow: hidden; } -.flex-wrap { - flex-wrap: wrap; +.tab-content>.flex-column:last-child { + justify-content: flex-start; + border-left: 1px solid #999; } -.tab-content { - width: inherit; -} - -.job-sql-search-field { +.sql-search-field { display: flex; flex-direction: row; } -.job-sql-search-field input:hover, -.job-sql-search-field select:hover { - background-color: #333; +detail { + flex-shrink: 0; + /*overflow-x: scroll;*/ } -#activitiestools label { - margin: 0 1rem; +detail .flex-row { + justify-content: flex-end; } -#logout-button { - position: relative; - left: -100%; +#refreshbutton { + max-height: unset; + height: 2.5rem; + border: 1px solid lightgray; } -#logout-button input { - color: white; +#auto-refresh-button { + color: black; +} + +#auto-refresh-button input { + width: auto; + vertical-align: middle; } diff --git a/public_html/index.html b/public_html/index.html index e066e75..03a78fd 100644 --- a/public_html/index.html +++ b/public_html/index.html @@ -1,194 +1,205 @@ - + Coalition Server - - - - + + + + - - -