refactor Components, add newRoom.vue/userSearch.vue/popup.vue/overlay.vue/imageViewer.vue, some design changes
parent
c0d9de4fcf
commit
18bb86a7a9
@ -0,0 +1,41 @@
|
|||||||
|
<template>
|
||||||
|
<div class="viewer" ref="images">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import Viewer from 'viewerjs';
|
||||||
|
import 'viewerjs/dist/viewer.css';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'imageViewer',
|
||||||
|
props: {
|
||||||
|
options: Object
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
new Viewer(this.$refs.images, this.options||{
|
||||||
|
inline: false,
|
||||||
|
navbar: false,
|
||||||
|
button: true,
|
||||||
|
toolbar: {
|
||||||
|
reset: {show: 1, size: 'large'},
|
||||||
|
zoomIn: {show: 1, size: 'large'},
|
||||||
|
zoomOut: {show: 1, size: 'large'},
|
||||||
|
rotateLeft: {show: 1, size: 'large'},
|
||||||
|
rotateRight: {show: 1, size: 'large'}
|
||||||
|
},
|
||||||
|
zoomRatio: 0.25,
|
||||||
|
minZoomRatio: 0.5,
|
||||||
|
maxZoomRatio: 10,
|
||||||
|
toggleOnDblclick: true,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.viewer{
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,24 @@
|
|||||||
|
<template>
|
||||||
|
<div v-if="this.$slots.default" class="overlay">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'overlay'
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.overlay{
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
|
background-color: #111d;
|
||||||
|
user-select: none;
|
||||||
|
z-index: 50;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,91 @@
|
|||||||
|
<template>
|
||||||
|
<div class="popup">
|
||||||
|
<div class="scrollContainer" ref="scrollContainer">
|
||||||
|
<div class="content">
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
<icon v-if="onClose" class="closeBtn" @click.native="onClose(false)" ic="./sym/ic_close_white.svg" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import icon from '@/components/layout/icon';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'popup',
|
||||||
|
components: {
|
||||||
|
icon
|
||||||
|
},
|
||||||
|
props: {
|
||||||
|
onClose: Function
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
calcMaxHeight(){
|
||||||
|
this.$refs.scrollContainer.style.maxHeight = `calc(${this.$el.parentElement.clientHeight}px - 4rem`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
this.calcMaxHeight();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.popup{
|
||||||
|
position: relative;
|
||||||
|
top: 5rem;
|
||||||
|
width: calc(100% - 4rem);
|
||||||
|
max-width: 30rem;
|
||||||
|
min-height: 10rem;
|
||||||
|
background-color: #1d1d1d;
|
||||||
|
box-shadow: 6px 6px 20px #111;
|
||||||
|
border-radius: 1rem;
|
||||||
|
z-index: 30;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
.scrollContainer{
|
||||||
|
position: relative;
|
||||||
|
max-height: 30rem;
|
||||||
|
top: 0;
|
||||||
|
width: calc(100% - 2rem);
|
||||||
|
padding: 0 1rem 0 1rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
@media (max-width: 30rem) {
|
||||||
|
.popup{
|
||||||
|
transform: unset;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.scrollContainer{
|
||||||
|
max-height: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@media (max-height: 40rem) {
|
||||||
|
.popup{
|
||||||
|
top: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
.scrollContainer{
|
||||||
|
max-height: 100% !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.closeBtn{
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
right: 0;
|
||||||
|
background-color: #0000;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
.content{
|
||||||
|
position: relative;
|
||||||
|
padding: 1rem 0 1rem 0;
|
||||||
|
width: 100%;
|
||||||
|
height: auto;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,33 @@
|
|||||||
|
<template>
|
||||||
|
<popup :on-close="callback">
|
||||||
|
<h2>{{title}}</h2>
|
||||||
|
<p>{{question}}</p>
|
||||||
|
<textbtn :text="action" @click.native="callback(true)"/>
|
||||||
|
<textbtn text="Cancel" @click.native="callback(false)" class="outline"/>
|
||||||
|
</popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import textbtn from '@/components/layout/textbtn';
|
||||||
|
import popup from '@/components/layout/popup';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'popupQuestion',
|
||||||
|
components: {
|
||||||
|
textbtn,
|
||||||
|
popup
|
||||||
|
},
|
||||||
|
props:{
|
||||||
|
title: String,
|
||||||
|
question: String,
|
||||||
|
callback: Function,
|
||||||
|
action: {
|
||||||
|
type: String,
|
||||||
|
default: 'Apply'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
</style>
|
@ -0,0 +1,55 @@
|
|||||||
|
<template>
|
||||||
|
<button class="btn">
|
||||||
|
<div class="btnText">{{text}}</div>
|
||||||
|
</button>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: "textbtn",
|
||||||
|
props:{
|
||||||
|
text: String,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.btn{
|
||||||
|
cursor: pointer;
|
||||||
|
border: none;
|
||||||
|
height: 2.5rem;
|
||||||
|
padding-left: 1.5rem;
|
||||||
|
padding-right: 1.5rem;
|
||||||
|
background-color: var(--primary);
|
||||||
|
box-shadow: var(--shadow100);
|
||||||
|
border-radius: 1rem;
|
||||||
|
margin: 0.2rem;
|
||||||
|
}
|
||||||
|
.btn.primary{
|
||||||
|
background-color: var(--primary);
|
||||||
|
}
|
||||||
|
.btn.underline{
|
||||||
|
background-color: unset;
|
||||||
|
text-decoration: underline;
|
||||||
|
color: #fff;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
.btn.rounded{
|
||||||
|
border-radius: 1.25rem;
|
||||||
|
}
|
||||||
|
.btn.outline{
|
||||||
|
background-color: unset;
|
||||||
|
box-shadow: none;
|
||||||
|
text-decoration: underline;
|
||||||
|
border: #fff solid 1px;
|
||||||
|
}
|
||||||
|
.btn.squared{
|
||||||
|
border-radius: 0;
|
||||||
|
}
|
||||||
|
.btnText {
|
||||||
|
position: relative;
|
||||||
|
font-size: 1rem;
|
||||||
|
color:#fff;
|
||||||
|
font-family:Arial, "lucida console", sans-serif;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,86 @@
|
|||||||
|
<template>
|
||||||
|
<popup :on-close="callback">
|
||||||
|
<h2>New room</h2>
|
||||||
|
<input v-model="name" type="text" placeholder="Room name">
|
||||||
|
<select v-model="access">
|
||||||
|
<option>private</option>
|
||||||
|
<option>public</option>
|
||||||
|
</select><br>
|
||||||
|
<textarea v-model="description" placeholder="Room description"></textarea><br>
|
||||||
|
<h3>Add User</h3>
|
||||||
|
<user-search :filter="prop=>!users.find(temp=>temp===prop)" :callback="addUser" class="userSearch"/>
|
||||||
|
<h3 v-if="users.length">User</h3>
|
||||||
|
<div>
|
||||||
|
<user-list-element
|
||||||
|
v-for="user in users"
|
||||||
|
:user="user" :key="user.userId"
|
||||||
|
@click.native="removeUser(user)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<textbtn :text="action" @click.native="createRoom({name, users, description, access}).then(callback)"/>
|
||||||
|
<textbtn text="Cancel" @click.native="callback(false)" class="outline"/>
|
||||||
|
<overlay v-if="loading"><throbber text="loading"/></overlay>
|
||||||
|
</popup>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import textbtn from '@/components/layout/textbtn';
|
||||||
|
import popup from '@/components/layout/popup';
|
||||||
|
import userListElement from '@/components/matrix/userListElement';
|
||||||
|
import UserSearch from '@/components/matrix/userSearch';
|
||||||
|
import overlay from '@/components/layout/overlay';
|
||||||
|
import throbber from '@/components/layout/throbber';
|
||||||
|
import {createRoom} from '@/lib/matrixUtils';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'popupQuestion',
|
||||||
|
components: {
|
||||||
|
UserSearch,
|
||||||
|
textbtn,
|
||||||
|
popup,
|
||||||
|
userListElement,
|
||||||
|
overlay,
|
||||||
|
throbber
|
||||||
|
},
|
||||||
|
props:{
|
||||||
|
props: Object,
|
||||||
|
callback: Function,
|
||||||
|
action: {
|
||||||
|
type: String,
|
||||||
|
default: 'Apply'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data(){
|
||||||
|
return{
|
||||||
|
name: this.props.name,
|
||||||
|
description: this.props.description,
|
||||||
|
users: [],
|
||||||
|
loading: false,
|
||||||
|
access: 'private'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
addUser(user){
|
||||||
|
if (this.users.find(tmp => tmp === user)) return;
|
||||||
|
this.users.push(user);
|
||||||
|
this.userSearch = '';
|
||||||
|
},
|
||||||
|
removeUser(user){
|
||||||
|
this.users = this.users.filter(tmp => tmp !== user);
|
||||||
|
},
|
||||||
|
async createRoom(props){
|
||||||
|
this.loading = true;
|
||||||
|
return await createRoom(props);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
textarea{
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
.userSearch{
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,78 @@
|
|||||||
|
<template>
|
||||||
|
<div class="userSearch">
|
||||||
|
<div v-if="userSearch" class="box">
|
||||||
|
<div class="results">
|
||||||
|
<user-list-element
|
||||||
|
v-for="user in matrix.client.getUsers()
|
||||||
|
.filter(prop=>matchResults(prop.displayName, userSearch)||matchResults(prop.userId, userSearch))
|
||||||
|
.filter(filter)
|
||||||
|
.slice(0,16)"
|
||||||
|
:user="user" :key="user.userId"
|
||||||
|
@click.native="callback(user); userSearch='';"
|
||||||
|
:compact="true"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<div class="filler"></div>
|
||||||
|
</div>
|
||||||
|
<input v-model="userSearch" type="text" placeholder="search" class="input">
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import userListElement from '@/components/matrix/userListElement';
|
||||||
|
import {matrix} from '@/main';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'userSearch',
|
||||||
|
components:{
|
||||||
|
userListElement
|
||||||
|
},
|
||||||
|
props:{
|
||||||
|
callback: Function,
|
||||||
|
filter: Function
|
||||||
|
},
|
||||||
|
methods:{
|
||||||
|
matchResults(prop, search){
|
||||||
|
return prop.toLowerCase().includes(search.toLowerCase().trim());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
data(){
|
||||||
|
return {
|
||||||
|
matrix,
|
||||||
|
userSearch: ''
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.userSearch{
|
||||||
|
position: relative;
|
||||||
|
background-color: #1d1d1d;
|
||||||
|
height: 2.2rem;
|
||||||
|
width: 14rem;
|
||||||
|
margin: 0.2rem;
|
||||||
|
}
|
||||||
|
.input{
|
||||||
|
position: absolute;
|
||||||
|
width: 13rem;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.filler{
|
||||||
|
height: 2.5rem;
|
||||||
|
}
|
||||||
|
.box{
|
||||||
|
position: absolute;
|
||||||
|
bottom: -0.4rem;
|
||||||
|
left: -0.4rem;
|
||||||
|
background-color: var(--grey500);
|
||||||
|
box-shadow: var(--shadow200);
|
||||||
|
width: calc(100% + 0.8rem);
|
||||||
|
border-radius: 0.6rem;
|
||||||
|
}
|
||||||
|
.results{
|
||||||
|
max-height: 10.5rem;
|
||||||
|
overflow-y: auto;
|
||||||
|
overflow-x: hidden;
|
||||||
|
}
|
||||||
|
</style>
|
@ -1,34 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="questionBox">
|
|
||||||
<p class="text">{{question}}</p>
|
|
||||||
<textbtn text="yes" @click.native="callback(true)"/>
|
|
||||||
<textbtn text="no" @click.native="callback(false)"/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import textbtn from '@/components/textbtn';
|
|
||||||
export default {
|
|
||||||
name: 'popupQuestion',
|
|
||||||
components: {textbtn},
|
|
||||||
props:{
|
|
||||||
question: String,
|
|
||||||
callback: Function
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped lang="scss">
|
|
||||||
.questionBox{
|
|
||||||
position: absolute;
|
|
||||||
width: auto;
|
|
||||||
background-color: #1d1d1d;
|
|
||||||
box-shadow: 6px 6px 10px #111;
|
|
||||||
border-radius: 1.5rem;
|
|
||||||
.text{
|
|
||||||
position: relative;
|
|
||||||
width: 100%;
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,34 +0,0 @@
|
|||||||
<template>
|
|
||||||
<button class="btn">
|
|
||||||
<div class="btnText">{{text}}</div>
|
|
||||||
</button>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
export default {
|
|
||||||
name: "textbtn",
|
|
||||||
props:{
|
|
||||||
text: String
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.btn{
|
|
||||||
cursor: pointer;
|
|
||||||
border: none;
|
|
||||||
height: 2.5rem;
|
|
||||||
padding-left: 2rem;
|
|
||||||
padding-right: 2rem;
|
|
||||||
background-color: #00BCD4;
|
|
||||||
box-shadow: 3px 3px 10px #222;
|
|
||||||
border-radius: 1.25rem;
|
|
||||||
margin: 1rem;
|
|
||||||
}
|
|
||||||
.btnText {
|
|
||||||
position: relative;
|
|
||||||
font-size: 1.4rem;
|
|
||||||
color:#fff;
|
|
||||||
font-family:Arial, "lucida console", sans-serif;
|
|
||||||
}
|
|
||||||
</style>
|
|
@ -1,36 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="overlay">
|
|
||||||
<throbber :text="text" class="throbber"/>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script>
|
|
||||||
import throbber from "@/components/throbber";
|
|
||||||
export default {
|
|
||||||
name: "throbberOverlay",
|
|
||||||
components:{
|
|
||||||
throbber
|
|
||||||
},
|
|
||||||
props: {
|
|
||||||
text: String
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style scoped>
|
|
||||||
.throbber{
|
|
||||||
position: absolute;
|
|
||||||
top: 50%;
|
|
||||||
left: 50%;
|
|
||||||
transform: translate(-50%, -50%);
|
|
||||||
}
|
|
||||||
.overlay{
|
|
||||||
position: fixed;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
height: 100%;
|
|
||||||
width: 100%;
|
|
||||||
background-color: #111d;
|
|
||||||
user-select: none;
|
|
||||||
}
|
|
||||||
</style>
|
|
Loading…
Reference in New Issue