ButtonGroup, CodeMirror keyMap

This commit is contained in:
Vincent Fiduccia 2019-08-29 15:11:22 -07:00
parent b592b6a337
commit 2264786c1c
No known key found for this signature in database
GPG Key ID: 2B29AD6BB2BB2582
12 changed files with 191 additions and 56 deletions

View File

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

View File

@ -157,7 +157,7 @@ export default {
timerDone() {
if ( this.phase === SUCCESS || this.phase === ERROR ) {
this.state = ACTION;
this.phase = ACTION;
}
}
}

View File

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

View File

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

View File

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

View File

@ -237,7 +237,10 @@ export default {
return;
}
this.$router.replace({ name: this.doneRoute });
this.$router.replace({
name: this.doneRoute,
params: { resource: this.obj.type }
});
}
}
};

View File

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

View File

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

View File

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

View File

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

View File

@ -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]);

View File

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