Initial commit
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
<template>
|
||||
<li class="apps__item">
|
||||
<div class="apps__icon">
|
||||
<img :src="oAuthApp.icon_url || require('../../assets/icons/apps/default.svg')">
|
||||
</div>
|
||||
|
||||
<div class="apps__item-info">
|
||||
<span class="text is-small is-semibold apps__item-title">{{ oAuthApp.name }}</span>
|
||||
<span class="text is-small apps__item-description">{{ oAuthApp.description || 'No description provided' }}</span>
|
||||
</div>
|
||||
|
||||
<slot />
|
||||
</li>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'AppElement',
|
||||
props: {
|
||||
oAuthApp: Object
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import 'new-dashboard/styles/variables';
|
||||
|
||||
.apps {
|
||||
&__item {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
justify-content: space-between;
|
||||
padding: 28px 0;
|
||||
border-bottom: 1px solid $neutral--300;
|
||||
}
|
||||
|
||||
&__item-info {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
&__item-title,
|
||||
&__item-description {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
&__item-title {
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
&__item-description {
|
||||
color: $neutral--600;
|
||||
}
|
||||
|
||||
&__icon {
|
||||
display: flex;
|
||||
position: relative;
|
||||
flex: 0 0 auto;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 56px;
|
||||
height: 56px;
|
||||
overflow: hidden;
|
||||
border: 1px solid $neutral--300;
|
||||
border-radius: 2px;
|
||||
|
||||
img {
|
||||
max-width: 100%;
|
||||
max-height: 100%;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,74 @@
|
||||
<template>
|
||||
<section class="apps">
|
||||
<div class="apps__title">
|
||||
<h2 class="text is-small is-semibold">{{ $t(`OAuthAppsPage.title`) }}</h2>
|
||||
|
||||
<router-link class="button button--small" :to="{ name: 'oauth_app_new' }">
|
||||
{{ $t(`OAuthAppsPage.newAppButton`) }}
|
||||
</router-link>
|
||||
</div>
|
||||
|
||||
<Spinner v-if="isFetchingApps" class="apps__spinner"/>
|
||||
|
||||
<p v-if="!isFetchingApps && !hasOAuthApps" v-html="$t(`OAuthAppsPage.emptyDescription`)" class="text is-caption u-mt--32"></p>
|
||||
<div v-else class="apps__list">
|
||||
<ul>
|
||||
<AppElement v-for="oAuthApp in oAuthApps" :key="oAuthApp.id" :oAuthApp="oAuthApp">
|
||||
<router-link
|
||||
class="button button--outline button--edit"
|
||||
:to="{ name: 'oauth_app_edit', params: {id: oAuthApp.id } }">
|
||||
{{ $t('OAuthAppsPage.editButton') }}
|
||||
</router-link>
|
||||
</AppElement>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<p class="text is-small u-mt--20" v-html="$t(`OAuthAppsPage.description`)"></p>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
import AppElement from './AppElement';
|
||||
import Spinner from '../Spinner';
|
||||
|
||||
export default {
|
||||
name: 'AppList',
|
||||
components: {
|
||||
AppElement,
|
||||
Spinner
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
isFetchingApps: state => state.oAuthApps.isFetching,
|
||||
oAuthApps: state => state.oAuthApps.list,
|
||||
error: state => state.oAuthApps.error,
|
||||
hasOAuthApps: state => !state.oAuthApps.isFetching && !!Object.keys(state.oAuthApps.list).length
|
||||
})
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped lang="scss">
|
||||
@import 'new-dashboard/styles/variables';
|
||||
|
||||
.apps {
|
||||
&__spinner {
|
||||
margin: 120px auto;
|
||||
}
|
||||
|
||||
&__title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
padding-bottom: 16px;
|
||||
border-bottom: 1px solid $neutral--300;
|
||||
}
|
||||
}
|
||||
|
||||
.button--edit {
|
||||
align-self: center;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,73 @@
|
||||
<template>
|
||||
<ul class="app-tabs">
|
||||
<li class="app-tabs-item">
|
||||
<a :href="`${ baseUrl }/your_apps`" class="text is-small is-txtPrimary app-tabs-link">{{ $t(`SettingsPages.tabs.apiKeys`) }}</a>
|
||||
</li>
|
||||
<li class="app-tabs-item is-active">
|
||||
<router-link :to="{ name: 'oauth_apps_list' }" class="text is-small is-txtPrimary app-tabs-link">
|
||||
{{ $t(`SettingsPages.tabs.oAuthApps`) }}
|
||||
</router-link>
|
||||
</li>
|
||||
<li class="app-tabs-item">
|
||||
<a :href="`${ baseUrl }/your_apps/mobile`" class="text is-small is-txtPrimary app-tabs-link">{{ $t(`SettingsPages.tabs.mobileApps`) }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'AppTabs',
|
||||
computed: {
|
||||
...mapState({
|
||||
baseUrl: state => state.user.base_url
|
||||
})
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import 'new-dashboard/styles/variables';
|
||||
|
||||
.app-tabs {
|
||||
display: flex;
|
||||
margin-bottom: 26px;
|
||||
border-bottom: 1px solid $neutral--300;
|
||||
}
|
||||
|
||||
.app-tabs-item {
|
||||
position: relative;
|
||||
margin-right: 32px;
|
||||
padding-bottom: 34px;
|
||||
transform: translate3d(0, 1px, 0);
|
||||
|
||||
&.is-active {
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 1px;
|
||||
background: $neutral--800;
|
||||
}
|
||||
|
||||
.app-tabs-link {
|
||||
color: $text__color;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.app-tabs-link {
|
||||
&.is-active {
|
||||
color: $text__color;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,78 @@
|
||||
<template>
|
||||
<section>
|
||||
<div class="appform__title">
|
||||
<router-link :to="{ name: 'oauth_apps_list' }">
|
||||
<img class="oauthapps__back" svg-inline src="new-dashboard/assets/icons/apps/back-arrow.svg" />
|
||||
</router-link>
|
||||
<h2 class="text is-small is-semibold u-ml--12">{{ $t(`OAuthAppsPage.form.newTitle`) }}</h2>
|
||||
</div>
|
||||
|
||||
<FormComponent :oAuthApplication="app" :error="error" @submit="onSubmit">
|
||||
<div class="appform__toolbar">
|
||||
<div class="u-flex">
|
||||
<router-link :to="{ name: 'oauth_apps_list' }" class="button button--ghost u-mr--28">
|
||||
{{ $t(`OAuthAppsPage.form.cancelButton`) }}
|
||||
</router-link>
|
||||
|
||||
<button class="button button--primary" type="submit" value="Submit">
|
||||
{{ $t(`OAuthAppsPage.form.saveButton`) }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</FormComponent>
|
||||
|
||||
<DeleteAppModal ref="deleteAppModal" :app="app"/>
|
||||
<RegenerateCredentialsModal ref="regenerateCredentialsModal" :app="app"/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import FormComponent from './FormComponent';
|
||||
import DeleteAppModal from './modals/DeleteAppModal';
|
||||
import RegenerateCredentialsModal from './modals/RegenerateCredentialsModal';
|
||||
|
||||
export default {
|
||||
name: 'CreateApp',
|
||||
components: {
|
||||
FormComponent,
|
||||
DeleteAppModal,
|
||||
RegenerateCredentialsModal
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
app: {},
|
||||
error: {}
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
onSubmit (app) {
|
||||
this.createApp(app);
|
||||
},
|
||||
createApp (app) {
|
||||
this.$store.dispatch('oAuthApps/create', app)
|
||||
.then(
|
||||
createdApp => {
|
||||
this.$router.push({name: 'oauth_app_edit', params: { id: createdApp.id }});
|
||||
},
|
||||
error => {
|
||||
this.error = error;
|
||||
window.scrollTo(0, 0);
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import 'new-dashboard/styles/variables';
|
||||
|
||||
.appform__title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 28px;
|
||||
border-bottom: 1px solid $neutral--300;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,181 @@
|
||||
<template>
|
||||
<section>
|
||||
<div class="appform__title">
|
||||
<router-link :to="{ name: 'oauth_apps_list' }">
|
||||
<img class="oauthapps__back" svg-inline src="../../assets/icons/apps/back-arrow.svg" />
|
||||
</router-link>
|
||||
|
||||
<h2 class="text is-small is-semibold u-ml--12">
|
||||
{{ $t(`OAuthAppsPage.form.editTitle`)}}
|
||||
</h2>
|
||||
</div>
|
||||
|
||||
<Spinner v-if="isFetchingOAuthApps" class="apps__spinner"/>
|
||||
|
||||
<section class="appform__content" v-if="!isFetchingOAuthApps">
|
||||
<div class="u-mb--64">
|
||||
<div class="u-mb--16">
|
||||
<span class="appform__label">{{ $t(`OAuthAppsPage.form.ownedby`) }}</span>
|
||||
<span class="text is-small">{{ app.username }}</span>
|
||||
</div>
|
||||
|
||||
<div class="u-mb--16">
|
||||
<span class="appform__label">{{ $t(`OAuthAppsPage.form.clientId`) }}</span>
|
||||
<span class="text is-small">{{ app.client_id }}</span>
|
||||
</div>
|
||||
|
||||
<div class="u-mb--16">
|
||||
<span class="appform__label">{{ $t(`OAuthAppsPage.form.clientSecret`) }}</span>
|
||||
<span class="text is-small">{{ app.client_secret }}</span>
|
||||
</div>
|
||||
|
||||
<div class="u-flex u-mb--24">
|
||||
<img src="../../assets/icons/apps/warning.svg" />
|
||||
<span class="text is-small is-txtSoftGrey u-ml--8">{{ $t(`OAuthAppsPage.form.clientSecretWarning`) }}</span>
|
||||
</div>
|
||||
|
||||
<button class="button button--outline u-mb--24" @click="openRegenerateCredentialsModal">
|
||||
{{ $t(`OAuthAppsPage.form.clientSecretButton`) }}
|
||||
</button>
|
||||
|
||||
<span class="text is-small is-txtSoftGrey" v-html="$t(`OAuthAppsPage.form.clientSecretDesc`)"></span>
|
||||
</div>
|
||||
|
||||
<div ref="formScroll" class="appform__title u-mb--24">
|
||||
<h2 class="text is-caption">{{ $t(`OAuthAppsPage.form.appInformationTitle`) }}</h2>
|
||||
</div>
|
||||
|
||||
<FormComponent
|
||||
v-if="!isFetchingOAuthApps"
|
||||
:oAuthApplication="app"
|
||||
:formTitle="$t(`OAuthAppsPage.form.editTitle`)"
|
||||
:error="error"
|
||||
@submit="onSubmit">
|
||||
<div class="appform__toolbar u-flex__justify--between">
|
||||
<button type="button" class="button button--outline button--delete u-mr--48" @click="openDeleteAppModal">
|
||||
{{ $t(`OAuthAppsPage.form.deleteAppButton`) }}
|
||||
</button>
|
||||
|
||||
<div class="u-flex">
|
||||
<router-link :to="{ name: 'oauth_apps_list' }" class="button button--ghost u-mr--28">
|
||||
{{ $t(`OAuthAppsPage.form.cancelButton`) }}
|
||||
</router-link>
|
||||
|
||||
<button class="button button--primary" type="submit" value="Submit">
|
||||
{{ $t(`OAuthAppsPage.form.saveButton`) }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</FormComponent>
|
||||
</section>
|
||||
|
||||
<DeleteAppModal ref="deleteAppModal" :app="app"/>
|
||||
<RegenerateCredentialsModal ref="regenerateCredentialsModal" :app="app"/>
|
||||
</section>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
import FormComponent from './FormComponent';
|
||||
import Spinner from '../Spinner';
|
||||
import DeleteAppModal from './modals/DeleteAppModal';
|
||||
import RegenerateCredentialsModal from './modals/RegenerateCredentialsModal';
|
||||
|
||||
export default {
|
||||
name: 'EditApp',
|
||||
components: {
|
||||
FormComponent,
|
||||
DeleteAppModal,
|
||||
RegenerateCredentialsModal,
|
||||
Spinner
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
error: {}
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
list: state => state.oAuthApps.list,
|
||||
isFetchingOAuthApps: state => state.oAuthApps.isFetching,
|
||||
app (state) {
|
||||
if (this.isFetchingOAuthApps) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return this.list[this.$route.params.id];
|
||||
}
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
onSubmit (app) {
|
||||
return this.updateApp(app);
|
||||
},
|
||||
updateApp (app) {
|
||||
this.$store.dispatch('oAuthApps/update', app)
|
||||
.then(
|
||||
() => this.$router.push({ name: 'oauth_apps_list' }),
|
||||
(error) => {
|
||||
this.error = error;
|
||||
window.scrollTo(0, this.$refs.formScroll.offsetTop);
|
||||
}
|
||||
);
|
||||
},
|
||||
deleteApp () {
|
||||
this.$store.dispatch('oAuthApps/delete', this.app)
|
||||
.then(
|
||||
() => this.$router.push({ name: 'oauth_apps_list' })
|
||||
);
|
||||
},
|
||||
openDeleteAppModal () {
|
||||
this.$refs.deleteAppModal.open();
|
||||
},
|
||||
openRegenerateCredentialsModal () {
|
||||
this.$refs.regenerateCredentialsModal.open();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import 'new-dashboard/styles/variables';
|
||||
|
||||
.appform__title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 28px;
|
||||
border-bottom: 1px solid $neutral--300;
|
||||
}
|
||||
|
||||
.appform_spinner {
|
||||
margin: 120px auto;
|
||||
}
|
||||
|
||||
.appform__label {
|
||||
margin-bottom: 8px;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
line-height: 16px;
|
||||
|
||||
&--optional {
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.appform__toolbar {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: flex-end;
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
border-top: 1px solid $neutral--400;
|
||||
}
|
||||
|
||||
.button--delete {
|
||||
border: 1px solid $red--600;
|
||||
color: $red--600;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,240 @@
|
||||
<template>
|
||||
<form id="app" @submit="onSubmit">
|
||||
<div class="appform__block">
|
||||
<label class="appform__label" for="app.name">{{ $t(`OAuthAppsPage.form.appName`) }}</label>
|
||||
|
||||
<input class="appform__input" :class="{'has-error': !!error.name}" type="text" name="app.name" id="app.name" v-model="app.name">
|
||||
<span v-if="error.name" class="appform__error u-mt--4">
|
||||
{{ getStringErrorFromArray(error.name, $t(`OAuthAppsPage.form.appName`)) }}
|
||||
</span>
|
||||
|
||||
<span class="appform__input-desc">{{ $t(`OAuthAppsPage.form.appNameDesc`) }}</span>
|
||||
</div>
|
||||
|
||||
<div class="appform__block">
|
||||
<label class="appform__label" for="app.website_url">{{ $t(`OAuthAppsPage.form.webUrl`) }}</label>
|
||||
<input class="appform__input" type="text" name="app.website_url" id="app.website_url" v-model="app.website_url">
|
||||
<span v-if="error.website_url" class="appform__error u-mt--4">
|
||||
{{ getStringErrorFromArray(error.website_url, $t(`OAuthAppsPage.form.webUrl`)) }}
|
||||
</span>
|
||||
<span class="appform__input-desc">{{ $t(`OAuthAppsPage.form.webUrlDesc`) }}</span>
|
||||
</div>
|
||||
|
||||
<div class="appform__block">
|
||||
<label class="appform__label" for="app.description">{{ $t(`OAuthAppsPage.form.description`) }}<span class="appform__label--optional"> {{ $t(`OAuthAppsPage.form.optional`) }}</span></label>
|
||||
<textarea class="appform__input appform__input--textarea" type="text" name="app.description" id="app.description" v-model="app.description"></textarea>
|
||||
<span class="appform__input-desc" v-html="$t(`OAuthAppsPage.form.descriptionDesc`)"></span>
|
||||
</div>
|
||||
|
||||
<div class="appform__block">
|
||||
<label class="appform__label" for="appCallbacks">{{ $t(`OAuthAppsPage.form.callbackUrls`) }}</label>
|
||||
<ul>
|
||||
<li v-for="(callbackUrl, k) in app.redirect_uris" :key="k">
|
||||
<input class="appform__input" :class="{'has-error': !!error.redirect_uris}" type="text" name="callbackUrl" id="callbackUrl" v-model="callbackUrl.name" :placeholder="$t(`OAuthAppsPage.form.callbackUrlPlaceholder`)">
|
||||
<span v-show="shouldShowDelete(k, app.redirect_uris)" class="appform__link u-ml--16 appform__link--delete" @click="removeCallbackUrl(k)">{{ $t(`OAuthAppsPage.form.callbackUrlDelete`) }}</span>
|
||||
<span v-show="k == app.redirect_uris.length-1" class="appform__link u-ml--16" @click="addCallbackUrl(k)">{{ $t(`OAuthAppsPage.form.callbackUrlAddMore`) }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<span v-if="error.redirect_uris" class="appform__error">
|
||||
{{ getStringErrorFromArray(error.redirect_uris, $t(`OAuthAppsPage.form.callbackUrls`)) }}
|
||||
</span>
|
||||
|
||||
<span class="appform__input-desc" v-html="$t(`OAuthAppsPage.form.callbackUrlsDesc`)"></span>
|
||||
</div>
|
||||
|
||||
<div class="appform__block">
|
||||
<label class="appform__label" for="app.logoUrl">
|
||||
{{ $t(`OAuthAppsPage.form.logoUpload`) }}<span class="appform__label--optional"> {{ $t(`OAuthAppsPage.form.optional`) }}</span>
|
||||
</label>
|
||||
|
||||
<UploadImage :currentImage="app.icon_url" @imageUpload="onImageUploaded">
|
||||
<p class="appform__input-desc appform__input-desc--12" v-html="$t(`OAuthAppsPage.form.logoUploadDesc`)"></p>
|
||||
<p v-if="error.icon_url" class="appform__error u-mt--4">
|
||||
{{ getStringErrorFromArray(error.icon_url, $t(`OAuthAppsPage.form.logo`)) }}
|
||||
</p>
|
||||
</UploadImage>
|
||||
</div>
|
||||
|
||||
<slot />
|
||||
</form>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import UploadImage from '../UploadImage';
|
||||
|
||||
export default {
|
||||
name: 'FormComponent',
|
||||
components: {
|
||||
UploadImage
|
||||
},
|
||||
props: {
|
||||
oAuthApplication: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {};
|
||||
}
|
||||
},
|
||||
error: {
|
||||
type: Object,
|
||||
default () {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
oAuthApplication (newApplication) {
|
||||
this.app = newApplication;
|
||||
this.app.redirect_uris = this.redirectUrisToArrayObjects(this.app.redirect_uris);
|
||||
}
|
||||
},
|
||||
data () {
|
||||
const app = {
|
||||
redirect_uris: [{ name: '' }],
|
||||
...this.$props.oAuthApplication
|
||||
};
|
||||
|
||||
if (this.$props.oAuthApplication &&
|
||||
this.$props.oAuthApplication.redirect_uris) {
|
||||
app.redirect_uris = this.redirectUrisToArrayObjects(this.$props.oAuthApplication.redirect_uris);
|
||||
}
|
||||
|
||||
return { app };
|
||||
},
|
||||
methods: {
|
||||
getStringErrorFromArray (errorArray, fieldName) {
|
||||
const errors = errorArray.map(error => (`${fieldName} ${error}.`));
|
||||
return errors.join(' ');
|
||||
},
|
||||
shouldShowDelete (index) {
|
||||
return index > 0;
|
||||
},
|
||||
onSubmit (event) {
|
||||
event.preventDefault();
|
||||
|
||||
const app = {
|
||||
...this.app,
|
||||
redirect_uris: this.redirectUrisToArrayStrings(this.app.redirect_uris)
|
||||
};
|
||||
|
||||
this.$emit('submit', app);
|
||||
},
|
||||
addCallbackUrl (index) {
|
||||
this.app.redirect_uris.push({ name: '' });
|
||||
},
|
||||
removeCallbackUrl (index) {
|
||||
this.app.redirect_uris.splice(index, 1);
|
||||
},
|
||||
redirectUrisToArrayObjects (redirectUris) {
|
||||
return redirectUris.map(r => ({ name: r }));
|
||||
},
|
||||
redirectUrisToArrayStrings (redirectUris) {
|
||||
return redirectUris.map(r => r.name).filter(Boolean);
|
||||
},
|
||||
onImageUploaded (imageSrc) {
|
||||
this.app.icon_url = imageSrc;
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import 'new-dashboard/styles/variables';
|
||||
|
||||
.appform__title {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: start;
|
||||
margin-bottom: 16px;
|
||||
padding-bottom: 28px;
|
||||
border-bottom: 1px solid $neutral--300;
|
||||
}
|
||||
|
||||
.appform__block {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
|
||||
.appform__label,
|
||||
.appform__input {
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-size: 12px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
.appform__label {
|
||||
margin-bottom: 8px;
|
||||
font-weight: 600;
|
||||
|
||||
&--optional {
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
.appform__input {
|
||||
width: 300px;
|
||||
margin-bottom: 6px;
|
||||
padding: 12px;
|
||||
border: 1px solid $neutral--400;
|
||||
border-radius: 4px;
|
||||
|
||||
&.has-error {
|
||||
border: 1px solid $danger__color;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
border: 1px solid $blue--700;
|
||||
}
|
||||
|
||||
&:focus {
|
||||
border: 1px solid $neutral--400;
|
||||
}
|
||||
|
||||
&--textarea {
|
||||
min-height: 60px;
|
||||
}
|
||||
|
||||
&-desc {
|
||||
color: $neutral--600;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-size: 10px;
|
||||
line-height: 16px;
|
||||
}
|
||||
|
||||
&-desc--12 {
|
||||
margin-top: 4px;
|
||||
font-size: 12px;
|
||||
}
|
||||
}
|
||||
|
||||
.appform__link {
|
||||
color: $color-primary;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-size: 12px;
|
||||
line-height: 22px;
|
||||
cursor: pointer;
|
||||
|
||||
&--delete {
|
||||
color: $danger__color;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.appform__toolbar {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
justify-content: flex-end;
|
||||
width: 100%;
|
||||
height: 70px;
|
||||
border-top: 1px solid $neutral--400;
|
||||
}
|
||||
|
||||
.appform__error {
|
||||
color: $danger__color;
|
||||
font-size: 10px;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,95 @@
|
||||
<template>
|
||||
<ul class="settingssidebar">
|
||||
<li class="settingssidebar-item">
|
||||
<a :href="`${ baseUrl }/profile`" class="text is-txtPrimary settingssidebar-link">{{ $t(`SettingsPages.sidebar.profile`) }}</a>
|
||||
</li>
|
||||
<li class="settingssidebar-item">
|
||||
<a :href="`${ baseUrl }/account`" class="text is-txtPrimary settingssidebar-link">{{ $t(`SettingsPages.sidebar.account`) }}</a>
|
||||
</li>
|
||||
<li class="settingssidebar-item">
|
||||
<router-link :to="{ name: 'connected_apps' }" class="text is-txtPrimary settingssidebar-link" :class="{'is-active': isConnectedAppsPage()}">{{ $t(`SettingsPages.sidebar.connectedApps`) }} </router-link>
|
||||
</li>
|
||||
<!--
|
||||
<li v-if="!isLocallyHosted && (isOrgAdmin || !isInsideOrg)" class="settingssidebar-item">
|
||||
<a :href="planUrl" class="text is-txtPrimary settingssidebar-link">{{ $t(`SettingsPages.sidebar.billing`) }}</a>
|
||||
</li>
|
||||
-->
|
||||
<li v-if="isOrgAdmin" class="settingssidebar-item">
|
||||
<a :href="`${ baseUrl }/organization`" class="text is-txtPrimary settingssidebar-link">{{ $t(`SettingsPages.sidebar.organizationSettings`) }}</a>
|
||||
</li>
|
||||
<span class="settingssidebar-separator"></span>
|
||||
<li class="settingssidebar-item">
|
||||
<a :href="`${ baseUrl }/your_apps`" class="text is-txtPrimary settingssidebar-link" :class="{'is-active': isDevelopersSettingsPage()}">{{ $t(`SettingsPages.sidebar.developerSettings`) }}</a>
|
||||
</li>
|
||||
</ul>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapState } from 'vuex';
|
||||
|
||||
export default {
|
||||
name: 'SettingsSidebar',
|
||||
data () {
|
||||
return {
|
||||
developerSettingsPages: [
|
||||
'oauth_apps',
|
||||
'oauth_app_new',
|
||||
'oauth_app_edit',
|
||||
'oauth_apps_list'
|
||||
]
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
...mapState({
|
||||
baseUrl: state => state.user.base_url,
|
||||
user: state => state.user,
|
||||
planUrl: state => state.config.plan_url,
|
||||
isLocallyHosted: state => state.config.cartodb_com_hosted
|
||||
}),
|
||||
isInsideOrg () {
|
||||
return this.$store.getters['user/isOrganizationUser'];
|
||||
},
|
||||
isOrgAdmin () {
|
||||
return this.user.org_admin;
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
isConnectedAppsPage () {
|
||||
return (this.$route || {}).name === 'connected_apps';
|
||||
},
|
||||
isDevelopersSettingsPage () {
|
||||
return this.developerSettingsPages.includes((this.$route || {}).name);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@import 'new-dashboard/styles/variables';
|
||||
|
||||
.settingssidebar-item {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.settingssidebar-link {
|
||||
font-size: 14px;
|
||||
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
&.is-active {
|
||||
color: #333;
|
||||
font-weight: 700;
|
||||
}
|
||||
}
|
||||
|
||||
.settingssidebar-separator {
|
||||
display: flex;
|
||||
width: 240px;
|
||||
height: 1px;
|
||||
margin: 20px 0;
|
||||
background-color: rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
</style>
|
||||
@@ -0,0 +1,54 @@
|
||||
<template>
|
||||
<Modal ref="deleteAppModal" name="deleteAppModal">
|
||||
<div class="oauthapps__modal">
|
||||
<div class="oauthapps__modal-inner">
|
||||
<div class="oauthapps__icon u-mb--24">
|
||||
<img class="oauthapps_svgicon" svg-inline src="new-dashboard/assets/icons/apps/default.svg">
|
||||
<img class="oauthapps__badge" svg-inline src="new-dashboard/assets/icons/apps/trash.svg">
|
||||
</div>
|
||||
<p class="text is-caption u-mb--8" v-html="$t('OAuthAppsPage.deleteModal.title', { name: app.name })"></p>
|
||||
<p class="text is-small is-txtSoftGrey" v-html="$t('OAuthAppsPage.deleteModal.subtitle')"></p>
|
||||
<div class="oauthapps__modal-actions">
|
||||
<button class="oauthapps__button button button--ghost u-mr--12" @click="close">{{ $t(`OAuthAppsPage.deleteModal.cancelButton`) }}</button>
|
||||
<button class="oauthapps__modal-button oauthapps__modal-button--delete" @click="deleteApp">{{ $t(`OAuthAppsPage.deleteModal.deleteButton`) }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Modal from 'new-dashboard/components/Modal';
|
||||
|
||||
export default {
|
||||
name: 'DeleteAppModal',
|
||||
components: {
|
||||
Modal
|
||||
},
|
||||
props: {
|
||||
app: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open () {
|
||||
this.$refs.deleteAppModal.open();
|
||||
},
|
||||
close () {
|
||||
this.$refs.deleteAppModal.close();
|
||||
},
|
||||
deleteApp () {
|
||||
this.$store.dispatch('oAuthApps/delete', this.app)
|
||||
.then(() => {
|
||||
this.$router.push({ name: 'oauth_apps_list' });
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import 'new-dashboard/styles/variables';
|
||||
@import './modal-styles.scss';
|
||||
</style>
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
<template>
|
||||
<Modal ref="regenerateCredentialsModal" name="regenerateCredentialsModal">
|
||||
<div class="oauthapps__modal">
|
||||
<div class="oauthapps__modal-inner">
|
||||
<div class="oauthapps__icon u-mb--24">
|
||||
<img class="oauthapps_svgicon" svg-inline src="new-dashboard/assets/icons/apps/default.svg">
|
||||
<img class="oauthapps__badge" svg-inline src="new-dashboard/assets/icons/apps/key.svg">
|
||||
</div>
|
||||
<p class="text is-caption u-mb--8" v-html="$t('OAuthAppsPage.regenerateModal.title', { name: app.name })"></p>
|
||||
<p class="text is-small is-txtSoftGrey" v-html="$t('OAuthAppsPage.regenerateModal.subtitle')"></p>
|
||||
<div class="oauthapps__modal-actions">
|
||||
<button class="oauthapps__modal-button u-mr--12" @click="close">{{ $t(`OAuthAppsPage.regenerateModal.cancelButton`) }}</button>
|
||||
<button class="oauthapps__modal-button oauthapps__modal-button--regenerate" @click="regenerateCredentials">{{ $t(`OAuthAppsPage.regenerateModal.regenerateButton`) }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Modal from 'new-dashboard/components/Modal';
|
||||
|
||||
export default {
|
||||
name: 'RegenerateCredentialsModal',
|
||||
components: {
|
||||
Modal
|
||||
},
|
||||
props: {
|
||||
app: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
open () {
|
||||
this.$refs.regenerateCredentialsModal.open();
|
||||
},
|
||||
close () {
|
||||
this.$refs.regenerateCredentialsModal.close();
|
||||
},
|
||||
regenerateCredentials () {
|
||||
this.$store.dispatch('oAuthApps/regenerateCredentials', this.app);
|
||||
this.close();
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import 'new-dashboard/styles/variables';
|
||||
@import './modal-styles.scss';
|
||||
</style>
|
||||
@@ -0,0 +1,78 @@
|
||||
.oauthapps__modal {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: space-around;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.oauthapps__icon {
|
||||
display: flex;
|
||||
position: relative;
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
border: 1px solid $neutral--400;
|
||||
border-radius: 2px;
|
||||
|
||||
.oauthapps_svgicon {
|
||||
margin: auto;
|
||||
}
|
||||
|
||||
.oauthapps__badge {
|
||||
position: absolute;
|
||||
top: -8px;
|
||||
right: -8px;
|
||||
}
|
||||
}
|
||||
|
||||
.oauthapps__modal-inner {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
width: 960px;
|
||||
margin: 0 auto;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.oauthapps__modal-actions {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
width: 100%;
|
||||
margin-top: 54px;
|
||||
padding-top: 38px;
|
||||
border-top: 1px solid $neutral--300;
|
||||
}
|
||||
|
||||
.oauthapps__modal-button {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 12px 18px;
|
||||
border: 1px solid $color-primary;
|
||||
border-radius: 4px;
|
||||
background-color: transparent;
|
||||
color: $color-primary;
|
||||
font-family: 'Open Sans', sans-serif;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0;
|
||||
text-transform: uppercase;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-color: transparent;
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
&--regenerate,
|
||||
&--delete {
|
||||
border: none;
|
||||
background-color: $button-alert__bg-color;
|
||||
color: $white;
|
||||
|
||||
&:hover {
|
||||
background-color: $button-alert__bg-color--hover;
|
||||
text-decoration: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user