mirror of https://github.com/rancher/dashboard.git
ButtonGroup, CodeMirror keyMap
This commit is contained in:
parent
b592b6a337
commit
2264786c1c
|
|
@ -97,27 +97,26 @@ fieldset[disabled] .btn {
|
|||
vertical-align: middle;
|
||||
text-align: center;
|
||||
padding: 0;
|
||||
overflow: hidden;
|
||||
background: var(--input-bg);
|
||||
border-radius: $border-radius;
|
||||
border: 4px solid transparent;
|
||||
|
||||
.btn, .btn-xs, .btn-sm, .btn-lg {
|
||||
.btn {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
border-radius: 0;
|
||||
|
||||
&.active {
|
||||
@extend .bg-primary;
|
||||
}
|
||||
|
||||
&:first-child {
|
||||
border-top-right-radius: 0;
|
||||
border-bottom-right-radius: 0;
|
||||
border-top-left-radius: $border-radius;
|
||||
border-bottom-left-radius: $border-radius;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
border-top-left-radius: 0;
|
||||
border-bottom-left-radius: 0;
|
||||
border-top-right-radius: $border-radius;
|
||||
border-bottom-right-radius: $border-radius;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -157,7 +157,7 @@ export default {
|
|||
|
||||
timerDone() {
|
||||
if ( this.phase === SUCCESS || this.phase === ERROR ) {
|
||||
this.state = ACTION;
|
||||
this.phase = ACTION;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
<script>
|
||||
export default {
|
||||
props: {
|
||||
value: {
|
||||
type: [String, Number, Boolean, Object],
|
||||
required: true,
|
||||
},
|
||||
|
||||
inactiveClass: {
|
||||
type: String,
|
||||
default: 'bg-default',
|
||||
},
|
||||
|
||||
activeClass: {
|
||||
type: String,
|
||||
default: 'bg-primary',
|
||||
},
|
||||
|
||||
options: {
|
||||
type: Array,
|
||||
required: true,
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
optionObjects() {
|
||||
const value = this.value;
|
||||
|
||||
return this.options.map((opt) => {
|
||||
let out;
|
||||
|
||||
if ( opt && typeof opt === 'object' && typeof opt.value !== 'undefined' ) {
|
||||
out = Object.assign({}, opt);
|
||||
} else {
|
||||
out = { label: opt, value: opt };
|
||||
}
|
||||
|
||||
const active = value === out.value;
|
||||
|
||||
out.class = {
|
||||
btn: true,
|
||||
[this.inactiveClass]: !active,
|
||||
[this.activeClass]: active,
|
||||
};
|
||||
|
||||
return out;
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
change(value) {
|
||||
this.$emit('input', value);
|
||||
}
|
||||
}
|
||||
};
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-trim-whitespace class="btn-group">
|
||||
<button
|
||||
v-for="(opt,idx) in optionObjects"
|
||||
:key="idx"
|
||||
type="button"
|
||||
:class="opt.class"
|
||||
@click="change(opt.value)"
|
||||
>
|
||||
<slot name="option" :label="opt.label" :value="opt.value">
|
||||
<i v-if="opt.icon" :class="{icon: true, [opt.icon]: true}" />
|
||||
<span v-if="opt.label">{{ opt.label }}</span>
|
||||
</slot>
|
||||
</button>
|
||||
</div>
|
||||
</template>
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
<script>
|
||||
import $ from 'jquery';
|
||||
import { THEME, KEYMAP } from '~/store/prefs';
|
||||
|
||||
export default {
|
||||
props: {
|
||||
|
|
@ -31,11 +32,15 @@ export default {
|
|||
},
|
||||
|
||||
combinedOptions() {
|
||||
const theme = this.$store.getters['prefs/get'](THEME);
|
||||
const keymap = this.$store.getters['prefs/get'](KEYMAP);
|
||||
|
||||
const out = {
|
||||
// codemirror options
|
||||
tabSize: 2,
|
||||
mode: 'yaml',
|
||||
theme: 'base16-dark',
|
||||
keyMap: keymap,
|
||||
theme: `base16-${ theme }`,
|
||||
lineNumbers: true,
|
||||
line: true,
|
||||
viewportMargin: Infinity,
|
||||
|
|
|
|||
|
|
@ -9,14 +9,7 @@
|
|||
table-actions
|
||||
>
|
||||
<template v-if="groupable" #header-middle>
|
||||
<div v-trim-whitespace class="btn-group">
|
||||
<button type="button" :class="{'btn': true, 'bg-default': true, 'active': group == 'none'}" @click="setGroup('none')">
|
||||
<i class="icon icon-list-flat" />
|
||||
</button>
|
||||
<button type="button" :class="{'btn': true, 'bg-default': true, 'active': group == 'namespace'}" @click="setGroup('namespace')">
|
||||
<i class="icon icon-list-grouped" />
|
||||
</button>
|
||||
</div>
|
||||
<ButtonGroup v-model="group" :options="groupOptions" />
|
||||
</template>
|
||||
</SortableTable>
|
||||
</div>
|
||||
|
|
@ -24,11 +17,12 @@
|
|||
|
||||
<script>
|
||||
import { mapPref, GROUP_RESOURCES } from '@/store/prefs';
|
||||
import SortableTable from '@/components/SortableTable';
|
||||
import { headersFor } from '@/utils/table-headers';
|
||||
import ButtonGroup from '~/components/ButtonGroup';
|
||||
import SortableTable from '~/components/SortableTable';
|
||||
import { headersFor } from '~/utils/table-headers';
|
||||
|
||||
export default {
|
||||
components: { SortableTable },
|
||||
components: { ButtonGroup, SortableTable },
|
||||
|
||||
props: {
|
||||
resource: {
|
||||
|
|
@ -75,7 +69,14 @@ export default {
|
|||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
},
|
||||
|
||||
groupOptions() {
|
||||
return [
|
||||
{ value: 'none', icon: 'icon-list-flat' },
|
||||
{ value: 'namespace', icon: 'icon-list-grouped' }
|
||||
];
|
||||
},
|
||||
},
|
||||
|
||||
methods: {
|
||||
|
|
|
|||
|
|
@ -237,7 +237,10 @@ export default {
|
|||
return;
|
||||
}
|
||||
|
||||
this.$router.replace({ name: this.doneRoute });
|
||||
this.$router.replace({
|
||||
name: this.doneRoute,
|
||||
params: { resource: this.obj.type }
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
|
|||
|
|
@ -19,8 +19,6 @@ export default {
|
|||
},
|
||||
|
||||
computed: {
|
||||
theme: mapPref(THEME),
|
||||
|
||||
packages() {
|
||||
const namespaces = this.$store.getters['namespaces'] || [];
|
||||
const { clusterLevel, namespaceLevel } = groupsForCounts(this.$store.getters['v1/counts'], namespaces);
|
||||
|
|
@ -81,19 +79,9 @@ export default {
|
|||
</div>
|
||||
|
||||
<div class="header-right text-right">
|
||||
<div v-trim-whitespace class="btn-group theme-picker">
|
||||
<button type="button" :class="{'light': true, 'btn': true, 'btn-sm': true, 'bg-default': true, 'active': theme === 'light'}" @click="theme='light'">
|
||||
<i class="icon icon-dot" />
|
||||
</button>
|
||||
<button type="button" :class="{'dark': true, 'btn': true, 'btn-sm': true, 'bg-default': true, 'active': theme === 'dark'}" @click="theme='dark'">
|
||||
<i class="icon icon-dot" />
|
||||
</button>
|
||||
</div>
|
||||
<!--
|
||||
<nuxt-link :to="{name: 'prefs'}">
|
||||
<i class="icon icon-2x icon-gear" />
|
||||
<i class="icon icon-3x icon-gear" />
|
||||
</nuxt-link>
|
||||
-->
|
||||
</div>
|
||||
</header>
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ export default {
|
|||
{{ schema.attributes.kind }}
|
||||
</h2>
|
||||
<nuxt-link to="create" append tag="button" type="button" class="btn bg-primary right-action">
|
||||
Add
|
||||
Create
|
||||
</nuxt-link>
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -29,7 +29,7 @@ export default {
|
|||
{{ schema.attributes.kind }}
|
||||
</h2>
|
||||
<nuxt-link to="create" append tag="button" type="button" class="btn bg-primary right-action">
|
||||
Add
|
||||
Create
|
||||
</nuxt-link>
|
||||
</div>
|
||||
<ResourceTable :resource="$route.params.resource" :rows="rows" />
|
||||
|
|
|
|||
|
|
@ -1,10 +1,38 @@
|
|||
<script>
|
||||
import { mapPref, THEME } from '~/store/prefs';
|
||||
import ButtonGroup from '~/components/ButtonGroup';
|
||||
import { mapPref, THEME, KEYMAP } from '~/store/prefs';
|
||||
import { ucFirst } from '~/utils/string';
|
||||
|
||||
const KEYMAP_LABELS = {
|
||||
sublime: 'Normal human',
|
||||
emacs: 'Emacs',
|
||||
vim: 'Vim',
|
||||
};
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
theme: mapPref(THEME),
|
||||
// multi-line
|
||||
components: { ButtonGroup },
|
||||
|
||||
computed: {
|
||||
theme: mapPref(THEME),
|
||||
keymap: mapPref(KEYMAP),
|
||||
|
||||
themeOptions() {
|
||||
return this.$store.getters['prefs/options'](THEME).map((value) => {
|
||||
return {
|
||||
label: ucFirst(value),
|
||||
value
|
||||
};
|
||||
});
|
||||
},
|
||||
|
||||
keymapOptions() {
|
||||
return this.$store.getters['prefs/options'](KEYMAP).map((value) => {
|
||||
return {
|
||||
label: KEYMAP_LABELS[value] || ucFirst(value),
|
||||
value
|
||||
};
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
|
@ -13,13 +41,24 @@ export default {
|
|||
<div>
|
||||
<h1>Preferences</h1>
|
||||
|
||||
<div v-trim-whitespace class="btn-group">
|
||||
<button type="button" :class="{'btn': true, 'bg-default': true, 'active': theme === 'light'}" @click="theme='light'">
|
||||
Light
|
||||
</button>
|
||||
<button type="button" :class="{'btn': true, 'bg-default': true, 'active': theme === 'dark'}" @click="theme='dark'">
|
||||
Dark
|
||||
</button>
|
||||
</div>
|
||||
<h6>Theme</h6>
|
||||
<ButtonGroup v-model="theme" :options="themeOptions" />
|
||||
|
||||
<h6>YAML Editor Mode</h6>
|
||||
<ButtonGroup v-model="keymap" :options="keymapOptions" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
h1 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
h6 {
|
||||
margin: 20px 0 0 0;
|
||||
|
||||
&:first-of-type {
|
||||
margin-top: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -91,7 +91,12 @@ export default (config = {}) => {
|
|||
} else if ( obj && typeof obj === 'object' ) {
|
||||
if ( obj.__rehydrate ) {
|
||||
const type = obj.type;
|
||||
const map = state.types[type].map;
|
||||
const cache = state.types[type];
|
||||
|
||||
if ( !cache ) {
|
||||
return obj;
|
||||
}
|
||||
const map = cache.map;
|
||||
const keyField = keyFieldFor(type);
|
||||
const entry = map.get(obj[keyField]);
|
||||
|
||||
|
|
|
|||
|
|
@ -2,9 +2,13 @@ import Vue from 'vue';
|
|||
|
||||
const all = {};
|
||||
|
||||
export const create = function(name, def, parseJSON = false) {
|
||||
export const create = function(name, def, opt = {}) {
|
||||
const parseJSON = opt.parseJSON === true;
|
||||
const options = opt.options;
|
||||
|
||||
all[name] = {
|
||||
def,
|
||||
options,
|
||||
parseJSON
|
||||
};
|
||||
|
||||
|
|
@ -24,12 +28,14 @@ export const mapPref = function(name) {
|
|||
};
|
||||
|
||||
// --------------------
|
||||
const parseJSON = true; // Shortcut for setting it below
|
||||
|
||||
export const NAMESPACES = create('ns', [], true);
|
||||
export const EXPANDED_GROUPS = create('open_groups', [], true);
|
||||
export const NAMESPACES = create('ns', [], { parseJSON });
|
||||
export const EXPANDED_GROUPS = create('open_groups', [], { parseJSON });
|
||||
export const GROUP_RESOURCES = create('group_by', 'namespace');
|
||||
export const DIFF = create('diff', 'unified');
|
||||
export const THEME = create('theme', 'dark');
|
||||
export const DIFF = create('diff', 'unified', { options: ['unified', 'split'] });
|
||||
export const THEME = create('theme', 'dark', { options: ['light', 'dark'] });
|
||||
export const KEYMAP = create('keymap', 'sublime', { options: ['sublime', 'emacs', 'vim'] });
|
||||
export const ROWS_PER_PAGE = create('per_page', 100);
|
||||
export const DATE_FORMAT = create('date_format', 'ddd, MMM D, Y');
|
||||
export const TIME_FORMAT = create('time_format', 'h:mm:ss a');
|
||||
|
|
@ -66,6 +72,20 @@ export const getters = {
|
|||
const def = JSON.parse(JSON.stringify(entry.def));
|
||||
|
||||
return def;
|
||||
},
|
||||
|
||||
options: state => (key) => {
|
||||
const entry = all[key];
|
||||
|
||||
if (!entry) {
|
||||
throw new Error(`Unknown preference: ${ key }`);
|
||||
}
|
||||
|
||||
if (!entry.options) {
|
||||
throw new Error(`Preference does not have options: ${ key }`);
|
||||
}
|
||||
|
||||
return entry.options.slice();
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -84,7 +104,8 @@ export const actions = {
|
|||
loadCookies({ commit }) {
|
||||
for (const key in all) {
|
||||
const entry = all[key];
|
||||
const opt = { parseJSON: entry.parseJSON !== false };
|
||||
|
||||
const opt = { parseJSON: entry.parseJSON === true };
|
||||
|
||||
const val = this.$cookies.get(`${ prefix }${ key }`, opt);
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue