code stytling adjustment
This commit is contained in:
parent
dd90d4d4de
commit
91b0ebfea2
@ -104,17 +104,58 @@ p {
|
|||||||
height: 100%;
|
height: 100%;
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
}
|
}
|
||||||
.btn-link {text-decoration: none; color: $primary;}
|
.btn-link {
|
||||||
.dropdown-menu {border: none; box-shadow: 0px 0px 24px 0px #D4D3E380; padding: 0; overflow: hidden;
|
text-decoration: none;
|
||||||
.btn-link {text-decoration: none; height: 33px; width: 100%; color: #0D1637; font-size: 14px; text-align: left; border-radius: 0;
|
color: $primary;
|
||||||
&:hover {background-color: #F3F6FF;}
|
}
|
||||||
&.active {background-color: #1748F8; color: white;}
|
.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;
|
||||||
}
|
}
|
||||||
.dropdown-new {color: #1748F8;
|
&.active {
|
||||||
&:hover {background-color: white;}
|
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;
|
||||||
}
|
}
|
||||||
.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}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,7 +2,15 @@
|
|||||||
<div class="freeleaps-editor">
|
<div class="freeleaps-editor">
|
||||||
<div v-if="!disabled" class="editor-control">
|
<div v-if="!disabled" class="editor-control">
|
||||||
<div v-for="(item, index) in iconList" :key="index" class="editor-item">
|
<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">
|
<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" />
|
<svg-icon :icon="item.icon" class-name="icon" />
|
||||||
</button>
|
</button>
|
||||||
<div class="dropmenu drop-style" v-if="item.type === 'style'">
|
<div class="dropmenu drop-style" v-if="item.type === 'style'">
|
||||||
@ -14,7 +22,9 @@
|
|||||||
<a href="#" @click="iconClick($event, 'pre', 'style')"><pre>code</pre></a>
|
<a href="#" @click="iconClick($event, 'pre', 'style')"><pre>code</pre></a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" @click="iconClick($event, 'blockquote', 'style')"><blockquote>引用</blockquote></a>
|
<a href="#" @click="iconClick($event, 'blockquote', 'style')"
|
||||||
|
><blockquote>引用</blockquote></a
|
||||||
|
>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" @click="iconClick($event, 'h1', 'style')"><h1>标题一</h1></a>
|
<a href="#" @click="iconClick($event, 'h1', 'style')"><h1>标题一</h1></a>
|
||||||
@ -23,13 +33,13 @@
|
|||||||
<a href="#" @click="iconClick($event, 'h2', 'style')"><h2>标题二</h2></a>
|
<a href="#" @click="iconClick($event, 'h2', 'style')"><h2>标题二</h2></a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" @click="iconClick($event, 'h3', 'style')"><h3>标题三 </h3></a>
|
<a href="#" @click="iconClick($event, 'h3', 'style')"><h3>标题三</h3></a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" @click="iconClick($event, 'h4', 'style')"><h4>标题四 </h4></a>
|
<a href="#" @click="iconClick($event, 'h4', 'style')"><h4>标题四</h4></a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" @click="iconClick($event, 'h5', 'style')"><h5>标题五 </h5></a>
|
<a href="#" @click="iconClick($event, 'h5', 'style')"><h5>标题五</h5></a>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<a href="#" @click="iconClick($event, 'h6', 'style')"><h6>标题六</h6></a>
|
<a href="#" @click="iconClick($event, 'h6', 'style')"><h6>标题六</h6></a>
|
||||||
@ -66,7 +76,14 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="editor-body" :contenteditable="!disabled" spellcheck="false" ref="editor" v-html="content" @blur="updateAction" />
|
<div
|
||||||
|
class="editor-body"
|
||||||
|
:contenteditable="!disabled"
|
||||||
|
spellcheck="false"
|
||||||
|
ref="editor"
|
||||||
|
v-html="content"
|
||||||
|
@blur="updateAction"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
@ -160,7 +177,7 @@ export default {
|
|||||||
drop: false,
|
drop: false,
|
||||||
canChoose: true,
|
canChoose: true,
|
||||||
choose: false
|
choose: false
|
||||||
},
|
}
|
||||||
// {
|
// {
|
||||||
// name: '对齐方式',
|
// name: '对齐方式',
|
||||||
// type: 'alignjustify',
|
// type: 'alignjustify',
|
||||||
@ -173,7 +190,7 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
iconClick (event, type, dropType) {
|
iconClick(event, type, dropType) {
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
this.$refs.editor.focus()
|
this.$refs.editor.focus()
|
||||||
this.selectedRange = this.getSelect()
|
this.selectedRange = this.getSelect()
|
||||||
@ -278,37 +295,212 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<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;
|
.freeleaps-editor {
|
||||||
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; }
|
position: relative;
|
||||||
code, kbd, pre, samp { font-family: Menlo, Monaco, Consolas, "Courier New", monospace; }
|
background-color: #fff;
|
||||||
.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; }
|
border-radius: 4px;
|
||||||
.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);
|
border: 1px solid #a9a9a9;
|
||||||
ul {padding: 10px; margin-bottom: 0;}
|
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
|
||||||
ul li { text-align: left; list-style: none;
|
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
|
||||||
a { display: block; padding: 5px 10px; white-space: nowrap; }
|
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, 0.15);
|
||||||
|
border-radius: 4px;
|
||||||
|
box-shadow: 0 6px 12px rgba(0, 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;
|
.drop-align {
|
||||||
p { font-size: 14px; color: #68747f; margin: 0 0 10px; }
|
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;
|
.editor-item {
|
||||||
.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;
|
position: relative;
|
||||||
&::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; }
|
vertical-align: middle;
|
||||||
&::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; }
|
border: 1px solid #ccc;
|
||||||
&:hover, &.activity{ color: #333; background-color: #e6e6e6; border-color: #e6e6e6; }
|
cursor: pointer;
|
||||||
&:hover:after, &:hover:before { visibility: visible; }
|
line-height: 20px;
|
||||||
&.activity + .dropmenu { display: block; }
|
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, 0.8);
|
||||||
|
-webkit-transform: translateX(-50%);
|
||||||
|
transform: translateX(-50%);
|
||||||
|
visibility: hidden;
|
||||||
|
opacity: 0.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, 0.8);
|
||||||
|
border-bottom: 6px solid currentColor;
|
||||||
|
border-left: 6px solid transparent;
|
||||||
|
border-right: 6px solid transparent;
|
||||||
|
visibility: hidden;
|
||||||
|
opacity: 0.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>
|
||||||
<style>
|
<style>
|
||||||
.freeleaps-editor blockquote { padding: 10px 20px; font-size: 17.5px; border-left: 5px solid #f86466; background: white; }
|
.freeleaps-editor blockquote {
|
||||||
.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; }
|
padding: 10px 20px;
|
||||||
.editor-body blockquote { margin-bottom: 30px; }
|
font-size: 17.5px;
|
||||||
.editor-body pre { margin-bottom: 10px; }
|
border-left: 5px solid #f86466;
|
||||||
.editor-body ul { padding-left: 40px; list-style-type: disc; }
|
background: white;
|
||||||
.editor-body ol { padding-left: 40px; }
|
}
|
||||||
|
.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>
|
</style>
|
||||||
@ -1,19 +1,30 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="input-selector-container">
|
<div class="input-selector-container">
|
||||||
<div class="input-selector-btn" data-bs-toggle="dropdown" aria-expanded="false" id="input-selector-btn">
|
<div
|
||||||
<span>{{selected || ''}}</span>
|
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" />
|
<svg-icon icon="dropdown" class-name="selector-dropdown-icon" />
|
||||||
</div>
|
</div>
|
||||||
<ul class="dropdown-menu" aria-labelledby="input-selector-btn">
|
<ul class="dropdown-menu" aria-labelledby="input-selector-btn">
|
||||||
<li>
|
<li>
|
||||||
<button v-if="!inputing" class="btn btn-link dropdown-new" @click="newAction">+ NEW</button>
|
<button v-if="!inputing" class="btn btn-link dropdown-new" @click="newAction">+ NEW</button>
|
||||||
<div v-if="inputing" class="dropdown-new-input-container">
|
<div v-if="inputing" class="dropdown-new-input-container">
|
||||||
<input type="text" v-model="newval" @keyup.enter="newItemAction">
|
<input type="text" v-model="newval" @keyup.enter="newItemAction" />
|
||||||
<svg-icon v-if="newval" icon="msg-enter" class-name="dropdown-new-input-icon" />
|
<svg-icon v-if="newval" icon="msg-enter" class-name="dropdown-new-input-icon" />
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
<li v-for="item in selectList" :key="item">
|
<li v-for="item in selectList" :key="item">
|
||||||
<button class="btn btn-link" @click="selectItem(item)" :class="item==selected ? 'active' : ''">{{item}}</button>
|
<button
|
||||||
|
class="btn btn-link"
|
||||||
|
@click="selectItem(item)"
|
||||||
|
:class="item == selected ? 'active' : ''"
|
||||||
|
>
|
||||||
|
{{ item }}
|
||||||
|
</button>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@ -39,8 +50,8 @@ export default {
|
|||||||
newval: ''
|
newval: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() { },
|
mounted() {},
|
||||||
components: {SvgIcon},
|
components: { SvgIcon },
|
||||||
methods: {
|
methods: {
|
||||||
newAction($event) {
|
newAction($event) {
|
||||||
$event.stopPropagation()
|
$event.stopPropagation()
|
||||||
@ -48,11 +59,14 @@ export default {
|
|||||||
this.inputing = true
|
this.inputing = true
|
||||||
},
|
},
|
||||||
selectItem(item) {
|
selectItem(item) {
|
||||||
this.$emit('selectedChange', {selected: item, isNew: false})
|
this.$emit('selectedChange', { selected: item, isNew: false })
|
||||||
},
|
},
|
||||||
newItemAction() {
|
newItemAction() {
|
||||||
if (!this.newval) return
|
if (!this.newval) return
|
||||||
this.$emit('selectedChange', {selected: this.newval, isNew: this.selectList.indexOf(this.newval) === -1})
|
this.$emit('selectedChange', {
|
||||||
|
selected: this.newval,
|
||||||
|
isNew: this.selectList.indexOf(this.newval) === -1
|
||||||
|
})
|
||||||
this.newval = ''
|
this.newval = ''
|
||||||
this.inputing = false
|
this.inputing = false
|
||||||
}
|
}
|
||||||
@ -61,10 +75,31 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
.input-selector-container {width: fit-content; height: fit-content; position: relative;
|
.input-selector-container {
|
||||||
.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;
|
width: fit-content;
|
||||||
>span {font-size: 18px; font-weight: 500; color: #242424; flex: 1; text-align: left;}
|
height: fit-content;
|
||||||
.selector-dropdown-icon {color: #242424; padding: 3px;}
|
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>
|
</style>
|
||||||
|
|||||||
@ -10,7 +10,7 @@
|
|||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import * as PDFJS from "pdfjs-dist/build/pdf"
|
import * as PDFJS from 'pdfjs-dist/build/pdf'
|
||||||
import { WorksapceApi } from '@/utils/index'
|
import { WorksapceApi } from '@/utils/index'
|
||||||
PDFJS.GlobalWorkerOptions.workerSrc = import('pdfjs-dist/build/pdf.worker.entry')
|
PDFJS.GlobalWorkerOptions.workerSrc = import('pdfjs-dist/build/pdf.worker.entry')
|
||||||
|
|
||||||
@ -31,51 +31,57 @@ export default {
|
|||||||
this.renderPDF()
|
this.renderPDF()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
renderPage (num) {
|
renderPage(num) {
|
||||||
const canvas = document.getElementById("theCanvas");
|
const canvas = document.getElementById('theCanvas')
|
||||||
const context = canvas.getContext("2d");
|
const context = canvas.getContext('2d')
|
||||||
const scale = 1.5;
|
const scale = 1.5
|
||||||
this.loadingTask.promise.then((pdf) => {
|
this.loadingTask.promise.then((pdf) => {
|
||||||
pdf.getPage(num).then((page) => {
|
pdf.getPage(num).then((page) => {
|
||||||
const viewport = page.getViewport({ scale });
|
const viewport = page.getViewport({ scale })
|
||||||
canvas.height = viewport.height;
|
canvas.height = viewport.height
|
||||||
canvas.width = viewport.width;
|
canvas.width = viewport.width
|
||||||
const renderContext = {
|
const renderContext = {
|
||||||
canvasContext: context,
|
canvasContext: context,
|
||||||
viewport: viewport,
|
viewport: viewport
|
||||||
};
|
}
|
||||||
page.render(renderContext);
|
page.render(renderContext)
|
||||||
});
|
})
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
async renderPDF() {
|
async renderPDF() {
|
||||||
const response = await WorksapceApi.fetchAttachedFileAsMediaData("66673218fa83335c3b1b11ec", "6667321afa83335c3b1b11ee")
|
const response = await WorksapceApi.fetchAttachedFileAsMediaData(
|
||||||
this.loadingTask = PDFJS.getDocument({url: response.data});
|
'66673218fa83335c3b1b11ec',
|
||||||
|
'6667321afa83335c3b1b11ee'
|
||||||
|
)
|
||||||
|
this.loadingTask = PDFJS.getDocument({ url: response.data })
|
||||||
this.loadingTask.promise.then((pdf) => {
|
this.loadingTask.promise.then((pdf) => {
|
||||||
this.numPages = pdf.numPages;
|
this.numPages = pdf.numPages
|
||||||
this.renderPage(1);
|
this.renderPage(1)
|
||||||
});
|
})
|
||||||
},
|
},
|
||||||
prev() {
|
prev() {
|
||||||
if (this.currentPage > 1) {
|
if (this.currentPage > 1) {
|
||||||
this.currentPage--;
|
this.currentPage--
|
||||||
this.renderPage(this.currentPage);
|
this.renderPage(this.currentPage)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
next() {
|
next() {
|
||||||
if (this.currentPage < this.numPages) {
|
if (this.currentPage < this.numPages) {
|
||||||
this.currentPage++;
|
this.currentPage++
|
||||||
this.renderPage(this.currentPage);
|
this.renderPage(this.currentPage)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.pdf-container{position: relative;
|
.pdf-container {
|
||||||
.operate{position: absolute; right: 0; top: 0; }
|
position: relative;
|
||||||
|
.operate {
|
||||||
|
position: absolute;
|
||||||
|
right: 0;
|
||||||
|
top: 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|||||||
@ -1,23 +1,43 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="header-container">
|
<div class="header-container">
|
||||||
<div class="header-content">
|
<div class="header-content">
|
||||||
<div class="information-bar" @click="gotoMessages" :class="activePath == 'message'?'active':''">
|
<div
|
||||||
|
class="information-bar"
|
||||||
|
@click="gotoMessages"
|
||||||
|
:class="activePath == 'message' ? 'active' : ''"
|
||||||
|
>
|
||||||
<img alt="freeleaps logo" src="@/assets/message.png" />
|
<img alt="freeleaps logo" src="@/assets/message.png" />
|
||||||
</div>
|
</div>
|
||||||
<div class="navigation-container" role="navigation">
|
<div class="navigation-container" role="navigation">
|
||||||
<button class="navigation-item" @click="gotoWorkspace" :class="activePath == 'Workspace'?'active':''">
|
<button
|
||||||
|
class="navigation-item"
|
||||||
|
@click="gotoWorkspace"
|
||||||
|
:class="activePath == 'Workspace' ? 'active' : ''"
|
||||||
|
>
|
||||||
<svg-icon icon="workspace" class-name="icon" />
|
<svg-icon icon="workspace" class-name="icon" />
|
||||||
Workspace
|
Workspace
|
||||||
</button>
|
</button>
|
||||||
<button class="navigation-item" @click="gotoRequests" :class="activePath == 'Requests'?'active':''">
|
<button
|
||||||
|
class="navigation-item"
|
||||||
|
@click="gotoRequests"
|
||||||
|
:class="activePath == 'Requests' ? 'active' : ''"
|
||||||
|
>
|
||||||
<svg-icon icon="requests" class-name="icon" />
|
<svg-icon icon="requests" class-name="icon" />
|
||||||
Requests
|
Requests
|
||||||
</button>
|
</button>
|
||||||
<button class="navigation-item" @click="gotoProviders" :class="activePath == 'Providers'?'active':''">
|
<button
|
||||||
|
class="navigation-item"
|
||||||
|
@click="gotoProviders"
|
||||||
|
:class="activePath == 'Providers' ? 'active' : ''"
|
||||||
|
>
|
||||||
<svg-icon icon="providers" class-name="icon" />
|
<svg-icon icon="providers" class-name="icon" />
|
||||||
Providers
|
Providers
|
||||||
</button>
|
</button>
|
||||||
<button class="navigation-item" @click="gotoIssueRequest" :class="activePath == 'Post'?'active':''">
|
<button
|
||||||
|
class="navigation-item"
|
||||||
|
@click="gotoIssueRequest"
|
||||||
|
:class="activePath == 'Post' ? 'active' : ''"
|
||||||
|
>
|
||||||
<svg-icon icon="post" class-name="icon" />
|
<svg-icon icon="post" class-name="icon" />
|
||||||
Post
|
Post
|
||||||
</button>
|
</button>
|
||||||
@ -163,7 +183,9 @@ export default {
|
|||||||
top: 0;
|
top: 0;
|
||||||
background-color: #f44837;
|
background-color: #f44837;
|
||||||
}
|
}
|
||||||
&.active {border: 1px solid $primary;}
|
&.active {
|
||||||
|
border: 1px solid $primary;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.profile-container {
|
.profile-container {
|
||||||
|
|||||||
@ -56,9 +56,7 @@ export default {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
this.message = applicantValidator.emailValidator.validate(
|
this.message = applicantValidator.emailValidator.validate(this.email)
|
||||||
this.email
|
|
||||||
);
|
|
||||||
|
|
||||||
if (this.message != null) return
|
if (this.message != null) return
|
||||||
|
|
||||||
|
|||||||
@ -1,8 +1,13 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="message-container">
|
<div class="message-container">
|
||||||
<div class="message-hub-conainter">
|
<div class="message-hub-conainter">
|
||||||
<div v-if="conversations && conversations.length>0" class="conversation-list-container">
|
<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)">
|
<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" />
|
<img class="participant-portrait" alt="user portrait" src="@/assets/profile.png" />
|
||||||
<div class="conversation-summary-container">
|
<div class="conversation-summary-container">
|
||||||
<div class="conversation-summary-header-container">
|
<div class="conversation-summary-header-container">
|
||||||
@ -10,33 +15,58 @@
|
|||||||
{{ conversation.summary.contact.first_name }}
|
{{ conversation.summary.contact.first_name }}
|
||||||
{{ conversation.summary.contact.last_name }}
|
{{ conversation.summary.contact.last_name }}
|
||||||
</span>
|
</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>
|
||||||
<div class="conversation-summary-highlight-container">{{ conversation.summary.last_message.message_body }}</div>
|
<div class="conversation-summary-highlight-container">
|
||||||
|
{{ conversation.summary.last_message.message_body }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!conversations || conversations.length==0" class="conversation-list-empty-container">
|
</div>
|
||||||
|
<div
|
||||||
|
v-if="!conversations || conversations.length == 0"
|
||||||
|
class="conversation-list-empty-container"
|
||||||
|
>
|
||||||
Empty conversation
|
Empty conversation
|
||||||
</div>
|
</div>
|
||||||
<div class="message-panel-container">
|
<div class="message-panel-container">
|
||||||
<div v-if="current_thread" class="message-thread-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" :class="item.sender_profile.me ? 'me': ''">
|
<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-header-container">
|
||||||
<img class="message-item-sender-portrait" alt="user portrait" src="@/assets/profile.png" />
|
<img
|
||||||
|
class="message-item-sender-portrait"
|
||||||
|
alt="user portrait"
|
||||||
|
src="@/assets/profile.png"
|
||||||
|
/>
|
||||||
<span class="message-item-sender-fullname">
|
<span class="message-item-sender-fullname">
|
||||||
{{ item.sender_profile.first_name }}
|
{{ item.sender_profile.first_name }}
|
||||||
{{ item.sender_profile.last_name }}
|
{{ item.sender_profile.last_name }}
|
||||||
</span>
|
</span>
|
||||||
<span class="message-item-create-time"> {{ getDateFromFulltimeString(item.raw_data.create_time) }}</span>
|
<span class="message-item-create-time">
|
||||||
|
{{ getDateFromFulltimeString(item.raw_data.create_time) }}</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="message-item-message-body">{{ item.raw_data.message_body }}</div>
|
<div class="message-item-message-body">{{ item.raw_data.message_body }}</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="!current_thread" class="message-thread-empty-container">Please choose conversation</div>
|
<div v-if="!current_thread" class="message-thread-empty-container">
|
||||||
|
Please choose conversation
|
||||||
|
</div>
|
||||||
<div class="message-writing-panel-container">
|
<div class="message-writing-panel-container">
|
||||||
<svg-icon icon="msg-enter" class-name="writing-message-enter" />
|
<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)" />
|
<input
|
||||||
|
class="writing-message-input"
|
||||||
|
type="text"
|
||||||
|
v-model="writtenMessage"
|
||||||
|
@keypress.enter="sendMessage(current_thread.conversation.information.conversation_id)"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -101,43 +131,196 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.message-container { display: flex; align-items: center; width: 100%; height: $body-height; padding: 24px 24px 0 24px; justify-content: center;
|
.message-container {
|
||||||
.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;
|
display: flex;
|
||||||
.conversation-list-container {height: 100%; overflow: auto; width: 300px;
|
align-items: center;
|
||||||
.conversation-container {background-color: #F3F3F5; display: flex; cursor: pointer; height: 98px; padding: 18px;
|
width: 100%;
|
||||||
.participant-portrait {width: 36px; height: 36px; border-radius: 18px; margin-right: 16px;}
|
height: $body-height;
|
||||||
.conversation-summary-container {display: flex; flex-direction: column; flex: 1; overflow: hidden;
|
padding: 24px 24px 0 24px;
|
||||||
.conversation-summary-header-container {display: flex; align-items: center; height: 22px; color: #0D1637;
|
justify-content: center;
|
||||||
.participant-fullname {font-weight: 500; flex: 1; white-space: nowrap; text-overflow: ellipsis; overflow: hidden;}
|
.message-hub-conainter {
|
||||||
.conversation-last-update-date {white-space: nowrap; flex-shrink: 0;}
|
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-highlight-container {font-size: 14px; color: #6E7387; white-space: normal; overflow: hidden; flex: 1; text-align: left; word-break: break-word}
|
.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;
|
||||||
}
|
}
|
||||||
&:hover {opacity: .78;}
|
.conversation-last-update-date {
|
||||||
&.selected {background-color: transparent;}
|
white-space: nowrap;
|
||||||
|
flex-shrink: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.conversation-list-empty-container {height: 100%; overflow: auto; width: 300px; background-color: #F3F3F5; display: flex; align-items: center; justify-content: center;}
|
.conversation-summary-highlight-container {
|
||||||
.message-panel-container {height: 100%; overflow: auto; flex: 1; padding-bottom: 98px; position: relative;
|
font-size: 14px;
|
||||||
.message-thread-container {height: 100%; overflow: auto; padding: 20px 32px; display: flex; flex-direction: column;
|
color: #6e7387;
|
||||||
.message-item-container {max-width: 70%; margin-bottom: 15px; width: fit-content; display: flex; flex-direction: column;
|
white-space: normal;
|
||||||
.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%;
|
overflow: hidden;
|
||||||
.message-item-sender-portrait {width: 36px; height: 36px; border-radius: 18px; }
|
flex: 1;
|
||||||
.message-item-sender-fullname {overflow: hidden; white-space: nowrap; text-overflow: ellipsis; color: #16181E; font-weight: 500; margin: 0 7px; }
|
text-align: left;
|
||||||
.message-item-create-time {color: #737478; white-space: nowrap; flex-shrink: 0; font-size: 16px; }
|
word-break: break-word;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.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;
|
||||||
}
|
}
|
||||||
.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}
|
|
||||||
|
|
||||||
&.me {align-self: flex-end;
|
&.me {
|
||||||
.message-item-header-container {flex-direction: row-reverse; align-self: flex-end;}
|
align-self: flex-end;
|
||||||
.message-item-message-body {background-color: $primary; color: white; 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%;
|
.message-thread-empty-container {
|
||||||
.writing-message-enter {position: absolute; height: 24px; width: 24px; background-color: #F3F3F5; padding: 7px; color: #9EA2AF; top: 37px; right: 37px; border-radius: 7px;}
|
height: 100%;
|
||||||
.writing-message-input {height: 50px; border: 1px solid #E1E1E1; box-shadow: none; width: 100%; padding: 0 48px 0 12px; border-radius: 12px;}
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,22 +1,43 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="request-hub">
|
<div class="request-hub">
|
||||||
<div v-for="(group, index) in requestGroups" :key="index" class="request-invitations" :id="group.name">
|
<div
|
||||||
|
v-for="(group, index) in requestGroups"
|
||||||
|
:key="index"
|
||||||
|
class="request-invitations"
|
||||||
|
:id="group.name"
|
||||||
|
>
|
||||||
<div v-if="group.data" class="accordion" id="request-invitation-container">
|
<div v-if="group.data" class="accordion" id="request-invitation-container">
|
||||||
<div v-for="(request, index) in group.data" :key="index" :id="request.id" class="accordion-item my-3">
|
<div
|
||||||
|
v-for="(request, index) in group.data"
|
||||||
|
:key="index"
|
||||||
|
:id="request.id"
|
||||||
|
class="accordion-item my-3"
|
||||||
|
>
|
||||||
<h2 class="accordion-header">
|
<h2 class="accordion-header">
|
||||||
<button class="accordion-button collapsed" type="button" data-bs-toggle="collapse"
|
<button
|
||||||
:data-bs-target="'#collapse' + index" aria-expanded="false" :aria-controls="'collapse' + index">
|
class="accordion-button collapsed"
|
||||||
|
type="button"
|
||||||
|
data-bs-toggle="collapse"
|
||||||
|
:data-bs-target="'#collapse' + index"
|
||||||
|
aria-expanded="false"
|
||||||
|
:aria-controls="'collapse' + index"
|
||||||
|
>
|
||||||
<div class="request-content-container">
|
<div class="request-content-container">
|
||||||
<div class="request-content-issuer-container">
|
<div class="request-content-issuer-container">
|
||||||
<label class="request-content-label" for="request-content-issuer-box">Issuer</label>
|
<label class="request-content-label" for="request-content-issuer-box"
|
||||||
|
>Issuer</label
|
||||||
|
>
|
||||||
<div class="request-content-box" id="request-content-issuer-box">
|
<div class="request-content-box" id="request-content-issuer-box">
|
||||||
<span class="request-content-issuer-text">
|
<span class="request-content-issuer-text">
|
||||||
{{ request.issuer_profile.first_name }}
|
{{ request.issuer_profile.first_name }}
|
||||||
{{ request.issuer_profile.last_name }}</span>
|
{{ request.issuer_profile.last_name }}</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="request-content-title-container">
|
<div class="request-content-title-container">
|
||||||
<label class="request-content-label" for="request-content-title-box">Request</label>
|
<label class="request-content-label" for="request-content-title-box"
|
||||||
|
>Request</label
|
||||||
|
>
|
||||||
<div class="request-content-box" id="request-content-title-box">
|
<div class="request-content-box" id="request-content-title-box">
|
||||||
<span class="request-content-title-text"> {{ request.title }}</span>
|
<span class="request-content-title-text"> {{ request.title }}</span>
|
||||||
</div>
|
</div>
|
||||||
@ -40,8 +61,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
</h2>
|
</h2>
|
||||||
<div :id="'collapse' + index" class="accordion-collapse collapse"
|
<div
|
||||||
data-bs-parent="#request-invitation-container">
|
:id="'collapse' + index"
|
||||||
|
class="accordion-collapse collapse"
|
||||||
|
data-bs-parent="#request-invitation-container"
|
||||||
|
>
|
||||||
<div class="accordion-body">
|
<div class="accordion-body">
|
||||||
<div class="request-description-container">
|
<div class="request-description-container">
|
||||||
<button class="make-proposal-button" type="button" @click="Propose(request)">
|
<button class="make-proposal-button" type="button" @click="Propose(request)">
|
||||||
@ -49,51 +73,95 @@
|
|||||||
</button>
|
</button>
|
||||||
<div class="request-description-content" v-html="request.content"></div>
|
<div class="request-description-content" v-html="request.content"></div>
|
||||||
<div v-for="(file, index) in request.attached_files" :key="index">
|
<div v-for="(file, index) in request.attached_files" :key="index">
|
||||||
<button @click="previewAttachedFile(request.id, file.document_id)">Preview{{ file.file_name }}</button>
|
<button @click="previewAttachedFile(request.id, file.document_id)">
|
||||||
<button @click="downloadAttachedFile(request.id, file.document_id)">Download{{ file.file_name }}</button>
|
Preview{{ file.file_name }}
|
||||||
|
</button>
|
||||||
|
<button @click="downloadAttachedFile(request.id, file.document_id)">
|
||||||
|
Download{{ file.file_name }}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="issuer-profile-container">
|
<div class="issuer-profile-container">
|
||||||
<label class="issuer-profile-label" for="issuer-achievement-container">Issuer profile</label>
|
<label class="issuer-profile-label" for="issuer-achievement-container"
|
||||||
|
>Issuer profile</label
|
||||||
|
>
|
||||||
<div class="issuer-achievement-container" id="issuer-achievement-container">
|
<div class="issuer-achievement-container" id="issuer-achievement-container">
|
||||||
<div class="issuer-achievement-isssuer-container">
|
<div class="issuer-achievement-isssuer-container">
|
||||||
<label class="issuer-achievement-label" for="issuer-achievement-isssuer-content-div">Name</label>
|
<label
|
||||||
<div class="issuer-achievement-content-container" id="issuer-achievement-isssuer-content-div">
|
class="issuer-achievement-label"
|
||||||
|
for="issuer-achievement-isssuer-content-div"
|
||||||
|
>Name</label
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="issuer-achievement-content-container"
|
||||||
|
id="issuer-achievement-isssuer-content-div"
|
||||||
|
>
|
||||||
<span class="issuer-achievement-issuer-text">
|
<span class="issuer-achievement-issuer-text">
|
||||||
{{ request.issuer_profile.first_name }}
|
{{ request.issuer_profile.first_name }}
|
||||||
{{ request.issuer_profile.last_name }}</span>
|
{{ request.issuer_profile.last_name }}</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="issuer-achievement-stay-container">
|
<div class="issuer-achievement-stay-container">
|
||||||
<label class="issuer-achievement-label" for="issuer-achievement-stay-content-div">Stay on
|
<label
|
||||||
Freeleaps</label>
|
class="issuer-achievement-label"
|
||||||
<div class="issuer-achievement-content-container" id="issuer-achievement-stay-content-div">
|
for="issuer-achievement-stay-content-div"
|
||||||
|
>Stay on Freeleaps</label
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="issuer-achievement-content-container"
|
||||||
|
id="issuer-achievement-stay-content-div"
|
||||||
|
>
|
||||||
<span class="issuer-achievement-stay-content-text">
|
<span class="issuer-achievement-stay-content-text">
|
||||||
{{ request.issuer_achievement.activeness.days_of_staying_on }} day(s)</span>
|
{{ request.issuer_achievement.activeness.days_of_staying_on }} day(s)</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="issuer-achievement-paid-container">
|
<div class="issuer-achievement-paid-container">
|
||||||
<label class="issuer-achievement-label" for="issuer-achievement-paid-content-div">Total
|
<label
|
||||||
payment</label>
|
class="issuer-achievement-label"
|
||||||
<div class="issuer-achievement-content-container" id="issuer-achievement-stay-content-div">
|
for="issuer-achievement-paid-content-div"
|
||||||
|
>Total payment</label
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="issuer-achievement-content-container"
|
||||||
|
id="issuer-achievement-stay-content-div"
|
||||||
|
>
|
||||||
<span class="issuer-achievement-paid-content-text">
|
<span class="issuer-achievement-paid-content-text">
|
||||||
{{ request.issuer_achievement.issuer.spending.total }}
|
{{ request.issuer_achievement.issuer.spending.total }}
|
||||||
{{ request.issuer_achievement.issuer.spending.currency }}</span>
|
{{ request.issuer_achievement.issuer.spending.currency }}</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="issuer-achievement-deposit-container">
|
<div class="issuer-achievement-deposit-container">
|
||||||
<label class="issuer-achievement-label" for="issuer-achievement-deposit-content-div">Deposit</label>
|
<label
|
||||||
<div class="issuer-achievement-content-container" id="issuer-achievement-deposit-content-div">
|
class="issuer-achievement-label"
|
||||||
|
for="issuer-achievement-deposit-content-div"
|
||||||
|
>Deposit</label
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="issuer-achievement-content-container"
|
||||||
|
id="issuer-achievement-deposit-content-div"
|
||||||
|
>
|
||||||
<span class="issuer-achievement-deposit-content-text">
|
<span class="issuer-achievement-deposit-content-text">
|
||||||
{{ request.issuer_achievement.issuer.deposit.available }}
|
{{ request.issuer_achievement.issuer.deposit.available }}
|
||||||
{{ request.issuer_achievement.issuer.deposit.currency }}</span>
|
{{ request.issuer_achievement.issuer.deposit.currency }}</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="issuer-achievement-credit-container">
|
<div class="issuer-achievement-credit-container">
|
||||||
<label class="issuer-achievement-label" for="issuer-achievement-credit-content-div">Credit</label>
|
<label
|
||||||
<div class="issuer-achievement-content-container" id="issuer-achievement-credit-content-div">
|
class="issuer-achievement-label"
|
||||||
|
for="issuer-achievement-credit-content-div"
|
||||||
|
>Credit</label
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="issuer-achievement-content-container"
|
||||||
|
id="issuer-achievement-credit-content-div"
|
||||||
|
>
|
||||||
<span class="issuer-achievement-credit-content-text">
|
<span class="issuer-achievement-credit-content-text">
|
||||||
{{ request.issuer_achievement.activeness.credit }}</span>
|
{{ request.issuer_achievement.activeness.credit }}</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -140,36 +208,36 @@ export default {
|
|||||||
return DateUtils.FromJsonToDateString(fulltime)
|
return DateUtils.FromJsonToDateString(fulltime)
|
||||||
},
|
},
|
||||||
previewAttachedFile(request_id, document_id) {
|
previewAttachedFile(request_id, document_id) {
|
||||||
WorksapceApi.fetchAttachedFileAsMediaData(request_id, document_id).then(response => {
|
WorksapceApi.fetchAttachedFileAsMediaData(request_id, document_id)
|
||||||
|
.then((response) => {
|
||||||
let media_data = response.data
|
let media_data = response.data
|
||||||
console.log(media_data)
|
console.log(media_data)
|
||||||
//TODO: navigate to the preview page
|
//TODO: navigate to the preview page
|
||||||
}).catch((error) => {
|
})
|
||||||
|
.catch((error) => {
|
||||||
this.mnx_backendErrorHandler(error)
|
this.mnx_backendErrorHandler(error)
|
||||||
}
|
})
|
||||||
)
|
|
||||||
},
|
},
|
||||||
downloadAttachedFile(request_id, document_id) {
|
downloadAttachedFile(request_id, document_id) {
|
||||||
WorksapceApi.fetchAttachedFileAsDownload(request_id, document_id).then(response => {
|
WorksapceApi.fetchAttachedFileAsDownload(request_id, document_id)
|
||||||
|
.then((response) => {
|
||||||
// create file link in browser's memory
|
// create file link in browser's memory
|
||||||
const href = URL.createObjectURL(response.data);
|
const href = URL.createObjectURL(response.data)
|
||||||
|
|
||||||
// create "a" HTML element with href to file & click
|
// create "a" HTML element with href to file & click
|
||||||
const link = document.createElement('a');
|
const link = document.createElement('a')
|
||||||
link.href = href;
|
link.href = href
|
||||||
link.setAttribute('download', 'file.pdf'); //or any other extension
|
link.setAttribute('download', 'file.pdf') //or any other extension
|
||||||
document.body.appendChild(link);
|
document.body.appendChild(link)
|
||||||
link.click();
|
link.click()
|
||||||
|
|
||||||
// clean up "a" element & remove ObjectURL
|
// clean up "a" element & remove ObjectURL
|
||||||
document.body.removeChild(link);
|
document.body.removeChild(link)
|
||||||
URL.revokeObjectURL(href); //TODO: navigate to the preview page
|
URL.revokeObjectURL(href) //TODO: navigate to the preview page
|
||||||
}).catch((error) => {
|
})
|
||||||
|
.catch((error) => {
|
||||||
this.mnx_backendErrorHandler(error)
|
this.mnx_backendErrorHandler(error)
|
||||||
}
|
})
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -911,24 +911,48 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
.workspace-container {width: 100%; display: flex; align-items: center; justify-content: center}
|
.workspace-container {
|
||||||
|
width: 100%;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
.workspace-header {
|
.workspace-header {
|
||||||
@extend .flex-row-container;
|
@extend .flex-row-container;
|
||||||
@extend .justify-content-end;
|
@extend .justify-content-end;
|
||||||
}
|
}
|
||||||
|
|
||||||
.workspace-body {width: 100%; max-width: $body-width; padding: 24px 0;
|
.workspace-body {
|
||||||
.accordion {box-shadow: 0px 0px 24px 0px #D4D3E380; border: none; border-radius: 12px; margin-bottom: 16px;
|
width: 100%;
|
||||||
.accordion-item {border: none;
|
max-width: $body-width;
|
||||||
.accordion-header {border: none;
|
padding: 24px 0;
|
||||||
.accordion-button {box-shadow: none; padding: 12px}
|
.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 {display: flex; align-items: center; margin: 0 24px 0 0; border: 1px dashed #AEBFFD; border-radius: 3px; flex: 1}
|
.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 {
|
.workspace-item-bar-left {
|
||||||
@extend .flex-row-container;
|
@extend .flex-row-container;
|
||||||
|
|||||||
@ -105,14 +105,23 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="action-bar">
|
<div class="action-bar">
|
||||||
<input-selector :select-list="products" :selected="selectedProduct" @selectedChange="selectedChange" />
|
<input-selector
|
||||||
|
:select-list="products"
|
||||||
|
:selected="selectedProduct"
|
||||||
|
@selectedChange="selectedChange"
|
||||||
|
/>
|
||||||
<div class="upload-contianer">
|
<div class="upload-contianer">
|
||||||
<label class="btn btn-link">
|
<label class="btn btn-link">
|
||||||
<span v-if="!uploadFile">Upload file</span>
|
<span v-if="!uploadFile">Upload file</span>
|
||||||
<span v-if="uploadFile">{{uploadFile.name}}</span>
|
<span v-if="uploadFile">{{ uploadFile.name }}</span>
|
||||||
<input type="file" hidden @change="handleFileUpload"/>
|
<input type="file" hidden @change="handleFileUpload" />
|
||||||
</label>
|
</label>
|
||||||
<svg-icon v-if="uploadFile" icon="delete" class-name="delete-icon" @click.stop="clearFile" />
|
<svg-icon
|
||||||
|
v-if="uploadFile"
|
||||||
|
icon="delete"
|
||||||
|
class-name="delete-icon"
|
||||||
|
@click.stop="clearFile"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex-1" />
|
<div class="flex-1" />
|
||||||
<button
|
<button
|
||||||
@ -176,7 +185,7 @@ export default {
|
|||||||
type: String
|
type: String
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
components: {FreeleapsEditor, InputSelector, SvgIcon },
|
components: { FreeleapsEditor, InputSelector, SvgIcon },
|
||||||
mounted() {
|
mounted() {
|
||||||
this.initProducts()
|
this.initProducts()
|
||||||
this.initiateFromInput()
|
this.initiateFromInput()
|
||||||
@ -208,7 +217,7 @@ export default {
|
|||||||
initProducts() {
|
initProducts() {
|
||||||
WorksapceApi.fetchProducts()
|
WorksapceApi.fetchProducts()
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
this.products = (response.data || []).map(p => p.name)
|
this.products = (response.data || []).map((p) => p.name)
|
||||||
})
|
})
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
this.mnx_backendErrorHandler(error)
|
this.mnx_backendErrorHandler(error)
|
||||||
@ -325,9 +334,16 @@ export default {
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.upload-contianer {display: flex; align-items: center;}
|
.upload-contianer {
|
||||||
.delete-icon {color: $primary; cursor: pointer;
|
display: flex;
|
||||||
&:hover {opacity: .78;}
|
align-items: center;
|
||||||
|
}
|
||||||
|
.delete-icon {
|
||||||
|
color: $primary;
|
||||||
|
cursor: pointer;
|
||||||
|
&:hover {
|
||||||
|
opacity: 0.78;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
.request-issue-container {
|
.request-issue-container {
|
||||||
@extend .flex-colum-container;
|
@extend .flex-colum-container;
|
||||||
|
|||||||
@ -311,10 +311,7 @@ class WorksapceApi {
|
|||||||
formData.append('request_id', request_id)
|
formData.append('request_id', request_id)
|
||||||
formData.append('file', file)
|
formData.append('file', file)
|
||||||
|
|
||||||
const request = backendAxios.post(
|
const request = backendAxios.post('/api/workspace/request/attach-file-for-request', formData, {
|
||||||
'/api/workspace/request/attach-file-for-request',
|
|
||||||
formData,
|
|
||||||
{
|
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'multipart/form-data',
|
'Content-Type': 'multipart/form-data',
|
||||||
Authorization: `Bearer ${jwt}`
|
Authorization: `Bearer ${jwt}`
|
||||||
@ -335,23 +332,18 @@ class WorksapceApi {
|
|||||||
}
|
}
|
||||||
)
|
)
|
||||||
return request
|
return request
|
||||||
|
|
||||||
}
|
}
|
||||||
static fetchAttachedFileAsDownload(request_id, document_id) {
|
static fetchAttachedFileAsDownload(request_id, document_id) {
|
||||||
let jwt = userUtils.getJwtToken()
|
let jwt = userUtils.getJwtToken()
|
||||||
const request = backendAxios.get(
|
const request = backendAxios.get('/api/workspace/request/fetch-attached-file-as-download', {
|
||||||
'/api/workspace/request/fetch-attached-file-as-download',
|
|
||||||
{
|
|
||||||
params: {
|
params: {
|
||||||
request_id: request_id,
|
request_id: request_id,
|
||||||
document_id: document_id,
|
document_id: document_id
|
||||||
},
|
},
|
||||||
responseType: 'blob',
|
responseType: 'blob',
|
||||||
headers: { Authorization: `Bearer ${jwt}` }
|
headers: { Authorization: `Bearer ${jwt}` }
|
||||||
}
|
})
|
||||||
)
|
|
||||||
return request
|
return request
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user