Masthead & other detail cleanup & text wrapping behavior

This commit is contained in:
Vincent Fiduccia 2020-12-09 02:29:36 -07:00
parent 9fb5315b0c
commit 9b1c5431c6
No known key found for this signature in database
GPG Key ID: 2B29AD6BB2BB2582
16 changed files with 155 additions and 128 deletions

View File

@ -1,7 +0,0 @@
# ASSETS
**This directory is not required, you can delete it if you don't want to use it.**
This directory contains your un-compiled assets such as LESS, SASS, or JavaScript.
More information about the usage of this directory in [the documentation](https://nuxtjs.org/guide/assets#webpacked).

View File

@ -104,7 +104,7 @@ $spacing-property-map: (
}
.text-normal {
font-weight: normal;
font-size: initial;
}
.text-italic {
@ -139,6 +139,10 @@ $spacing-property-map: (
display: block !important;
}
.inline {
display: inline !important;
}
.inline-block {
display: inline-block !important;
}

View File

@ -1234,6 +1234,7 @@ promptRemove:
rbac:
roleBinding:
noData: There are no members associated with this resource.
user:
label: User
role:
@ -1317,7 +1318,7 @@ resourceTable:
namespace: Group by Namespace
project: Group by Project
groupLabel:
namespace: "<span>Namespace:</span> {name}"
namespace: "<span>Namespace:</span> {name/&}"
notInANamespace: Not Namespaced
notInAProject: Not in a Project
project: "<span>Project:</span> {name}"
@ -1325,9 +1326,15 @@ resourceTable:
workspace: "<span>Workspace:</span> {name}"
resourceTabs:
tabs:
conditions: Conditions
events: Recent Events
conditions:
tab: Conditions
events:
tab: Recent Events
related:
tab: Related Resources
from: Referred To By
to: Refers To
resourceYaml:
errors:
@ -1560,6 +1567,7 @@ tableHeaders:
resources: Resources
restarts: Restarts
rioImage: Image
role: Role
roles: Roles
scale: Scale
selector: Selector
@ -1569,6 +1577,7 @@ tableHeaders:
started: Started
state: State
status: Status
subject: Subject
success: Success
summary: Summary
target: Target
@ -1867,7 +1876,7 @@ workload:
podIP: Pod IP
podRestarts: Pod Restarts
workload: Workload
pods: Pods
pods: Pods by State
runs: Runs
gaugeStates:
active: Active

View File

@ -140,10 +140,10 @@ export default {
<template>
<div :class="{'force-wrap': true, 'with-copy':copy}">
<h4 v-if="labelKey" v-t="labelKey" />
<h4 v-else-if="label">
<h5 v-if="labelKey" v-t="labelKey" />
<h5 v-else-if="label">
{{ label }}
</h4>
</h5>
<span v-if="isEmpty" v-t="'detailText.empty'" class="text-italic" />
<span v-else-if="isBinary" class="text-italic">{{ t('detailText.binary', {n: size}) }}</span>
@ -169,7 +169,7 @@ export default {
.with-copy {
border: solid thin var(--border);
border-radius: var(--border-radius);
padding: 20px;
padding: 10px;
position: relative;
background-color: var(--input-bg);
border-radius: var(--border-radius);

View File

@ -135,10 +135,9 @@ export default {
$spacing: 5px;
&:not(.empty) {
border-top: 1px solid var(--border);
padding-bottom: 10px;
border-bottom: 1px solid var(--border);
margin: 20px 0;
padding: 20px 0;
margin-bottom: 10px;
}
.tags {

View File

@ -67,14 +67,21 @@ export default {
const cluster = this.$store.getters['clusterId'];
const inStore = this.$store.getters['currentProduct'].inStore;
const out = [];
return this.filteredRelationships.map((r) => {
for ( const r of this.filteredRelationships) {
const state = r.state || 'active';
const stateColor = colorForState(state, r.error, r.transitioning);
const type = r[`${ this.direction }Type`];
const schema = this.$store.getters[`${ inStore }/schemaFor`](type);
let name = r[`${ this.direction }Id`];
// Skip things like toType/toNamspace+selector for now
if ( !name ) {
continue;
}
let namespace = null;
const idx = name.indexOf('/');
const key = `${ type }/${ namespace }/${ name }`;
@ -95,7 +102,7 @@ export default {
}
};
return {
out.push({
type,
real: this.$store.getters[`${ inStore }/byId`](type, r[`${ this.direction }Id`]),
id: r[`${ this.direction }Id`],
@ -113,16 +120,18 @@ export default {
stateDisplay: stateDisplay(state),
stateBackground: stateColor.replace('text-', 'bg-'),
groupByLabel: namespace,
};
});
});
}
return out;
},
headers() {
return [
STATE,
TYPE,
NAME,
NAMESPACE,
TYPE,
];
},
},

View File

@ -291,8 +291,8 @@ export default {
{{ parent.displayName }}:
</nuxt-link>
<t :k="'resourceDetail.header.' + realMode" :subtype="resourceSubtype" :name="value.nameDisplay" />
<BadgeState v-if="!isCreate && parent.showState" class="masthead-state" :value="value" />
</h1>
<BadgeState v-if="!isCreate && parent.showState" :value="value" />
</div>
<div v-if="!isCreate" class="subheader">
<span v-if="isNamespace && project">{{ t("resourceDetail.masthead.project") }}: {{ project.nameDisplay }}</span>
@ -302,31 +302,33 @@ export default {
</div>
</div>
<slot name="right">
<div class="actions">
<ButtonGroup
v-if="showSensitiveToggle"
:value="!!hideSensitiveData"
icon-size="lg"
:options="sensitiveOptions"
@input="toggleSensitiveData"
/>
<div class="actions-container">
<div class="actions">
<ButtonGroup
v-if="showSensitiveToggle"
:value="!!hideSensitiveData"
icon-size="lg"
:options="sensitiveOptions"
@input="toggleSensitiveData"
/>
<ButtonGroup
v-if="viewOptions && isView"
v-model="currentView"
:options="viewOptions"
/>
<ButtonGroup
v-if="viewOptions && isView"
v-model="currentView"
:options="viewOptions"
/>
<button
v-if="isView"
ref="actions"
aria-haspopup="true"
type="button"
class="btn btn-sm role-multi-action actions"
@click="showActions"
>
<i class="icon icon-actions" />
</button>
<button
v-if="isView"
ref="actions"
aria-haspopup="true"
type="button"
class="btn btn-sm role-multi-action actions"
@click="showActions"
>
<i class="icon icon-actions" />
</button>
</div>
</div>
</slot>
</header>
@ -343,6 +345,13 @@ export default {
<style lang='scss' scoped>
.masthead {
padding-bottom: 10px;
border-bottom: 1px solid var(--border);
margin-bottom: 10px;
}
HEADER {
margin: 0;
}
.primaryheader {
@ -351,7 +360,7 @@ export default {
align-items: center;
h1 {
margin-right: 8px;
margin: 0;
}
}
@ -373,7 +382,7 @@ export default {
justify-content: flex-end;
align-items:center;
& .btn-group {
margin-right: 5px;
margin-right: 10px;
}
}
@ -381,4 +390,10 @@ export default {
margin: 3px 0 0 0;
}
.masthead-state {
font-size: initial;
display: inline-block;
position: relative;
top: -2px;
}
</style>

View File

@ -58,24 +58,28 @@ export default {
<template>
<header>
<TypeDescription :resource="resource" />
<h1>
{{ typeDisplay }} <Favorite v-if="isExplorer" :resource="resource" />
</h1>
<div class="actions">
<n-link
v-if="isCreatable"
:to="createLocation"
class="btn role-primary"
>
{{ t("resourceList.head.create") }}
</n-link>
<n-link
v-else-if="isYamlCreatable"
:to="yamlCreateLocation"
class="btn role-primary"
>
{{ t("resourceList.head.createFromYaml") }}
</n-link>
<div class="title">
<h1 class="m-0">
{{ typeDisplay }} <Favorite v-if="isExplorer" :resource="resource" />
</h1>
</div>
<div class="actions-container">
<div class="actions">
<n-link
v-if="isCreatable"
:to="createLocation"
class="btn role-primary"
>
{{ t("resourceList.head.create") }}
</n-link>
<n-link
v-else-if="isYamlCreatable"
:to="yamlCreateLocation"
class="btn role-primary"
>
{{ t("resourceList.head.createFromYaml") }}
</n-link>
</div>
</div>
</header>
</template>

View File

@ -1,6 +1,6 @@
<script>
export default {
inject: ['addTab', 'removeTab'],
inject: ['addTab', 'removeTab', 'sideTabs'],
props: {
label: {
@ -71,7 +71,9 @@ export default {
:aria-hidden="!active"
role="tabpanel"
>
<h2>{{ label }}</h2>
<h2 v-if="sideTabs">
{{ label }}
</h2>
<slot />
</section>
</template>

View File

@ -40,6 +40,8 @@ export default {
const tabs = this.tabs;
return {
sideTabs: this.sideTabs,
addTab(tab) {
const existing = findBy(tabs, 'name', tab.name);

View File

@ -10,13 +10,15 @@ import Conditions from '@/components/form/Conditions';
import { EVENT } from '@/config/types';
import SortableTable from '@/components/SortableTable';
import { _VIEW } from '@/config/query-params';
import RelatedResources from '@/components/RelatedResources';
export default {
components: {
Tabbed,
Tab,
Conditions,
SortableTable
SortableTable,
RelatedResources,
},
mixins: [CreateEditView],
@ -54,17 +56,15 @@ export default {
computed: {
showConditions() {
return this.isView && !!this.value?.status?.conditions;
const inStore = this.$store.getters['currentProduct'].inStore;
return this.isView && this.value?.type && this.$store.getters[`${ inStore }/pathExistsInSchema`](this.value.type, 'status.conditions');
},
showEvents() {
return this.isView && !this.$fetchState.pending && this.hasEvents && this.events.length;
},
hasCustomTabs() {
return !!Object.keys(this.$slots).length;
},
eventHeaders() {
return [
{
@ -114,14 +114,14 @@ export default {
</script>
<template>
<Tabbed v-if="hasCustomTabs || showConditions || showEvents" v-bind="$attrs">
<Tabbed v-bind="$attrs">
<slot />
<Tab v-if="showConditions" :label="t('resourceTabs.tabs.conditions')" name="conditions" :weight="-1">
<Tab v-if="showConditions" label-key="resourceTabs.conditions.tab" name="conditions" :weight="-1">
<Conditions :value="value" />
</Tab>
<Tab v-if="showEvents" :label="t('resourceTabs.tabs.events')" name="events" :weight="-2">
<Tab v-if="showEvents" label-key="resourceTabs.events.tab" name="events" :weight="-2">
<SortableTable
:rows="events"
:headers="eventHeaders"
@ -132,5 +132,13 @@ export default {
default-sort-by="date"
/>
</Tab>
<Tab name="related" label-key="resourceTabs.related.tab" :weight="-3">
<h3 v-t="'resourceTabs.related.from'" />
<RelatedResources :ignore-types="[value.type]" :value="value" direction="from" />
<h3 v-t="'resourceTabs.related.to'" class="mt-20" />
<RelatedResources :ignore-types="[value.type]" :value="value" direction="to" />
</Tab>
</Tabbed>
</template>

View File

@ -52,6 +52,9 @@ export default {
<div v-for="(row,idx) in parsedRows" :key="idx" class="mb-20">
<DetailText :value="row.value" :label="row.key" :binary="row.binary" />
</div>
<div v-if="!parsedRows.length">
<div v-t="'sortableTable.noRows'" class="m-20 text-center" />
</div>
</Tab>
</ResourceTabs>
</template>

View File

@ -4,9 +4,7 @@ import { base64Decode } from '@/utils/crypto';
import CreateEditView from '@/mixins/create-edit-view';
import ResourceTabs from '@/components/form/ResourceTabs';
import DetailText from '@/components/DetailText';
import RelatedResources from '@/components/RelatedResources';
import Tab from '@/components/Tabbed/Tab';
import { WORKLOAD_TYPES } from '@/config/types';
const types = [
TYPES.OPAQUE,
@ -23,7 +21,6 @@ export default {
components: {
ResourceTabs,
DetailText,
RelatedResources,
Tab,
},
@ -143,18 +140,6 @@ export default {
return rows;
},
hasRelatedWorkloads() {
const { relationships = [] } = this.value.metadata;
for (const r in relationships) {
if (r.rel === 'owner' && WORKLOAD_TYPES.includes(r.fromType)) {
return true;
}
}
return false;
},
dataLabel() {
switch (this.value._type) {
case TYPES.TLS:
@ -219,13 +204,23 @@ export default {
</div>
<div v-else>
<div v-for="(row,idx) in parsedRows" :key="idx" class="mb-20">
<div v-for="(row,idx) in parsedRows" :key="idx" class="entry">
<DetailText :value="row.value" :label="row.key" :conceal="true" />
</div>
<div v-if="!parsedRows.length">
<div v-t="'sortableTable.noRows'" class="m-20 text-center" />
</div>
</div>
</Tab>
<Tab v-if="hasRelatedWorkloads" name="workloads" label-key="secret.relatedWorkloads">
<RelatedResources :ignore-types="['pod']" :value="value" rel="uses" direction="from" />
</Tab>
</ResourceTabs>
</template>
<style lang="scss" scoped>
.entry {
margin-top: 10px;
&:first-of-type {
margin-top: 0;
}
}
</style>

View File

@ -20,19 +20,6 @@ export default {
mixins: [CreateEditView],
props: {
value: {
type: Object,
default: () => {
return {};
}
},
mode: {
type: String,
default: 'view'
}
},
async fetch() {
const hash = {
pods: this.value.pods(),
@ -195,7 +182,7 @@ export default {
<template>
<Loading v-if="$fetchState.pending" />
<div v-else>
<h3 class="mt-20">
<h3>
{{ isJob || isCronJob ? t('workload.detailTop.runs') :t('workload.detailTop.pods') }}
</h3>
<div v-if="pods" class="gauges mb-20">
@ -220,7 +207,7 @@ export default {
/>
</template>
</div>
<ResourceTabs>
<ResourceTabs :value="value">
<Tab v-if="jobs && jobs.length" name="jobs" :label="t('tableHeaders.jobs')">
<ResourceTable
:rows="jobs"
@ -247,11 +234,11 @@ export default {
</div>
</template>
<style lang='scss' scoped>
.gauges {
display: flex;
justify-content: space-around;
&>*{
<style lang='scss' scoped>
.gauges {
display: flex;
justify-content: space-around;
&>*{
flex: 1;
margin-right: $column-gutter;
}

View File

@ -333,11 +333,6 @@ export default {
margin-bottom: 20px;
align-items: center;
H1 {
grid-area: title;
margin: 0;
}
.type-banner {
grid-area: type-banner;
}
@ -350,9 +345,10 @@ export default {
grid-area: title;
}
.actions {
.actions-container {
grid-area: actions;
margin-left: auto;
height: 100%;
margin-left: 8px;
}
}

View File

@ -1,3 +1,4 @@
import { _EDIT, _YAML } from '@/config/query-params';
import impl from './impl';
export default {
@ -6,12 +7,12 @@ export default {
props: {
mode: {
type: String,
required: true,
default: _EDIT,
},
as: {
type: String,
required: true,
default: _YAML,
},
value: {