*: move to tailwind css

I really like it!

TODO: Extract more components
This commit is contained in:
Simone Gotti 2019-05-21 12:13:21 +02:00
parent e47c3b977c
commit 2891b62b6c
41 changed files with 1448 additions and 1553 deletions

View File

@ -1,4 +1,12 @@
{ {
"compilerOptions": {
"baseUrl": ".",
"paths": {
"*": [
"types/*"
]
}
},
"include": [ "include": [
"./src/**/*" "./src/**/*"
] ]

170
package-lock.json generated
View File

@ -3055,11 +3055,6 @@
"integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=", "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug=",
"dev": true "dev": true
}, },
"bulma": {
"version": "0.7.4",
"resolved": "https://registry.npmjs.org/bulma/-/bulma-0.7.4.tgz",
"integrity": "sha512-krG2rP6eAX1WE0sf6O0SC/FUVSOBX4m1PBC2+GKLpb2pX0qanaDqcv9U2nu75egFrsHkI0zdWYuk/oGwoszVWg=="
},
"bytes": { "bytes": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
@ -3187,6 +3182,12 @@
"integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==", "integrity": "sha512-faqwZqnWxbxn+F1d399ygeamQNy3lPp/H9H6rNrqYh4FSVCtcY+3cub1MxA8o9mDd55mM8Aghuu/kuyYA6VTsA==",
"dev": true "dev": true
}, },
"camelcase-css": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
"integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
"dev": true
},
"camelcase-keys": { "camelcase-keys": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz", "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-2.1.0.tgz",
@ -3421,8 +3422,7 @@
"version": "4.6.0", "version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=", "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
"dev": true, "dev": true
"optional": true
}, },
"coa": { "coa": {
"version": "2.0.2", "version": "2.0.2",
@ -5743,8 +5743,7 @@
"ansi-regex": { "ansi-regex": {
"version": "2.1.1", "version": "2.1.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"aproba": { "aproba": {
"version": "1.2.0", "version": "1.2.0",
@ -5765,14 +5764,12 @@
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"balanced-match": "^1.0.0", "balanced-match": "^1.0.0",
"concat-map": "0.0.1" "concat-map": "0.0.1"
@ -5787,20 +5784,17 @@
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"console-control-strings": { "console-control-strings": {
"version": "1.1.0", "version": "1.1.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"core-util-is": { "core-util-is": {
"version": "1.0.2", "version": "1.0.2",
@ -5917,8 +5911,7 @@
"inherits": { "inherits": {
"version": "2.0.3", "version": "2.0.3",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"ini": { "ini": {
"version": "1.3.5", "version": "1.3.5",
@ -5930,7 +5923,6 @@
"version": "1.0.0", "version": "1.0.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
@ -5945,7 +5937,6 @@
"version": "3.0.4", "version": "3.0.4",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
@ -6057,8 +6048,7 @@
"number-is-nan": { "number-is-nan": {
"version": "1.0.1", "version": "1.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true
"optional": true
}, },
"object-assign": { "object-assign": {
"version": "4.1.1", "version": "4.1.1",
@ -6070,7 +6060,6 @@
"version": "1.4.0", "version": "1.4.0",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"wrappy": "1" "wrappy": "1"
} }
@ -6192,7 +6181,6 @@
"version": "1.0.2", "version": "1.0.2",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"code-point-at": "^1.0.0", "code-point-at": "^1.0.0",
"is-fullwidth-code-point": "^1.0.0", "is-fullwidth-code-point": "^1.0.0",
@ -6212,7 +6200,6 @@
"version": "3.0.1", "version": "3.0.1",
"bundled": true, "bundled": true,
"dev": true, "dev": true,
"optional": true,
"requires": { "requires": {
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
@ -7788,6 +7775,12 @@
"integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=", "integrity": "sha1-0jM6NtnncXyK0vfKyv7HwytERmQ=",
"dev": true "dev": true
}, },
"lodash.toarray": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.toarray/-/lodash.toarray-4.4.0.tgz",
"integrity": "sha1-JMS/zWsvuji/0FlNsRedjptlZWE=",
"dev": true
},
"lodash.transform": { "lodash.transform": {
"version": "4.6.0", "version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.transform/-/lodash.transform-4.6.0.tgz", "resolved": "https://registry.npmjs.org/lodash.transform/-/lodash.transform-4.6.0.tgz",
@ -8289,6 +8282,15 @@
"lower-case": "^1.1.1" "lower-case": "^1.1.1"
} }
}, },
"node-emoji": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.10.0.tgz",
"integrity": "sha512-Yt3384If5H6BYGVHiHwTL+99OzJKHhgp82S8/dktEK73T26BazdgZ4JZh92xSVtGNJvz9UbXdNAc5hcrXV42vw==",
"dev": true,
"requires": {
"lodash.toarray": "^4.4.0"
}
},
"node-forge": { "node-forge": {
"version": "0.7.5", "version": "0.7.5",
"resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz", "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.7.5.tgz",
@ -8516,6 +8518,12 @@
"integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==", "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==",
"dev": true "dev": true
}, },
"normalize.css": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/normalize.css/-/normalize.css-8.0.1.tgz",
"integrity": "sha512-qizSNPO93t1YUuUhP22btGOo3chcvDFqFaj2TRybP0DMxkHOCTYwp3n34fel4a31ORXy4m1Xq0Gyqpb5m33qIg==",
"dev": true
},
"npm-run-path": { "npm-run-path": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
@ -9179,6 +9187,47 @@
"postcss": "^7.0.0" "postcss": "^7.0.0"
} }
}, },
"postcss-functions": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postcss-functions/-/postcss-functions-3.0.0.tgz",
"integrity": "sha1-DpTQFERwCkgd4g3k1V+yZAVkJQ4=",
"dev": true,
"requires": {
"glob": "^7.1.2",
"object-assign": "^4.1.1",
"postcss": "^6.0.9",
"postcss-value-parser": "^3.3.0"
},
"dependencies": {
"postcss": {
"version": "6.0.23",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
"integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
"dev": true,
"requires": {
"chalk": "^2.4.1",
"source-map": "^0.6.1",
"supports-color": "^5.4.0"
}
},
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"dev": true
}
}
},
"postcss-js": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-2.0.1.tgz",
"integrity": "sha512-8XQGohCbj6+kq8e3w6WlexkGaSjb5S8zoXnH49eB8JC6+qN2kQW+ib6fTjRgCpRRN9eeFOhMlD0NDjThW1DCBg==",
"dev": true,
"requires": {
"camelcase-css": "^2.0.1",
"postcss": "^7.0.14"
}
},
"postcss-load-config": { "postcss-load-config": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz", "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.0.0.tgz",
@ -9443,6 +9492,16 @@
} }
} }
}, },
"postcss-nested": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-4.1.2.tgz",
"integrity": "sha512-9bQFr2TezohU3KRSu9f6sfecXmf/x6RXDedl8CHF6fyuyVW7UqgNMRdWMHZQWuFY6Xqs2NYk+Fj4Z4vSOf7PQg==",
"dev": true,
"requires": {
"postcss": "^7.0.14",
"postcss-selector-parser": "^5.0.0"
}
},
"postcss-normalize-charset": { "postcss-normalize-charset": {
"version": "4.0.1", "version": "4.0.1",
"resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz",
@ -9645,6 +9704,12 @@
"utila": "~0.4" "utila": "~0.4"
} }
}, },
"pretty-hrtime": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz",
"integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE=",
"dev": true
},
"private": { "private": {
"version": "0.1.8", "version": "0.1.8",
"resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz", "resolved": "https://registry.npmjs.org/private/-/private-0.1.8.tgz",
@ -11462,6 +11527,57 @@
} }
} }
}, },
"tailwindcss": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-1.0.1.tgz",
"integrity": "sha512-tNyvmizhIY9ydXX8m84S/69851QROZzbH6RB/Q4w0K27OssupGcyXeD8zumzb9Yuzq6PifBH2A6ehjuBPklnYA==",
"dev": true,
"requires": {
"autoprefixer": "^9.4.5",
"bytes": "^3.0.0",
"chalk": "^2.4.1",
"fs-extra": "^8.0.0",
"lodash": "^4.17.11",
"node-emoji": "^1.8.1",
"normalize.css": "^8.0.1",
"postcss": "^7.0.11",
"postcss-functions": "^3.0.0",
"postcss-js": "^2.0.0",
"postcss-nested": "^4.1.1",
"postcss-selector-parser": "^6.0.0",
"pretty-hrtime": "^1.0.3"
},
"dependencies": {
"cssesc": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
"integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
"dev": true
},
"fs-extra": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.0.1.tgz",
"integrity": "sha512-W+XLrggcDzlle47X/XnS7FXrXu9sDo+Ze9zpndeBxdgv88FHLm1HtmkhEwavruS6koanBjp098rUpHs65EmG7A==",
"dev": true,
"requires": {
"graceful-fs": "^4.1.2",
"jsonfile": "^4.0.0",
"universalify": "^0.1.0"
}
},
"postcss-selector-parser": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.2.tgz",
"integrity": "sha512-36P2QR59jDTOAiIkqEprfJDsoNrvwFei3eCqKd1Y0tUsBimsq39BLp7RD+JWny3WgB1zGhJX8XVePwm9k4wdBg==",
"dev": true,
"requires": {
"cssesc": "^3.0.0",
"indexes-of": "^1.0.1",
"uniq": "^1.0.1"
}
}
}
},
"tapable": { "tapable": {
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz", "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.1.tgz",

View File

@ -12,7 +12,6 @@
"@mdi/font": "^3.6.95", "@mdi/font": "^3.6.95",
"ansi_up": "^3.0.0", "ansi_up": "^3.0.0",
"axios": "^0.18.0", "axios": "^0.18.0",
"bulma": "^0.7.4",
"moment": "^2.23.0", "moment": "^2.23.0",
"moment-duration-format": "^2.2.2", "moment-duration-format": "^2.2.2",
"v-click-outside": "^2.1.3", "v-click-outside": "^2.1.3",
@ -30,6 +29,7 @@
"eslint-plugin-vue": "^5.2.2", "eslint-plugin-vue": "^5.2.2",
"node-sass": "^4.11.0", "node-sass": "^4.11.0",
"sass-loader": "^7.1.0", "sass-loader": "^7.1.0",
"tailwindcss": "^1.0.1",
"vue-template-compiler": "^2.6.10" "vue-template-compiler": "^2.6.10"
}, },
"eslintConfig": { "eslintConfig": {
@ -46,14 +46,9 @@
"parser": "babel-eslint" "parser": "babel-eslint"
} }
}, },
"postcss": {
"plugins": {
"autoprefixer": {}
}
},
"browserslist": [ "browserslist": [
"> 1%", "> 1%",
"last 2 versions", "last 2 versions",
"not ie <= 8" "not ie <= 8"
] ]
} }

6
postcss.config.js Normal file
View File

