Browse Source

Merge pull request #2910 from nocodb/feat/gui-v2-percent-cell

feat(gui-v2): percent cell
pull/2945/head
աɨռɢӄաօռɢ 2 years ago committed by GitHub
parent
commit
40299421d0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 67
      packages/nc-gui-v2/components/cell/Percent.vue
  2. 3
      packages/nc-gui-v2/components/smartsheet-header/CellIcon.vue
  3. 2
      packages/nc-gui-v2/components/smartsheet/Cell.vue
  4. 2
      packages/nc-gui-v2/composables/useColumn.ts
  5. 30
      packages/nc-gui-v2/utils/percentUtils.ts

67
packages/nc-gui-v2/components/cell/Percent.vue

@ -0,0 +1,67 @@
<script setup lang="ts">
import { computed, inject } from '#imports'
import { ColumnInj } from '~/context'
import { getPercentStep, isValidPercent, renderPercent } from '@/utils/percentUtils'
interface Props {
modelValue: number | string
}
const { modelValue } = defineProps<Props>()
const emit = defineEmits(['update:modelValue'])
const column = inject(ColumnInj)
const percent = ref()
const isEdited = ref(false)
const percentType = computed(() => column?.meta?.precision || 0)
const percentStep = computed(() => getPercentStep(percentType.value))
const localState = computed({
get: () => {
return renderPercent(modelValue, percentType.value, !isEdited.value)
},
set: (val) => {
if (val === null) val = 0
if (isValidPercent(val, column?.meta?.negative)) {
percent.value = val / 100
}
},
})
function onKeyDown(evt: KeyboardEvent) {
isEdited.value = true
return ['e', 'E', '+', '-'].includes(evt.key) && evt.preventDefault()
}
function onBlur() {
if (isEdited.value) {
emit('update:modelValue', percent.value)
isEdited.value = false
}
}
function onKeyDownEnter() {
if (isEdited.value) {
emit('update:modelValue', percent.value)
isEdited.value = false
}
}
</script>
<template>
<input
v-if="isEdited"
v-model="localState"
type="number"
:step="percentStep"
@keydown="onKeyDown"
@blur="onBlur"
@keydown.enter="onKeyDownEnter"
/>
<input v-else v-model="localState" type="text" @focus="isEdited = true" />
</template>

3
packages/nc-gui-v2/components/smartsheet-header/CellIcon.vue

@ -18,6 +18,7 @@ import AttachmentIcon from '~icons/mdi/image-multiple-outline'
import URLIcon from '~icons/mdi/link'
import EmailIcon from '~icons/mdi/email'
import CurrencyIcon from '~icons/mdi/currency-usd-circle-outline'
import PercentIcon from '~icons/mdi/percent-outline'
const { columnMeta } = defineProps<{ columnMeta?: ColumnType }>()
@ -56,6 +57,8 @@ const icon = computed(() => {
return URLIcon
} else if (additionalColMeta.isCurrency) {
return CurrencyIcon
} else if (additionalColMeta.isPercent) {
return PercentIcon
} else if (additionalColMeta.isString) {
return StringIcon
} else {

2
packages/nc-gui-v2/components/smartsheet/Cell.vue

@ -43,6 +43,7 @@ const {
isString,
isSingleSelect,
isMultiSelect,
isPercent,
} = useColumn(column)
</script>
@ -202,6 +203,7 @@ todo :
<!-- v-on="parentListeners"
/>
-->
<CellPercent v-else-if="isPercent" v-model="localState" />
<CellText v-else v-model="localState" />
<!-- v-on="$listeners" <span v-if="hint" class="nc-hint">{{ hint }}</span> -->

2
packages/nc-gui-v2/composables/useColumn.ts

@ -31,6 +31,7 @@ export function useColumn(column: ColumnType) {
const isRating = uiDatatype === UITypes.Rating
const isCurrency = uiDatatype === 'Currency'
const isDuration = uiDatatype === UITypes.Duration
const isPercent = uiDatatype === UITypes.Percent
const isAutoSaved = [
UITypes.SingleLineText,
UITypes.LongText,
@ -72,5 +73,6 @@ export function useColumn(column: ColumnType) {
isManualSaved,
isSingleSelect,
isMultiSelect,
isPercent,
}
}

30
packages/nc-gui-v2/utils/percentUtils.ts

@ -0,0 +1,30 @@
export const precisions = [
{ id: 0, title: '1' },
{ id: 1, title: '1.0' },
{ id: 2, title: '1.00' },
{ id: 3, title: '1.000' },
{ id: 4, title: '1.0000' },
{ id: 5, title: '1.00000' },
{ id: 6, title: '1.000000' },
{ id: 7, title: '1.0000000' },
{ id: 8, title: '1.00000000' },
]
export function renderPercent(value: any, precision: number, withPercentSymbol = true) {
if (!value) return value
value = (Number(value) * 100).toFixed(precision)
if (withPercentSymbol) return padPercentSymbol(value)
return value
}
export function isValidPercent(value: any, negative: boolean): boolean {
return negative ? /^-?\d{1,20}(\.\d+)?$/.test(value) : /^\d{1,20}(\.\d+)?$/.test(value)
}
export function getPercentStep(precision: number): string {
return (1 / 10 ** precision).toString()
}
function padPercentSymbol(value: any) {
return value ? `${value}%` : value
}
Loading…
Cancel
Save