This commit is contained in:
min.jiang 2024-06-11 03:48:17 +08:00
parent be9cc494ef
commit dd90d4d4de
33 changed files with 622 additions and 392 deletions

View File

@ -11,13 +11,11 @@
},
"dependencies": {
"@popperjs/core": "^2.11.8",
"@vueup/vue-quill": "^1.2.0",
"axios": "^1.4.0",
"bootstrap": "^5.3.1",
"buffer": "^6.0.3",
"pdfjs-dist": "^4.2.67",
"pdfjs-dist": "3.5.141",
"pinia": "^2.1.6",
"quill": "^1.3.7",
"vue": "^3.3.4",
"vue-router": "^4.2.4",
"vuex": "^4.1.0"

View File

@ -104,3 +104,17 @@ p {
height: 100%;
margin: 0 auto;
}
.btn-link {text-decoration: none; color: $primary;}
.dropdown-menu {border: none; box-shadow: 0px 0px 24px 0px #D4D3E380; padding: 0; overflow: hidden;
.btn-link {text-decoration: none; height: 33px; width: 100%; color: #0D1637; font-size: 14px; text-align: left; border-radius: 0;
&:hover {background-color: #F3F6FF;}
&.active {background-color: #1748F8; color: white;}
}
.dropdown-new {color: #1748F8;
&:hover {background-color: white;}
}
.dropdown-new-input-container {padding: 6px 12px; position: relative;
input {border: 1px solid #E7E8EB; box-shadow: none; border-radius: 3px; padding: 0 20px 0 5px; height: 22px; font-size: 14px;}
.dropdown-new-input-icon {width: 16px; height: 16px; padding: 3px; color: #3D455F; background-color: #EEEFF1; border-radius: 3px; position: absolute; top: 10px; right: 15px}
}
}

View File

@ -0,0 +1,314 @@
<template>
<div class="freeleaps-editor">
<div v-if="!disabled" class="editor-control">
<div v-for="(item, index) in iconList" :key="index" class="editor-item">
<button class="item-icon" :class="{'activity': item.choose}" :data-info="item.name" @click="iconClick($event, item.type)" :data-bs-toggle="item.drop ? 'dropdown' : ''" data-bs-auto-close="outside" aria-expanded="false">
<svg-icon :icon="item.icon" class-name="icon" />
</button>
<div class="dropmenu drop-style" v-if="item.type === 'style'">
<ul>
<li>
<a href="#" @click="iconClick($event, 'p', 'style')"><p>正文</p></a>
</li>
<li>
<a href="#" @click="iconClick($event, 'pre', 'style')"><pre>code</pre></a>
</li>
<li>
<a href="#" @click="iconClick($event, 'blockquote', 'style')"><blockquote>引用</blockquote></a>
</li>
<li>
<a href="#" @click="iconClick($event, 'h1', 'style')"><h1>标题一</h1></a>
</li>
<li>
<a href="#" @click="iconClick($event, 'h2', 'style')"><h2>标题二</h2></a>
</li>
<li>
<a href="#" @click="iconClick($event, 'h3', 'style')"><h3>标题三 </h3></a>
</li>
<li>
<a href="#" @click="iconClick($event, 'h4', 'style')"><h4>标题四 </h4></a>
</li>
<li>
<a href="#" @click="iconClick($event, 'h5', 'style')"><h5>标题五 </h5></a>
</li>
<li>
<a href="#" @click="iconClick($event, 'h6', 'style')"><h6>标题六</h6></a>
</li>
</ul>
</div>
<div class="dropmenu drop-style" v-if="item.type === 'alignjustify'">
<ul>
<li>
<a href="#" @click="iconClick($event, 'justifyCenter', 'alignjustify')">
<i class="iconfont icon-aligncenter"></i>
<span>居中</span>
</a>
</li>
<li>
<a href="#" @click="iconClick($event, 'justifyLeft', 'alignjustify')">
<i class="iconfont icon-alignleft"></i>
<span>左对齐</span>
</a>
</li>
<li>
<a href="#" @click="iconClick($event, 'justifyRight', 'alignjustify')">
<i class="iconfont icon-alignright"></i>
<span>右对齐</span>
</a>
</li>
<li>
<a href="#" @click="iconClick($event, 'justifyFull', 'alignjustify')">
<i class="iconfont icon-alignjustify"></i>
<span>默认对齐</span>
</a>
</li>
</ul>
</div>
</div>
</div>
<div class="editor-body" :contenteditable="!disabled" spellcheck="false" ref="editor" v-html="content" @blur="updateAction" />
</div>
</template>
<script>
import SvgIcon from '@/components/SvgIcon.vue'
export default {
name: 'FreeleapsEditor',
props: {
content: {
type: String,
default: ''
},
disabled: {
type: Boolean,
default: false
}
},
emits: ['update:content'],
components: { SvgIcon },
data() {
return {
selectedRange: '',
iconList: [
// {
// name: '', // hover
// type: 'style', //
// icon: 'fe-paragraph', //
// drop: true, //
// canChoose: true, //
// choose: false
// },
{
name: '粗体',
type: 'bold',
icon: 'fe-bold',
drop: false,
canChoose: true,
choose: false
},
{
name: '斜体',
type: 'italic',
icon: 'fe-italic',
drop: false,
canChoose: true,
choose: false
},
{
name: '下划线',
type: 'underline',
icon: 'fe-underline',
drop: false,
canChoose: true,
choose: false
},
// {
// name: '线',
// type: 'strike',
// icon: 'fe-strike',
// drop: false,
// canChoose: true,
// choose: false
// },
// {
// name: '',
// type: 'clear',
// icon: 'fe-clear',
// drop: false,
// canChoose: false,
// choose: false
// },
// {
// name: '',
// type: 'fontFamily',
// icon: 'fe-char',
// drop: false,
// canChoose: true,
// choose: false
// },
{
name: '无序列表',
type: 'unorderedlist',
icon: 'fe-unorderedlist',
drop: false,
canChoose: true,
choose: false
},
{
name: '有序列表',
type: 'orderedlist',
icon: 'fe-orderedlist',
drop: false,
canChoose: true,
choose: false
},
// {
// name: '',
// type: 'alignjustify',
// icon: 'fe-alignjustify',
// drop: true,
// canChoose: true,
// choose: false
// }
]
}
},
methods: {
iconClick (event, type, dropType) {
event.preventDefault()
this.$refs.editor.focus()
this.selectedRange = this.getSelect()
this.restoreSelection()
this.changeStyle(type)
this.$nextTick(() => {
if (dropType) {
type = dropType
}
let arr = []
arr = this.iconList.map((val) => {
if (type === val.type && val.canChoose) {
val.choose = val.choose ? false : true
}
return val
})
if (type === 'clear') {
arr = this.iconList.map((val) => {
val.choose = false
return val
})
}
this.iconList = arr
})
},
getSelect() {
if (window.getSelection) {
var sel = window.getSelection()
if (sel.rangeCount > 0) {
return sel.getRangeAt(0)
}
} else if (document.selection) {
return document.selection.createRange()
}
return null
},
//
changeStyle(type) {
switch (type) {
case 'bold':
document.execCommand('bold', false)
break
case 'underline':
document.execCommand('underline', false)
break
case 'strike':
document.execCommand('strikeThrough', false)
break
case 'italic':
document.execCommand('italic', false)
break
case 'clear':
document.execCommand('removeFormat', false)
break
case 'unorderedlist':
document.execCommand('insertUnorderedList', false)
break
case 'orderedlist':
document.execCommand('insertorderedList', false)
break
case 'h1':
case 'h2':
case 'h3':
case 'h4':
case 'h5':
case 'h6':
case 'p':
case 'pre':
case 'blockquote':
document.execCommand('formatBlock', false, type)
break
case 'justifyCenter':
case 'justifyFull':
case 'justifyLeft':
case 'justifyRight':
document.execCommand(type, false)
break
default:
console.log('none')
}
},
restoreSelection() {
var selection = window.getSelection()
if (this.selectedRange) {
try {
selection.removeAllRanges()
} catch (ex) {
document.body.createTextRange().select()
document.selection.empty()
}
selection.addRange(this.selectedRange)
}
},
updateAction($event) {
let html = $event.target.innerHTML || ''
this.$emit('update:content', html)
}
}
}
</script>
<style lang="scss" scoped>
.freeleaps-editor {position: relative; background-color: #fff; border-radius: 4px; border: 1px solid #a9a9a9; box-shadow: 0 1px 1px rgba(0, 0, 0, .05); font-family: "Helvetica Neue", Helvetica, Arial, sans-serif;
h1, h2, h3, h4, h5, h6, .h1, .h2, .h3, .h4, .h5, .h6, p, a{ font-family: inherit; font-weight: 500; line-height: 1.1; color: inherit; margin: 0; text-decoration: none; }
code, kbd, pre, samp { font-family: Menlo, Monaco, Consolas, "Courier New", monospace; }
.editor-control { display: flex; flex-flow: row wrap; min-height: 40px; color: #333; border-bottom: 1px solid transparent; border-top-left-radius: 3px; border-top-right-radius: 3px; background-color: #f5f5f5; border-color: #ddd; }
.dropmenu { display: none; position: absolute; top: 32px; left: 0; min-width: 160px; padding: 5px 0; margin: 2px 0 0; font-size: 14px; text-align: left; list-style: none; background-color: #fff; background-clip: padding-box; border: 1px solid #ccc; border: 1px solid rgba(0, 0, 0, .15); border-radius: 4px; box-shadow: 0 6px 12px rgba(0, 0, 0, .175);
ul {padding: 10px; margin-bottom: 0;}
ul li { text-align: left; list-style: none;
a { display: block; padding: 5px 10px; white-space: nowrap; }
}
}
.drop-align { min-width: 100px; }
.editor-body { height: 300px; padding: 10px; color: #000; background-color: #fff; overflow: auto; outline: none; text-align: left; border-radius: 4px;
p { font-size: 14px; color: #68747f; margin: 0 0 10px; }
}
}
.editor-item { position: relative; vertical-align: middle; border: 1px solid #ccc; cursor: pointer; line-height: 20px; border-radius: 3px; margin: 4px 0 4px 5px; background-color: white;
.item-icon { position: relative; display: inline-block; width: 100%; height: 100%; padding: 2px 10px; font-size: 18px; font-weight: normal; white-space: nowrap; vertical-align: middle; touch-action: manipulation; cursor: pointer; user-select: none; background-color: #fff; border: 1px solid white; outline: none; transition: all 0.1s ease-out; border-radius: 3px;
&::after { position: absolute; top: 0; content: attr(data-info); top: 40px; left: 20px; padding: 5px 8px; border-radius: 4px; white-space: nowrap; line-height: 1.5; font-size: 13px; color: #fff; background: rgba(0,0,0,.8); -webkit-transform: translateX(-50%); transform: translateX(-50%); visibility: hidden; opacity: .9; letter-spacing: 1px; z-index: 9999; }
&::before { position: absolute; content: ""; top: 35px; left: 20px; width: 0; height: 0; margin: 0 0 0 -6px; font-size: 0; color: rgba(0,0,0,.8); border-bottom: 6px solid currentColor; border-left: 6px solid transparent; border-right: 6px solid transparent; visibility: hidden; opacity: .9; z-index: 9999; }
&:hover, &.activity{ color: #333; background-color: #e6e6e6; border-color: #e6e6e6; }
&:hover:after, &:hover:before { visibility: visible; }
&.activity + .dropmenu { display: block; }
}
}
</style>
<style>
.freeleaps-editor blockquote { padding: 10px 20px; font-size: 17.5px; border-left: 5px solid #f86466; background: white; }
.freeleaps-editor pre { display: block; padding: 9.5px; font-size: 13px; line-height: 1.42857143; color: #333; word-break: break-all; word-wrap: break-word; background-color: #f5f5f5; border: 1px solid #ccc; border-radius: 4px; }
.editor-body blockquote { margin-bottom: 30px; }
.editor-body pre { margin-bottom: 10px; }
.editor-body ul { padding-left: 40px; list-style-type: disc; }
.editor-body ol { padding-left: 40px; }
</style>

View File

@ -0,0 +1,70 @@
<template>
<div class="input-selector-container">
<div class="input-selector-btn" data-bs-toggle="dropdown" aria-expanded="false" id="input-selector-btn">
<span>{{selected || ''}}</span>
<svg-icon icon="dropdown" class-name="selector-dropdown-icon" />
</div>
<ul class="dropdown-menu" aria-labelledby="input-selector-btn">
<li>
<button v-if="!inputing" class="btn btn-link dropdown-new" @click="newAction">+ NEW</button>
<div v-if="inputing" class="dropdown-new-input-container">
<input type="text" v-model="newval" @keyup.enter="newItemAction">
<svg-icon v-if="newval" icon="msg-enter" class-name="dropdown-new-input-icon" />
</div>
</li>
<li v-for="item in selectList" :key="item">
<button class="btn btn-link" @click="selectItem(item)" :class="item==selected ? 'active' : ''">{{item}}</button>
</li>
</ul>
</div>
</template>
<script>
import SvgIcon from '@/components/SvgIcon.vue'
export default {
name: 'InputSelector',
props: {
selectList: {
type: Array,
default: () => []
},
selected: {
type: String,
default: ''
}
},
data() {
return {
inputing: true,
newval: ''
}
},
mounted() { },
components: {SvgIcon},
methods: {
newAction($event) {
$event.stopPropagation()
this.newval = ''
this.inputing = true
},
selectItem(item) {
this.$emit('selectedChange', {selected: item, isNew: false})
},
newItemAction() {
if (!this.newval) return
this.$emit('selectedChange', {selected: this.newval, isNew: this.selectList.indexOf(this.newval) === -1})
this.newval = ''
this.inputing = false
}
}
}
</script>
<style lang="scss">
.input-selector-container {width: fit-content; height: fit-content; position: relative;
.input-selector-btn {width: 153px; height: 30px; display: flex; align-items: center; overflow: hidden; cursor: pointer; border: 1px solid #E7E8EB; border-radius: 3px; padding: 0 3px 0 5px;
>span {font-size: 18px; font-weight: 500; color: #242424; flex: 1; text-align: left;}
.selector-dropdown-icon {color: #242424; padding: 3px;}
}
}
</style>

View File

@ -1,81 +1,81 @@
<template>
<div class="pdf-reader">
<canvas ref="canvas"></canvas>
<div id="pdf-container" class="pdf-container">
<canvas id="theCanvas"></canvas>
<div class="oprate">
<button class="btn btn-link" @click="prev">prev</button>
<span> {{ currentPage }} / {{ numPages }} </span>
<button class="btn btn-link" @click="next">next</button>
</div>
</div>
</template>
<script>
// import { getDocument } from 'pdfjs-dist'
import * as PDFJS from 'pdfjs-dist'
// import pdfjsWorker from "pdfjs-dist/build/pdf.worker.entry";
import { ContentApi } from '@/utils/index'
// PDFJS.GlobalWorkerOptions.workerSrc = import('pdfjs-dist/build/pdf.worker')
import * as PDFJS from "pdfjs-dist/build/pdf"
import { WorksapceApi } from '@/utils/index'
PDFJS.GlobalWorkerOptions.workerSrc = import('pdfjs-dist/build/pdf.worker.entry')
export default {
name: 'PDFReader',
props: {
document: { type: String, default: '' }
},
data() {
return {
loadingTask: null,
currentPage: 1,
numPages: 0,
selectedPage: 1
}
},
mounted() {
this.renderPDF()
},
methods: {
async renderPDF() {
// const response = await DocumentApi.download(this.document)
const response = await ContentApi.retrieve_blog_content(this.document)
console.log('response', response)
// var fr = new FileReader();
// fr.onload = async function(){
// const doc = await getDocument({url: this.result}).promise
// const page = await doc.getPage(1)
// const canvas = this.$refs.canvas
// const context = canvas.getContext('2d')
// const viewport = page.getViewport({ scale: 1 })
// canvas.width = viewport.width
// canvas.height = viewport.height
// await page.render({
// canvasContext: context,
// viewport
// })
// }
// fr.readAsDataURL(response.data);
const doc = await PDFJS.getDocument({ data: response.data }).promise
const page = await doc.getPage(1)
const canvas = this.$refs.canvas
const context = canvas.getContext('2d')
const viewport = page.getViewport({ scale: 1 })
canvas.width = viewport.width
canvas.height = viewport.height
await page.render({
renderPage (num) {
const canvas = document.getElementById("theCanvas");
const context = canvas.getContext("2d");
const scale = 1.5;
this.loadingTask.promise.then((pdf) => {
pdf.getPage(num).then((page) => {
const viewport = page.getViewport({ scale });
canvas.height = viewport.height;
canvas.width = viewport.width;
const renderContext = {
canvasContext: context,
viewport
})
viewport: viewport,
};
page.render(renderContext);
});
});
},
base64StringToUint8Array(base64String) {
var padding = '='.repeat((4 - (base64String.length % 4)) % 4)
var base64 = (base64String + padding).replace(/\-/g, '+').replace(/_/g, '/')
var rawData = atob(base64)
var outputArray = new Uint8Array(rawData.length)
for (var i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i)
async renderPDF() {
const response = await WorksapceApi.fetchAttachedFileAsMediaData("66673218fa83335c3b1b11ec", "6667321afa83335c3b1b11ee")
this.loadingTask = PDFJS.getDocument({url: response.data});
this.loadingTask.promise.then((pdf) => {
this.numPages = pdf.numPages;
this.renderPage(1);
});
},
prev() {
if (this.currentPage > 1) {
this.currentPage--;
this.renderPage(this.currentPage);
}
return outputArray
},
next() {
if (this.currentPage < this.numPages) {
this.currentPage++;
this.renderPage(this.currentPage);
}
}
}
}
</script>
<style scoped>
.pdf-reader {
width: 100%;
height: 100%;
<style lang="scss" scoped>
.pdf-container{position: relative;
.operate{position: absolute; right: 0; top: 0; }
}
</style>

View File

@ -1,70 +0,0 @@
<template>
<div class="vue-quill-container">
<QuillEditor
ref="quillRef"
v-model:content="quillData"
:options="quillOptions"
content-type="html"
@text-change="quillChange()"
/>
</div>
</template>
<script>
const toolbarOptions = [
['bold', 'italic', 'underline', 'strike'],
['blockquote', 'code-block'],
[{ list: 'ordered' }, { list: 'bullet' }],
[{ script: 'sub' }, { script: 'super' }],
[{ indent: '-1' }, { indent: '+1' }],
[{ direction: 'rtl' }],
[{ size: ['small', false, 'large', 'huge'] }],
[{ header: [1, 2, 3, 4, 5, 6, false] }],
[{ color: [] }, { background: [] }],
[{ font: [] }],
[{ align: [] }],
['clean']
]
import { QuillEditor } from '@vueup/vue-quill'
import 'quill/dist/quill.core.css'
import 'quill/dist/quill.snow.css'
import 'quill/dist/quill.bubble.css'
export default {
name: 'VueQuill',
props: {
content: {
type: String,
default: ''
}
},
emits: ['update:content'],
components: { QuillEditor },
data() {
return {
quillData: this.content,
quillOptions: {
theme: 'snow',
placeholder: '请输入',
modules: {
toolbar: {
container: toolbarOptions
}
}
}
}
},
methods: {
quillChange() {
this.$emit('update:content', this.quillData)
}
}
}
</script>
<style>
.vue-quill-container {
width: 100%;
height: 100%;
min-height: 100px;
}
</style>

View File

@ -1,23 +1,23 @@
<template>
<div class="header-container">
<div class="header-content">
<div class="information-bar" @click="gotoMessages">
<div class="information-bar" @click="gotoMessages" :class="activePath == 'message'?'active':''">
<img alt="freeleaps logo" src="@/assets/message.png" />
</div>
<div class="navigation-container" role="navigation">
<button class="navigation-item active" @click="gotoWorkspace">
<button class="navigation-item" @click="gotoWorkspace" :class="activePath == 'Workspace'?'active':''">
<svg-icon icon="workspace" class-name="icon" />
Workspace
</button>
<button class="navigation-item" @click="gotoRequests">
<button class="navigation-item" @click="gotoRequests" :class="activePath == 'Requests'?'active':''">
<svg-icon icon="requests" class-name="icon" />
Requests
</button>
<button class="navigation-item" @click="gotoProviders">
<button class="navigation-item" @click="gotoProviders" :class="activePath == 'Providers'?'active':''">
<svg-icon icon="providers" class-name="icon" />
Providers
</button>
<button class="navigation-item" @click="gotoIssueRequest">
<button class="navigation-item" @click="gotoIssueRequest" :class="activePath == 'Post'?'active':''">
<svg-icon icon="post" class-name="icon" />
Post
</button>
@ -61,10 +61,17 @@ export default {
if (this.userIdentityNote.length > 8) {
this.userIdentityNote = this.userIdentityNote.slice(0, 5) + '...'
}
console.log('watch', this.$route.meta)
},
data() {
return {
userIdentityNote: this.mnx_getUserIdentity()
userIdentityNote: this.mnx_getUserIdentity(),
activePath: this.$route.meta.activePath
}
},
watch: {
$route(to) {
this.activePath = to.meta.activePath
}
},
methods: {
@ -156,6 +163,7 @@ export default {
top: 0;
background-color: #f44837;
}
&.active {border: 1px solid $primary;}
}
.profile-container {

View File

@ -0,0 +1 @@
<svg viewBox="0 0 1025 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5138" width="64" height="64"><path d="M993.310029 179.7115H892.968039l-45.464399 813.855781c-0.938917 16.951554-14.971621 30.209501-31.940191 30.209501H209.743828c-16.970573 0-30.998272-13.247937-31.936188-30.17747l-46.19311-813.887812H32.346588c-17.689275 0-32.002252-14.322987-32.002252-31.996247 0-17.666252 14.312978-31.989239 32.002252-31.989239h120.931097c1.457423 0 2.888821 0.106104 4.294194 0.294287a32.138385 32.138385 0 0 1 4.266166-0.294287h167.931996V31.99024c0-17.666252 14.312978-31.989239 31.998248-31.989239h301.08603c17.685271 0 31.995245 14.322987 31.995245 31.989239v83.735774H862.722502c1.656618 0 3.301224 0.129126 4.919805 0.382373a32.19444 32.19444 0 0 1 4.953838-0.382373H993.310029c17.685271 0 31.999249 14.322987 31.99925 31.989239 0 17.673259-14.313978 31.996246-31.99925 31.996247zM630.852066 63.986487H393.767539v51.739527h237.084527V63.986487zM195.710123 179.7115l44.280243 780.079796H785.316911l43.558538-780.079796H195.710123zM701.535093 869.624242c-0.964942 17.024626-15.060708 30.178471-31.903156 30.178472-0.625611 0-1.21819-0.014014-1.840797-0.046045-17.659245-1.000978-31.126397-16.119742-30.12542-33.757967l33.652865-592.997099c1.00398-17.666252 16.37399-30.883159 33.750959-30.132426 17.655241 0.997975 31.122393 16.120743 30.124419 33.758968L701.535093 869.624242z m-189.207773 30.178472c-17.692278 0-31.998248-14.319984-31.998249-31.993244V274.816375c0-17.673259 14.305971-31.992242 31.998249-31.992242 17.683269 0 31.996246 14.318983 31.996246 31.992242v592.993095c0 17.673259-14.312978 31.993243-31.996246 31.993244z m-156.621951-0.046045a35.334506 35.334506 0 0 1-1.843801 0.046045c-16.843449 0-30.93521-13.153846-31.904156-30.178472L288.301544 276.628145c-1.000978-17.638225 12.469177-32.760993 30.122417-33.758968 17.220817-0.79878 32.749982 12.466174 33.753963 30.132426l33.64886 592.997099c1.001978 17.638225-12.465173 32.756989-30.121415 33.757967z" p-id="5139"></path></svg>

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

@ -0,0 +1 @@
<svg viewBox="0 0 1331 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4137" width="64" height="64"><path d="M552.5504 896.512L45.1584 244.1216A102.4 102.4 0 0 1 125.952 78.848h1014.784a102.4 102.4 0 0 1 80.896 165.2736l-507.4944 652.288a102.4 102.4 0 0 1-161.6896 0z" p-id="4138"></path></svg>

After

Width:  |  Height:  |  Size: 307 B

View File

@ -0,0 +1 @@
<svg viewBox="0 0 1066 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3055" width="64" height="64"><path d="M170.666667 298.666667h768a42.666667 42.666667 0 1 0 0-85.333334H170.666667a42.666667 42.666667 0 1 0 0 85.333334z m768 426.666666H170.666667a42.666667 42.666667 0 0 0 0 85.333334h768a42.666667 42.666667 0 1 0 0-85.333334z m0-170.666666H170.666667a42.666667 42.666667 0 0 0 0 85.333333h768a42.666667 42.666667 0 1 0 0-85.333333z m0-170.666667H170.666667a42.666667 42.666667 0 1 0 0 85.333333h768a42.666667 42.666667 0 0 0 0-85.333333z" p-id="3056"></path></svg>

After

Width:  |  Height:  |  Size: 583 B

View File

@ -0,0 +1 @@
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1304" width="64" height="64"><path d="M697.8 481.4c33.6-35 54.2-82.3 54.2-134.3v-10.2C752 229.3 663.9 142 555.3 142H259.4c-15.1 0-27.4 12.3-27.4 27.4v679.1c0 16.3 13.2 29.5 29.5 29.5h318.7c117 0 211.8-94.2 211.8-210.5v-11c0-73-37.4-137.3-94.2-175.1zM328 238h224.7c57.1 0 103.3 44.4 103.3 99.3v9.5c0 54.8-46.3 99.3-103.3 99.3H328V238z m366.6 429.4c0 62.9-51.7 113.9-115.5 113.9H328V542.7h251.1c63.8 0 115.5 51 115.5 113.9v10.8z" p-id="1305"></path></svg>

After

Width:  |  Height:  |  Size: 537 B

View File

@ -0,0 +1 @@
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2418" width="64" height="64"><path d="M792.864 922.112l103.584-2.176L572.576 110.24h-89.184L161.696 919.936H264l66.944-167.936h394.112l67.808 170.112zM369.216 656L528 257.632 686.784 656h-317.568z" p-id="2419"></path></svg>

After

Width:  |  Height:  |  Size: 307 B

View File

@ -0,0 +1 @@
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2256" width="64" height="64"><path d="M311.769043 997.487304h653.668174v-66.782608H311.769043z" p-id="2257"></path><path d="M638.447304 760.186435l-152.665043-153.355131-152.665044-153.35513L650.245565 134.92313 955.575652 441.633391 638.425043 760.186435z m-173.723826 174.458435h-165.487304L70.77287 717.000348l215.129043-216.086261 18.031304 18.120348L591.187478 807.602087l-126.441739 127.042783z m540.91687-537.6L694.633739 84.658087c-23.752348-23.863652-65.113043-23.774609-88.776348 0L262.28313 429.768348 13.94087 679.201391c-21.147826 21.25913-17.986783 57.677913 7.791304 83.500522L262.906435 992.52313a33.391304 33.391304 0 0 0 22.995478 9.216h192.645565c8.859826 0 17.341217-3.539478 23.596522-9.839304l159.877565-160.567652 343.574261-345.110261A62.73113 62.73113 0 0 0 1024.005565 441.633391c0-16.851478-6.522435-32.678957-18.365217-44.588521z" p-id="2258"></path></svg>

After

Width:  |  Height:  |  Size: 968 B

View File

@ -0,0 +1 @@
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1619" width="64" height="64"><path d="M798 160H366c-4.4 0-8 3.6-8 8v64c0 4.4 3.6 8 8 8h181.2l-156 544H229c-4.4 0-8 3.6-8 8v64c0 4.4 3.6 8 8 8h432c4.4 0 8-3.6 8-8v-64c0-4.4-3.6-8-8-8H474.4l156-544H798c4.4 0 8-3.6 8-8v-64c0-4.4-3.6-8-8-8z" p-id="1620"></path></svg>

After

Width:  |  Height:  |  Size: 347 B

View File

@ -0,0 +1 @@
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2894" width="64" height="64"><path d="M920 760H336c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h584c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z m0-568H336c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h584c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8z m0 284H336c-4.4 0-8 3.6-8 8v56c0 4.4 3.6 8 8 8h584c4.4 0 8-3.6 8-8v-56c0-4.4-3.6-8-8-8zM216 712H100c-2.2 0-4 1.8-4 4v34c0 2.2 1.8 4 4 4h72.4v20.5h-35.7c-2.2 0-4 1.8-4 4v34c0 2.2 1.8 4 4 4h35.7V838H100c-2.2 0-4 1.8-4 4v34c0 2.2 1.8 4 4 4h116c2.2 0 4-1.8 4-4V716c0-2.2-1.8-4-4-4zM100 188h38v120c0 2.2 1.8 4 4 4h40c2.2 0 4-1.8 4-4V152c0-4.4-3.6-8-8-8h-78c-2.2 0-4 1.8-4 4v36c0 2.2 1.8 4 4 4z m116 240H100c-2.2 0-4 1.8-4 4v36c0 2.2 1.8 4 4 4h68.4l-70.3 77.7c-1.3 1.5-2.1 3.4-2.1 5.4V592c0 2.2 1.8 4 4 4h116c2.2 0 4-1.8 4-4v-36c0-2.2-1.8-4-4-4h-68.4l70.3-77.7c1.3-1.5 2.1-3.4 2.1-5.4V432c0-2.2-1.8-4-4-4z" p-id="2895"></path></svg>

After

Width:  |  Height:  |  Size: 926 B

View File

@ -0,0 +1 @@
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1147" width="64" height="64"><path d="M149.333333 149.333333h448a42.666667 42.666667 0 1 1 0 85.333334H149.333333a42.666667 42.666667 0 1 1 0-85.333334z m0 640h448a42.666667 42.666667 0 1 1 0 85.333334H149.333333a42.666667 42.666667 0 1 1 0-85.333334z m0-320h725.333334a42.666667 42.666667 0 1 1 0 85.333334H149.333333a42.666667 42.666667 0 1 1 0-85.333334z" p-id="1148"></path></svg>

After

Width:  |  Height:  |  Size: 468 B

View File

@ -0,0 +1 @@
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2095" width="64" height="64"><path d="M952 474H569.9c-10-2-20.5-4-31.6-6-15.9-2.9-22.2-4.1-30.8-5.8-51.3-10-82.2-20-106.8-34.2-35.1-20.5-52.2-48.3-52.2-85.1 0-37 15.2-67.7 44-89 28.4-21 68.8-32.1 116.8-32.1 54.8 0 97.1 14.4 125.8 42.8 14.6 14.4 25.3 32.1 31.8 52.6 1.3 4.1 2.8 10 4.3 17.8 0.9 4.8 5.2 8.2 9.9 8.2h72.8c5.6 0 10.1-4.6 10.1-10.1v-1c-0.7-6.8-1.3-12.1-2-16-7.3-43.5-28-81.7-59.7-110.3-44.4-40.5-109.7-61.8-188.7-61.8-72.3 0-137.4 18.1-183.3 50.9-25.6 18.4-45.4 41.2-58.6 67.7-13.5 27.1-20.3 58.4-20.3 92.9 0 29.5 5.7 54.5 17.3 76.5 8.3 15.7 19.6 29.5 34.1 42H72c-4.4 0-8 3.6-8 8v60c0 4.4 3.6 8 8 8h433.2c2.1 0.4 3.9 0.8 5.9 1.2 30.9 6.2 49.5 10.4 66.6 15.2 23 6.5 40.6 13.3 55.2 21.5 35.8 20.2 53.3 49.2 53.3 89 0 35.3-15.5 66.8-43.6 88.8-30.5 23.9-75.6 36.4-130.5 36.4-43.7 0-80.7-8.5-110.2-25-29.1-16.3-49.1-39.8-59.7-69.5-0.8-2.2-1.7-5.2-2.7-9-1.2-4.4-5.3-7.5-9.7-7.5h-79.7c-5.6 0-10.1 4.6-10.1 10.1v1c0.2 2.3 0.4 4.2 0.6 5.7 6.5 48.8 30.3 88.8 70.7 118.8 47.1 34.8 113.4 53.2 191.8 53.2 84.2 0 154.8-19.8 204.2-57.3 25-18.9 44.2-42.2 57.1-69 13-27.1 19.7-57.9 19.7-91.5 0-31.8-5.8-58.4-17.8-81.4-5.8-11.2-13.1-21.5-21.8-30.8H952c4.4 0 8-3.6 8-8v-60c0-4.3-3.6-7.9-8-7.9z" p-id="2096"></path></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -0,0 +1 @@
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="1934" width="64" height="64"><path d="M824 804H200c-4.4 0-8 3.4-8 7.6v60.8c0 4.2 3.6 7.6 8 7.6h624c4.4 0 8-3.4 8-7.6v-60.8c0-4.2-3.6-7.6-8-7.6zM512 728c69.4 0 134.6-27.1 183.8-76.2C745 602.7 772 537.4 772 468V156c0-6.6-5.4-12-12-12h-60c-6.6 0-12 5.4-12 12v312c0 97-79 176-176 176s-176-79-176-176V156c0-6.6-5.4-12-12-12h-60c-6.6 0-12 5.4-12 12v312c0 69.4 27.1 134.6 76.2 183.8C377.3 701 442.6 728 512 728z" p-id="1935"></path></svg>

After

Width:  |  Height:  |  Size: 515 B

View File

@ -0,0 +1 @@
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="2733" width="64" height="64"><path d="M192 277.333333H106.666667V192h85.333333v85.333333z m725.333333 0H277.333333V192h640v85.333333zM192 554.666667H106.666667v-85.333334h85.333333v85.333334z m725.333333 0H277.333333v-85.333334h640v85.333334zM192 832H106.666667v-85.333333h85.333333v85.333333z m725.333333 0H277.333333v-85.333333h640v85.333333z" p-id="2734"></path></svg>

After

Width:  |  Height:  |  Size: 455 B

View File

@ -0,0 +1 @@
<svg viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="3264" width="64" height="64"><path d="M789.333333 128a192 192 0 0 1 191.786667 182.954667L981.333333 320v213.333333a192 192 0 0 1-182.954666 191.786667L789.333333 725.333333H110.976l118.314667 135.253334a21.333333 21.333333 0 0 1 0.682666 27.349333l-2.688 2.773333a21.333333 21.333333 0 0 1-27.306666 0.682667l-2.773334-2.688-149.248-170.624a21.333333 21.333333 0 0 1-3.84-21.76l1.536-3.2 2.304-3.114667 149.333334-170.709333a21.333333 21.333333 0 0 1 34.346666 24.96l-2.261333 3.114667L111.018667 682.666667H789.333333a149.333333 149.333333 0 0 0 149.12-141.141334L938.666667 533.333333v-213.333333a149.333333 149.333333 0 0 0-141.141334-149.12L789.333333 170.666667H512a21.333333 21.333333 0 0 1-3.84-42.325334L512 128h277.333333z" p-id="3265"></path></svg>

After

Width:  |  Height:  |  Size: 843 B

View File

@ -33,7 +33,8 @@
<script>
import {
UserAuthApi
UserAuthApi,
applicantValidator
// userProfileValidator,
} from '../../utils/index'
import { signinActionEnum } from '../../types/index'
@ -55,9 +56,9 @@ export default {
return
}
// this.message = userProfileValidator.emailValidator.validate(
// this.email
// );
this.message = applicantValidator.emailValidator.validate(
this.email
);
if (this.message != null) return

View File

@ -38,7 +38,7 @@
</template>
<script>
import { UserAuthApi, passwordValidator } from '../../utils/index'
import { UserAuthApi, applicantValidator } from '../../utils/index'
export default {
name: 'NewUserSetPassword',
props: {},
@ -67,7 +67,8 @@ export default {
this.message = 'The two passwords are not matched'
return
}
this.message = passwordValidator.validate(this.password)
this.message = applicantValidator.emailValidator.validate(this.password)
// console.log('EmailValidator', EmailValidator)
if (this.message != null) return
UserAuthApi.updatePassword(this.password, this.password2)

View File

@ -1,6 +1,6 @@
<template>
<div style="width: 100vw; height: 100vh">
<PDFReader document="6662431ee312d5389c612020" />
<div class="pdf-viewer">
<PDFReader />
</div>
</template>
<script>
@ -50,3 +50,6 @@ export default {
}
}
</script>
<style lang="scss" scoped>
// .pdf-viewer {height: $body-height;}
</style>

View File

@ -1,81 +1,52 @@
<template>
<div class="message-container">
<div class="message-hub-conainter">
<div class="conversation-list-container">
<div
v-for="(conversation, index) in conversations"
:key="index"
class="conversation-container"
@click="selectConversation(conversation)"
>
<div class="participant-portrait-container">
<img
class="participant-portrait"
alt="user portrait"
src="@/assets/images/default-user-portrait.png"
/>
</div>
<div v-if="conversations && conversations.length>0" class="conversation-list-container">
<div v-for="(conversation, index) in conversations" :key="index" class="conversation-container" @click="selectConversation(conversation)">
<img class="participant-portrait" alt="user portrait" src="@/assets/profile.png" />
<div class="conversation-summary-container">
<div class="conversation-summary-header-container">
<span class="participant-fullname">
{{ conversation.summary.contact.first_name }}
{{ conversation.summary.contact.last_name }}
</span>
<span class="conversation-last-update-date">
{{ getDateFromFulltimeString(conversation.summary.last_message.create_time) }}</span
>
<span class="conversation-last-update-date">{{ getDateFromFulltimeString(conversation.summary.last_message.create_time) }}</span>
</div>
<div class="conversation-summary-highlight-container">
<span class="conversation-last-message-summary">{{
conversation.summary.last_message.message_body
}}</span>
<div class="conversation-summary-highlight-container">{{ conversation.summary.last_message.message_body }}</div>
</div>
</div>
</div>
<div v-if="!conversations || conversations.length==0" class="conversation-list-empty-container">
Empty conversation
</div>
<div class="message-panel-container">
<div v-if="current_thread" class="message-thread-container">
<div
v-for="(item, index) in current_thread.conversation.messages"
:key="index"
class="message-item-container"
>
<div v-for="(item, index) in current_thread.conversation.messages" :key="index" class="message-item-container" :class="item.sender_profile.me ? 'me': ''">
<div class="message-item-header-container">
<div class="message-item-sender-info">
<img
class="message-item-sender-portrait"
alt="user portrait"
src="@/assets/images/default-user-portrait.png"
/>
<img class="message-item-sender-portrait" alt="user portrait" src="@/assets/profile.png" />
<span class="message-item-sender-fullname">
{{ item.sender_profile.first_name }}
{{ item.sender_profile.last_name }}
</span>
<span class="message-item-create-time"> {{ getDateFromFulltimeString(item.raw_data.create_time) }}</span>
</div>
<div class="message-item-additional-info-container">
<span class="message-item-create-time">
{{ getDateFromFulltimeString(item.raw_data.create_time) }}</span
>
</div>
</div>
<div class="message-item-message-body-container">
<p class="message-item-message-body-span">{{ item.raw_data.message_body }}</p>
</div>
<div class="message-item-message-body">{{ item.raw_data.message_body }}</div>
</div>
</div>
<div v-if="!current_thread" class="message-thread-empty-container">Please choose conversation</div>
<div class="message-writing-panel-container">
<input
class="writing-message-input"
type="text"
v-model="writtenMessage"
@keypress.enter="sendMessage(current_thread.conversation.information.conversation_id)"
/>
<svg-icon icon="msg-enter" class-name="writing-message-enter" />
<input class="writing-message-input" type="text" v-model="writtenMessage" @keypress.enter="sendMessage(current_thread.conversation.information.conversation_id)" />
</div>
</div>
</div>
</div>
</template>
<script>
import SvgIcon from '../../../components/SvgIcon.vue'
import { MessageHubApi, DateUtils } from '../../../utils/index'
export default {
components: { SvgIcon },
name: 'MessageHub',
props: {},
mounted() {
@ -130,139 +101,45 @@ export default {
}
</script>
<style lang="scss" scoped>
.message-hub-conainter {
@extend .flex-row-container;
@extend .justify-content-between;
@extend .border;
@extend .w-100;
}
.message-container { display: flex; align-items: center; width: 100%; height: $body-height; padding: 24px 24px 0 24px; justify-content: center;
.message-hub-conainter { display: flex; box-shadow: 0px 0px 24px 0px #D4D3E380; border-radius: 12px; width: 100%; max-width: $body-width; height: 100%; overflow: hidden;
.conversation-list-container {height: 100%; overflow: auto; width: 300px;
.conversation-container {background-color: #F3F3F5; display: flex; cursor: pointer; height: 98px; padding: 18px;
.participant-portrait {width: 36px; height: 36px; border-radius: 18px; margin-right: 16px;}
.conversation-summary-container {display: flex; flex-direction: column; flex: 1; overflow: hidden;
.conversation-summary-header-container {display: flex; align-items: center; height: 22px; color: #0D1637;
.participant-fullname {font-weight: 500; flex: 1; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;}
.conversation-last-update-date {white-space: nowrap; flex-shrink: 0;}
}
.conversation-summary-highlight-container {font-size: 14px; color: #6E7387; white-space: normal; overflow: hidden; flex: 1; text-align: left; word-break: break-word}
}
&:hover {opacity: .78;}
&.selected {background-color: transparent;}
}
}
.conversation-list-empty-container {height: 100%; overflow: auto; width: 300px; background-color: #F3F3F5; display: flex; align-items: center; justify-content: center;}
.message-panel-container {height: 100%; overflow: auto; flex: 1; padding-bottom: 98px; position: relative;
.message-thread-container {height: 100%; overflow: auto; padding: 20px 32px; display: flex; flex-direction: column;
.message-item-container {max-width: 70%; margin-bottom: 15px; width: fit-content; display: flex; flex-direction: column;
.message-item-header-container {display: flex; align-items: center; margin-bottom: 6px; width: 100%; overflow: hidden; font-size: 18px; width: fit-content; max-width: 100%;
.message-item-sender-portrait {width: 36px; height: 36px; border-radius: 18px; }
.message-item-sender-fullname {overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: #16181E; font-weight: 500; margin: 0 7px; }
.message-item-create-time {color: #737478; white-space: nowrap; flex-shrink: 0; font-size: 16px; }
}
.message-item-message-body {font-size: 14px; line-height: 17px; color: #0D1637; background-color: #F3F3F5; padding: 12px; border-radius: 12px; overflow: hidden; width: fit-content; max-width: 100%; text-align: left; word-break: break-word}
.conversation-list-container {
@extend .flex-colum-container;
@extend .justify-content-start;
@extend .w-40;
@extend .m-1;
@extend .border;
min-height: 80vh;
}
.conversation-container {
@extend .flex-row-container;
@extend .justify-content-between;
@extend .border;
@extend .w-100;
@extend .my-3;
@extend .focus-ring;
cursor: pointer;
}
.participant-portrait-container {
@extend .float-start;
}
.participant-portrait {
@extend .img-fluid;
}
.conversation-summary-container {
@extend .flex-colum-container;
@extend .w-90;
}
.conversation-summary-header-container {
@extend .flex-row-container;
@extend .justify-content-between;
@extend .w-100;
}
.participant-fullname {
@extend .text-start;
@extend .label-text-light;
}
.conversation-last-update-date {
@extend .text-start;
@extend .label-text-light;
}
.conversation-summary-highlight-container {
@extend .container;
}
.conversation-last-message-summary {
@extend .d-inline-block;
@extend .text-truncate;
@extend .w-100;
}
.message-panel-container {
@extend .flex-colum-container;
@extend .w-60;
@extend .m-1;
@extend .border;
@extend .justify-content-between;
min-height: 80vh;
}
.message-thread-container {
@extend .flex-colum-container;
@extend .m-1;
@extend .border;
@extend .align-items-start;
@extend .flex-grow-1;
}
.message-item-container {
@extend .flex-colum-container;
@extend .m-1;
}
.message-item-header-container {
@extend .flex-row-container;
@extend .justify-content-between;
@extend .w-100;
}
.message-item-sender-info {
@extend .m-1;
}
.message-item-additional-info-container {
@extend .m-1;
}
.message-item-sender-portrait {
@extend .img-fluid;
height: 2vh;
}
.message-item-sender-fullname {
@extend .label-text;
@extend .mx-1;
}
.message-item-create-time {
@extend .label-text;
@extend .mx-1;
}
.message-item-message-body-container {
@extend .container;
}
.message-item-message-body-span {
@extend .text-start;
}
.message-writing-panel-container {
@extend .flex-colum-container;
@extend .border;
min-height: 10vh;
}
.writing-message-input {
@extend .text-start;
@extend .w-100;
@extend .flex-grow-1;
&.me {align-self: flex-end;
.message-item-header-container {flex-direction: row-reverse; align-self: flex-end;}
.message-item-message-body {background-color: $primary; color: white; align-self: flex-end;}
}
}
}
.message-thread-empty-container {height: 100%; overflow: auto; padding: 20px 32px; display: flex; align-items: center; justify-content: center;}
.message-writing-panel-container {height: 98px; padding: 24px; background-color: white; position: absolute; bottom: 0; left: 0; width: 100%;
.writing-message-enter {position: absolute; height: 24px; width: 24px; background-color: #F3F3F5; padding: 7px; color: #9EA2AF; top: 37px; right: 37px; border-radius: 7px;}
.writing-message-input {height: 50px; border: 1px solid #E1E1E1; box-shadow: none; width: 100%; padding: 0 48px 0 12px; border-radius: 12px;}
}
}
}
}
</style>

View File

@ -1,6 +1,6 @@
<template>
<div class="workspace-container">
<div class="workspace-header"></div>
<!-- <div class="workspace-header"></div> -->
<div class="workspace-body">
<div
class="accordion"
@ -911,34 +911,36 @@ export default {
</script>
<style scoped lang="scss">
.workspace-container {
@extend .flex-colum-container;
}
.workspace-container {width: 100%; display: flex; align-items: center; justify-content: center}
.workspace-header {
@extend .flex-row-container;
@extend .justify-content-end;
}
.workspace-body {
@extend .container;
.workspace-body {width: 100%; max-width: $body-width; padding: 24px 0;
.accordion {box-shadow: 0px 0px 24px 0px #D4D3E380; border: none; border-radius: 12px; margin-bottom: 16px;
.accordion-item {border: none;
.accordion-header {border: none;
.accordion-button {box-shadow: none; padding: 12px}
}
}
}
}
.workspace-item-bar {
@extend .flex-row-container;
}
.workspace-item-bar {display: flex; align-items: center; margin: 0 24px 0 0; border: 1px dashed #AEBFFD; border-radius: 3px; flex: 1}
.workspace-item-bar-left {
@extend .flex-row-container;
@extend .flex-grow-1;
@extend .border;
// @extend .border;
@extend .me-3;
}
.workspace-item-bar-right {
@extend .flex-row-container;
@extend .w-20;
@extend .border;
// @extend .border;
}
.project-item-title-container {

View File

@ -105,22 +105,16 @@
</div>
</div>
<div class="action-bar">
<div class="product-dropdown-container">
<label>Product Name:</label>
<select class="product-dropdown" v-model="selectedProduct">
<option value="new">New ...</option>
<option v-for="product in products" :value="product.name" :key="product">
{{ product.name }}
</option>
</select>
<input
v-if="selectedProduct === 'new'"
type="text"
class="product-input-box"
v-model="newProduct"
placeholder="Enter new product name"
/>
<input-selector :select-list="products" :selected="selectedProduct" @selectedChange="selectedChange" />
<div class="upload-contianer">
<label class="btn btn-link">
<span v-if="!uploadFile">Upload file</span>
<span v-if="uploadFile">{{uploadFile.name}}</span>
<input type="file" hidden @change="handleFileUpload"/>
</label>
<svg-icon v-if="uploadFile" icon="delete" class-name="delete-icon" @click.stop="clearFile" />
</div>
<div class="flex-1" />
<button
class="action-button"
type="button"
@ -150,12 +144,12 @@
@blur="descriptionDone($event)"
contenteditable="true"
/> -->
<VueQuill v-model:content="content" />
<freeleaps-editor v-model:content="content" />
</div>
<div class="file-upload-container">
<!-- <div class="file-upload-container">
<label for="file-upload" class="file-upload-label">Upload File:</label>
<input type="file" id="file-upload" class="file-upload-input" @change="handleFileUpload" />
</div>
</div> -->
<div class="action-footer">
<button class="cancel-button" @click="back">Back</button>
<button class="submit-button" @click="submit">Submit</button>
@ -166,7 +160,9 @@
<script>
import { WorksapceApi, textAreaAujuster, requestIssueUtils } from '../../../../utils/index'
import { requestIssuingModelEnum } from '../../../../types/index'
import VueQuill from '@/components/VueQuill.vue'
import FreeleapsEditor from '@/components/FreeleapsEditor.vue'
import InputSelector from '@/components/InputSelector.vue'
import SvgIcon from '@/components/SvgIcon.vue'
export default {
name: 'IssueRequest',
@ -180,7 +176,7 @@ export default {
type: String
}
},
components: { VueQuill },
components: {FreeleapsEditor, InputSelector, SvgIcon },
mounted() {
this.initProducts()
this.initiateFromInput()
@ -194,26 +190,36 @@ export default {
request_id: null,
availableTemplates: null,
existingRequests: null,
products: null,
products: [],
selectedProduct: null,
newProduct: null,
uploadFile: null
}
},
methods: {
handleFileUpload(event) {
if (event.target.files[0]) {
this.uploadFile = event.target.files[0]
}
},
clearFile() {
this.uploadFile = null
},
initProducts() {
WorksapceApi.fetchProducts()
.then((response) => {
this.products = response.data
this.products = (response.data || []).map(p => p.name)
})
.catch((error) => {
this.mnx_backendErrorHandler(error)
})
},
selectedChange(item) {
this.selectedProduct = item.selected
if (item.isNew) {
this.products.push(item.selected)
}
},
fetchExisting() {
WorksapceApi.fetchMyExistingRequests('')
.then((response) => {
@ -290,9 +296,6 @@ export default {
},
submit() {
var product = this.selectedProduct
if (this.selectedProduct === 'new') {
product = this.newProduct.trim()
}
if (!product) {
alert('Please input a product name or select a product')
@ -322,6 +325,10 @@ export default {
}
</script>
<style lang="scss" scoped>
.upload-contianer {display: flex; align-items: center;}
.delete-icon {color: $primary; cursor: pointer;
&:hover {opacity: .78;}
}
.request-issue-container {
@extend .flex-colum-container;
}

View File

@ -1,3 +1,2 @@
export { store } from './store/index'
export { router } from './router/index'
export { pdfjsLib } from './pdfjs/index'

View File

@ -1 +0,0 @@
export { pdfjsLib } from './pdfjs.js'

View File

@ -1,7 +0,0 @@
import * as pdfjsLib from 'pdfjs-dist'
//need to set worker before the pdfjs can be used.
// pdfjsLib.GlobalWorkerOptions.workerPort = new Worker(
// new URL('pdfjs-dist/build/pdf.worker.mjs', import.meta.url)
// )
export { pdfjsLib }

View File

@ -235,7 +235,7 @@ const router = createRouter({
{
name: 'request-issue',
path: '/request-issue/:loadFrom',
meta: { requiredRoles: [userRoleEnum.PERSONAL] },
meta: { requiredRoles: [userRoleEnum.PERSONAL], activePath: 'Post' },
components: { default: IssueRequest, footer: FooterGuest, header: HeaderUser },
props: (route) => {
/**
@ -298,21 +298,21 @@ const router = createRouter({
{
name: 'message-hub',
path: '/message-hub',
meta: { requiredRoles: [userRoleEnum.PERSONAL] },
meta: { requiredRoles: [userRoleEnum.PERSONAL], activePath: 'message' },
components: { default: MessageHub, footer: FooterGuest, header: HeaderUser }
},
// provider hub
{
name: 'provider-hub',
path: '/provider-hub',
meta: { requiredRoles: [userRoleEnum.PERSONAL] },
meta: { requiredRoles: [userRoleEnum.PERSONAL], activePath: 'Providers' },
components: { default: ProviderHub, footer: FooterGuest, header: HeaderUser }
},
//request hub
{
name: 'request-hub',
path: '/request-hub',
meta: { requiredRoles: [userRoleEnum.PERSONAL] },
meta: { requiredRoles: [userRoleEnum.PERSONAL], activePath: 'Requests' },
components: { default: RequestHub, footer: FooterGuest, header: HeaderUser }
},
{
@ -370,7 +370,7 @@ const router = createRouter({
{
name: 'work-space',
path: '/work-space',
meta: { requiredRoles: [userRoleEnum.PERSONAL], active: 'workspace' },
meta: { requiredRoles: [userRoleEnum.PERSONAL], activePath: 'Workspace' },
components: { default: Workspace, footer: FooterGuest, header: HeaderUser }
}
],

View File

@ -13,6 +13,6 @@ export { userUtils, userProfileUtils, requestIssueUtils, requestHubUtils } from
export { ValueChecker, DateUtils, OIDUtils } from './common/index'
export { passwordValidator } from './validator/index'
export { passwordValidator, applicantValidator } from './validator/index'
export { textAreaAujuster, tooltip, elementHandler, mediaDataHandler } from './html/index'

View File

@ -1 +1,2 @@
export { passwordValidator } from './passwordValidator'
export { applicantValidator } from './applicantValidator'

View File

@ -38,7 +38,7 @@ export default defineConfig({
server: {
proxy: {
'^/api/': {
target: 'http://localhost:8001/',
target: 'https://freeleaps-alpha.com',
ws: true,
changeOrigin: true
}