@ -0,0 +1,6 @@
module.exports = {
"plugins": [
require('tailwindcss')('tailwind.js'),
require('autoprefixer')(),
]
}

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,87 +1,117 @@
<template> <template>
<div id="app"> <div id="app">
<nav class="navbar is-light has-shadow" role="navigation" aria-label="main navigation"> <nav class="bg-gray-800 p-3 text-white">
<div class="container"> <div class="container flex items-center justify-between flex-wrap bg-gray-800">
<div class="navbar-brand"> <div class="mr-6">
<a class="navbar-item" href="/"> <router-link
<h1>Agola</h1> class="font-semibold flex items-center flex-shrink-0 text-xl tracking-tight"
</a> to="/"
<a
role="button"
class="navbar-burger burger"
aria-label="menu"
aria-expanded="false"
data-target="navbarBasicExample"
> >
<span aria-hidden="true"></span> <img class="w-10 mr-2" src="/img/agola-logo-circle.svg">
<span aria-hidden="true"></span> Agola
<span aria-hidden="true"></span> </router-link>
</a>
</div> </div>
<div class="navbar-menu"> <div class="block lg:hidden">
<div class="navbar-start"></div> <button
<div class="navbar-end"> class="flex items-center px-3 py-2 border rounded text-blue-200 border-blue-400 hover:text-white hover:border-white"
<div @click="toggleNav()"
v-if="user" >
class="navbar-item has-dropdown" <svg
v-click-outside="() => createDropdownActive = false" class="fill-current h-3 w-3"
v-bind:class="{ 'is-active': createDropdownActive }" viewBox="0 0 20 20"
xmlns="http://www.w3.org/2000/svg"
> >
<a class="navbar-link" @click="toggleCreateDropdown()"> <title>Menu</title>
<i class="mdi mdi-plus-box mdi-24px"/> <path d="M0 3h20v2H0V3zm0 6h20v2H0V9zm0 6h20v2H0v-2z"></path>
</a> </svg>
<div class="navbar-dropdown"> </button>
<router-link class="navbar-item" to="/neworganization">New Organization</router-link> </div>
</div> <div
class="w-full block flex-grow lg:flex lg:items-center lg:w-auto"
:class="{'hidden' : !navActive}"
>
<div class="text-sm lg:flex-grow"></div>
<div v-if="user" class="relative mr-3">
<button
v-click-outside="() => createDropdownActive = false"
@click="toggleCreateDropdown()"
class="relative flex items-center focus:outline-none"
>
<i class="mdi mdi-plus-box mdi-24px"/>
<i class="mdi mdi-chevron-down"></i>
</button>
<div
v-if="createDropdownActive"
class="z-10 origin-top-right absolute right-0 mt-2 w-64 bg-white rounded-lg border shadow-md py-2 text-dark"
>
<ul>
<li>
<router-link
class="block px-4 py-2 hover:bg-blue-500 hover:text-white"
to="/neworganization"
>New Organization</router-link>
</li>
</ul>
</div>
</div>
<div v-if="user" class="relative">
<div class="flex">
<button
v-click-outside="() => userDropdownActive = false"
@click="toggleUserDropdown()"
class="relative flex items-center focus:outline-none"
>
{{user.username}}
<i class="mdi mdi-chevron-down"></i>
</button>
</div> </div>
<div <div
v-if="user" v-if="userDropdownActive"
class="navbar-item has-dropdown" class="z-10 origin-top-right absolute right-0 mt-2 w-64 bg-white rounded-lg border shadow-md py-2 text-dark"
v-click-outside="() => userDropdownActive = false"
v-bind:class="{ 'is-active': userDropdownActive }"
> >
<a class="navbar-link" @click="toggleUserDropdown()">{{user.username}}</a> <ul>
<div class="navbar-dropdown"> <li class="block px-4 py-2 border-b">
<div class="navbar-item">
Logged as&nbsp; Logged as&nbsp;
<b>{{user.username}}</b> <b>{{user.username}}</b>
</div> </li>
<hr class="navbar-divider"> <li>
<router-link class="navbar-item" to="/logout"> <hr class="navbar-divider">
<i class="mdi mdi-logout"></i>Logout </li>
</router-link> <li>
</div> <router-link
</div> class="block px-4 py-2 hover:bg-blue-500 hover:text-white"
<div v-else class="navbar-item"> to="/logout"
<router-link class="button" to="/register">Sign up</router-link> >
<router-link class="button" to="/login">Login</router-link> <i class="mdi mdi-logout"></i>Logout
</router-link>
</li>
</ul>
</div> </div>
</div> </div>
<div v-else class="navbar-item">
<router-link class="btn btn-blue" to="/register">Sign up</router-link>
<router-link class="ml-2 btn btn-blue" to="/login">Login</router-link>
</div>
</div> </div>
</div> </div>
</nav> </nav>
<div v-if="error" class="container"> <div v-if="error" class="container h-screen" role="alert">
<div class="message is-danger global-error-message"> <div v-if="error" class="h-full flex justify-center items-center" role="alert">
<div class="message-body"> <div v-if="error" class="w-full" role="alert">
<nav class="level"> <div class="bg-red-500 text-white font-bold rounded-t px-4 py-2">Error</div>
<div class="level-left"> <div class="border border-t-0 border-red-400 rounded-b bg-red-100 px-4 py-3 text-red-700">
<div class="level-item"> <p class="mb-8">Failed to fetch data: {{ error }}</p>
<p>Failed to fetch data: {{ error }}</p> <button class="btn btn-red" @click="reload()">Retry</button>
</div> </div>
</div>
<div class="level-right">
<div class="level-item">
<button class="button is-danger" @click="reload()">Retry</button>
</div>
</div>
</nav>
</div> </div>
</div> </div>
</div> </div>
<div v-else class="main-container container">
<router-view v-if="routerActive"></router-view> <div v-else class="container mt-6 flex">
<div class="flex-grow">
<router-view v-if="routerActive"></router-view>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -104,6 +134,7 @@ export default {
data() { data() {
return { return {
routerActive: true, routerActive: true,
navActive: false,
userDropdownActive: false, userDropdownActive: false,
createDropdownActive: false createDropdownActive: false
}; };
@ -129,6 +160,9 @@ export default {
this.routerActive = false; this.routerActive = false;
this.$nextTick(() => (this.routerActive = true)); this.$nextTick(() => (this.routerActive = true));
}, },
toggleNav() {
this.navActive = !this.navActive;
},
toggleUserDropdown() { toggleUserDropdown() {
this.userDropdownActive = !this.userDropdownActive; this.userDropdownActive = !this.userDropdownActive;
}, },
@ -140,13 +174,4 @@ export default {
</script> </script>
<style lang="scss"> <style lang="scss">
@import "@/css/main.scss";
.main-container {
margin-top: 2rem;
}
.global-error-message {
margin-top: 10rem;
}
</style> </style>

View File

@ -1,32 +1,30 @@
<template> <template>
<div class="item"> <div
<div class="mb-2 border-l-5 rounded-l"
class="touchable" :class="stepClass(step)"
:class="stepClass(step)" role="tab"
role="tab" :aria-expanded="active ? 'true' : 'false'"
:aria-expanded="active ? 'true' : 'false'" >
> <div class="px-4 py-4 border border-l-0 rounded-r">
<div class="item-content"> <div class="cursor-pointer flex justify-between" @click.prevent="toggle">
<div class="header" @click.prevent="toggle"> <div>
<span class="icon"> <i
<i class="inline-block mr-1 mdi mdi-arrow-right"
class="mdi mdi-arrow-right" :class="{ 'arrow-down': active, 'arrow-right': !active }"
:class="{ 'arrow-down': active, 'arrow-right': !active }" ></i>
></i> <span class="w-1/3 font-bold">{{step.name}}</span>
</span>
<span class="name">{{step.name}}</span>
<span class="duration">{{duration}}</span>
</div>
<div class="log-container" v-show="active">
<Log
v-bind:runid="runid"
v-bind:taskid="taskid"
v-bind:setup="setup"
v-bind:step="stepnum"
v-bind:stepphase="step.phase"
v-bind:show="active"
/>
</div> </div>
<span class>{{duration}}</span>
</div>
<div class="p-1 log-container" v-show="active">
<Log
v-bind:runid="runid"
v-bind:taskid="taskid"
v-bind:setup="setup"
v-bind:step="stepnum"
v-bind:stepphase="step.phase"
v-bind:show="active"
/>
</div> </div>
</div> </div>
</div> </div>
@ -98,54 +96,6 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
.item {
}
.item-content {
margin-bottom: 5px;
border: 1px solid $grey-lighter;
border-left: 0 solid;
padding: 10px;
}
.header {
display: flex;
justify-content: space-between;
align-items: center;
}
.success {
border-left: 5px solid $green;
}
.failed {
border-left: 5px solid $red;
}
.running {
border-left: 5px solid $blue;
}
.unknown {
border-left: 5px solid $grey-lighter;
}
.name {
flex: 0 0 30%;
font-weight: bold;
cursor: pointer;
}
.duration {
margin-left: auto;
}
.log-container {
padding: 10px;
}
.arrow-right { .arrow-right {
transition: transform 0.2s ease-in-out; transition: transform 0.2s ease-in-out;
} }

View File

@ -1,26 +1,32 @@
<template> <template>
<div> <div>
<h4 class="title is-4">New Organization</h4> <h4 class="mb-4 text-xl font-bold">New Organization</h4>
<div class="field"> <div class="field">
<div class="control"> <div class="control">
<input class="input" type="text" placeholder="Organization name" v-model="orgName"> <input
class="mb-4 appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline"
type="text"
placeholder="Organization name"
v-model="orgName"
>
</div> </div>
</div> </div>
<div class="field"> <div class="mb-4">
<div class="control"> <label>
<label class="checkbox"> <input type="checkbox" v-model="orgIsPrivate">
<input type="checkbox" v-model="orgIsPrivate"> Private
Private </label>
</label>
</div>
</div> </div>
<div class="field is-grouped"> <button
<div class="control"> class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
<button class="button is-primary" @click="createOrg()">Create Organization</button> @click="createOrg()"
</div> >Create Organization</button>
</div> <div
<div v-if="createOrgError" class="message is-danger"> v-if="createOrgError"
<div class="message-body">{{ createOrgError }}</div> class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
role="alert"
>
<span class="block sm:inline">{{ createOrgError }}</span>
</div> </div>
</div> </div>
</template> </template>
@ -67,7 +73,6 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
</style> </style>

View File

@ -1,21 +1,21 @@
<template> <template>
<div> <div>
<h4 class="title is-4">Create Project</h4> <h4 class="mb-4 text-xl font-bold">Create Project</h4>
<div class="field">
<div class="control"> <input
<input class="input" type="text" placeholder="Project name" v-model="projectName"> class="mb-4 appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline"
</div> type="text"
</div> placeholder="Project Name"
<div class="field"> v-model="projectName"
<div class="control"> >
<label class="checkbox"> <div class="mb-4">
<input type="checkbox" v-model="projectIsPrivate"> <label>
Private <input type="checkbox" v-model="projectIsPrivate">
</label> Private
</div> </label>
</div> </div>
<h4 class="title is-4">Available remote repositories</h4> <h4 class="text-xl">Available remote repositories</h4>
<div v-for="remoteSource in remoteSources" v-bind:key="remoteSource.id"> <div v-for="remoteSource in remoteSources" v-bind:key="remoteSource.id">
<remoterepos <remoterepos
class="remoterepos" class="remoterepos"
@ -24,18 +24,18 @@
v-on:reposelected="repoSelected(remoteSource, $event)" v-on:reposelected="repoSelected(remoteSource, $event)"
/> />
</div> </div>
<div class="field is-grouped"> <button
<div class="control"> class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
<button v-bind:class="{ 'spinner': createProjectLoading }"
class="button is-primary" :disabled="!createProjectButtonEnabled"
v-bind:class="{ 'is-loading': createProjectLoading }" @click="createProject()"
:disabled="!createProjectButtonEnabled" >Create Project</button>
@click="createProject()" <div
>Create Project</button> v-if="createProjectError"
</div> class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
</div> role="alert"
<div v-if="createProjectError" class="message is-danger"> >
<div class="message-body">{{ createProjectError }}</div> <span class="block sm:inline">{{ createProjectError }}</span>
</div> </div>
</div> </div>
</template> </template>
@ -164,23 +164,5 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
.item-list {
.item {
margin-bottom: 5px;
border: 1px solid $grey-lighter;
cursor: pointer;
display: flex;
padding: 10px;
}
.name {
font-weight: bold;
}
}
.remoterepos {
margin-top: 1rem;
margin-bottom: 1rem;
}
</style> </style>

View File

@ -1,29 +1,37 @@
<template> <template>
<div> <div>
<div class="field has-addons is-pulled-rigth"> <div class="relative mr-3">
<p class="control"> <div class="flex">
<button class="button" @click="clicked">{{ buttonValue }}</button> <button
</p> @click="clicked"
<div class="control"> class="relative flex items-center focus:outline-none bg-transparent bg-green-500 hover:bg-green-600 text-white font-semibold hover:text-white py-2 px-4 border border-green-700 rounded rounded-r-none"
<div >{{ buttonValue }}</button>
class="dropdown is-right" <button
v-click-outside="() => dropdownActive = false" v-click-outside="() => dropdownActive = false"
v-bind:class="{ 'is-active': dropdownActive }" @click="toggleDropdown"
class="relative flex items-center focus:outline-none bg-transparent bg-green-500 hover:bg-green-600 text-white font-semibold hover:text-white py-2 px-4 border border-l-0 border-green-700 rounded rounded-l-none"
> >
<div class="dropdown-trigger"> <i class="mdi mdi-chevron-down"></i>
<button class="button" @click="toggleDropdown"> </button>
<span class="icon is-small"> </div>
<i class="mdi mdi-chevron-down"></i> <div
</span> v-if="dropdownActive"
</button> class="z-10 origin-top-right absolute right-0 mt-2 w-64 bg-white rounded-lg border shadow-md py-2"
</div> >
<div class="dropdown-menu" role="menu"> <ul>
<div class="dropdown-content"> <li>
<a href="#" class="dropdown-item" @click="setButton('project')">New Project</a> <a
<a href="#" class="dropdown-item" @click="setButton('projectgroup')">New Project Group</a> href="#"
</div> class="block px-4 py-2 hover:bg-blue-500 hover:text-white"
</div> @click="setButton('project')"
</div> >New Project</a>
<a
href="#"
class="block px-4 py-2 hover:bg-blue-500 hover:text-white"
@click="setButton('projectgroup')"
>New Project Group</a>
</li>
</ul>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,37 +1,32 @@
<template> <template>
<div> <div>
<h4 class="title is-4">Create Project Group</h4> <h4 class="mb-4 text-xl font-bold">Create Project Group</h4>
<div class="field">
<div class="control"> <input
<input class="mb-4 appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline"
class="input" type="text"
type="text" placeholder="Project Group Name"
placeholder="Project Group Name" v-model="projectGroupName"
v-model="projectGroupName" >
> <div class="mb-4">
</div> <label>
</div> <input type="checkbox" v-model="projectGroupIsPrivate">
<div class="field"> Private
<div class="control"> </label>
<label class="checkbox">
<input type="checkbox" v-model="projectGroupIsPrivate">
Private
</label>
</div>
</div> </div>
<div class="field is-grouped"> <button
<div class="control"> class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
<button v-bind:class="{ 'spinner': createProjectGroupLoading }"
class="button is-primary" :disabled="!createProjectGroupButtonEnabled"
v-bind:class="{ 'is-loading': createProjectGroupLoading }" @click="createProjectGroup()"
:disabled="!createProjectGroupButtonEnabled" >Create ProjectGroup</button>
@click="createProjectGroup()" <div
>Create Project Group</button> v-if="createProjectGroupError"
</div> class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
</div> role="alert"
<div v-if="createProjectGroupError" class="message is-danger"> >
<div class="message-body">{{ createProjectGroupError }}</div> <span class="block sm:inline">{{ createProjectGroupError }}</span>
</div> </div>
</div> </div>
</template> </template>
@ -115,20 +110,6 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
.item-list {
.item {
margin-bottom: 5px;
border: 1px solid $grey-lighter;
cursor: pointer;
display: flex;
padding: 10px;
}
.name {
font-weight: bold;
}
}
</style> </style>

View File

@ -1,10 +1,10 @@
<template> <template>
<div class="dark"> <div class="dark">
<div class="log"> <div class="p-3 rounded bg-gray-900 text-white">
<div class="stream-line" v-for="(item, index) in items" :key="index"> <div class="font-mono leading-normal text-xs" v-for="(item, index) in items" :key="index">
<div v-html="item"/> <div v-html="item"/>
</div> </div>
<div v-if="lastitem" class="stream-line"> <div v-if="lastitem" class="font-mono leading-snug text-xs">
<div v-html="lastitem"/> <div v-html="lastitem"/>
</div> </div>
</div> </div>
@ -141,22 +141,4 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.log {
background-color: #222;
color: #f1f1f1;
font-family: Cousine, monospace, "Noto Color Emoji";
font-size: 12px;
line-height: 19px;
white-space: pre-wrap;
word-wrap: break-word;
text-align: left;
font-size: 12px;
padding: 5px;
.stream-line {
pre {
line-height: 1.2;
}
}
}
</style> </style>

View File

@ -1,32 +1,36 @@
<template> <template>
<div> <div class="w-full max-w-xs">
<div class="field"> <form
<p class="control has-icons-left has-icons-right"> class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4"
<input v-model="username" class="input" type="email" placeholder="Email"> @submit.prevent="$emit('login', { username, password })"
<span class="icon is-small is-left"> >
<i class="fas fa-envelope"></i> <div class="mb-4">
</span> <label class="block text-sm font-bold mb-2" for="username">Username</label>
<span class="icon is-small is-right"> <input
<i class="fas fa-check"></i> class="appearance-none border rounded w-full py-2 px-3 leading-tight focus:outline-none focus:shadow-outline"
</span> id="username"
</p> type="text"
</div> placeholder="Username"
<div class="field"> v-model="username"
<p class="control has-icons-left"> >
<input v-model="password" class="input" type="password" placeholder="Password"> </div>
<span class="icon is-small is-left"> <div class="mb-6">
<i class="fas fa-lock"></i> <label class="block text-sm font-bold mb-2" for="password">Password</label>
</span> <input
</p> class="appearance-none border rounded w-full py-2 px-3 mb-3 leading-tight focus:outline-none focus:shadow-outline"
</div> id="password"
<div class="field"> type="password"
<p class="control"> placeholder="******************"
v-model="password"
>
</div>
<div class="flex justify-center">
<button <button
@click="$emit('login', { username, password })" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
class="button is-info is-fullwidth" type="submit"
>{{action}} with {{name}}</button> >{{action}} with {{name}}</button>
</p> </div>
</div> </form>
</div> </div>
</template> </template>

View File

@ -1,13 +1,13 @@
<template> <template>
<div> <div>
<h4 class="title is-4">Organization Members</h4> <h4 class="mb-3 text-xl">Organization Members</h4>
<ul v-if="members.length" class="item-list"> <ul v-if="members.length">
<li class="item" v-for="member in members" v-bind:key="member.user.id"> <li class="flex" v-for="member in members" v-bind:key="member.user.id">
<span class="name">{{member.user.username}}</span> <span class="w-1/2 font-bold">{{member.user.username}}</span>
<span class="role">{{member.role}}</span> <span class="w-1/2">{{member.role}}</span>
</li> </li>
</ul> </ul>
<div v-else class="item-list">No Members</div> <div v-else>No Members</div>
</div> </div>
</template> </template>
@ -47,54 +47,4 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
.item-list {
.item {
border: 1px solid $grey-lighter;
border-bottom: 0;
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
}
.item:last-child {
border-bottom: 1px solid $grey-lighter;
}
.name {
flex: 0 0 30%;
font-weight: bold;
cursor: pointer;
}
.role {
flex: 0 0 40%;
}
.stillrunning {
flex: 0 0 10%;
}
.waitingapproval {
flex: 0 0 10%;
}
.source-info {
flex: 0 0 10%;
overflow: hidden;
white-space: nowrap;
a {
overflow: hidden;
text-overflow: ellipsis;
}
}
.commit {
display: block;
font-size: 0.8rem;
}
}
</style> </style>

View File

@ -1,13 +1,17 @@
<template> <template>
<nav class="breadcrumb" aria-label="breadcrumbs"> <nav class="mb-4 bg-grey-light rounded font-sans w-full">
<ul> <ol class="list-reset flex text-grey-dark">
<li> <li>
<a>{{ownertype}}</a> <a>{{ownertype}}</a>
</li> </li>
<li>
<span class="mx-2">/</span>
</li>
<li> <li>
<router-link :to="ownerLink(ownertype, ownername)">{{ownername}}</router-link> <router-link :to="ownerLink(ownertype, ownername)">{{ownername}}</router-link>
</li> </li>
<li v-for="(ref, i) in projectref" v-bind:key="i"> <li v-for="(ref, i) in projectref" v-bind:key="i">
<span class="mx-2">/</span>
<router-link <router-link
v-if="i+1 < projectref.length" v-if="i+1 < projectref.length"
:to="projectGroupLink(ownertype, ownername, projectref.slice(0, i+1))" :to="projectGroupLink(ownertype, ownername, projectref.slice(0, i+1))"
@ -19,11 +23,12 @@
</li> </li>
<li v-for="(ref, i) in projectgroupref" v-bind:key="i"> <li v-for="(ref, i) in projectgroupref" v-bind:key="i">
<span class="mx-2">/</span>
<router-link <router-link
:to="projectGroupLink(ownertype, ownername, projectgroupref.slice(0, i+1))" :to="projectGroupLink(ownertype, ownername, projectgroupref.slice(0, i+1))"
>{{ref}}</router-link> >{{ref}}</router-link>
</li> </li>
</ul> </ol>
</nav> </nav>
</template> </template>
@ -50,5 +55,4 @@ export default {
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
</style> </style>

View File

@ -1,81 +1,87 @@
<template> <template>
<div> <div>
<nav class="panel"> <div class="panel">
<p class="panel-heading">Project Group Settings</p> <p class="panel-title">Project Group Settings</p>
<div class="panel-block is-block"> <div class="p-4">
<div v-if="!isRootProjectGroup" class="field"> <div v-if="!isRootProjectGroup" class="mb-4">
<label class="label">Project Group Name</label> <label class="block font-bold mb-2">Project Group Name</label>
<div class="control"> <div class="control">
<input class="input" type="text" placeholder="Text input" v-model="projectGroup.name"> <input
class="appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline"
type="text"
placeholder="Project Group Name"
v-model="projectGroup.name"
>
</div> </div>
</div> </div>
<div class="field"> <div class="mb-4">
<div class="control"> <label class="checkbox">
<label class="checkbox"> <input type="checkbox" v-model="projectGroupIsPrivate">
<input type="checkbox" v-model="projectGroupIsPrivate"> Private
Private </label>
</label>
</div>
</div> </div>
<button class="btn btn-blue" @click="updateProjectGroup()">Update</button>
<div class="field is-grouped"> <div
<div class="control"> v-if="updateProjectGroupError"
<button class="button is-primary" @click="updateProjectGroup()">Update</button> class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
</div> role="alert"
</div> >
<span class="block sm:inline">{{ updateProjectGroupError }}</span>
<div v-if="updateProjectGroupError" class="message is-danger">
<div class="message-body">{{ updateProjectGroupError }}</div>
</div> </div>
</div> </div>
</nav> </div>
<nav class="panel">
<p class="panel-heading">Variables</p> <div class="panel">
<div class="panel-block is-block"> <p class="panel-title">Variables</p>
<div class="p-4">
<projectvars :variables="variables" :allvariables="allvariables"/> <projectvars :variables="variables" :allvariables="allvariables"/>
</div> </div>
</nav> </div>
<nav v-if="!isRootProjectGroup" class="panel is-danger">
<p class="panel-heading is-danger">Danger Zone</p>
<div class="panel-block is-block">
<div>
<div>
<h4 class="title is-4">Delete This Project Group</h4>
<div class="message is-danger"> <div v-if="!isRootProjectGroup" class="panel">
<div class="message-body"> <p class="panel-title">Danger Zone</p>
This operation <div class="p-4">
<strong>CANNOT</strong> be undone. <h4 class="mb-4 title text-xl">Delete This Project Group</h4>
This operation will remove <div
<strong>{{projectGroupPath}}</strong> class="mb-4 bg-red-100 border-l-4 border-red-500 text-red-700 p-4 rounded"
</div> role="alert"
</div> >
<label class="label"> <p>
Please type the project group name for confirmation: This operation
<span <strong>CANNOT</strong> be undone.
class="has-text-danger" This operation will remove
>{{ projectGroupName }}</span> <strong>{{projectGroupPath}}</strong>
</label> </p>
<div class="field">
<input
v-model="projectGroupNameToDelete"
class="input"
type="email"
placeholder="Project Group name to delete"
>
</div>
<button
class="button is-danger"
@click="deleteProjectGroup()"
:disabled="!deleteButtonEnabled"
>Delete Project Group</button>
</div>
</div> </div>
<div v-if="deleteProjectGroupError" class="message is-danger"> <label class="block mb-2">
<div class="message-body">{{ deleteProjectGroupError }}</div> Please type the project group name for confirmation:
<span
class="text-red-500 font-bold"
>{{ projectGroupName }}</span>
</label>
<div class="mb-4">
<input
class="appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline"
v-model="projectGroupNameToDelete"
type="email"
placeholder="Project Group name to delete"
>
</div> </div>
<button
class="btn btn-red"
@click="deleteProjectGroup()"
:disabled="!deleteButtonEnabled"
>Delete Project Group</button>
</div> </div>
</nav> </div>
<div
v-if="deleteProjectGroupError"
class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
role="alert"
>
<span class="block sm:inline">{{ deleteProjectGroupError }}</span>
</div>
</div> </div>
</template> </template>
@ -218,10 +224,5 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
.panel-heading {
font-weight: 700;
}
</style> </style>

View File

@ -1,33 +1,37 @@
<template> <template>
<div> <div>
<h4 class="title is-4">Projects</h4> <h4 class="text-xl my-3">Projects</h4>
<div v-if="projects.length > 0"> <ul v-if="projects.length > 0">
<div class="item-list" v-for="project in projects" v-bind:key="project.id"> <li class="mb-2 border rounded-l" v-for="project in projects" v-bind:key="project.id">
<router-link <div class="pl-4 py-4 flex items-center">
tag="div" <router-link class="item" :to="projectLink(ownertype, ownername, ref(project.name))">
class="item" <span class="font-bold">{{project.name}}</span>
:to="projectLink(ownertype, ownername, ref(project.name))" </router-link>
> </div>
<span class="name">{{project.name}}</span> </li>
</router-link> </ul>
</div> <div v-else class="font-bold">No projects</div>
</div>
<div v-else class="item-list">No projects</div>
<hr> <hr class="my-6 border-t">
<h4 class="title is-4">Project Groups</h4>
<div v-if="projectgroups.length > 0"> <h4 class="text-xl my-3">Project Groups</h4>
<div class="item-list" v-for="projectgroup in projectgroups" v-bind:key="projectgroup.id"> <ul v-if="projectgroups.length > 0">
<router-link <li
tag="div" class="mb-2 border rounded-l"
class="item" v-for="projectgroup in projectgroups"
:to="projectGroupLink(ownertype, ownername, ref(projectgroup.name))" v-bind:key="projectgroup.id"
> >
<span class="name">{{projectgroup.name}}</span> <div class="pl-4 py-4 flex items-center">
</router-link> <router-link
</div> class="item"
</div> :to="projectGroupLink(ownertype, ownername, ref(projectgroup.name))"
<div v-else class="item-list">No project groups</div> >
<span class="font-bold">{{projectgroup.name}}</span>
</router-link>
</div>
</li>
</ul>
<div v-else class="font-bold">No project groups</div>
</div> </div>
</template> </template>
@ -109,18 +113,4 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
.item-list {
.item {
margin-bottom: 5px;
border: 1px solid $grey-lighter;
cursor: pointer;
display: flex;
padding: 10px;
}
.name {
font-weight: bold;
}
}
</style> </style>

View File

@ -1,95 +1,103 @@
<template> <template>
<div> <div>
<nav class="panel"> <div class="panel">
<p class="panel-heading">Project Settings</p> <p class="panel-title">Project Settings</p>
<div class="panel-block is-block"> <div class="p-4">
<div class="field"> <div class="mb-4">
<label class="label">Project Name</label> <label class="block font-bold mb-2">Project Name</label>
<div class="control"> <input
<input class="input" type="text" placeholder="Text input" v-model="project.name"> class="appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline"
</div> type="text"
placeholder="Project Name"
v-model="project.name"
>
</div> </div>
<div class="field"> <div class="mb-4">
<div class="control"> <label class="checkbox">
<label class="checkbox"> <input type="checkbox" v-model="projectIsPrivate">
<input type="checkbox" v-model="projectIsPrivate"> Private
Private </label>
</label>
</div>
</div> </div>
<button class="btn btn-blue" @click="updateProject()">Update</button>
<div class="field is-grouped"> <div
<div class="control"> v-if="updateProjectError"
<button class="button is-primary" @click="updateProject()">Update</button> class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
</div> role="alert"
</div> >
<span class="block sm:inline">{{ updateProjectError }}</span>
<div v-if="updateProjectError" class="message is-danger">
<div class="message-body">{{ updateProjectError }}</div>
</div> </div>
</div> </div>
</nav> </div>
<nav class="panel">
<p class="panel-heading">Variables</p> <div class="panel">
<div class="panel-block is-block"> <p class="panel-title">Variables</p>
<div class="p-4">
<projectvars :variables="variables" :allvariables="allvariables"/> <projectvars :variables="variables" :allvariables="allvariables"/>
</div> </div>
</nav> </div>
<nav class="panel is-danger">
<p class="panel-heading is-danger">Danger Zone</p>
<div class="panel-block is-block">
<div>
<h4 class="title is-4">Delete This Project</h4>
<div class="message is-danger"> <div class="panel">
<div class="message-body"> <p class="panel-title">Danger Zone</p>
This operation <div class="p-4">
<strong>CANNOT</strong> be undone. <h4 class="mb-4 title text-xl">Delete This Project</h4>
This operation will remove <div
<strong>{{projectPath}}</strong> class="mb-4 bg-red-100 border-l-4 border-red-500 text-red-700 p-4 rounded"
</div> role="alert"
</div> >
<label class="label"> <p>
Please type the project name for confirmation: This operation
<span <strong>CANNOT</strong> be undone.
class="has-text-danger" This operation will remove
>{{ projectName }}</span> <strong>{{projectPath}}</strong>
</label> </p>
<div class="field"> </div>
<input <label class="block mb-2">
v-model="projectNameToDelete" Please type the project name for confirmation:
class="input" <span
type="email" class="text-red-500 font-bold"
placeholder="Project name to delete" >{{ projectName }}</span>
> </label>
</div> <div class="mb-4">
<button <input
class="button is-danger" class="appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline"
@click="deleteProject()" v-model="projectNameToDelete"
:disabled="!deleteButtonEnabled" type="email"
>Delete Project</button> placeholder="Project name to delete"
>
</div>
<button
class="btn btn-red"
@click="deleteProject()"
:disabled="!deleteButtonEnabled"
>Delete Project</button>
<div v-if="deleteProjectError" class="message is-danger"> <div
<div class="message-body">{{ deleteProjectError }}</div> v-if="deleteProjectError"
</div> class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
role="alert"
>
<span class="block sm:inline">{{ deleteProjectError }}</span>
</div> </div>
</div> </div>
<div class="panel-block is-block"> <div class="p-4 border-t">
<div> <h4 class="mb-4 title text-xl">Change remote repository linked account</h4>
<h4 class="title is-4">Change remote repository linked account</h4> <div
<div class="message is-danger"> class="mb-4 bg-red-100 border-l-4 border-red-500 text-red-700 p-4 rounded"
<div role="alert"
class="message-body" >
>This operation will change the linked account associated with the project remote repository to the current user linked account</div> <p>This operation will change the linked account associated with the project remote repository to the current user linked account</p>
</div> </div>
<button class="button is-danger" @click="updateRepoLinkedAccount()">Change</button> <button class="btn btn-red" @click="updateRepoLinkedAccount()">Change</button>
<div v-if="updateRepoLinkedAccountError" class="message is-danger"> <div
<div class="message-body">{{ updateRepoLinkedAccountError }}</div> v-if="updateRepoLinkedAccountError"
</div> class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
role="alert"
>
<span class="block sm:inline">{{ updateRepoLinkedAccountError }}</span>
</div> </div>
</div> </div>
</nav> </div>
</div> </div>
</template> </template>
@ -237,9 +245,4 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
.panel-heading {
font-weight: 700;
}
</style> </style>

View File

@ -1,11 +1,12 @@
<template> <template>
<div> <div>
<h5 class="title is-5">Local variables</h5> <h5 class="text-2xl">Local variables</h5>
<vars v-if="allvariables.length" :variables="variables"/> <vars v-if="allvariables.length" :variables="variables"/>
<span v-else>No variables</span> <span v-else>No variables</span>
<hr> <hr class="my-6 border-t">
<h5 class="title is-5">All variables</h5>
<h5 class="text-2xl">All variables</h5>
<vars v-if="allvariables.length" :variables="allvariables" :showparentpath="true"/> <vars v-if="allvariables.length" :variables="allvariables" :showparentpath="true"/>
<span v-else>No variables</span> <span v-else>No variables</span>
</div> </div>
@ -25,6 +26,5 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
</style> </style>

View File

@ -1,21 +1,37 @@
<template> <template>
<div> <div class="w-full max-w-xs">
<div class="field"> <form
<p class="control has-icons-left has-icons-right"> class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4"
<input v-model="username" class="input" type="email" placeholder="Email"> @submit.prevent="$emit('login', { username })"
<span class="icon is-small is-left"> >
<i class="fas fa-envelope"></i> <div class="mb-4">
</span> <label class="block text-sm font-bold mb-2" for="username">Remote Username</label>
<span class="icon is-small is-right"> <input
<i class="fas fa-check"></i> class="appearance-none border rounded w-full py-2 px-3 leading-tight focus:outline-none focus:shadow-outline"
</span> id="username"
</p> type="text"
</div> placeholder="Username"
<div class="field"> :disabled="true"
<p class="control"> v-model="remoteUsername"
<button @click="$emit('login', { username })" class="button is-info is-fullwidth">Register</button> >
</p> </div>
</div> <div class="mb-4">
<label class="block text-sm font-bold mb-2" for="username">Username</label>
<input
class="appearance-none border rounded w-full py-2 px-3 leading-tight focus:outline-none focus:shadow-outline"
id="username"
type="text"
placeholder="Username"
v-model="username"
>
</div>
<div class="flex justify-center">
<button
class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
type="submit"
>Register</button>
</div>
</form>
</div> </div>
</template> </template>
@ -24,6 +40,7 @@
export default { export default {
name: "RegisterForm", name: "RegisterForm",
props: { props: {
remoteUsername: String,
username: String username: String
} }
}; };

View File

@ -1,23 +1,21 @@
<template> <template>
<div> <div class="mb-2 border-solid border-gray-300 rounded border shadow-sm">
<p class="bg-gray-200 px-4 py-3 border-solid border-gray-300 border-b">
repositories from
<strong>{{ remotesource.name }}</strong>
</p>
<div v-if="remoterepos.length > 0"> <div v-if="remoterepos.length > 0">
<nav class="panel"> <label
<p class="panel-heading"> class="block px-4 py-2 border-b"
repositories from v-for="(repo, index) in remoterepos"
<strong>{{ remotesource.name }}</strong> v-bind:key="repo.id"
</p> @click="select(index)"
<label >
class="panel-block" <input type="radio" :checked="selectedrepo == index && selected">
v-for="(repo, index) in remoterepos" {{repo.path}}
v-bind:key="repo.id" </label>
@click="select(index)"
>
<input type="radio" :checked="selectedrepo == index && selected">
{{repo.path}}
</label>
</nav>
</div> </div>
<div v-else class="item-list">No remote repositories</div> <div v-else class="block px-4 py-2 border-b">No remote repositories</div>
</div> </div>
</template> </template>
@ -58,22 +56,4 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
.item-list {
.item {
margin-bottom: 5px;
border: 1px solid $grey-lighter;
cursor: pointer;
display: flex;
padding: 10px;
}
.name {
font-weight: bold;
}
}
.panel-block input[type="radio"] {
margin-right: 0.75em;
}
</style> </style>

View File

@ -3,50 +3,49 @@
<RunDetail :run="run" :ownertype="ownertype" :ownername="ownername" :projectref="projectref"/> <RunDetail :run="run" :ownertype="ownertype" :ownername="ownername" :projectref="projectref"/>
<div v-if="run"> <div v-if="run">
<div v-if="run.phase != 'setuperror'"> <div v-if="run.phase != 'setuperror'">
<div class="tabs"> <div class="m-4 text-xl font-bold">Tasks</div>
<ul>
<li>
<a>Tasks</a>
</li>
</ul>
</div>
<div v-if="run" class="tasks-list"> <ul v-if="run">
<div v-for="task in run.sortedTasks" v-bind:key="task.id" :class="taskClass(task)"> <li
<div class="task-content"> class="mb-2 border-l-5 rounded-l"
<div class="columns"> v-for="task in run.sortedTasks"
<router-link class="column is-10" tag="a" :to="runTaskLink(task)"> v-bind:key="task.id"
<span class="name">{{task.name}}</span> :class="taskClass(task)"
</router-link> >
<div class="column"> <div class="pl-4 py-4 flex justify-between items-center border border-l-0 rounded-r">
<span <router-link class="w-1/3 font-bold" tag="a" :to="runTaskLink(task)">
class="tag" <span class="w-1/3 font-bold">{{task.name}}</span>
v-if="run.tasks_waiting_approval.includes(task.id)" </router-link>
>Waiting approval</span> <div class="column">
</div> <span
<div class="parents column"> class="tag"
<span v-if="parents(task).length > 0">depends on: &nbsp;</span> v-if="run.tasks_waiting_approval.includes(task.id)"
<span class="parent" v-for="dep in parents(task)" v-bind:key="dep">{{dep}}</span> >Waiting approval</span>
</div> </div>
<div class="w-40">
<span class="block" v-if="parents(task).length > 0">depends on: &nbsp;</span>
<span
class="font-thin text-gray-600"
v-for="dep in parents(task)"
v-bind:key="dep"
>{{dep}}</span>
</div> </div>
<!-- <span <!-- <span
class="duration" class="duration"
v-if="duration && (step.Phase == 'success' || step.Phase == 'failed') " v-if="duration && (step.Phase == 'success' || step.Phase == 'failed') "
>{{duration}}</span>--> >{{duration}}</span>-->
</div> </div>
</div> </li>
</div> </ul>
</div> </div>
<div v-else> <div v-else>
<div class="tabs"> <h2 class="my-4 text-2xl">Setup Errors</h2>
<ul> <div class="p-3 rounded bg-gray-800 text-white">
<li> <pre
<a>Setup Errors</a> class="font-mono leading-snug text-xs"
</li> v-for="(error, i) in run.setup_errors"
</ul> v-bind:key="i"
</div> >{{error}}</pre>
<div class="setuperrors">
<span class="error-line" v-for="(error, i) in run.setup_errors" v-bind:key="i">{{error}}</span>
</div> </div>
</div> </div>
</div> </div>
@ -138,65 +137,4 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
.tasks-list {
.task-content {
margin-bottom: 5px;
border: 1px solid $grey-lighter;
border-left: 0 solid;
justify-content: space-between;
align-items: center;
padding: 10px;
}
.success {
border-left: 5px solid $green;
}
.failed {
border-left: 5px solid $red;
}
.running {
border-left: 5px solid $blue;
}
.unknown {
border-left: 5px solid $grey-lighter;
}
.name {
font-weight: bold;
}
.parents {
margin-left: 1rem;
margin-right: 0rem;
font-weight: lighter;
font-size: 0.8rem;
.parent {
font-weight: normal;
}
}
}
.setuperrors {
background-color: #222;
color: #f1f1f1;
font-family: Cousine, monospace;
font-size: 12px;
line-height: 19px;
white-space: pre-wrap;
word-wrap: break-word;
text-align: left;
font-size: 12px;
padding: 5px;
.error-line {
pre {
line-height: 1.2;
}
}
}
</style> </style>

View File

@ -1,110 +1,128 @@
<template> <template>
<div> <div>
<div v-if="run != null"> <div v-if="run != null">
<div class="run"> <div
<div :class="runResultClass(run)"> v-if="stopRunError"
<div class="run-content"> class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
<div class="item-content columns"> role="alert"
<div class="run-title column is-10"> >
<span class="run-name">{{run.name}}</span> <span class="block sm:inline">{{ stopRunError }}</span>
<span </div>
class="tag" <div
:class="'is-'+runResultClass(run)" v-if="cancelRunError"
>{{ runStatus(run) | capitalize }}</span> class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
<span v-if="stillRunning(run)" class="stillrunning tag">Still running</span> role="alert"
<span v-if="!stillRunning(run)" class="stillrunning"></span> >
</div> <span class="block sm:inline">{{ cancelRunError }}</span>
<div class="run-actions column is-2 is-pulled-right"> </div>
<div <div
v-if="run.can_restart_from_scratch || run.can_restart_from_failed_tasks" v-if="restartRunError"
class="dropdown is-right" class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
v-click-outside="() => dropdownActive = false" role="alert"
v-bind:class="{ 'is-active': dropdownActive }" >
> <span class="block sm:inline">{{ restartRunError }}</span>
<div class="dropdown-trigger"> </div>
<button class="button" @click="toggleDropdown()">
<span>Restart</span> <div class="mb-2 border-l-5 rounded shadow" :class="runResultClass(run)">
<span class="icon is-small"> <div class="p-4 border border-l-0 rounded-r">
<i class="mdi mdi-restart" aria-hidden="true"></i> <div class="flex items-start justify-between">
</span> <div class="flex items-center">
</button> <span class="text-2xl mr-3">{{run.name}}</span>
</div> <span
<div class="dropdown-menu" role="menu"> class="mr-3 rounded px-2 py-1 text-xs"
<div class="dropdown-content"> :class="'is-' + runResultClass(run)"
<a >{{ runStatus(run) | capitalize }}</span>
v-if="run.can_restart_from_scratch" <span
class="dropdown-item" v-if="stillRunning(run)"
@click="restartRun(run.id, true)" class="rounded bg-gray-500 text-white px-2 py-1 text-xs"
>From start</a> >Still running</span>
<a
v-if="run.can_restart_from_failed_tasks"
class="dropdown-item"
@click="restartRun(run.id)"
>From failed tasks</a>
</div>
</div>
</div>
<button
class="button is-danger"
v-if="run.phase == 'queued'"
@click="cancelRun(run.id)"
>Cancel</button>
<button
class="button is-danger"
v-if="run.phase == 'running'"
:disabled="run.stopping"
@click="stopRun(run.id)"
>Stop</button>
</div>
</div> </div>
<div class="item-content columns"> <div class="relative mr-3">
<div class="commitmessage column">{{run.annotations.message}}</div> <div
<div class="source-info column"> v-if="run.can_restart_from_scratch || run.can_restart_from_failed_tasks"
<a :href="run.annotations.commit_link" class="commit" target="_blank"> class="flex"
<i class="mdi mdi-source-commit mdi-rotate-90"></i> v-click-outside="() => dropdownActive = false"
<span>{{run.annotations.commit_sha.substring(0,8)}}</span> >
</a> <div class="flex items-center">
<a <button class="btn btn-blue" @click="toggleDropdown()">
v-if="run.annotations.event_type == 'push'" <span>Restart</span>
:href="run.annotations.branch_link" <i class="ml-3 mdi mdi-restart" aria-hidden="true"></i>
class="commit" </button>
target="_blank" </div>
>
<i class="mdi mdi-source-branch"></i>
<span>{{run.annotations.branch}}</span>
</a>
<a
v-else-if="run.annotations.event_type == 'tag'"
:href="run.annotations.tag_link"
class="commit"
target="_blank"
>
<i class="mdi mdi-tag"></i>
<span>{{run.annotations.tag}}</span>
</a>
<a
v-else-if="run.annotations.event_type == 'pull_request'"
:href="run.annotations.pull_request_link"
class="commit"
target="_blank"
>
<i class="mdi mdi-source-pull"></i>
<span>PR #{{run.annotations.pull_request_id}}</span>
</a>
</div> </div>
<div
v-if="dropdownActive"
class="z-10 origin-top-right absolute right-0 mt-2 w-64 bg-white rounded-lg border shadow-md py-2"
>
<ul>
<li>
<a
v-if="run.can_restart_from_scratch"
class="block px-4 py-2 hover:bg-blue-500 hover:text-white"
@click="restartRun(run.id, true)"
>From start</a>
</li>
<li>
<a
v-if="run.can_restart_from_failed_tasks"
class="block px-4 py-2 hover:bg-blue-500 hover:text-white"
@click="restartRun(run.id)"
>From failed tasks</a>
</li>
</ul>
</div>
<button
class="btn btn-red"
v-if="run.phase == 'queued'"
@click="cancelRun(run.id)"
>Cancel</button>
<button
class="btn btn-red"
v-if="run.phase == 'running'"
:disabled="run.stopping"
@click="stopRun(run.id)"
>Stop</button>
</div>
</div>
<div class="flex">
<div class="w-1/2">{{run.annotations.message}}</div>
<div class="w-1/2">
<a :href="run.annotations.commit_link" class="block" target="_blank">
<i class="mdi mdi-source-commit mdi-rotate-90"></i>
<span>{{run.annotations.commit_sha.substring(0,8)}}</span>
</a>
<a
v-if="run.annotations.event_type == 'push'"
:href="run.annotations.branch_link"
class="block"
target="_blank"
>
<i class="mdi mdi-source-branch"></i>
<span>{{run.annotations.branch}}</span>
</a>
<a
v-else-if="run.annotations.event_type == 'tag'"
:href="run.annotations.tag_link"
class="block"
target="_blank"
>
<i class="mdi mdi-tag"></i>
<span>{{run.annotations.tag}}</span>
</a>
<a
v-else-if="run.annotations.event_type == 'pull_request'"
:href="run.annotations.pull_request_link"
class="block"
target="_blank"
>
<i class="mdi mdi-source-pull"></i>
<span>PR #{{run.annotations.pull_request_id}}</span>
</a>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div v-if="stopRunError" class="message is-danger">
<div class="message-body">{{ stopRunError }}</div>
</div>
<div v-if="cancelRunError" class="message is-danger">
<div class="message-body">{{ cancelRunError }}</div>
</div>
<div v-if="cancelRunError" class="message is-danger">
<div class="message-body">{{ cancelRunError }}</div>
</div>
</div> </div>
</div> </div>
</template> </template>
@ -222,100 +240,4 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
.run {
margin-bottom: 2rem;
.run-content {
margin-bottom: 5px;
border: 1px solid $grey-lighter;
border-left: 0 solid;
display: block;
justify-content: space-between;
align-items: center;
padding: 10px;
}
.run-title {
align-items: center;
padding-left: 5px;
margin-bottom: 25px;
.run-name {
padding-left: 5px;
font-size: 1.5rem;
padding-right: 1rem;
}
.success {
border-left: 0px solid $green;
}
.failed {
border-left: 5px solid $red;
}
.running {
border-left: 5px solid $blue;
}
.unknown {
border-left: 5px solid $grey-lighter;
}
}
.run-actions {
text-align: right;
}
.item-content {
}
.success {
border-left: 5px solid $green;
}
.failed {
border-left: 5px solid $red;
}
.running {
border-left: 5px solid $blue;
}
.unknown {
border-left: 5px solid $grey-lighter;
}
.setuperror {
border-left: 5px solid $yellow;
}
.name {
font-weight: bold;
cursor: pointer;
}
.commitmessage {
}
.stillrunning {
}
.source-info {
overflow: hidden;
white-space: nowrap;
a {
overflow: hidden;
text-overflow: ellipsis;
}
}
.commit {
display: block;
font-size: 0.8rem;
}
}
</style> </style>

View File

@ -1,34 +1,44 @@
<template> <template>
<div> <div>
<div v-if="runs.length > 0"> <div v-if="runs.length > 0">
<div class="item-list"> <ul>
<div v-for="run in runs" v-bind:key="run.id" :class="runResultClass(run)"> <li
<div class="item-content"> class="mb-2 border-l-5 rounded-l"
v-for="run in runs"
v-bind:key="run.id"
:class="runResultClass(run)"
>
<div class="pl-4 flex items-center border border-l-0 rounded-r">
<router-link <router-link
v-if="projectref" v-if="projectref"
tag="div" class="w-1/3 font-bold"
class="name"
:to="projectRunLink(ownertype, ownername, projectref, run.id)" :to="projectRunLink(ownertype, ownername, projectref, run.id)"
> >
<span class>{{run.name}}</span>
</router-link>
<router-link v-else class="w-1/3 font-bold" :to="userLocalRunLink(ownername, run.id)">
<span>{{run.name}}</span> <span>{{run.name}}</span>
</router-link> </router-link>
<router-link v-else tag="div" class="name" :to="userLocalRunLink(ownername, run.id)"> <div class="w-1/3">{{run.annotations.message}}</div>
<span>{{run.name}}</span> <span
</router-link> v-if="waitingApproval(run)"
<div class="commitmessage">{{run.annotations.message}}</div> class="w-1/5 inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold mr-2"
<span v-if="waitingApproval(run)" class="waitingapproval tag">Waiting Approval</span> >Waiting Approval</span>
<span v-if="!waitingApproval(run)" class="waitingapproval"></span> <span v-if="!waitingApproval(run)" class="w-1/5"></span>
<span v-if="stillRunning(run)" class="stillrunning tag">Still running</span> <span
<span v-if="!stillRunning(run)" class="stillrunning"></span> v-if="stillRunning(run)"
<div class="source-info"> class="w-1/5 inline-block bg-gray-200 rounded-full px-3 py-1 text-sm font-semibold mr-2"
<a :href="run.annotations.commit_link" class="commit" target="_blank"> >Still running</span>
<span v-if="!stillRunning(run)" class="w-1/5"></span>
<div class="w-32">
<a :href="run.annotations.commit_link" class="block" target="_blank">
<i class="mdi mdi-source-commit mdi-rotate-90"></i> <i class="mdi mdi-source-commit mdi-rotate-90"></i>
<span>{{run.annotations.commit_sha.substring(0,8)}}</span> <span>{{run.annotations.commit_sha.substring(0,8)}}</span>
</a> </a>
<a <a
v-if="run.annotations.event_type == 'push'" v-if="run.annotations.event_type == 'push'"
:href="run.annotations.branch_link" :href="run.annotations.branch_link"
class="commit" class="block whitespace-no-wrap overflow-x-hidden"
target="_blank" target="_blank"
> >
<i class="mdi mdi-source-branch"></i> <i class="mdi mdi-source-branch"></i>
@ -37,7 +47,7 @@
<a <a
v-else-if="run.annotations.event_type == 'tag'" v-else-if="run.annotations.event_type == 'tag'"
:href="run.annotations.tag_link" :href="run.annotations.tag_link"
class="commit" class="block"
target="_blank" target="_blank"
> >
<i class="mdi mdi-tag"></i> <i class="mdi mdi-tag"></i>
@ -46,7 +56,7 @@
<a <a
v-else-if="run.annotations.event_type == 'pull_request'" v-else-if="run.annotations.event_type == 'pull_request'"
:href="run.annotations.pull_request_link" :href="run.annotations.pull_request_link"
class="commit" class="block"
target="_blank" target="_blank"
> >
<i class="mdi mdi-source-pull"></i> <i class="mdi mdi-source-pull"></i>
@ -54,17 +64,17 @@
</a> </a>
</div> </div>
</div> </div>
</div> </li>
</div> </ul>
<div class="has-text-centered"> <div class="flex justify-center my-3">
<button <button
v-if="hasMoreRuns" v-if="hasMoreRuns"
class="button is-primary is-outlined is-fullwidth load-more-button" class="bg-transparent hover:bg-blue-500 text-blue-700 font-semibold hover:text-white py-2 px-4 border border-blue-500 hover:border-transparent rounded"
@click="loadMoreRuns()" @click="loadMoreRuns()"
>Load more...</button> >Load more...</button>
</div> </div>
</div> </div>
<div v-else class="item-list">No runs</div> <div v-else class>No runs</div>
</div> </div>
</template> </template>
@ -218,88 +228,4 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
.project-title {
display: flex;
align-items: center;
padding-left: 5px;
margin-bottom: 25px;
.project-name {
padding-left: 5px;
font-size: 1.5rem;
padding-right: 1rem;
}
}
.item-list {
.item-content {
margin-bottom: 5px;
border: 1px solid $grey-lighter;
border-left: 0 solid;
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
}
.success {
border-left: 5px solid $green;
}
.failed {
border-left: 5px solid $red;
}
.running {
border-left: 5px solid $blue;
}
.unknown {
border-left: 5px solid $grey-lighter;
}
.setuperror {
border-left: 5px solid $yellow;
}
.name {
flex: 0 0 30%;
font-weight: bold;
cursor: pointer;
}
.commitmessage {
flex: 0 0 40%;
}
.stillrunning {
flex: 0 0 10%;
}
.waitingapproval {
flex: 0 0 10%;
}
.source-info {
flex: 0 0 10%;
overflow: hidden;
white-space: nowrap;
a {
overflow: hidden;
text-overflow: ellipsis;
}
}
.commit {
display: block;
font-size: 0.8rem;
}
}
.load-more-button {
margin-top: 1rem;
margin-bottom: 2rem;
}
</style> </style>

View File

@ -2,18 +2,20 @@
<div> <div>
<RunDetail :run="run"/> <RunDetail :run="run"/>
<div v-if="task != null"> <div v-if="task != null">
<div class="columns"> <div class="mt-8 mb-4 flex justify-between items-center">
<div class="task-title column is-10"> <div class="flex items-center">
<span class="task-name" v-html="task.name"/> <span class="text-2xl mr-3">{{task.name}}</span>
<span class="tag" :class="taskClass(task)">{{ task.status | capitalize }}</span>
</div> <span
<div class="task-actions column is-2 is-pulled-right"> class="mr-3 rounded px-2 py-1 text-xs"
<button :class="taskClass(task)"
class="button is-primary" >{{ task.status | capitalize }}</span>
v-if="task.waiting_approval"
@click="approveTask(run.id, task.id)"
>Approve</button>
</div> </div>
<button
v-if="task.waiting_approval"
class="btn btn-blue"
@click="approveTask(run.id, task.id)"
>Approve</button>
</div> </div>
<Collapse <Collapse
v-bind:runid="runid" v-bind:runid="runid"
@ -98,20 +100,4 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.task-title {
display: flex;
align-items: center;
padding-left: 5px;
margin-bottom: 25px;
.task-name {
padding-left: 5px;
font-size: 1.5rem;
padding-right: 1rem;
}
}
.task-actions {
text-align: right;
}
</style> </style>

View File

@ -1,107 +1,147 @@
<template> <template>
<div> <div>
<nav class="panel"> <div class="panel">
<p class="panel-heading">Linked Accounts</p> <p class="panel-title">Linked Accounts</p>
<div class="panel-block is-block"> <div class="p-4">
<div class="message is-danger"> <div
<div class="mb-4 bg-red-100 border-l-4 border-red-500 text-red-700 p-4 rounded"
class="message-body" role="alert"
>Removing a Linked Account will also block all the projects that uses this Linked Account to access their remote repository</div> >
<p>Removing a Linked Account will also block all the projects that uses this Linked Account to access their remote repository</p>
</div> </div>
<ul v-if="user.linked_accounts"> <ul v-if="user.linked_accounts">
<li class="item-list" v-for="(la, index) in user.linked_accounts" v-bind:key="index"> <li
<div class="level item"> class="flex justify-between items-center mb-2"
<div class="level-left"> v-for="(la, index) in user.linked_accounts"
<div class="level-item"> v-bind:key="index"
<div> >
<span class="name">{{la.remote_user_name}}</span> <div>
<span class="remotesource-name">(on remote source {{laRemoteSourceName(la)}})</span> <span class="font-bold">{{la.remote_user_name}}</span>
</div> <span class="ml-1">(on remote source {{laRemoteSourceName(la)}})</span>
</div>
</div>
<div class="level-right">
<div class="level-item">
<button class="button is-primary" @click="deleteLinkedAccount(la)">Delete</button>
</div>
</div>
</div> </div>
<button class="btn btn-red" @click="deleteLinkedAccount(la)">Delete</button>
</li> </li>
<div v-if="deleteLinkedAccountError" class="message is-danger"> <div
<div class="message-body">{{ deleteLinkedAccountError }}</div> v-if="deleteLinkedAccountError"
class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
role="alert"
>
<span class="block sm:inline">{{ deleteLinkedAccountError }}</span>
</div> </div>
</ul> </ul>
<div v-else>No linked accounts</div> <div v-else>No linked accounts</div>
</div> </div>
<div v-if="remotesources.length" class="panel-block is-block"> <div v-if="remotesources.length" class="p-4 border-t">
<h5 class="title is-5">Add new linked account</h5> <h5 class="mb-3 text-xl">Add new linked account</h5>
<div class="field is-grouped">
<div class="control"> <div class="inline-block">
<div class="select"> <div class="flex mb-3 relative w-64">
<select v-model="selectedRemoteSourceName"> <select
<option v-for="rs in remotesources" v-bind:key="rs.id">{{ rs.name }}</option> class="block appearance-none w-full bg-white border border-gray-400 hover:border-gray-500 px-4 py-2 pr-8 rounded shadow leading-tight focus:outline-none focus:shadow-outline"
</select> v-model="selectedRemoteSourceName"
>
<option v-for="rs in remotesources" v-bind:key="rs.id">{{ rs.name }}</option>
</select>
<div class="pointer-events-none absolute inset-y-0 right-0 flex items-center px-2">
<svg
class="fill-current h-4 w-4"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
>
<path
d="M9.293 12.95l.707.707L15.657 8l-1.414-1.414L10 10.828 5.757 6.586 4.343 8z"
></path>
</svg>
</div> </div>
</div> </div>
<button class="button is-primary" @click="addLinkedAccount()">Add Linked Account</button>
</div> </div>
</div>
</nav>
<nav class="panel"> <button class="ml-3 btn btn-blue" @click="addLinkedAccount()">Add Linked Account</button>
<p class="panel-heading">User Tokens</p> </div>
<div class="panel-block is-block"> </div>
<div v-if="user.tokens">
<div class="item-list" v-for="token in user.tokens" v-bind:key="token"> <div class="panel">
<nav class="level item"> <p class="panel-title">User Tokens</p>
<div class="level-left"> <div class="p-4">
<div class="level-item"> <ul v-if="user.tokens">
<div class="control"> <li
<input class="flex justify-between items-center mb-2"
class="input" v-for="token in user.tokens"
disabled v-bind:key="token"
type="text" >
placeholder="Token name" <span class="font-bold">{{token}}</span>
:value="token" <button class="btn btn-red" @click="deleteUserToken(token)">Delete</button>
> </li>
</div> <div
</div> v-if="deleteUserTokenError"
</div> class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
<div class="level-right"> role="alert"
<div class="level-item"> >
<button class="button is-primary" @click="deleteUserToken(token)">Delete</button> <span class="block sm:inline">{{ deleteUserTokenError }}</span>
</div>
</div>
</nav>
</div> </div>
<div v-if="deleteUserTokenError" class="message is-danger"> </ul>
<div class="message-body">{{ deleteUserTokenError }}</div>
</div>
</div>
<div v-else>No user tokens</div> <div v-else>No user tokens</div>
</div> </div>
<div class="panel-block is-block"> <div class="p-4 border-t">
<div v-if="token" class="notification is-success"> <div
<button class="delete" @click="closeNewTokenNotification()"></button> v-if="token"
User token created: {{token}} class="my-3 relative bg-teal-100 border-t-4 border-teal-500 rounded-b text-teal-900 px-4 py-3 shadow-md"
</div> role="alert"
<h5 class="title is-5">Create new User Token</h5> >
<div class="field is-grouped"> <div class="flex">
<div class="control"> <div class="py-1">
<input <svg
class="input is-primary" class="fill-current h-6 w-6 text-teal-500 mr-4"
type="text" xmlns="http://www.w3.org/2000/svg"
placeholder="Token name" viewBox="0 0 20 20"
v-model="newtokenname" >
> <path
d="M2.93 17.07A10 10 0 1 1 17.07 2.93 10 10 0 0 1 2.93 17.07zm12.73-1.41A8 8 0 1 0 4.34 4.34a8 8 0 0 0 11.32 11.32zM9 11V9h2v6H9v-4zm0-6h2v2H9V5z"
></path>
</svg>
</div>
<div>
<p class="font-bold">User token created. Copy it now since it won't be showed again</p>
<p class="text-sm">{{token}}</p>
</div>
</div> </div>
<button class="button is-primary" @click="createUserToken()">Create Token</button> <span
class="absolute top-0 bottom-0 right-0 px-4 py-3"
@click="closeNewTokenNotification()"
>
<svg
class="fill-current h-6 w-6 text-teal-500"
role="button"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
>
<title>Close</title>
<path
d="M14.348 14.849a1.2 1.2 0 0 1-1.697 0L10 11.819l-2.651 3.029a1.2 1.2 0 1 1-1.697-1.697l2.758-3.15-2.759-3.152a1.2 1.2 0 1 1 1.697-1.697L10 8.183l2.651-3.031a1.2 1.2 0 1 1 1.697 1.697l-2.758 3.152 2.758 3.15a1.2 1.2 0 0 1 0 1.698z"
></path>
</svg>
</span>
</div> </div>
<div v-if="createUserTokenError" class="message is-danger"> <h5 class="mb-3 text-xl">Create new User Token</h5>
<div class="message-body">{{ createUserTokenError }}</div> <div class="control">
<input
class="shadow appearance-none border rounded py-2 px-3 leading-tight focus:outline-none focus:shadow-outline"
type="text"
placeholder="Token name"
v-model="newtokenname"
>
<button class="ml-3 btn btn-blue" @click="createUserToken()">Create Token</button>
</div>
<div
v-if="createUserTokenError"
class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
role="alert"
>
<span class="block sm:inline">{{ createUserTokenError }}</span>
</div> </div>
</div> </div>
</nav> </div>
</div> </div>
</template> </template>
@ -219,18 +259,5 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
.item-list {
.item {
padding: 10px;
}
.name {
font-weight: bold;
}
.remotesource-name {
margin-left: 0.5rem;
}
}
</style> </style>

View File

@ -1,64 +1,54 @@
<template> <template>
<div> <div>
<div class="columns has-text-weight-bold"> <div class="my-3 flex font-bold">
<div class="column is-2">Name</div> <div class="w-1/3">Name</div>
<div class="column is-10"> <div class="w-2/3">
<div class="columns"> <div class="flex">
<div class="column is-2">Secret Name</div> <div class="w-1/3">Secret Name</div>
<div class="column is-2">Secret Value</div> <div class="w-1/3">Secret Value</div>
<div class="column"> <div class="w-1/3">
<div class="columns"> <div class="flex">
<div class="column">Conditions</div> <div class="w-1/3 mr-2">Conditions</div>
<div class="column">Include</div> <div class="w-1/3 mr-2">Include</div>
<div class="column">Exclude</div> <div class="w-1/3 mr-2">Exclude</div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
</div> </div>
<div class="columns" v-for="variable in variables" v-bind:key="variable.id"> <div class="flex" v-for="variable in variables" v-bind:key="variable.id">
<div class="column is-2"> <div class="w-1/3">
<span class="name">{{variable.name}}</span> <span class="name">{{variable.name}}</span>
<div v-if="showparentpath" class="var-parent-path">from {{variable.parent_path}}</div> <div v-if="showparentpath" class="text-sm font-light">from {{variable.parent_path}}</div>
</div> </div>
<div class="column is-10"> <div class="w-2/3">
<div class="item-list" v-for="val in variable.values" v-bind:key="val.id"> <div class="flex" v-for="val in variable.values" v-bind:key="val.id">
<div class="columns"> <div class="w-1/3">
<div class="column is-2"> <span>{{val.secret_name}}</span>
<span class="secret-name">{{val.secret_name}}</span> <div
<div v-if="val.matching_secret_parent_path"
v-if="val.matching_secret_parent_path" class="text-sm"
class="matching-secret" >using secret from {{val.matching_secret_parent_path}}</div>
>using secret from {{val.matching_secret_parent_path}}</div> <div v-else class="text-sm text-red-600">no matching secret</div>
<div v-else class="no-matching-secret">no matching secret</div> </div>
</div> <div class="w-1/3">
<div class="column is-2"> <span>{{val.secret_var}}</span>
<span class="secret-var">{{val.secret_var}}</span> </div>
</div> <div class="w-1/3">
<div class="column"> <div v-if="val.when">
<div v-if="val.when"> <div v-if="val.when.branch">
<div v-if="val.when.branch"> <div class="flex">
<div class="columns"> <div class="w-1/3">
<div class="column"> <span>branch</span>
<span>branch</span> </div>
<div class="w-1/3">
<div v-for="include in val.when.branch.include" v-bind:key="include.match">
<span>{{include.match}}</span>
</div> </div>
<div class="column"> </div>
<div <div class="w-1/3">
class="item-list" <div v-for="exclude in val.when.branch.exclude" v-bind:key="exclude.match">
v-for="include in val.when.branch.include" <span>{{exclude.match}}</span>
v-bind:key="include.match"
>
<span class="secret-name">{{include.match}}</span>
</div>
</div>
<div class="column">
<div
class="item-list"
v-for="exclude in val.when.branch.exclude"
v-bind:key="exclude.match"
>
<span class="secret-name">{{exclude.match}}</span>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -83,30 +73,6 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
@import "~bulma/bulma.sass";
.name {
}
.secret-name {
font-weight: bold;
}
.var-parent-path {
@extend .has-text-weight-light;
@extend .is-size-7;
}
.matching-secret {
@extend .has-text-weight-light;
@extend .is-size-7;
}
.no-matching-secret {
@extend .has-text-danger;
@extend .is-size-7;
}
</style> </style>

View File

@ -1,6 +1,19 @@
// ** $ansi-black: #222;
// black $ansi-black-bright: #222;
// ** $ansi-red: #c0392b;
$ansi-red-bright: #e74c3c;
$ansi-green: #27af60;
$ansi-green-bright: #2ecc71;
$ansi-yellow: #f39c12;
$ansi-yellow-bright: #f1c40f;
$ansi-blue: #2e8dcd;
$ansi-blue-bright: #3498db;
$ansi-magenta: #8e44ad;
$ansi-magenta-bright: #9b59b6;
$ansi-cyan: #0097a4;
$ansi-cyan-bright: #02c8d9;
$ansi-white: #bdc3c7;
$ansi-white-bright: #ffffff;
.ansi-black-fg { .ansi-black-fg {
color: $ansi-black; color: $ansi-black;
@ -16,10 +29,6 @@
background-color: $ansi-black-bright; background-color: $ansi-black-bright;
} }
// **
// red
// **
.ansi-red-fg { .ansi-red-fg {
color: $ansi-red; color: $ansi-red;
} }
@ -34,10 +43,6 @@
background-color: $ansi-red-bright; background-color: $ansi-red-bright;
} }
// **
// green
// **
.ansi-green-fg { .ansi-green-fg {
color: $ansi-green; color: $ansi-green;
} }
@ -52,10 +57,6 @@
background-color: $ansi-green-bright; background-color: $ansi-green-bright;
} }
// **
// yellow
// **
.ansi-yellow-fg { .ansi-yellow-fg {
color: $ansi-yellow; color: $ansi-yellow;
} }
@ -70,10 +71,6 @@
background-color: $ansi-yellow-bright; background-color: $ansi-yellow-bright;
} }
// **
// blue
// **
.ansi-blue-fg { .ansi-blue-fg {
color: $ansi-blue; color: $ansi-blue;
} }
@ -88,10 +85,6 @@
background-color: $ansi-blue-bright; background-color: $ansi-blue-bright;
} }
// **
// magenta
// **
.ansi-magenta-fg { .ansi-magenta-fg {
color: $ansi-magenta; color: $ansi-magenta;
} }
@ -106,10 +99,6 @@
background-color: $ansi-magenta-bright; background-color: $ansi-magenta-bright;
} }
// **
// cyan
// **
.ansi-cyan-fg { .ansi-cyan-fg {
color: $ansi-cyan; color: $ansi-cyan;
} }
@ -124,10 +113,6 @@
background-color: $ansi-cyan-bright; background-color: $ansi-cyan-bright;
} }
// **
// white
// **
.ansi-white-fg { .ansi-white-fg {
color: $ansi-white; color: $ansi-white;
} }

