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