mirror of https://github.com/rancher/dashboard.git
commit
87765eaea7
|
|
@ -13,7 +13,8 @@
|
||||||
"${workspaceFolder}/**/*.js"
|
"${workspaceFolder}/**/*.js"
|
||||||
],
|
],
|
||||||
"envFile": "${workspaceFolder}/.env",
|
"envFile": "${workspaceFolder}/.env",
|
||||||
"outputCapture": "std"
|
"outputCapture": "std",
|
||||||
}
|
},
|
||||||
]
|
]
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -69,8 +69,6 @@ BUTTON,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
A {
|
A {
|
||||||
@include link-color(var(--link-text), var(--link-hover-text));
|
@include link-color(var(--link-text), var(--link-hover-text));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
$light : #6C6C76;
|
$light : #6C6C76;
|
||||||
|
|
||||||
//dark secondary
|
//dark secondary
|
||||||
$ligher : #B6B6C2;
|
$lighter : #B6B6C2;
|
||||||
|
|
||||||
// dark main text
|
// dark main text
|
||||||
$lightest : #FFFFFF;
|
$lightest : #FFFFFF;
|
||||||
|
|
@ -50,8 +50,9 @@
|
||||||
|
|
||||||
--login-bg : #{$darkest};
|
--login-bg : #{$darkest};
|
||||||
--body-bg : #{$darker};
|
--body-bg : #{$darker};
|
||||||
--body-text : #{$lightest};
|
--body-text : #{$lighter};
|
||||||
--scrollbar-thumb : #{$lighter};
|
--scrollbar-thumb : #{$medium};
|
||||||
|
--scrollbar-thumb-dropdown : #{$darker};
|
||||||
--header-bg : #{$primary};
|
--header-bg : #{$primary};
|
||||||
--box-bg : #{$darker};
|
--box-bg : #{$darker};
|
||||||
--border : #{$medium};
|
--border : #{$medium};
|
||||||
|
|
@ -100,3 +101,4 @@
|
||||||
--tabbed-border : #{$medium};
|
--tabbed-border : #{$medium};
|
||||||
--tabbed-container-bg : #{$darkest};
|
--tabbed-container-bg : #{$darkest};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -59,6 +59,7 @@ $selected: rgba($primary, .5);
|
||||||
--body-bg : white;
|
--body-bg : white;
|
||||||
--body-text : black;
|
--body-text : black;
|
||||||
--scrollbar-thumb : #{$dark};
|
--scrollbar-thumb : #{$dark};
|
||||||
|
--scrollbar-thumb-dropdown : #{$lighter};
|
||||||
--scrollbar-track : transparent;
|
--scrollbar-track : transparent;
|
||||||
--disabled-bg : #{$disabled};
|
--disabled-bg : #{$disabled};
|
||||||
--header-bg : #{$primary};
|
--header-bg : #{$primary};
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
font-family: inherit;
|
font-family: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
.v-select,
|
.v-select,
|
||||||
.v-select * {
|
.v-select * {
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
|
@ -38,6 +39,11 @@
|
||||||
text-align: left;
|
text-align: left;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
background: var(--dropdown-bg);
|
background: var(--dropdown-bg);
|
||||||
|
&::-webkit-scrollbar-thumb {
|
||||||
|
background-color: var(--scrollbar-thumb-dropdown) !important;
|
||||||
|
border-radius: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.vs__dropdown-option {
|
.vs__dropdown-option {
|
||||||
|
|
@ -80,6 +86,7 @@
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
padding: 4px 6px 0 3px;
|
padding: 4px 6px 0 3px;
|
||||||
|
pointer-events: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.vs--searchable .vs__dropdown-toggle {
|
.vs--searchable .vs__dropdown-toggle {
|
||||||
|
|
@ -154,28 +161,6 @@ $transition-duration: 150ms;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.vs__selected {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
background-color: #f0f0f0;
|
|
||||||
border: 1px solid var(--dropdown-border);
|
|
||||||
border-radius: 4px;
|
|
||||||
color: #333;
|
|
||||||
margin: 4px 2px 0px 2px;
|
|
||||||
padding: 0 0.25em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.vs__deselect {
|
|
||||||
display: inline-flex;
|
|
||||||
appearance: none;
|
|
||||||
margin-left: 4px;
|
|
||||||
padding: 0;
|
|
||||||
border: 0;
|
|
||||||
cursor: pointer;
|
|
||||||
background: none;
|
|
||||||
fill: rgba(60,60,60,0.5);
|
|
||||||
text-shadow: 0 1px 0 #fff;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* States */
|
/* States */
|
||||||
|
|
||||||
|
|
@ -192,3 +177,26 @@ $transition-duration: 150ms;
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.vs__selected {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
background-color: #f0f0f0;
|
||||||
|
border: 1px solid var(--dropdown-border);
|
||||||
|
border-radius: 4px;
|
||||||
|
color: var(--body-text);
|
||||||
|
margin: 4px 2px 0px 2px;
|
||||||
|
padding: 0 0.25em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.vs__deselect {
|
||||||
|
display: inline-flex;
|
||||||
|
appearance: none;
|
||||||
|
margin-left: 4px;
|
||||||
|
padding: 0;
|
||||||
|
border: 0;
|
||||||
|
cursor: pointer;
|
||||||
|
background: none;
|
||||||
|
fill: rgba(60,60,60,0.26);
|
||||||
|
text-shadow: 0 1px 0 #fff
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,108 @@
|
||||||
|
<script>
|
||||||
|
import { mapState } from 'vuex';
|
||||||
|
export default {
|
||||||
|
props: {
|
||||||
|
// filter files displayed in dropdown - default to .yml and Dockerfile files
|
||||||
|
filePattern: {
|
||||||
|
type: RegExp,
|
||||||
|
default: () => {
|
||||||
|
new RegExp('^.*\.(yml)$|.*(Dockerfile)\..*', 'i');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// page to redirect back to from GH
|
||||||
|
path: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
selectedRepo: null,
|
||||||
|
selectedBranch: null,
|
||||||
|
selectedFile: null
|
||||||
|
};
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
...mapState('github', ['repositories', 'branches', 'files', 'scopes']),
|
||||||
|
hasPrivate() {
|
||||||
|
return this.scopes.includes('repo');
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.$store.dispatch('github/getRepositories', { page: 0 });
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
selectRepo(repo) {
|
||||||
|
this.selectedBranch = null;
|
||||||
|
this.selectedRepo = repo;
|
||||||
|
this.$emit('selectedRepo', repo);
|
||||||
|
this.$store.dispatch('github/getBranches', { repo });
|
||||||
|
},
|
||||||
|
selectBranch(branch) {
|
||||||
|
this.selectedBranch = branch;
|
||||||
|
this.$emit('selectedBranch', branch);
|
||||||
|
this.$store.dispatch('github/getContents', {
|
||||||
|
repo: this.selectedRepo,
|
||||||
|
branch: this.selectedBranch,
|
||||||
|
filePattern: this.filePattern
|
||||||
|
});
|
||||||
|
},
|
||||||
|
selectFile(file) {
|
||||||
|
this.$emit('selectedFile', file);
|
||||||
|
},
|
||||||
|
expandScope() {
|
||||||
|
this.$store.dispatch('auth/redirectToGithub', { scopes: ['repo'], route: this.path } );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<div v-if="!hasPrivate" class="expand-scope">
|
||||||
|
<a
|
||||||
|
href="#"
|
||||||
|
class="text-primary bg-transparent"
|
||||||
|
@click="expandScope"
|
||||||
|
>
|
||||||
|
grant access to private repos
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
<div class="repo-dropdown">
|
||||||
|
<v-select
|
||||||
|
placeholder="Choose repository"
|
||||||
|
:options="repositories"
|
||||||
|
label="name"
|
||||||
|
:value="selectedRepo"
|
||||||
|
:clearable="false"
|
||||||
|
@input="selectRepo"
|
||||||
|
>
|
||||||
|
</v-select>
|
||||||
|
</div>
|
||||||
|
<div class="branch-dropdown">
|
||||||
|
<v-select
|
||||||
|
v-if="selectedRepo"
|
||||||
|
placeholder="Choose branch"
|
||||||
|
:options="branches"
|
||||||
|
label="name"
|
||||||
|
:value="selectedBranch"
|
||||||
|
:clearable="false"
|
||||||
|
@input="selectBranch"
|
||||||
|
>
|
||||||
|
</v-select>
|
||||||
|
</div>
|
||||||
|
<div class="file-dropdown">
|
||||||
|
<v-select
|
||||||
|
v-if="selectedBranch"
|
||||||
|
placeholder="Choose file"
|
||||||
|
:options="files"
|
||||||
|
label="path"
|
||||||
|
:value="selectedFile"
|
||||||
|
:clearable="false"
|
||||||
|
@input="selectFile"
|
||||||
|
>
|
||||||
|
</v-select>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -28,7 +28,7 @@ export default {
|
||||||
Security,
|
Security,
|
||||||
Upgrading,
|
Upgrading,
|
||||||
Volumes,
|
Volumes,
|
||||||
Footer,
|
Footer
|
||||||
},
|
},
|
||||||
mixins: [CreateEditView],
|
mixins: [CreateEditView],
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@
|
||||||
"build": "./node_modules/.bin/nuxt build",
|
"build": "./node_modules/.bin/nuxt build",
|
||||||
"analyze": "./node_modules/.bin/nuxt build --analyze",
|
"analyze": "./node_modules/.bin/nuxt build --analyze",
|
||||||
"start": "./node_modules/.bin/nuxt start",
|
"start": "./node_modules/.bin/nuxt start",
|
||||||
"generate": "./node_modules/.bin/nuxt generate"
|
"generate": "./node_modules/.bin/nuxt generate",
|
||||||
|
"dev-debug": "node --inspect ./node_modules/.bin/nuxt"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@innologica/vue-dropdown-menu": "^0.1.3",
|
"@innologica/vue-dropdown-menu": "^0.1.3",
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
<script>
|
<script>
|
||||||
export default {
|
export default {
|
||||||
layout: 'unauthenticated',
|
layout: 'unauthenticated',
|
||||||
|
|
||||||
async fetch({ store, route, redirect }) {
|
async fetch({ store, route, redirect }) {
|
||||||
const res = await store.dispatch('auth/verify', {
|
const res = await store.dispatch('auth/verify', {
|
||||||
code: route.query.code,
|
code: route.query.code,
|
||||||
|
|
|
||||||
|
|
@ -55,7 +55,7 @@ export const actions = {
|
||||||
return authConfig;
|
return authConfig;
|
||||||
},
|
},
|
||||||
|
|
||||||
async redirectToGithub({ state, commit, dispatch }, opt) {
|
async redirectToGithub({ state, commit, dispatch }, opt = {}) {
|
||||||
const authConfig = await dispatch('getAuthProvider');
|
const authConfig = await dispatch('getAuthProvider');
|
||||||
|
|
||||||
const nonce = randomStr(16);
|
const nonce = randomStr(16);
|
||||||
|
|
@ -71,10 +71,12 @@ export const actions = {
|
||||||
if ( opt && opt.scopes ) {
|
if ( opt && opt.scopes ) {
|
||||||
scopes.push(...opt.scopes);
|
scopes.push(...opt.scopes);
|
||||||
}
|
}
|
||||||
|
if (!opt.route) {
|
||||||
|
opt.route = '/auth/verify';
|
||||||
|
}
|
||||||
const url = addParams(authConfig.redirectUrl, {
|
const url = addParams(authConfig.redirectUrl, {
|
||||||
scope: [...BASE_SCOPES, ...scopes].join(','),
|
scope: [...BASE_SCOPES, ...scopes].join(','),
|
||||||
redirect_uri: `${ window.location.origin }/auth/verify${ (window.location.search || '').includes('spa') ? '?spa' : '' }`,
|
redirect_uri: `${ window.location.origin }${ opt.route }${ (window.location.search || '').includes('spa') ? '?spa' : '' }`,
|
||||||
state: nonce
|
state: nonce
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
export const state = function() {
|
||||||
|
return {
|
||||||
|
repositories: [],
|
||||||
|
branches: [],
|
||||||
|
files: [],
|
||||||
|
scopes: []
|
||||||
|
}
|
||||||
|
;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const actions = {
|
||||||
|
// queries on repos for which users have push permissions are paginated and unfilterable
|
||||||
|
getRepositories({ commit }) {
|
||||||
|
// eslint-disable-next-line prefer-const
|
||||||
|
let page = 1;
|
||||||
|
const getRepos = (page) => {
|
||||||
|
let scopes;
|
||||||
|
|
||||||
|
fetch(`${ window.location.origin }/v1/github/user/repos?per_page=100&affiliation=owner,collaborator&page=${ page }`)
|
||||||
|
.then((res) => {
|
||||||
|
scopes = res.headers.get('x-oauth-scopes');
|
||||||
|
|
||||||
|
return res.json();
|
||||||
|
})
|
||||||
|
.then((json) => {
|
||||||
|
if (json.length) {
|
||||||
|
page++;
|
||||||
|
commit('addToRepositories', { repos: json, scopes });
|
||||||
|
|
||||||
|
return getRepos(page);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
getRepos(page);
|
||||||
|
},
|
||||||
|
getBranches({ commit }, payload) {
|
||||||
|
fetch(`${ window.location.origin }/v1/github/repos/${ payload.repo.owner.login }/${ payload.repo.name }/branches`)
|
||||||
|
.then(res => res.json())
|
||||||
|
.then((json) => {
|
||||||
|
commit({ type: 'addBranches', branches: json });
|
||||||
|
});
|
||||||
|
},
|
||||||
|
getContents({ commit }, payload) {
|
||||||
|
fetch(`${ window.location.origin }/v1/github/repos/${ payload.repo.owner.login }/${ payload.repo.name }/git/trees/${ payload.branch.sha }?recursive=1`)
|
||||||
|
.then(res => res.json())
|
||||||
|
.then((json) => {
|
||||||
|
const files = json.tree.filter(file => file.type === 'blob' && file.path.match(payload.filePattern));
|
||||||
|
|
||||||
|
commit({ type: 'addFiles', files });
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
export const mutations = {
|
||||||
|
addToRepositories(state, payload) {
|
||||||
|
state.repositories = [...state.repositories, ...payload.repos];
|
||||||
|
state.scopes = payload.scopes;
|
||||||
|
},
|
||||||
|
addBranches(state, payload) {
|
||||||
|
state.branches = payload.branches;
|
||||||
|
},
|
||||||
|
addFiles(state, payload) {
|
||||||
|
state.files = payload.files;
|
||||||
|
}
|
||||||
|
};
|
||||||
Loading…
Reference in New Issue