Browse Source

feat(nc-gui): kanban style

pull/3818/head
Wing-Kam Wong 2 years ago
parent
commit
59c777d30e
  1. 4
      packages/nc-gui/components/cell/Decimal.vue
  2. 4
      packages/nc-gui/components/cell/Float.vue
  3. 4
      packages/nc-gui/components/cell/Integer.vue
  4. 9
      packages/nc-gui/components/cell/MultiSelect.vue
  5. 9
      packages/nc-gui/components/cell/SingleSelect.vue
  6. 9
      packages/nc-gui/components/smartsheet-header/Cell.vue
  7. 9
      packages/nc-gui/components/smartsheet/Kanban.vue

4
packages/nc-gui/components/cell/Decimal.vue

@ -27,12 +27,12 @@ const focus: VNodeRef = (el) => (el as HTMLInputElement)?.focus()
v-if="editEnabled" v-if="editEnabled"
:ref="focus" :ref="focus"
v-model="vModel" v-model="vModel"
class="outline-none p-0 border-none w-full h-full prose-sm" class="outline-none p-0 border-none w-full h-full text-sm"
type="number" type="number"
step="0.1" step="0.1"
@blur="editEnabled = false" @blur="editEnabled = false"
/> />
<span v-else class="prose-sm">{{ vModel }}</span> <span v-else class="text-sm">{{ vModel }}</span>
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">

4
packages/nc-gui/components/cell/Float.vue

@ -27,12 +27,12 @@ const focus: VNodeRef = (el) => (el as HTMLInputElement)?.focus()
v-if="editEnabled" v-if="editEnabled"
:ref="focus" :ref="focus"
v-model="vModel" v-model="vModel"
class="outline-none p-0 border-none w-full h-full prose-sm" class="outline-none p-0 border-none w-full h-full text-sm"
type="number" type="number"
step="0.1" step="0.1"
@blur="editEnabled = false" @blur="editEnabled = false"
/> />
<span v-else class="prose-sm">{{ vModel }}</span> <span v-else class="text-sm">{{ vModel }}</span>
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">

4
packages/nc-gui/components/cell/Integer.vue