View File

@ -1,72 +0,0 @@
@import "~bulma/sass/utilities/initial-variables.sass";
@import "~bulma/sass/utilities/functions.sass";
$grey: #8c9b9d;
$grey-light: #a9afb7;
$grey-lighter: #dee2e5;
$orange: #e67e22;
$yellow: #f1b70e;
$green: #2ecc71;
$turquoise: #1abc9c;
$blue: #3498db;
$purple: #8e44ad;
$red: #e42522;
$white-ter: #ecf0f1;
$primary: #34495e !default;
$grey-lighter-invert: findColorInvert($grey-lighter);
$green-invert: findColorInvert($green);
$red-invert: findColorInvert($red);
$blue-invert: findColorInvert($red);
$custom-colors: (
"unknown": (
$grey-lighter,
$grey-lighter-invert
),
"success": (
$green,
$green-invert
),
"failed": (
$red,
$red-invert
),
"running": (
$blue,
$blue-invert
)
);
$link: $grey;
$tabs-link-active-color: $blue;
$tabs-link-active-border-bottom-color: $blue;
$tabs-link-hover-color: $blue;
$tabs-link-hover-border-bottom-color: $blue;
$spacing: 20px;
$breadcrumb-item-color: $grey-dark !default;
$breadcrumb-item-hover-color: $grey-dark !default;
$breadcrumb-item-padding-vertical: 0 !default;
$breadcrumb-item-padding-horizontal: 0.5em !default;
$breadcrumb-item-separator-color: $grey-light !default;
$ansi-black: #222;
$ansi-black-bright: #222;
$ansi-red: #c0392b;
$ansi-red-bright: #e74c3c;
$ansi-green: #27af60;
$ansi-green-bright: #2ecc71;
$ansi-yellow: #f39c12;
$ansi-yellow-bright: #f1c40f;
$ansi-blue: #2e8dcd;
$ansi-blue-bright: #3498db;
$ansi-magenta: #8e44ad;
$ansi-magenta-bright: #9b59b6;
$ansi-cyan: #0097a4;
$ansi-cyan-bright: #02c8d9;
$ansi-white: #bdc3c7;
$ansi-white-bright: #ffffff;

