Merge pull request #8 from rancherlabs/github-inputs

GitHub inputs
This commit is contained in:
Vincent Fiduccia 2019-10-15 11:44:01 -07:00 committed by GitHub
commit 87765eaea7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 222 additions and 36 deletions

5
.vscode/launch.json vendored
View File

@ -13,7 +13,8 @@
"${workspaceFolder}/**/*.js"
],
"envFile": "${workspaceFolder}/.env",
"outputCapture": "std"
}
"outputCapture": "std",
},
]
}

View File

@ -69,8 +69,6 @@ BUTTON,
}
}
A {
@include link-color(var(--link-text), var(--link-hover-text));

View File

@ -17,7 +17,7 @@
$light : #6C6C76;
//dark secondary
$ligher : #B6B6C2;
$lighter : #B6B6C2;
// dark main text
$lightest : #FFFFFF;
@ -50,8 +50,9 @@
--login-bg : #{$darkest};
--body-bg : #{$darker};
--body-text : #{$lightest};
--scrollbar-thumb : #{$lighter};
--body-text : #{$lighter};
--scrollbar-thumb : #{$medium};
--scrollbar-thumb-dropdown : #{$darker};
--header-bg : #{$primary};
--box-bg : #{$darker};
--border : #{$medium};
@ -100,3 +101,4 @@
--tabbed-border : #{$medium};
--tabbed-container-bg : #{$darkest};
}

View File

@ -59,6 +59,7 @@ $selected: rgba($primary, .5);
--body-bg : white;
--body-text : black;
--scrollbar-thumb : #{$dark};
--scrollbar-thumb-dropdown : #{$lighter};
--scrollbar-track : transparent;
--disabled-bg : #{$disabled};
--header-bg : #{$primary};

View File

@ -3,6 +3,7 @@
font-family: inherit;
}
.v-select,
.v-select * {
box-sizing: border-box;
@ -38,6 +39,11 @@
text-align: left;
list-style: none;
background: var(--dropdown-bg);
&::-webkit-scrollbar-thumb {
background-color: var(--scrollbar-thumb-dropdown) !important;
border-radius: 4px;
}
}
.vs__dropdown-option {
@ -80,6 +86,7 @@
display: flex;
align-items: center;
padding: 4px 6px 0 3px;
pointer-events: none;
}
.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 */
@ -192,3 +177,26 @@ $transition-duration: 150ms;
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
}

View File

@ -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>

View File

@ -28,7 +28,7 @@ export default {
Security,
Upgrading,
Volumes,
Footer,
Footer
},
mixins: [CreateEditView],

View File

@ -11,7 +11,8 @@
"build": "./node_modules/.bin/nuxt build",
"analyze": "./node_modules/.bin/nuxt build --analyze",
"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": {
"@innologica/vue-dropdown-menu": "^0.1.3",

View File

@ -1,7 +1,6 @@
<script>
export default {
layout: 'unauthenticated',
layout: 'unauthenticated',
async fetch({ store, route, redirect }) {
const res = await store.dispatch('auth/verify', {
code: route.query.code,

View File

@ -55,7 +55,7 @@ export const actions = {
return authConfig;
},
async redirectToGithub({ state, commit, dispatch }, opt) {
async redirectToGithub({ state, commit, dispatch }, opt = {}) {
const authConfig = await dispatch('getAuthProvider');
const nonce = randomStr(16);
@ -71,10 +71,12 @@ export const actions = {
if ( opt && opt.scopes ) {
scopes.push(...opt.scopes);
}
if (!opt.route) {
opt.route = '/auth/verify';
}
const url = addParams(authConfig.redirectUrl, {
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
});

66
store/github.js Normal file
View File

@ -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;
}
};