@ -31,12 +31,12 @@ function onKeyDown(evt: KeyboardEvent) {
v-if="editEnabled" v-if="editEnabled"
:ref="focus" :ref="focus"
v-model="vModel" v-model="vModel"
class="outline-none p-0 border-none w-full h-full prose-sm" class="outline-none p-0 border-none w-full h-full text-sm"
type="number" type="number"
@blur="editEnabled = false" @blur="editEnabled = false"
@keydown="onKeyDown" @keydown="onKeyDown"
/> />
<span v-else class="prose-sm">{{ vModel }}</span> <span v-else class="text-sm">{{ vModel }}</span>
</template> </template>
<style scoped lang="scss"> <style scoped lang="scss">

9
packages/nc-gui/components/cell/MultiSelect.vue

@ -4,6 +4,7 @@ import type { SelectOptionsType } from 'nocodb-sdk'
import { import {
ActiveCellInj, ActiveCellInj,
ColumnInj, ColumnInj,
IsKanbanInj,
ReadonlyInj, ReadonlyInj,
computed, computed,
h, h,
@ -38,6 +39,8 @@ const aselect = ref<typeof AntSelect>()
const isOpen = ref(false) const isOpen = ref(false)
const isKanban = inject(IsKanbanInj, ref(false))
const options = computed<SelectOptionsType[]>(() => { const options = computed<SelectOptionsType[]>(() => {
if (column?.value.colOptions) { if (column?.value.colOptions) {
const opts = column.value.colOptions const opts = column.value.colOptions
@ -140,7 +143,7 @@ watch(isOpen, (n, _o) => {
> >
<a-select-option v-for="op of options" :key="op.id" :value="op.title" @click.stop> <a-select-option v-for="op of options" :key="op.id" :value="op.title" @click.stop>
<a-tag class="rounded-tag" :color="op.color"> <a-tag class="rounded-tag" :color="op.color">
<span class="text-slate-500">{{ op.title }}</span> <span class="text-slate-500" :class="{ 'text-sm': isKanban }">{{ op.title }}</span>
</a-tag> </a-tag>
</a-select-option> </a-select-option>
<template #tagRender="{ value: val, onClose }"> <template #tagRender="{ value: val, onClose }">
@ -153,7 +156,7 @@ watch(isOpen, (n, _o) => {
:close-icon="h(MdiCloseCircle, { class: ['ms-close-icon'] })" :close-icon="h(MdiCloseCircle, { class: ['ms-close-icon'] })"
@close="onClose" @close="onClose"
> >
<span class="w-full text-slate-500">{{ val }}</span> <span class="w-full text-slate-500" :class="{ 'text-sm': isKanban }">{{ val }}</span>
</a-tag> </a-tag>
</template> </template>
</a-select> </a-select>
@ -187,7 +190,7 @@ watch(isOpen, (n, _o) => {
border-radius: 12px; border-radius: 12px;
} }
:deep(.ant-tag) { :deep(.ant-tag) {
@apply "rounded-tag"; @apply "rounded-tag" my-[2px];
} }
:deep(.ant-tag-close-icon) { :deep(.ant-tag-close-icon) {
@apply "text-slate-500"; @apply "text-slate-500";

9
packages/nc-gui/components/cell/SingleSelect.vue

@ -1,7 +1,7 @@
<script lang="ts" setup> <script lang="ts" setup>
import type { Select as AntSelect } from 'ant-design-vue' import type { Select as AntSelect } from 'ant-design-vue'
import type { SelectOptionsType } from 'nocodb-sdk' import type { SelectOptionsType } from 'nocodb-sdk'
import { ActiveCellInj, ColumnInj, ReadonlyInj, computed, inject, ref, useEventListener, watch } from '#imports' import { ActiveCellInj, ColumnInj, IsKanbanInj, ReadonlyInj, computed, inject, ref, useEventListener, watch } from '#imports'
interface Props { interface Props {
modelValue?: string | undefined modelValue?: string | undefined
@ -21,6 +21,8 @@ const aselect = ref<typeof AntSelect>()
const isOpen = ref(false) const isOpen = ref(false)
const isKanban = inject(IsKanbanInj, ref(false))
const vModel = computed({ const vModel = computed({
get: () => modelValue, get: () => modelValue,
set: (val) => emit('update:modelValue', val || null), set: (val) => emit('update:modelValue', val || null),
@ -80,7 +82,7 @@ watch(isOpen, (n, _o) => {
> >
<a-select-option v-for="op of options" :key="op.title" :value="op.title" @click.stop> <a-select-option v-for="op of options" :key="op.title" :value="op.title" @click.stop>
<a-tag class="rounded-tag" :color="op.color"> <a-tag class="rounded-tag" :color="op.color">
<span class="text-slate-500">{{ op.title }}</span> <span class="text-slate-500" :class="{ 'text-sm': isKanban }">{{ op.title }}</span>
</a-tag> </a-tag>
</a-select-option> </a-select-option>
</a-select> </a-select>
@ -88,8 +90,7 @@ watch(isOpen, (n, _o) => {
<style scoped lang="scss"> <style scoped lang="scss">
.rounded-tag { .rounded-tag {
padding: 0px 12px; @apply py-0 px-[12px] rounded-[12px];
border-radius: 12px;
} }
:deep(.ant-tag) { :deep(.ant-tag) {
@apply "rounded-tag"; @apply "rounded-tag";

9
packages/nc-gui/components/smartsheet-header/Cell.vue

@ -1,6 +1,6 @@
<script setup lang="ts"> <script setup lang="ts">
import type { ColumnType } from 'nocodb-sdk' import type { ColumnType } from 'nocodb-sdk'
import { ColumnInj, IsFormInj, inject, provide, ref, toRef, useUIPermission } from '#imports' import { ColumnInj, IsFormInj, IsKanbanInj, inject, provide, ref, toRef, useUIPermission } from '#imports'
const props = defineProps<{ column: ColumnType & { meta: any }; required?: boolean | number; hideMenu?: boolean }>() const props = defineProps<{ column: ColumnType & { meta: any }; required?: boolean | number; hideMenu?: boolean }>()
@ -8,6 +8,8 @@ const hideMenu = toRef(props, 'hideMenu')
const isForm = inject(IsFormInj, ref(false)) const isForm = inject(IsFormInj, ref(false))
const isKanban = inject(IsKanbanInj, ref(false))
const column = toRef(props, 'column') const column = toRef(props, 'column')
const { isUIAllowed } = useUIPermission() const { isUIAllowed } = useUIPermission()
@ -18,7 +20,10 @@ const editColumnDropdown = ref(false)
</script> </script>
<template> <template>
<div class="flex items-center w-full text-xs text-gray-500 font-weight-medium" :class="{ 'h-full': column }"> <div
class="flex items-center w-full text-xs text-gray-500 font-weight-medium"
:class="{ 'h-full': column, '!text-gray-400': isKanban }"
>
<SmartsheetHeaderCellIcon v-if="column" /> <SmartsheetHeaderCellIcon v-if="column" />
<span v-if="column" class="name" style="white-space: nowrap" :title="column.title">{{ column.title }}</span> <span v-if="column" class="name" style="white-space: nowrap" :title="column.title">{{ column.title }}</span>
<span v-if="(column.rqd && !column.cdf) || required" class="text-red-500">&nbsp;*</span> <span v-if="(column.rqd && !column.cdf) || required" class="text-red-500">&nbsp;*</span>

9
packages/nc-gui/components/smartsheet/Kanban.vue

@ -329,7 +329,7 @@ onMounted(async () => {
class="flex flex-col rounded-lg w-full" class="flex flex-col rounded-lg w-full"
> >
<div v-if="!isRowEmpty(record, col)" class="flex flex-row w-full justify-start pt-2"> <div v-if="!isRowEmpty(record, col)" class="flex flex-row w-full justify-start pt-2">
<div class="w-full text-gray-600"> <div class="w-full text-gray-400">
<LazySmartsheetHeaderVirtualCell v-if="isVirtualCol(col)" :column="col" :hide-menu="true" /> <LazySmartsheetHeaderVirtualCell v-if="isVirtualCol(col)" :column="col" :hide-menu="true" />
<LazySmartsheetHeaderCell v-else :column="col" :hide-menu="true" /> <LazySmartsheetHeaderCell v-else :column="col" :hide-menu="true" />
</div> </div>
@ -337,17 +337,19 @@ onMounted(async () => {
<div <div
v-if="!isRowEmpty(record, col)" v-if="!isRowEmpty(record, col)"
class="flex flex-row w-full items-center justify-start" class="flex flex-row w-full items-center justify-start"
:class="{ 'pt-2 pl-2': col.uidt !== UITypes.SingleSelect }" :class="{ 'pt- pl-2': col.uidt !== UITypes.SingleSelect }"
> >
<LazySmartsheetVirtualCell <LazySmartsheetVirtualCell
v-if="isVirtualCol(col)" v-if="isVirtualCol(col)"
v-model="record.row[col.title]" v-model="record.row[col.title]"
class="text-sm pt-1"
:column="col" :column="col"
:row="record" :row="record"
/> />
<LazySmartsheetCell <LazySmartsheetCell
v-else v-else
v-model="record.row[col.title]" v-model="record.row[col.title]"
class="text-sm pt-1"
:column="col" :column="col"
:edit-enabled="false" :edit-enabled="false"
:read-only="true" :read-only="true"
@ -364,6 +366,7 @@ onMounted(async () => {
<a-layout-footer> <a-layout-footer>
<div v-if="formattedData[stack.title] && countByStack[stack.title] >= 0" class="mt-5 text-center"> <div v-if="formattedData[stack.title] && countByStack[stack.title] >= 0" class="mt-5 text-center">
<mdi-plus <mdi-plus
v-if="!isPublic"
class="text-pint-500 text-lg text-primary cursor-pointer" class="text-pint-500 text-lg text-primary cursor-pointer"
@click="openNewRecordFormHook.trigger(stack.title === 'uncategorized' ? null : stack.title)" @click="openNewRecordFormHook.trigger(stack.title === 'uncategorized' ? null : stack.title)"
/> />
@ -387,7 +390,7 @@ onMounted(async () => {
> >
<div class="items-center justify-between" @click="handleCollapseStack(stackIdx)"> <div class="items-center justify-between" @click="handleCollapseStack(stackIdx)">
<a-skeleton v-if="!formattedData[stack.title] || !countByStack" class="!w-[150px] pl-5" :paragraph="false" /> <a-skeleton v-if="!formattedData[stack.title] || !countByStack" class="!w-[150px] pl-5" :paragraph="false" />
<div v-else class="nc-kanban-data-count mt-[7px] mx-[10px]"> <div v-else class="nc-kanban-data-count mt-[12px] mx-[10px]">
<div class="float-right flex gap-2 items-center cursor-pointer font-bold"> <div class="float-right flex gap-2 items-center cursor-pointer font-bold">
<LazyGeneralTruncateText>{{ stack.title }}</LazyGeneralTruncateText> <LazyGeneralTruncateText>{{ stack.title }}</LazyGeneralTruncateText>
<mdi-menu-down class="text-grey text-lg" /> <mdi-menu-down class="text-grey text-lg" />

Loading…
Cancel
Save