View File

@ -1,5 +0,0 @@
@import "@/css/_variables.scss";
@import "~bulma/bulma.sass";
@import "./css/_ansi.scss";

138
src/css/tailwind.scss Normal file
View File

@ -0,0 +1,138 @@
@tailwind base;
@tailwind components;
@import "@/css/_ansi.scss";
.btn {
@apply font-bold py-2 px-4 rounded;
}
.btn-blue {
@apply bg-blue-500 text-white;
}
.btn-blue:hover {
@apply bg-blue-700;
}
.btn-blue:disabled {
@apply bg-blue-500 opacity-50 cursor-not-allowed;
}
.btn-blue:focus {
@apply bg-blue-500 outline-none shadow-outline;
}
.btn-red {
@apply bg-red-500 text-white;
}
.btn-red:hover {
@apply bg-red-700;
}
.btn-red:disabled {
@apply bg-red-500 opacity-50 cursor-not-allowed;
}
.btn-red:focus {
@apply bg-red-500 outline-none shadow-outline;
}
.tab {
@apply flex border-b-2;
}
.tab-element {
@apply px-4 -m-2px border-b-2;
}
.tab-element:hover {
@apply border-blue-300 text-blue-500;
}
.tab-element-selected {
@apply border-b-2 border-blue-300 text-blue-500;
}
.panel {
@apply mb-2 border-solid border-gray-300 rounded border shadow;
}
.panel-title {
@apply bg-gray-200 px-4 py-3 border-solid border-gray-300 border-b text-xl font-bold;
}
.success {
@apply border-green-400;
}
.is-success {
@apply bg-green-400 text-white;
}
.failed {
@apply border-red-600;
}
.is-failed {
@apply bg-red-600 text-white;
}
.running {
@apply border-blue-500;
}
.is-running {
@apply bg-blue-500 text-white;
}
.unknown {
@apply border-gray-400;
}
.is-unknown {
@apply bg-gray-400 text-white;
}
.setuperror {
@apply border-yellow-500;
}
.is-setuperror {
@apply bg-yellow-500 text-white;
}
.spinner {
color: transparent !important;
pointer-events: none;
position: relative;
&:after {
animation: spinAround 500ms infinite linear;
border: 2px solid #dae1e7;
border-radius: 290486px;
border-right-color: transparent;
border-top-color: transparent;
content: "";
display: block;
width: 1em;
height: 1em;
left: calc(50% - (1em / 2));
top: calc(50% - (1em / 2));
position: absolute !important;
}
}
@keyframes spinAround {
from {
transform: rotate(0deg);
}
to {
transform: rotate(359deg);
}
}
@tailwind utilities;
html {
overflow-x: hidden;
overflow-y: scroll;
}
body {
@apply text-dark;
}

