|
@@ -7,24 +7,76 @@
|
|
|
<span>{{ $t('leftPanel.page') }} {{ pageNumber * 1 + 1 }}</span>
|
|
|
<span>{{ pageAnnotations.pageAnnotationsCount }}</span>
|
|
|
</div>
|
|
|
- <template v-for="(item) in pageAnnotations.annotations">
|
|
|
- <div v-if="!item.isDelete && item.type !== 'link'" class="annotation-item" @click="goToPage(item.pageIndex)">
|
|
|
+ <template v-for="(item, index) in pageAnnotations.annotations">
|
|
|
+ <div v-if="!item.isDelete && item.type !== 'link'" class="annotation-item" @click="goToPage(item.pageIndex, index)" :class="{ 'selected': selectedItemIndex === `${item.pageIndex}-${index}` }">
|
|
|
<div class="item-header">
|
|
|
<Highlight v-if="item.type === 'highlight'" />
|
|
|
<Squiggle v-else-if="item.type === 'squiggly'" />
|
|
|
<Strikeout v-else-if="item.type === 'strikeout'" />
|
|
|
<Underline v-else-if="item.type === 'underline'" />
|
|
|
<Ink v-else-if="item.type === 'ink'" />
|
|
|
- <LineTool v-else-if="item.type === 'line' && (((item.tail === 'None' || item.tail === 'Unknown') && (item.head === 'None' || item.head === 'Unknown')) || (!item.tail && !item.head))" />
|
|
|
- <ArrowTool v-else-if="item.type === 'line' && (item.tail === 'OpenArrow' || item.head === 'OpenArrow' || item.arrow)" />
|
|
|
+ <LineTool
|
|
|
+ v-else-if="item.type === 'line' && (((item.tail === 'None' || item.tail === 'Unknown') && (item.head === 'None' || item.head === 'Unknown')) || (!item.tail && !item.head))" />
|
|
|
+ <ArrowTool
|
|
|
+ v-else-if="item.type === 'line' && (item.tail === 'OpenArrow' || item.head === 'OpenArrow' || item.arrow)" />
|
|
|
<RectangleTool v-else-if="item.type === 'square'" />
|
|
|
<EllipseTool v-else-if="item.type === 'circle'" />
|
|
|
<Text v-else-if="item.type === 'freetext'" />
|
|
|
<Note v-else-if="item.type === 'text'" />
|
|
|
<Stamp v-else-if="item.type === 'image' || item.type === 'stamp'" />
|
|
|
- <span>{{ dayjs(item.date).format('DD/MM/YYYY HH:mm:ss') }}</span>
|
|
|
+
|
|
|
+ <div>
|
|
|
+ <p class="name">Guest</p>
|
|
|
+ <p class="date">{{ dayjs(item.date).format('DD/MM/YYYY HH:mm:ss') }}</p>
|
|
|
+ <div v-if="item.contents" class="item-content">{{ item.contents }}</div>
|
|
|
+ </div>
|
|
|
+ <n-popover trigger="hover" placement="bottom" class="mark-popover">
|
|
|
+ <template #trigger>
|
|
|
+ <div class="mark-box" :class="{ 'marked': item.marked }" @click="item.marked = !item.marked"></div>
|
|
|
+ </template>
|
|
|
+ <span>Marked</span>
|
|
|
+ </n-popover>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="item-reply" v-if="selectedItemIndex === `${item.pageIndex}-${index}`">
|
|
|
+ <input type="text" placeholder="Reply or add thoghts" v-model="replyText">
|
|
|
+ <div>
|
|
|
+ <span @click="cancel">Cancel</span>
|
|
|
+ <button :class="{ 'active': replyText }">Reply</button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div class="item-footer" v-if="selectedItemIndex === `${item.pageIndex}-${index}`">
|
|
|
+ <n-popover
|
|
|
+ ref="popover"
|
|
|
+ placement="bottom"
|
|
|
+ trigger="click"
|
|
|
+ :show-arrow="false"
|
|
|
+ to="#outerContainer"
|
|
|
+ :raw="true"
|
|
|
+ :z-index="96"
|
|
|
+ class="state-popover"
|
|
|
+ :show="showPopover"
|
|
|
+ @update:show="handleUpdateShow"
|
|
|
+ >
|
|
|
+ <template #trigger>
|
|
|
+ <Button :class="{ active: showPopover }">
|
|
|
+ <Accepted />
|
|
|
+ <!-- <component :is="state" /> -->
|
|
|
+ </Button>
|
|
|
+ </template>
|
|
|
+ <div class="drop-down">
|
|
|
+ <div class="drop-item" @click="setState('Accepted')"><Accepted />Accepted</div>
|
|
|
+ <div class="drop-item" @click="setState('Rejected')"><Rejected />Rejected</div>
|
|
|
+ <div class="drop-item" @click="setState('Cancelled')"><Cancelled />Cancelled</div>
|
|
|
+ </div>
|
|
|
+ </n-popover>
|
|
|
+ <div class="re">
|
|
|
+ <Reply />
|
|
|
+ <span>4</span>
|
|
|
+ <Return />
|
|
|
+ </div>
|
|
|
</div>
|
|
|
- <div v-if="item.contents" class="item-content">{{ item.contents }}</div>
|
|
|
</div>
|
|
|
</template>
|
|
|
</template>
|
|
@@ -35,82 +87,273 @@
|
|
|
</template>
|
|
|
|
|
|
<script setup>
|
|
|
- import { computed, ref, getCurrentInstance } from 'vue';
|
|
|
- import dayjs from 'dayjs'
|
|
|
- import core from '@/core'
|
|
|
- import { useDocumentStore } from '@/stores/modules/document'
|
|
|
+import { computed, ref, getCurrentInstance, watch } from 'vue'
|
|
|
+import dayjs from 'dayjs'
|
|
|
+import core from '@/core'
|
|
|
+import { useDocumentStore } from '@/stores/modules/document'
|
|
|
+import { useViewerStore } from '@/stores/modules/viewer'
|
|
|
+import { NPopover } from 'naive-ui'
|
|
|
|
|
|
- const useDocument = useDocumentStore()
|
|
|
+const useDocument = useDocumentStore()
|
|
|
+const useViewer = useViewerStore()
|
|
|
|
|
|
- let annotationsContainers = computed(() => useDocument.getAllAnnotations)
|
|
|
+let annotationsContainers = computed(() => useDocument.getAllAnnotations)
|
|
|
+const activePanelTab = computed(() => useViewer.getActiveElementTab('leftPanelTab'))
|
|
|
+const isOpen = computed(() => useViewer.isElementOpen('leftPanel'))
|
|
|
+// const showPopover = computed(() => popover.value && popover.value.getMergedShow())
|
|
|
|
|
|
- const markup = ['highlight', 'underline', 'squiggly', 'strikeout']
|
|
|
+const markup = ['highlight', 'underline', 'squiggly', 'strikeout']
|
|
|
+const replyText = ref('')
|
|
|
+const selectedItemIndex = ref('')
|
|
|
+const popover = ref(null)
|
|
|
+const showPopover = ref(false)
|
|
|
+const state = ref('Accepted')
|
|
|
|
|
|
- const setAnnotationList = ({ annotations }) => {
|
|
|
- useDocument.initAnnotations(annotations)
|
|
|
- const instance = getCurrentInstance();
|
|
|
- instance?.proxy?.$forceUpdate();
|
|
|
- }
|
|
|
- core.addEvent('annotationChanged', setAnnotationList)
|
|
|
+watch([activePanelTab, isOpen], (oldValue, newValue) => {
|
|
|
+ if (newValue[0] === 'ANNOTATION' || newValue[1]) cancel()
|
|
|
+})
|
|
|
+
|
|
|
+const setAnnotationList = ({ annotations }) => {
|
|
|
+ useDocument.initAnnotations(annotations)
|
|
|
+ const instance = getCurrentInstance();
|
|
|
+ instance?.proxy?.$forceUpdate();
|
|
|
+}
|
|
|
+core.addEvent('annotationChanged', setAnnotationList)
|
|
|
+
|
|
|
+const goToPage = (page, index) => {
|
|
|
+ core.pageNumberChanged({
|
|
|
+ value: (page * 1 + 1).toString()
|
|
|
+ })
|
|
|
+ selectedItemIndex.value = page + '-' + index
|
|
|
+}
|
|
|
+
|
|
|
+const cancel = (e) => {
|
|
|
+ e?.stopPropagation()
|
|
|
+ selectedItemIndex.value = ''
|
|
|
+ replyText.value = ''
|
|
|
+}
|
|
|
+
|
|
|
+const setState = (val) => {
|
|
|
+ state.value = val
|
|
|
+ showPopover.value = false
|
|
|
+}
|
|
|
+
|
|
|
+const handleUpdateShow = () => {
|
|
|
+ showPopover.value = !showPopover.value
|
|
|
+}
|
|
|
|
|
|
- const goToPage = (page) => {
|
|
|
- core.pageNumberChanged({
|
|
|
- value: (page * 1 + 1).toString()
|
|
|
- })
|
|
|
- }
|
|
|
</script>
|
|
|
|
|
|
<style lang="scss">
|
|
|
- .annotation-view {
|
|
|
- position: relative;
|
|
|
- height: calc(100% - 95px);
|
|
|
- overflow: auto;
|
|
|
- .page-title {
|
|
|
+.annotation-view {
|
|
|
+ position: relative;
|
|
|
+ padding: 0 8px;
|
|
|
+ height: calc(100% - 95px);
|
|
|
+ overflow: auto;
|
|
|
+
|
|
|
+ .page-title {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ padding: 6px 8px;
|
|
|
+ color: var(--c-side-title);
|
|
|
+
|
|
|
+ span {
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 20px;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .annotation-item {
|
|
|
+ margin-top: 4px;
|
|
|
+ padding: 4px 8px;
|
|
|
+ background: var(--c-side-annotation-bg);
|
|
|
+ border-radius: 4px;
|
|
|
+ border: 1.2px solid transparent;
|
|
|
+
|
|
|
+ & + .annotation-item {
|
|
|
+ margin-top: 8px;
|
|
|
+ }
|
|
|
+
|
|
|
+ &.selected {
|
|
|
+ border: 1.2px solid var(--c-findbar-input-border);
|
|
|
+ }
|
|
|
+
|
|
|
+ .item-header {
|
|
|
+ position: relative;
|
|
|
display: flex;
|
|
|
- justify-content: space-between;
|
|
|
- padding: 6px 16px;
|
|
|
- color: var(--c-side-title);
|
|
|
- background-color: var(--c-side-annotation-bg);
|
|
|
- span {
|
|
|
- font-size: 14px;
|
|
|
- line-height: 20px;
|
|
|
+ padding: 8px 22px 8px 0;
|
|
|
+ color: var(--c-side-text);
|
|
|
+
|
|
|
+ svg {
|
|
|
+ margin-top: 6px;
|
|
|
+ margin-right: 8px;
|
|
|
+ min-width: 20px;
|
|
|
}
|
|
|
- }
|
|
|
- .annotation-item {
|
|
|
- padding: 4px 16px 12px;
|
|
|
- .item-header {
|
|
|
- display: flex;
|
|
|
- align-items: center;
|
|
|
- padding: 6px 0;
|
|
|
- color: var(--c-side-text);
|
|
|
- span {
|
|
|
- margin-left: 8px;
|
|
|
- font-size: 14px;
|
|
|
- line-height: 20px;
|
|
|
- }
|
|
|
+
|
|
|
+ .name {
|
|
|
+ font-size: 12px;
|
|
|
+ font-weight: 700;
|
|
|
+ line-height: 16px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .date {
|
|
|
+ font-size: 10px;
|
|
|
+ line-height: 16px;
|
|
|
+ color: #999;
|
|
|
}
|
|
|
+
|
|
|
.item-content {
|
|
|
+ padding-top: 4px;
|
|
|
font-size: 14px;
|
|
|
- line-height: 20px;
|
|
|
+ line-height: 16px;
|
|
|
text-overflow: ellipsis;
|
|
|
display: -webkit-box;
|
|
|
-webkit-box-orient: vertical;
|
|
|
- -webkit-line-clamp: 2;
|
|
|
+ -webkit-line-clamp: 4;
|
|
|
overflow: hidden;
|
|
|
color: var(--c-side-annotation-text);
|
|
|
word-break: break-all;
|
|
|
}
|
|
|
+
|
|
|
+ .mark-box {
|
|
|
+ position: absolute;
|
|
|
+ top: 17px;
|
|
|
+ right: 0;
|
|
|
+ width: 14px;
|
|
|
+ height: 14px;
|
|
|
+ border: 1.2px solid #D9D9D9;
|
|
|
+ border-radius: 2px;
|
|
|
+ background: #fff;
|
|
|
+ cursor: pointer;
|
|
|
+
|
|
|
+ &.marked {
|
|
|
+ border-color: #999;
|
|
|
+ background: none;
|
|
|
+
|
|
|
+ &::before {
|
|
|
+ content: '';
|
|
|
+ width: 6px;
|
|
|
+ height: 6px;
|
|
|
+ background: #999;
|
|
|
+ border-radius: 50%;
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%, -50%);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
- .no-annotations {
|
|
|
- position: absolute;
|
|
|
- top: 50%;
|
|
|
- left: 50%;
|
|
|
- transform: translate(-50%, 50%);
|
|
|
- color: var(--c-side-text);
|
|
|
- text-align: center;
|
|
|
- font-weight: 700;
|
|
|
- font-size: 14px;
|
|
|
- line-height: 16px;
|
|
|
+
|
|
|
+ .item-reply {
|
|
|
+ padding: 8px 0 8px 28px;
|
|
|
+
|
|
|
+ input {
|
|
|
+ padding: 4px 4px 4px 8px;
|
|
|
+ width: 100%;
|
|
|
+ height: 24px;
|
|
|
+ background: var(--c-right-side-content-fillbox-bg);
|
|
|
+ border: 1px solid var(--c-right-side-content-fillbox-border);
|
|
|
+ border-radius: 1px;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 16px;
|
|
|
+ color: var(--c-text);
|
|
|
+
|
|
|
+ &::placeholder {
|
|
|
+ color: #999;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ > div {
|
|
|
+ margin-top: 4px;
|
|
|
+ display: flex;
|
|
|
+ justify-content: flex-end;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ span {
|
|
|
+ margin-right: 8px;
|
|
|
+ font-size: 12px;
|
|
|
+ line-height: 16px;
|
|
|
+ color: #999;
|
|
|
+ cursor: pointer;
|
|
|
+ }
|
|
|
+
|
|
|
+ button {
|
|
|
+ padding: 2px 6.5px;
|
|
|
+ border: none;
|
|
|
+ border-radius: 2px;
|
|
|
+ font-size: 12px;
|
|
|
+ line-height: 16px;
|
|
|
+ color: #999;
|
|
|
+ background: #D9D9D9;
|
|
|
+
|
|
|
+ &.active {
|
|
|
+ cursor: pointer;
|
|
|
+ color: #fff;
|
|
|
+ background: #1460F3;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ .item-footer {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ color: var(--c-side-annotation-text);
|
|
|
+
|
|
|
+ button {
|
|
|
+ color: var(--c-side-annotation-text);
|
|
|
+ }
|
|
|
+
|
|
|
+ .re {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+
|
|
|
+ span {
|
|
|
+ margin-left: 4px;
|
|
|
+ }
|
|
|
+
|
|
|
+ :last-child {
|
|
|
+ margin-left: 12px;
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ .no-annotations {
|
|
|
+ position: absolute;
|
|
|
+ top: 50%;
|
|
|
+ left: 50%;
|
|
|
+ transform: translate(-50%, 50%);
|
|
|
+ color: var(--c-side-text);
|
|
|
+ text-align: center;
|
|
|
+ font-weight: 700;
|
|
|
+ font-size: 14px;
|
|
|
+ line-height: 16px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.state-popover .drop-down .drop-item {
|
|
|
+ padding: 4px 8px;
|
|
|
+
|
|
|
+ &:hover {
|
|
|
+ color: var(--c-text);
|
|
|
+ background-color: var(--c-header-button-active);
|
|
|
+ }
|
|
|
+
|
|
|
+ svg {
|
|
|
+ margin-right: 8px;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.mark-popover {
|
|
|
+ padding: 4px !important;
|
|
|
+ color: #fff;
|
|
|
+ background: #414960 !important;
|
|
|
+
|
|
|
+ .n-popover-arrow {
|
|
|
+ background-color: #414960 !important;
|
|
|
+ }
|
|
|
+}
|
|
|
</style>
|