Merge remote-tracking branch 'origin/master'
This commit is contained in:
@@ -363,8 +363,7 @@
|
|||||||
:class="[props.col.classes, { 'sticky-col': isStickyCol(props.col.name), 'sticky-boundary': isStickyBoundary(props.col.name) }]"
|
:class="[props.col.classes, { 'sticky-col': isStickyCol(props.col.name), 'sticky-boundary': isStickyBoundary(props.col.name) }]"
|
||||||
:style="getBodyCellStyle(props.col)"
|
:style="getBodyCellStyle(props.col)"
|
||||||
>
|
>
|
||||||
<q-badge v-if="props.row.campaignLabel" color="primary" outline :label="props.row.campaignLabel" />
|
<q-badge v-if="props.row.campaignLabel" color="primary" outline :label="props.row.campaignLabel" class="campaign-badge" />
|
||||||
<span v-else class="text-grey-6">-</span>
|
|
||||||
</q-td>
|
</q-td>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -505,7 +504,7 @@ const topUrunAnaGrubu = ref(null)
|
|||||||
const selectedProductCodes = ref([])
|
const selectedProductCodes = ref([])
|
||||||
const selectedCampaignLabels = ref([])
|
const selectedCampaignLabels = ref([])
|
||||||
const campaignFilterSearch = ref('')
|
const campaignFilterSearch = ref('')
|
||||||
const selectedPriceOptions = ref(priceOptions.map((x) => x.value))
|
const selectedPriceOptions = ref(['usd5', 'try5'])
|
||||||
const leftDetailsExpanded = ref(true)
|
const leftDetailsExpanded = ref(true)
|
||||||
|
|
||||||
const rows = ref([])
|
const rows = ref([])
|
||||||
@@ -815,7 +814,7 @@ async function reloadData ({ page = 1 } = {}) {
|
|||||||
}
|
}
|
||||||
rows.value = buildRows(products, variants)
|
rows.value = buildRows(products, variants)
|
||||||
error.value = ''
|
error.value = ''
|
||||||
void loadImagesForRows(rows.value.slice(0, 120))
|
void loadImagesForRows(rows.value)
|
||||||
await nextTick()
|
await nextTick()
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
rows.value = []
|
rows.value = []
|
||||||
@@ -836,10 +835,18 @@ async function loadImagesForRows (list) {
|
|||||||
seen.add(key)
|
seen.add(key)
|
||||||
targets.push({ row, key })
|
targets.push({ row, key })
|
||||||
}
|
}
|
||||||
await Promise.all(targets.map(async ({ row, key }) => {
|
const concurrency = 12
|
||||||
|
let cursor = 0
|
||||||
|
let loaded = 0
|
||||||
|
const workers = Array.from({ length: Math.min(concurrency, targets.length) }, async () => {
|
||||||
|
for (;;) {
|
||||||
|
const target = targets[cursor]
|
||||||
|
cursor += 1
|
||||||
|
if (!target) return
|
||||||
|
const { row, key } = target
|
||||||
if (imageCache.has(key)) {
|
if (imageCache.has(key)) {
|
||||||
row.imageUrl = imageCache.get(key)
|
row.imageUrl = imageCache.get(key)
|
||||||
return
|
continue
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const res = await api.get('/product-images', {
|
const res = await api.get('/product-images', {
|
||||||
@@ -858,7 +865,11 @@ async function loadImagesForRows (list) {
|
|||||||
} catch {
|
} catch {
|
||||||
imageCache.set(key, '')
|
imageCache.set(key, '')
|
||||||
}
|
}
|
||||||
}))
|
loaded += 1
|
||||||
|
if (loaded % 12 === 0) rows.value = [...rows.value]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
await Promise.all(workers)
|
||||||
rows.value = [...rows.value]
|
rows.value = [...rows.value]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -978,26 +989,29 @@ function col (name, label, field, width, extra = {}) {
|
|||||||
const allColumns = [
|
const allColumns = [
|
||||||
col('image', '', 'imageUrl', 108, { align: 'center', classes: 'image-col sticky-col' }),
|
col('image', '', 'imageUrl', 108, { align: 'center', classes: 'image-col sticky-col' }),
|
||||||
col('brandGroupSelection', 'MARKA GRUBU', 'brandGroupSelection', 86, { classes: 'ps-col sticky-col' }),
|
col('brandGroupSelection', 'MARKA GRUBU', 'brandGroupSelection', 86, { classes: 'ps-col sticky-col' }),
|
||||||
col('marka', 'MARKA', 'marka', 62, { sortable: true, classes: 'ps-col sticky-col' }),
|
col('marka', 'MARKA', 'marka', 72, { sortable: true, classes: 'ps-col sticky-col' }),
|
||||||
col('productCode', 'URUN KODU', 'productCode', 112, { sortable: true, classes: 'ps-col product-code-col sticky-col' }),
|
col('productCode', 'URUN KODU', 'productCode', 112, { sortable: true, classes: 'ps-col product-code-col sticky-col' }),
|
||||||
col('variantCodes', 'VARYANT', 'variantCodes', 112, { classes: 'ps-col variant-col sticky-col' }),
|
col('variantCodes', 'VARYANT', 'variantCodes', 128, { classes: 'ps-col variant-col sticky-col' }),
|
||||||
col('variantStocks', 'STOK', 'stockQty', 62, { align: 'right', sortable: true, classes: 'ps-col variant-stock-col sticky-col' }),
|
col('variantStocks', 'STOK', 'stockQty', 72, { align: 'right', sortable: true, classes: 'ps-col variant-stock-col sticky-col' }),
|
||||||
col('campaignLabel', 'KAMPANYA', 'campaignLabel', 150, { classes: 'ps-col campaign-col sticky-col' }),
|
col('campaignLabel', 'KAMPANYA', 'campaignLabel', 150, { classes: 'ps-col campaign-col sticky-col' }),
|
||||||
col('campaignRate', 'IND %', 'campaignRate', 58, { align: 'right', classes: 'ps-col campaign-rate-col sticky-col' }),
|
col('campaignRate', 'IND %', 'campaignRate', 64, { align: 'right', classes: 'ps-col campaign-rate-col sticky-col' }),
|
||||||
col('askiliYan', 'ASKILI YAN', 'askiliYan', 58, { sortable: true, classes: 'ps-col' }),
|
col('askiliYan', 'ASKILI YAN', 'askiliYan', 72, { sortable: true, classes: 'ps-col' }),
|
||||||
col('kategori', 'KATEGORI', 'kategori', 58, { sortable: true, classes: 'ps-col' }),
|
col('kategori', 'KATEGORI', 'kategori', 82, { sortable: true, classes: 'ps-col' }),
|
||||||
col('urunIlkGrubu', 'URUN ILK GRUBU', 'urunIlkGrubu', 70, { sortable: true, classes: 'ps-col' }),
|
col('urunIlkGrubu', 'URUN ILK GRUBU', 'urunIlkGrubu', 88, { sortable: true, classes: 'ps-col' }),
|
||||||
col('urunAnaGrubu', 'URUN ANA GRUBU', 'urunAnaGrubu', 74, { sortable: true, classes: 'ps-col' }),
|
col('urunAnaGrubu', 'URUN ANA GRUBU', 'urunAnaGrubu', 96, { sortable: true, classes: 'ps-col' }),
|
||||||
col('urunAltGrubu', 'URUN ALT GRUBU', 'urunAltGrubu', 74, { sortable: true, classes: 'ps-col' }),
|
col('urunAltGrubu', 'URUN ALT GRUBU', 'urunAltGrubu', 96, { sortable: true, classes: 'ps-col' }),
|
||||||
col('icerik', 'ICERIK', 'icerik', 66, { sortable: true, classes: 'ps-col' }),
|
col('icerik', 'ICERIK', 'icerik', 112, { sortable: true, classes: 'ps-col' }),
|
||||||
col('karisim', 'KARISIM', 'karisim', 66, { sortable: true, classes: 'ps-col' }),
|
col('karisim', 'KARISIM', 'karisim', 96, { sortable: true, classes: 'ps-col' }),
|
||||||
...campaignPairs.flatMap((p) => [
|
...campaignPairs.flatMap((p) => [
|
||||||
col(p.base, p.base.toUpperCase().replace(/([A-Z]+)(\d)/, '$1 $2'), p.base, 78, { align: 'right', classes: `${p.base.slice(0, 3)}-col` }),
|
col(p.base, p.base.toUpperCase().replace(/([A-Z]+)(\d)/, '$1 $2'), p.base, 78, { align: 'right', classes: `${p.base.slice(0, 3)}-col` }),
|
||||||
col(p.derived, `${p.base.toUpperCase().replace(/([A-Z]+)(\d)/, '$1 $2')} KMP`, p.derived, 88, { align: 'right', classes: `${p.base.slice(0, 3)}-col campaign-price-col` })
|
col(p.derived, `${p.base.toUpperCase().replace(/([A-Z]+)(\d)/, '$1 $2')} KMP`, p.derived, 88, { align: 'right', classes: `${p.base.slice(0, 3)}-col campaign-price-col` })
|
||||||
])
|
])
|
||||||
]
|
]
|
||||||
|
|
||||||
const hideableLeftDetailColumnNames = new Set([
|
const compactHiddenColumnNames = new Set([
|
||||||
|
'variantStocks',
|
||||||
|
'campaignLabel',
|
||||||
|
'campaignRate',
|
||||||
'askiliYan',
|
'askiliYan',
|
||||||
'kategori',
|
'kategori',
|
||||||
'urunIlkGrubu',
|
'urunIlkGrubu',
|
||||||
@@ -1010,7 +1024,7 @@ const hideableLeftDetailColumnNames = new Set([
|
|||||||
const visibleColumns = computed(() => allColumns.filter((c) => {
|
const visibleColumns = computed(() => allColumns.filter((c) => {
|
||||||
if (/^(usd|eur|try)[1-6]$/.test(c.name)) return selectedPriceSet.value.has(c.name)
|
if (/^(usd|eur|try)[1-6]$/.test(c.name)) return selectedPriceSet.value.has(c.name)
|
||||||
if (/^(usd|eur|try)[1-6]Campaign$/.test(c.name)) return selectedPriceSet.value.has(c.name.replace(/Campaign$/, ''))
|
if (/^(usd|eur|try)[1-6]Campaign$/.test(c.name)) return selectedPriceSet.value.has(c.name.replace(/Campaign$/, ''))
|
||||||
if (!leftDetailsExpanded.value && hideableLeftDetailColumnNames.has(c.name)) return false
|
if (!leftDetailsExpanded.value && compactHiddenColumnNames.has(c.name)) return false
|
||||||
return true
|
return true
|
||||||
}))
|
}))
|
||||||
|
|
||||||
@@ -1027,9 +1041,30 @@ const tableStyle = computed(() => ({
|
|||||||
}))
|
}))
|
||||||
const stickyColumnNames = computed(() => {
|
const stickyColumnNames = computed(() => {
|
||||||
const visible = new Set(visibleColumns.value.map((x) => x.name))
|
const visible = new Set(visibleColumns.value.map((x) => x.name))
|
||||||
return ['image', 'brandGroupSelection', 'marka', 'productCode', 'variantCodes', 'variantStocks', 'campaignLabel', 'campaignRate'].filter((x) => visible.has(x))
|
const expanded = [
|
||||||
|
'image',
|
||||||
|
'brandGroupSelection',
|
||||||
|
'marka',
|
||||||
|
'productCode',
|
||||||
|
'variantCodes',
|
||||||
|
'variantStocks',
|
||||||
|
'campaignLabel',
|
||||||
|
'campaignRate',
|
||||||
|
'askiliYan',
|
||||||
|
'kategori',
|
||||||
|
'urunIlkGrubu',
|
||||||
|
'urunAnaGrubu',
|
||||||
|
'urunAltGrubu',
|
||||||
|
'icerik',
|
||||||
|
'karisim'
|
||||||
|
]
|
||||||
|
const compact = ['image', 'brandGroupSelection', 'marka', 'productCode', 'variantCodes']
|
||||||
|
return (leftDetailsExpanded.value ? expanded : compact).filter((x) => visible.has(x))
|
||||||
|
})
|
||||||
|
const stickyBoundaryColumnName = computed(() => {
|
||||||
|
const list = stickyColumnNames.value
|
||||||
|
return list.length ? list[list.length - 1] : ''
|
||||||
})
|
})
|
||||||
const stickyBoundaryColumnName = 'campaignRate'
|
|
||||||
const stickyColumnNameSet = computed(() => new Set(stickyColumnNames.value))
|
const stickyColumnNameSet = computed(() => new Set(stickyColumnNames.value))
|
||||||
const stickyLeftMap = computed(() => {
|
const stickyLeftMap = computed(() => {
|
||||||
const map = {}
|
const map = {}
|
||||||
@@ -1043,8 +1078,9 @@ const stickyLeftMap = computed(() => {
|
|||||||
return map
|
return map
|
||||||
})
|
})
|
||||||
const stickyScrollComp = computed(() => {
|
const stickyScrollComp = computed(() => {
|
||||||
const boundaryCol = allColumns.find((x) => x.name === stickyBoundaryColumnName)
|
const boundaryName = stickyBoundaryColumnName.value
|
||||||
return ((stickyLeftMap.value[stickyBoundaryColumnName] || 0) + extractWidth(boundaryCol?.style)) * 1.2
|
const boundaryCol = allColumns.find((x) => x.name === boundaryName)
|
||||||
|
return ((stickyLeftMap.value[boundaryName] || 0) + extractWidth(boundaryCol?.style)) * 1.2
|
||||||
})
|
})
|
||||||
|
|
||||||
function isStickyCol (name) {
|
function isStickyCol (name) {
|
||||||
@@ -1052,7 +1088,7 @@ function isStickyCol (name) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function isStickyBoundary (name) {
|
function isStickyBoundary (name) {
|
||||||
return name === stickyBoundaryColumnName
|
return name === stickyBoundaryColumnName.value
|
||||||
}
|
}
|
||||||
|
|
||||||
function getHeaderCellStyle (col) {
|
function getHeaderCellStyle (col) {
|
||||||
@@ -1081,12 +1117,11 @@ function exportCell (row, col) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function exportVisibleExcel () {
|
function exportVisibleExcel () {
|
||||||
const cols = visibleColumns.value
|
const cols = visibleColumns.value.filter((c) => c.name !== 'image')
|
||||||
const body = filteredRows.value.map((row) => `<tr>${cols.map((c) => {
|
const body = filteredRows.value.map((row) => `<tr>${cols.map((c) => {
|
||||||
if (c.name === 'image' && row.imageUrl) return `<td><img src="${row.imageUrl}" width="100" height="100"></td>`
|
|
||||||
return `<td>${escapeHtml(exportCell(row, c))}</td>`
|
return `<td>${escapeHtml(exportCell(row, c))}</td>`
|
||||||
}).join('')}</tr>`).join('')
|
}).join('')}</tr>`).join('')
|
||||||
const html = `<!doctype html><html><head><meta charset="utf-8"></head><body><table border="1"><thead><tr>${cols.map((c) => `<th>${escapeHtml(c.label || 'Gorsel')}</th>`).join('')}</tr></thead><tbody>${body}</tbody></table></body></html>`
|
const html = `<!doctype html><html><head><meta charset="utf-8"></head><body><table border="1"><thead><tr>${cols.map((c) => `<th>${escapeHtml(c.label)}</th>`).join('')}</tr></thead><tbody>${body}</tbody></table></body></html>`
|
||||||
const blob = new Blob([html], { type: 'application/vnd.ms-excel;charset=utf-8' })
|
const blob = new Blob([html], { type: 'application/vnd.ms-excel;charset=utf-8' })
|
||||||
const url = URL.createObjectURL(blob)
|
const url = URL.createObjectURL(blob)
|
||||||
const a = document.createElement('a')
|
const a = document.createElement('a')
|
||||||
@@ -1184,7 +1219,7 @@ onMounted(() => {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
--pricing-row-height: 108px;
|
--pricing-row-height: 108px;
|
||||||
--pricing-header-height: 72px;
|
--pricing-header-height: 88px;
|
||||||
--pricing-table-height: calc(100vh - 156px);
|
--pricing-table-height: calc(100vh - 156px);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1315,6 +1350,13 @@ onMounted(() => {
|
|||||||
border-bottom: 1px solid rgba(0, 0, 0, 0.08) !important;
|
border-bottom: 1px solid rgba(0, 0, 0, 0.08) !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.pricing-table :deep(td) {
|
||||||
|
overflow: hidden !important;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: middle !important;
|
||||||
|
}
|
||||||
|
|
||||||
.pricing-table :deep(th),
|
.pricing-table :deep(th),
|
||||||
.pricing-table :deep(.q-table thead tr),
|
.pricing-table :deep(.q-table thead tr),
|
||||||
.pricing-table :deep(.q-table thead tr.header-row-fixed),
|
.pricing-table :deep(.q-table thead tr.header-row-fixed),
|
||||||
@@ -1328,9 +1370,10 @@ onMounted(() => {
|
|||||||
.pricing-table :deep(th) {
|
.pricing-table :deep(th) {
|
||||||
padding-top: 0;
|
padding-top: 0;
|
||||||
padding-bottom: 0;
|
padding-bottom: 0;
|
||||||
white-space: nowrap;
|
white-space: normal;
|
||||||
word-break: normal;
|
word-break: break-word;
|
||||||
text-overflow: ellipsis;
|
overflow-wrap: anywhere;
|
||||||
|
overflow: hidden;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
@@ -1411,15 +1454,22 @@ onMounted(() => {
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
text-overflow: ellipsis;
|
|
||||||
white-space: normal;
|
white-space: normal;
|
||||||
|
word-break: break-word;
|
||||||
|
overflow-wrap: anywhere;
|
||||||
font-weight: 800;
|
font-weight: 800;
|
||||||
line-height: 1.15;
|
line-height: 1.12;
|
||||||
display: -webkit-box;
|
display: -webkit-box;
|
||||||
-webkit-line-clamp: 2;
|
-webkit-line-clamp: 4;
|
||||||
-webkit-box-orient: vertical;
|
-webkit-box-orient: vertical;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.campaign-badge {
|
||||||
|
max-width: 100%;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
.header-filter-btn {
|
.header-filter-btn {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
|
|||||||
Reference in New Issue
Block a user