View File

@ -1,3 +1,4 @@
import '@/css/tailwind.scss'
import "@mdi/font/css/materialdesignicons.css"; import "@mdi/font/css/materialdesignicons.css";
import Vue from "vue"; import Vue from "vue";

View File

@ -1,6 +1,13 @@
<template> <template>
<div> <div>
<div class="column is-4 is-offset-4"> <div
v-if="addLinkedAccountError"
class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
role="alert"
>
<span class="block sm:inline">{{ addLinkedAccountError }}</span>
</div>
<div class="my-6 flex justify-center items-center">
<div v-if="remotesource"> <div v-if="remotesource">
<LoginForm <LoginForm
v-if="remotesource.auth_type == 'password'" v-if="remotesource.auth_type == 'password'"
@ -10,13 +17,10 @@
/> />
<button <button
v-else v-else
class="button is-info is-fullwidth" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
@click="doAddLinkedAccount(remotesource.name)" @click="doAddLinkedAccount(remotesource.name)"
>Add Linked Account with {{remotesource.name}}</button> >Add Linked Account with {{remotesource.name}}</button>
</div> </div>
<div v-if="addLinkedAccountError" class="message is-danger">
<div class="message-body">{{ addLinkedAccountError }}</div>
</div>
</div> </div>
</div> </div>
</template> </template>

