start new media picker

This commit is contained in:
2020-05-14 16:05:33 +02:00
parent 4fd2f2fc23
commit 2b18892796
6 changed files with 294 additions and 5 deletions
@@ -64,7 +64,7 @@
};
export default {
name: 'uiMedia',
name: 'uiMediaOld',
props: {
disabled: {
@@ -0,0 +1,106 @@
<template>
<div class="ui-iconpicker" :class="{'is-disabled': disabled }">
<input ref="input" type="hidden" :value="value" />
<ui-select-button icon="fth-plus" label="@mediapicker.select_text" description="@mediapicker.select_description" @click="pick" :disabled="disabled" />
</div>
</template>
<script>
import PickMediaOverlay from './overlay';
import Overlay from 'zero/services/overlay';
import { each as _each, extend as _extend, debounce as _debounce, isArray as _isArray } from 'underscore';
import Strings from 'zero/services/strings.js';
const TYPES = {
ALL: 'all',
IMAGE: 'image',
VIDEO: 'video',
DOCUMENT: 'document',
OTHER: 'other'
};
const DISPLAY = {
DEFAULT: 'default',
BIG: 'big',
GRID: 'grid'
};
const MAX_FILENAME_LENGTH = 32;
const defaultConfig = {
// maximum media items
limit: 1,
// media type
type: TYPES.ALL,
// how the previews are displayed
display: DISPLAY.DEFAULT,
// whether the select button is disallowed
disallowSelect: false,
// whether file upload is disallowed
disallowUpload: false,
// allowed file extensions
fileExtensions: [],
// maximum file size in MiB
maxFileSize: 10
};
export default {
name: 'uiMediapicker',
props: {
value: {
type: [Array, String],
default: null
},
disabled: {
type: Boolean,
default: false
},
config: {
type: Object,
default: () =>
{
return defaultConfig;
}
},
},
computed: {
},
methods: {
onChange(value)
{
this.$emit('change', value);
this.$emit('input', value);
// TODO this does not trigger the forms dirty flag
},
pick()
{
if (this.disabled)
{
return;
}
let options = _extend({
title: '@iconpicker.title',
closeLabel: '@ui.close',
component: PickMediaOverlay,
model: this.value,
theme: 'dark',
}, typeof this.config === 'object' ? this.config : {});
return Overlay.open(options).then(value =>
{
this.onChange(value);
//this.$refs.input.value = value;
});
}
}
}
</script>
@@ -0,0 +1,183 @@
<template>
<ui-form v-if="!loading" ref="form" class="ui-mediapicker-overlay" v-slot="form">
<h2 class="ui-headline" v-localize="'@media.name'"></h2>
<!--<div class="app-confirm-buttons">
<ui-button v-if="!disabled" type="light" :submit="true" :state="form.state" label="@ui.save"></ui-button>
<ui-button type="light" :label="config.closeLabel" :disabled="loading" @click="config.close"></ui-button>
</div>-->
</ui-form>
</template>
<script>
import { debounce as _debounce, filter as _filter } from 'underscore';
export default {
props: {
model: String,
config: Object
},
data: () => ({
colors: [ 'default', 'gray', 'blue-gray', 'blue', 'teal', 'green', 'lime', 'yellow', 'orange', 'red', 'purple', 'brown' ],
icon: null,
color: null,
query: '',
items: []
}),
watch: {
model()
{
this.init();
},
query()
{
this.debouncedSearch();
}
},
created()
{
this.debouncedSearch = _debounce(this.search, 100);
this.items = this.config.items;
this.init();
},
mounted()
{
let $selected = this.$el.querySelector('.ui-iconpicker-overlay-item.is-active');
if ($selected)
{
let $scrollable = this.$el.querySelector('content');
const offset = $selected.offsetTop - $scrollable.clientHeight * 0.5 - 30;
$scrollable.scrollTop = offset < 0 ? 0 : offset;
}
},
methods: {
confirm()
{
const result = (this.icon || '') + ' ' + (this.color || '').trim();
this.config.confirm(result);
},
select(item)
{
this.icon = item;
this.confirm();
},
selectColor(color)
{
this.color = color === 'default' ? null : 'color-' + color;
},
init()
{
if (!this.model)
{
this.icon = null;
this.color = null;
}
else
{
const parts = this.model.split(' ');
this.icon = parts[0];
this.color = parts.length > 1 ? parts[1] : null;
}
},
search()
{
const query = this.query;
if (!query)
{
this.items = this.config.items;
}
else
{
this.items = _filter(this.config.items, function (item)
{
return item.toLowerCase().indexOf(query) > -1;
})
}
}
}
}
</script>
<style lang="scss">
.ui-iconpicker-overlay content
{
padding-top: 0;
}
.ui-iconpicker-overlay-items
{
display: grid;
grid-gap: 0;
grid-template-columns: repeat(auto-fill, 61px);
align-items: stretch;
}
.ui-iconpicker-overlay-item
{
display: block;
text-align: center;
font-size: 20px;
height: 60px;
border-radius: var(--radius);
/*border: 2px solid transparent;*/
&:hover, &.is-active
{
background: var(--color-box);
box-shadow: 0 0 20px var(--color-shadow);
}
&.is-active
{
//color: var(--color-primary);
}
}
.ui-iconpicker-overlay-search
{
margin-bottom: 20px;
}
.ui-iconpicker-overlay-colors
{
text-align: center;
display: flex;
justify-content: space-between;
align-items: center;
margin: 0 20px;
i
{
display: inline-block;
width: 16px;
height: 16px;
border-radius: 20px;
cursor: pointer;
transition: transform 0.2s ease;
&.is-active
{
transform: scale(1.4);
}
}
}
.ui-iconpicker-overlay-line
{
}
</style>
+1 -1
View File
@@ -30,7 +30,7 @@
</div>
</ui-property>
<ui-property label="@user.fields.avatar" description="@user.fields.avatar_text" :required="true">
<ui-media :config="avatarConfig" v-model="model.avatarId" :disabled="disabled" />
<ui-mediapicker :config="avatarConfig" v-model="model.avatarId" :disabled="disabled" />
</ui-property>
</div>
@@ -297,8 +297,8 @@
},
"mediapicker": {
"select_text": "Select",
"select_description": "from library",
"select_text": "Add media",
"select_description": "Upload or select",
"upload_text": "Upload",
"upload_description": "Upload a new file"
},
+1 -1
View File
@@ -13,7 +13,7 @@ namespace zero.Web
public ZeroMiddleware(RequestDelegate next, IZeroOptions options)
{
Next = next;
Options = options;
Options = options;
}