@markuxt/markuxt 0.1.14 → 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/action.yml +24 -0
- package/package.json +7 -1
- package/src/actions/sync-publications/index.ts +488 -0
- package/src/components/MemberCard.vue +13 -0
- package/src/pages/members/[...slug].vue +150 -0
- package/src/public/_markuxt/actions/sync-publications/index.ts +488 -0
- package/src/public/_markuxt/components/MemberCard.vue +13 -0
- package/src/public/_markuxt/pages/members/[...slug].vue +150 -0
|
@@ -70,6 +70,34 @@
|
|
|
70
70
|
<ContentRenderer :value="member" />
|
|
71
71
|
</div>
|
|
72
72
|
</div>
|
|
73
|
+
|
|
74
|
+
<!-- Publications -->
|
|
75
|
+
<div v-if="memberPublications.length > 0" class="profile-section animate-fade-in-up delay-400">
|
|
76
|
+
<div class="profile-section__header">
|
|
77
|
+
<FileText class="icon-inline" theme="outline" :size="22" fill="white" :stroke-width="2.8" />
|
|
78
|
+
<h3>{{ t('members.publications') }}</h3>
|
|
79
|
+
</div>
|
|
80
|
+
<div class="profile-section__body">
|
|
81
|
+
<div class="publications-grid">
|
|
82
|
+
<NuxtLink
|
|
83
|
+
v-for="pub in memberPublications"
|
|
84
|
+
:key="pub._id"
|
|
85
|
+
:to="pub._path"
|
|
86
|
+
class="publication-card"
|
|
87
|
+
>
|
|
88
|
+
<div class="publication-card__content">
|
|
89
|
+
<h4 class="publication-card__title">{{ pub.title }}</h4>
|
|
90
|
+
<p class="publication-card__authors">{{ formatAuthors(pub.authors) }}</p>
|
|
91
|
+
<div class="publication-card__meta">
|
|
92
|
+
<span class="publication-card__venue">{{ pub.venue }}</span>
|
|
93
|
+
<span class="publication-card__year">{{ pub.year }}</span>
|
|
94
|
+
</div>
|
|
95
|
+
</div>
|
|
96
|
+
<ArrowRight class="publication-card__arrow" theme="outline" :size="16" fill="currentColor" :stroke-width="2" />
|
|
97
|
+
</NuxtLink>
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
73
101
|
</div>
|
|
74
102
|
</div>
|
|
75
103
|
</main>
|
|
@@ -93,6 +121,8 @@ import Mail from '@icon-park/vue-next/es/icons/Mail'
|
|
|
93
121
|
import Google from '@icon-park/vue-next/es/icons/Google'
|
|
94
122
|
import Search from '@icon-park/vue-next/es/icons/Search'
|
|
95
123
|
import FileStaff from '@icon-park/vue-next/es/icons/FileStaff'
|
|
124
|
+
import FileText from '@icon-park/vue-next/es/icons/FileText'
|
|
125
|
+
import ArrowRight from '@icon-park/vue-next/es/icons/ArrowRight'
|
|
96
126
|
import Help from '@icon-park/vue-next/es/icons/Help'
|
|
97
127
|
|
|
98
128
|
const { t } = useI18n()
|
|
@@ -120,6 +150,40 @@ const { data: memberData } = await useAsyncData(`member-${slug.value}`, async ()
|
|
|
120
150
|
|
|
121
151
|
const member = computed(() => memberData.value)
|
|
122
152
|
|
|
153
|
+
// Fetch all publications for filtering by member ORCID
|
|
154
|
+
const { data: allPublications } = await useAsyncData('publications', async () => {
|
|
155
|
+
try {
|
|
156
|
+
return await queryContent('/publications')
|
|
157
|
+
.where({ _hidden: { $ne: true } })
|
|
158
|
+
.find()
|
|
159
|
+
} catch (e) {
|
|
160
|
+
console.error('Error fetching publications:', e)
|
|
161
|
+
return []
|
|
162
|
+
}
|
|
163
|
+
})
|
|
164
|
+
|
|
165
|
+
// Filter publications by member's ORCID
|
|
166
|
+
const memberPublications = computed(() => {
|
|
167
|
+
if (!member.value?.orcid || !allPublications.value) return []
|
|
168
|
+
|
|
169
|
+
const memberOrcid = member.value.orcid.trim()
|
|
170
|
+
|
|
171
|
+
return (allPublications.value || [])
|
|
172
|
+
.filter(pub => {
|
|
173
|
+
const authorsOrcid = pub.authors_orcid
|
|
174
|
+
if (!Array.isArray(authorsOrcid)) return false
|
|
175
|
+
return authorsOrcid.some(orcid => orcid === memberOrcid)
|
|
176
|
+
})
|
|
177
|
+
.sort((a, b) => (b.year || 0) - (a.year || 0)) // Sort by year descending
|
|
178
|
+
})
|
|
179
|
+
|
|
180
|
+
// Format authors list for display
|
|
181
|
+
const formatAuthors = (authors: string[] | undefined) => {
|
|
182
|
+
if (!Array.isArray(authors) || authors.length === 0) return ''
|
|
183
|
+
if (authors.length <= 2) return authors.join(' & ')
|
|
184
|
+
return `${authors[0]} et al.`
|
|
185
|
+
}
|
|
186
|
+
|
|
123
187
|
// Provide content ID for ProseImg/ProseVideo to resolve relative asset paths
|
|
124
188
|
provide('contentId', computed(() => member.value?._id || ''))
|
|
125
189
|
|
|
@@ -416,6 +480,92 @@ useHead({
|
|
|
416
480
|
box-shadow: var(--shadow-sm);
|
|
417
481
|
}
|
|
418
482
|
|
|
483
|
+
/* Publications Grid */
|
|
484
|
+
.publications-grid {
|
|
485
|
+
display: flex;
|
|
486
|
+
flex-direction: column;
|
|
487
|
+
gap: var(--spacing-sm);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
.publication-card {
|
|
491
|
+
display: flex;
|
|
492
|
+
align-items: center;
|
|
493
|
+
justify-content: space-between;
|
|
494
|
+
gap: var(--spacing-md);
|
|
495
|
+
padding: var(--spacing-lg);
|
|
496
|
+
background: var(--color-bg);
|
|
497
|
+
border: 1px solid var(--color-border);
|
|
498
|
+
border-radius: var(--radius-lg);
|
|
499
|
+
text-decoration: none;
|
|
500
|
+
transition: all var(--transition-base);
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
.publication-card:hover {
|
|
504
|
+
background: var(--color-bg-alt);
|
|
505
|
+
border-color: var(--color-secondary);
|
|
506
|
+
transform: translateX(4px);
|
|
507
|
+
box-shadow: var(--shadow-md);
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
.publication-card__content {
|
|
511
|
+
flex: 1;
|
|
512
|
+
min-width: 0;
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
.publication-card__title {
|
|
516
|
+
font-family: var(--font-display);
|
|
517
|
+
font-size: 1rem;
|
|
518
|
+
font-weight: 600;
|
|
519
|
+
color: var(--color-primary);
|
|
520
|
+
margin: 0 0 var(--spacing-xs) 0;
|
|
521
|
+
line-height: 1.4;
|
|
522
|
+
display: -webkit-box;
|
|
523
|
+
-webkit-line-clamp: 2;
|
|
524
|
+
line-clamp: 2;
|
|
525
|
+
-webkit-box-orient: vertical;
|
|
526
|
+
overflow: hidden;
|
|
527
|
+
}
|
|
528
|
+
|
|
529
|
+
.publication-card__authors {
|
|
530
|
+
font-size: 0.875rem;
|
|
531
|
+
color: var(--color-text-muted);
|
|
532
|
+
margin: 0 0 var(--spacing-xs) 0;
|
|
533
|
+
line-height: 1.4;
|
|
534
|
+
}
|
|
535
|
+
|
|
536
|
+
.publication-card__meta {
|
|
537
|
+
display: flex;
|
|
538
|
+
align-items: center;
|
|
539
|
+
gap: var(--spacing-sm);
|
|
540
|
+
flex-wrap: wrap;
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
.publication-card__venue {
|
|
544
|
+
font-size: 0.8125rem;
|
|
545
|
+
font-weight: 500;
|
|
546
|
+
color: var(--color-secondary);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
.publication-card__year {
|
|
550
|
+
font-size: 0.8125rem;
|
|
551
|
+
font-weight: 600;
|
|
552
|
+
color: var(--color-accent);
|
|
553
|
+
background: rgba(0, 217, 255, 0.1);
|
|
554
|
+
padding: 2px 8px;
|
|
555
|
+
border-radius: var(--radius-sm);
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
.publication-card__arrow {
|
|
559
|
+
flex-shrink: 0;
|
|
560
|
+
color: var(--color-secondary);
|
|
561
|
+
transition: transform var(--transition-fast);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
.publication-card:hover .publication-card__arrow {
|
|
565
|
+
transform: translateX(4px);
|
|
566
|
+
color: var(--color-accent);
|
|
567
|
+
}
|
|
568
|
+
|
|
419
569
|
/* ContentRenderer Markdown Styling */
|
|
420
570
|
.profile-section__body--content :deep(h2) {
|
|
421
571
|
font-family: var(--font-display);
|