View File

@ -1,24 +1,34 @@
<template> <template>
<div> <div>
<div v-if="error" class="message is-danger"> <div
<div class="message-header"> v-if="error"
<p>Login error</p> class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
</div> role="alert"
<div class="message-body">{{ error }}</div> >
<span class="block sm:inline">{{ error }}</span>
</div> </div>
<div class="column is-4 is-offset-4"> <div>
<div class="box" v-for="rs in remotesources" v-bind:key="rs.id"> <div
class="my-6 flex justify-center items-center"
v-for="rs in remotesources"
v-bind:key="rs.id"
>
<LoginForm <LoginForm
action="Login" action="Login"
:name="rs.name" :name="rs.name"
v-if="rs.auth_type == 'password'" v-if="rs.auth_type == 'password'"
v-on:login="doLogin($event.username, $event.password, rs.name)" v-on:login="doLogin($event.username, $event.password, rs.name)"
/> />
<button <div v-else class="w-full max-w-xs">
v-else <div class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4">
class="button is-info is-fullwidth" <div class="flex justify-center">
@click="doLogin(null, null, rs.name)" <button
>Login with {{rs.name}}</button> class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
@click="doLogin(null, null, rs.name)"
>Login with {{rs.name}}</button>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -1,10 +1,11 @@
<template> <template>
<div> <div>
<div v-if="error" class="message is-danger"> <div
<div class="message-header"> v-if="error"
<p>Error</p> class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
</div> role="alert"
<div class="message-body">{{ error }}</div> >
<span class="block sm:inline">{{ error }}</span>
</div> </div>
</div> </div>
</template> </template>

View File

@ -1,62 +1,67 @@
<template> <template>
<div> <div>
<nav class="breadcrumb" aria-label="breadcrumbs"> <nav class="mb-4 bg-grey-light rounded font-sans w-full">
<ul> <ol class="list-reset flex text-grey-dark">
<li> <li>
<a>org</a> <a>org</a>
</li> </li>
<li>
<span class="mx-2">/</span>
</li>
<li> <li>
<router-link :to="ownerLink('org', orgname)">{{orgname}}</router-link> <router-link :to="ownerLink('org', orgname)">{{orgname}}</router-link>
</li> </li>
</ul> </ol>
</nav> </nav>
<div class="name"> <div class="mb-8 flex justify-between">
<span class="is-size-3">{{orgname}}</span> <span class="text-3xl">{{orgname}}</span>
<div class="is-pulled-right"> <createprojectbutton v-on:click="goToCreate($event)"/>
<createprojectbutton v-on:click="goToCreate($event)"/>
</div>
</div> </div>
<div class="tabs"> <div class="flex justify-between">
<ul> <ul class="flex-grow tab">
<li :class="[{ 'is-active': $route.name === 'org projects' || $route.name === 'org' }]"> <li
class="tab-element"
:class="[{ 'tab-element-selected': $route.name === 'org projects' || $route.name === 'org' }]"
>
<router-link :to="ownerProjectsLink('org', orgname)"> <router-link :to="ownerProjectsLink('org', orgname)">
<span class="icon is-small"> <i class="mr-1 mdi mdi-home"/>
<i class="mdi mdi-home"/>
</span>
<span>Projects</span> <span>Projects</span>
</router-link> </router-link>
</li> </li>
<li :class="[{ 'is-active': $route.name === 'org members' }]"> <li
class="tab-element"
:class="[{ 'tab-element-selected': $route.name === 'org members' }]"
>
<router-link :to="orgMembersLink(orgname)"> <router-link :to="orgMembersLink(orgname)">
<span class="icon is-small"> <i class="mr-1 mdi mdi-account-group"/>
<i class="mdi mdi-account-group"/>
</span>
<span>Members</span> <span>Members</span>
</router-link> </router-link>
</li> </li>
</ul> </ul>
<ul class="is-right"> <ul class="flex tab">
<li :class="[{ 'is-active': $route.name.endsWith('org project group settings') }]"> <li
class="tab-element"
:class="[{ 'tab-element-selected': $route.name.endsWith('org project group settings') }]"
>
<router-link :to="projectGroupSettingsLink('org', orgname, [])"> <router-link :to="projectGroupSettingsLink('org', orgname, [])">
<span class="icon is-small"> <i class="mr-1 mdi mdi-settings"/>
<i class="mdi mdi-settings"/>
</span>
<span>Root Project Group Settings</span> <span>Root Project Group Settings</span>
</router-link> </router-link>
</li> </li>
<li :class="[{ 'is-active': $route.name.endsWith('org settings') }]"> <li
class="tab-element"
:class="[{ 'tab-element-selected': $route.name.endsWith('org settings') }]"
>
<router-link :to="ownerSettingsLink('org', orgname)"> <router-link :to="ownerSettingsLink('org', orgname)">
<span class="icon is-small"> <i class="mr-1 mdi mdi-settings"/>
<i class="mdi mdi-settings"/>
</span>
<span>Organization Settings</span> <span>Organization Settings</span>
</router-link> </router-link>
</li> </li>
</ul> </ul>
</div> </div>
<router-view></router-view> <router-view class="mt-8"></router-view>
</div> </div>
</template> </template>
@ -104,10 +109,4 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
.name {
padding-left: 5px;
margin-bottom: 25px;
}
</style> </style>

View File

@ -2,64 +2,62 @@
<div> <div>
<projbreadcrumbs :ownertype="ownertype" :ownername="ownername" :projectref="projectref"/> <projbreadcrumbs :ownertype="ownertype" :ownername="ownername" :projectref="projectref"/>
<div class="name"> <div class="mb-8">
<span class="is-size-3">{{projectName()}}</span> <span class="text-3xl">{{projectName()}}</span>
</div> </div>
<div class="tabs"> <div class="flex justify-between">
<ul> <ul class="flex-grow tab">
<li> <li class="tab-element">
<span class="icon is-small"> <i class="mr-1 mdi mdi-run-fast"/>
<i class="mdi mdi-run-fast"/>
</span>
<span>Runs</span> <span>Runs</span>
</li> </li>
<li> <li>
<tabarrow/> <tabarrow/>
</li> </li>
<li <li
:class="[{ 'is-active': $route.name.match('project runs') || $route.name.endsWith('project') }]" class="tab-element"
:class="[{ 'tab-element-selected': $route.name.match('project runs') || $route.name.endsWith('project') }]"
> >
<router-link :to="projectRunsLink(ownertype, ownername, projectref)"> <router-link :to="projectRunsLink(ownertype, ownername, projectref)">
<span class="icon is-small"> <i class="mr-1 mdi mdi-asterisk"/>
<i class="mdi mdi-asterisk"/>
</span>
<span>All</span> <span>All</span>
</router-link> </router-link>
</li> </li>
<li :class="[{ 'is-active': $route.name.match('project branches runs') }]"> <li
class="tab-element"
:class="[{ 'tab-element-selected': $route.name.match('project branches runs') }]"
>
<router-link :to="projectBranchesRunsLink(ownertype, ownername, projectref)"> <router-link :to="projectBranchesRunsLink(ownertype, ownername, projectref)">
<span class="icon is-small"> <i class="mr-1 mdi mdi-source-branch"/>
<i class="mdi mdi-source-branch"/>
</span>
<span>Branches</span> <span>Branches</span>
</router-link> </router-link>
</li> </li>
<li :class="[{ 'is-active': $route.name.match('project tags runs') }]"> <li
class="tab-element"
:class="[{ 'tab-element-selected': $route.name.match('project tags runs') }]"
>
<router-link :to="projectTagsRunsLink(ownertype, ownername, projectref)"> <router-link :to="projectTagsRunsLink(ownertype, ownername, projectref)">
<span class="icon is-small"> <i class="mr-1 mdi mdi-tag"/>
<i class="mdi mdi-tag"/>
</span>
<span>Tags</span> <span>Tags</span>
</router-link> </router-link>
</li> </li>
<li :class="[{ 'is-active': $route.name.match('project pull requests runs') }]"> <li
class="tab-element"
:class="[{ 'tab-element-selected': $route.name.match('project pull requests runs') }]"
>
<router-link :to="projectPRsRunsLink(ownertype, ownername, projectref)"> <router-link :to="projectPRsRunsLink(ownertype, ownername, projectref)">
<span class="icon is-small"> <i class="mr-1 mdi mdi-source-pull"/>
<i class="mdi mdi-source-pull"/>
</span>
<span>Pull Requests</span> <span>Pull Requests</span>
</router-link> </router-link>
</li> </li>
<li <li v-if="$route.name.endsWith('project run') || $route.name.endsWith('project run task')">
v-if="$route.name.endsWith('project run') || $route.name.endsWith('project run task')"
:class="[{ 'is-active': $route.name.endsWith('project run') }]"
>
<tabarrow/> <tabarrow/>
</li> </li>
<li <li
class="tab-element"
v-if="$route.name.endsWith('project run') || $route.name.endsWith('project run task')" v-if="$route.name.endsWith('project run') || $route.name.endsWith('project run task')"
:class="[{ 'is-active': $route.name.endsWith('project run') }]" :class="[{ 'tab-element-selected': $route.name.endsWith('project run') }]"
> >
<router-link :to="projectRunLink(ownertype, ownername, projectref, $route.params.runid)"> <router-link :to="projectRunLink(ownertype, ownername, projectref, $route.params.runid)">
<p v-if="run"> <p v-if="run">
@ -68,13 +66,10 @@
</p> </p>
</router-link> </router-link>
</li> </li>
<li <li v-if="$route.name.endsWith('project run task')">
v-if="$route.name.endsWith('project run task')"
:class="[{ 'is-active': $route.name.endsWith('project run') }]"
>
<tabarrow/> <tabarrow/>
</li> </li>
<li v-if="$route.name.endsWith('project run task')" class="is-active"> <li class="tab-element" v-if="$route.name.endsWith('project run task')">
<router-link <router-link
:to="projectRunTaskLink(ownertype, ownername, projectref, $route.params.runid, $route.params.taskid)" :to="projectRunTaskLink(ownertype, ownername, projectref, $route.params.runid, $route.params.taskid)"
> >
@ -85,18 +80,19 @@
</router-link> </router-link>
</li> </li>
</ul> </ul>
<ul class="is-right"> <ul class="flex tab">
<li :class="[{ 'is-active': $route.name.endsWith('project settings') }]"> <li
class="tab-element"
:class="[{ 'tab-element-selected': $route.name.endsWith('project settings') }]"
>
<router-link :to="projectSettingsLink(ownertype, ownername, projectref)"> <router-link :to="projectSettingsLink(ownertype, ownername, projectref)">
<span class="icon is-small"> <i class="mr-1 mdi mdi-settings"/>
<i class="mdi mdi-settings"/>
</span>
<span>Project Settings</span> <span>Project Settings</span>
</router-link> </router-link>
</li> </li>
</ul> </ul>
</div> </div>
<router-view></router-view> <router-view class="mt-8"></router-view>
</div> </div>
</template> </template>
@ -170,10 +166,4 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
.name {
padding-left: 5px;
margin-bottom: 25px;
}
</style> </style>

View File

@ -7,38 +7,36 @@
:projectgroupref="projectgroupref" :projectgroupref="projectgroupref"
/> />
<div class="name"> <div class="mb-8 flex justify-between">
<span class="is-size-3">{{projectGroupName()}}</span> <span class="text-3xl">{{projectGroupName()}}</span>
<div class="is-pulled-right"> <createprojectbutton v-on:click="goToCreate($event)"/>
<createprojectbutton v-on:click="goToCreate($event)"/>
</div>
</div> </div>
<div class="tabs"> <div class="flex justify-between">
<ul> <ul class="flex-grow tab">
<li <li
:class="[{ 'is-active': $route.name.match('project group project') || $route.name.endsWith('project group') }]" class="tab-element"
:class="[{ 'tab-element-selected': $route.name.match('project group project') || $route.name.endsWith('project group') }]"
> >
<router-link :to="projectGroupProjectsLink(ownertype, ownername, projectgroupref)"> <router-link :to="projectGroupProjectsLink(ownertype, ownername, projectgroupref)">
<span class="icon is-small"> <i class="mdi mdi-home"/>
<i class="mdi mdi-home"/>
</span>
<span>Projects</span> <span>Projects</span>
</router-link> </router-link>
</li> </li>
</ul> </ul>
<ul class="is-right"> <ul class="flex tab">
<li :class="[{ 'is-active': $route.name.endsWith('project group settings') }]"> <li
class="tab-element"
:class="[{ 'tab-element-selected': $route.name.endsWith('project group settings') }]"
>
<router-link :to="projectGroupSettingsLink(ownertype, ownername, projectgroupref)"> <router-link :to="projectGroupSettingsLink(ownertype, ownername, projectgroupref)">
<span class="icon is-small"> <i class="mdi mdi-settings"/>
<i class="mdi mdi-settings"/>
</span>
<span>Project Group Settings</span> <span>Project Group Settings</span>
</router-link> </router-link>
</li> </li>
</ul> </ul>
</div> </div>
<router-view></router-view> <router-view class="mt-8"></router-view>
</div> </div>
</template> </template>
@ -97,10 +95,4 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
.name {
padding-left: 5px;
margin-bottom: 25px;
}
</style> </style>

View File

@ -1,25 +1,44 @@
<template> <template>
<div> <div>
<div v-if="registeruser" class="column is-4 is-offset-4"> <div
<div>{{registeruser.remote_user_info.LoginName}}</div> v-if="error"
<RegisterForm class="mb-10 bg-red-100 border border-red-400 text-red-700 px-4 py-3 rounded relative"
:username="registeruser.remote_user_info.LoginName" role="alert"
v-on:login="doRegister(registeruser.remote_source_name, $event.username, registeruser.remote_source_login_name, registeruser.remote_source_login_password)" >
/> <span class="block sm:inline">{{ error }}</span>
</div> </div>
<div v-else class="column is-4 is-offset-4"> <div v-if="registeruser" class="my-6 flex justify-center items-center">
<div class="box" v-for="rs in remotesources" v-bind:key="rs.id"> <div>
<div>{{registeruser.remote_user_info.LoginName}}</div>
<RegisterForm
:remote-username="registeruser.remote_user_info.LoginName"
:username="registeruser.remote_user_info.LoginName"
v-on:login="doRegister(registeruser.remote_source_name, $event.username, registeruser.remote_source_login_name, registeruser.remote_source_login_password)"
/>
</div>
</div>
<div v-else>
<div
class="my-6 flex justify-center items-center"
v-for="rs in remotesources"
v-bind:key="rs.id"
>
<LoginForm <LoginForm
action="Register" action="Register"
:name="rs.name" :name="rs.name"
v-if="rs.auth_type == 'password'" v-if="rs.auth_type == 'password'"
v-on:login="doAuthorize(rs.name, $event.username, $event.password)" v-on:login="doAuthorize(rs.name, $event.username, $event.password)"
/> />
<button <div v-else class="w-full max-w-xs">
v-else <div class="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4">
class="button is-info is-fullwidth" <div class="flex justify-center">
@click="doAuthorize(rs.name)" <button
>Register with {{rs.name}}</button> class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline"
@click="doAuthorize(rs.name)"
>Register with {{rs.name}}</button>
</div>
</div>
</div>
</div> </div>
</div> </div>
</div> </div>
@ -33,7 +52,7 @@ import RegisterForm from "@/components/registerform";
import { fetchRemoteSources, register } from "@/util/data"; import { fetchRemoteSources, register } from "@/util/data";
import { authorizeurl, registerurl, fetch, doLogout } from "@/util/auth"; import { authorizeurl, fetch, doLogout } from "@/util/auth";
export default { export default {
name: "Register", name: "Register",

View File

@ -1,95 +1,99 @@
<template> <template>
<div> <div>
<nav class="breadcrumb" aria-label="breadcrumbs"> <nav class="mb-4 bg-grey-light rounded font-sans w-full">
<ul> <ol class="list-reset flex text-grey-dark">
<li> <li>
<a>user</a> <a>user</a>
</li> </li>
<li>
<span class="mx-2">/</span>
</li>
<li> <li>
<router-link :to="ownerLink('user', username)">{{username}}</router-link> <router-link :to="ownerLink('user', username)">{{username}}</router-link>
</li> </li>
</ul> </ol>
</nav> </nav>
<div class="name"> <div class="mb-8 flex justify-between">
<span class="is-size-3">{{username}}</span> <span class="text-3xl">{{username}}</span>
<div class="is-pulled-right"> <createprojectbutton v-on:click="goToCreate($event)"/>
<createprojectbutton v-on:click="goToCreate($event)"/>
</div>
</div> </div>
<div class="tabs"> <div class="flex justify-between">
<ul> <ul class="flex-grow tab">
<li :class="[{ 'is-active': $route.name === 'user projects' || $route.name === 'user' }]"> <li
class="tab-element"
:class="[{ 'tab-element-selected': $route.name === 'user projects' || $route.name === 'user' }]"
>
<router-link :to="ownerProjectsLink('user', username)"> <router-link :to="ownerProjectsLink('user', username)">
<span class="icon is-small"> <i class="mr-1 mdi mdi-home"/>
<i class="mdi mdi-home"/>
</span>
<span>Projects</span> <span>Projects</span>
</router-link> </router-link>
</li> </li>
<li :class="[{ 'is-active': $route.name === 'user local runs' }]"> <li
class="tab-element"
:class="[{ 'tab-element-selected': $route.name === 'user local runs' }]"
>
<router-link :to="userLocalRunsLink(username)"> <router-link :to="userLocalRunsLink(username)">
<span class="icon is-small"> <i class="mr-1 mdi mdi-run-fast"/>
<i class="mdi mdi-run-fast"/>
</span>
<span>Local Runs</span> <span>Local Runs</span>
</router-link> </router-link>
</li> </li>
<li <li v-if="$route.name === 'user local run' || $route.name == 'user local run task'">
v-if="$route.name === 'user local run' || $route.name == 'user local run task'"
:class="[{ 'is-active': $route.name === 'user local run' }]"
>
<tabarrow/> <tabarrow/>
</li> </li>
<li <li
class="tab-element"
v-if="$route.name === 'user local run' || $route.name == 'user local run task'" v-if="$route.name === 'user local run' || $route.name == 'user local run task'"
:class="[{ 'is-active': $route.name === 'user local run' }]" :class="[{ 'tab-element-selected': $route.name === 'user local run' }]"
> >
<router-link :to="userLocalRunLink(username, $route.params.runid)"> <router-link :to="userLocalRunLink(username, $route.params.runid)">
<p v-if="run"> <span v-if="run">
Run Run
<strong>#{{run.counter}}</strong> <strong>#{{run.counter}}</strong>
</p> </span>
</router-link> </router-link>
</li> </li>
<li <li v-if="$route.name === 'user local run task'">
v-if="$route.name === 'user local run task'"
:class="[{ 'is-active': $route.name === 'user local run' }]"
>
<tabarrow/> <tabarrow/>
</li> </li>
<li v-if="$route.name == 'user local run task'" class="is-active"> <li
class="tab-element"
v-if="$route.name == 'user local run task'"
:class="[{ 'tab-element-selected': $route.name === 'user local run task' }]"
>
<router-link <router-link
:to="userLocalRunTaskLink(username, $route.params.runid, $route.params.taskid)" :to="userLocalRunTaskLink(username, $route.params.runid, $route.params.taskid)"
> >
<p v-if="run"> <span v-if="run">
Task Task
<strong>{{run.tasks[$route.params.taskid].name}}</strong> <strong>{{run.tasks[$route.params.taskid].name}}</strong>
</p> </span>
</router-link> </router-link>
</li> </li>
</ul> </ul>
<ul class="is-right"> <ul class="flex tab">
<li :class="[{ 'is-active': $route.name.endsWith('user project group settings') }]"> <li
class="tab-element"
:class="[{ 'tab-element-selected': $route.name.endsWith('user project group settings') }]"
>
<router-link :to="projectGroupSettingsLink('user', username, [])"> <router-link :to="projectGroupSettingsLink('user', username, [])">
<span class="icon is-small"> <i class="mr-1 mdi mdi-settings"/>
<i class="mdi mdi-settings"/>
</span>
<span>Root Project Group Settings</span> <span>Root Project Group Settings</span>
</router-link> </router-link>
</li> </li>
<li :class="[{ 'is-active': $route.name.endsWith('user settings') }]"> <li
class="tab-element"
:class="[{ 'tab-element-selected': $route.name.endsWith('user settings') }]"
>
<router-link :to="ownerSettingsLink('user', username)"> <router-link :to="ownerSettingsLink('user', username)">
<span class="icon is-small"> <i class="mr-1 mdi mdi-settings"/>
<i class="mdi mdi-settings"/>
</span>
<span>User Settings</span> <span>User Settings</span>
</router-link> </router-link>
</li> </li>
</ul> </ul>
</div> </div>
<router-view></router-view> <router-view class="mt-8"></router-view>
</div> </div>
</template> </template>
@ -161,10 +165,4 @@ export default {
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
@import "@/css/_variables.scss";
.name {
padding-left: 5px;
margin-bottom: 25px;
}
</style> </style>

61
tailwind.js Normal file
View File

@ -0,0 +1,61 @@
module.exports = {
theme: {
extend: {
container: {
center: true,
padding: '2rem',
},
borderWidth: {
default: '1px',
'0': '0',
'2': '2px',
'4': '4px',
'5': '5px',
'6': '6px',
},
spacing: {
px: '1px',
'2px': '2px',
'3px': '3px',
'0': '0',
'1': '0.25rem',
'2': '0.5rem',
'3': '0.75rem',
'4': '1rem',
'5': '1.25rem',
'6': '1.5rem',
'8': '2rem',
'10': '2.5rem',
'12': '3rem',
'16': '4rem',
'20': '5rem',
'24': '6rem',
'32': '8rem',
'40': '10rem',
'48': '12rem',
'56': '14rem',
'64': '16rem',
},
colors: {
dark: '#4a4a4a',
}
}
},
variants: {
backgroundColor: ['responsive', 'hover', 'focus', 'disabled'],
borderColor: ['responsive', 'hover', 'focus', 'disabled'],
boxShadow: ['responsive', 'hover', 'focus', 'disabled'],
cursor: ['responsive', 'disabled'],
opacity: ['responsive', 'disabled'],
textColor: ['responsive', 'hover', 'focus', 'disabled'],
},
plugins: [
function ({ addVariant, e }) {
addVariant('disabled', ({ modifySelectors, separator }) => {
modifySelectors(({ className }) => {
return `.${e(`disabled${separator}${className}`)}:disabled`
})
})
}
]
}