update media library to include shared items
This commit is contained in:
@@ -94,7 +94,7 @@ namespace zero.Core.Api
|
||||
public async Task<ListResult<MediaListItem>> GetListByQuery(MediaListItemQuery query)
|
||||
{
|
||||
bool hasSearch = !query.Search.IsNullOrWhiteSpace();
|
||||
bool isRoot = !query.IsShared && query.FolderId.IsNullOrWhiteSpace();
|
||||
bool isRoot = query.FolderId.IsNullOrWhiteSpace();
|
||||
|
||||
query.SearchFor(entity => entity.Name);
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace zero.Core.Api
|
||||
.OrderByDescending(x => x.IsFolder)
|
||||
.ThenBy(query.OrderBy, query.OrderIsDescending, query.OrderType == ListQueryOrderType.String ? OrderingType.String : OrderingType.Double);
|
||||
|
||||
using IAsyncDocumentSession session = Store.OpenAsyncSession(query.IsShared ? Backoffice.Options.Raven.Database : null);
|
||||
using IAsyncDocumentSession session = Store.OpenAsyncSession();
|
||||
session.Advanced.MaxNumberOfRequestsPerSession = query.PageSize + 1;
|
||||
|
||||
IRavenQueryable<MediaListItem> dbQuery = session.Query<MediaListItem, Media_ByParent>().ProjectInto<MediaListItem>();
|
||||
|
||||
@@ -222,8 +222,6 @@ namespace zero.Core.Collections
|
||||
.OrderByDescending(x => x.IsFolder)
|
||||
.ThenBy(query.OrderBy, query.OrderIsDescending, query.OrderType == ListQueryOrderType.String ? OrderingType.String : OrderingType.Double);
|
||||
|
||||
Session.Advanced.MaxNumberOfRequestsPerSession = query.PageSize + 1;
|
||||
|
||||
IRavenQueryable<MediaListItem> dbQuery = Session.Query<MediaListItem, Media_ByParent>().ProjectInto<MediaListItem>();
|
||||
|
||||
if (!hasSearch || !query.SearchIsGlobal)
|
||||
@@ -233,22 +231,15 @@ namespace zero.Core.Collections
|
||||
|
||||
ListResult<MediaListItem> result = await dbQuery.ToQueriedListAsyncX(query);
|
||||
|
||||
string[] ids = result.Items.Where(x => x.IsFolder).Select(x => x.Id).ToArray();
|
||||
|
||||
List<Media_ByChildren.Result> children = await Session.Query<Media_ByChildren.Result, Media_ByChildren>()
|
||||
.Where(x => x.ParentId.In(ids))
|
||||
.ToListAsync();
|
||||
|
||||
foreach (MediaListItem item in result.Items)
|
||||
{
|
||||
if (item.IsFolder)
|
||||
{
|
||||
item.Children = await Session.Query<MediaListItem, Media_ByParent>().CountAsync(x => x.ParentId == item.Id);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO this is only inserted when we have a core/shared database and a multi-tenancy setup
|
||||
if (isRoot && Database != Context.Options.Raven.Database)
|
||||
{
|
||||
result.Items.Insert(0, new MediaListItem()
|
||||
{
|
||||
Id = "shared",
|
||||
IsFolder = true
|
||||
});
|
||||
item.Children = children.FirstOrDefault(x => x.ParentId == item.Id)?.ChildrenCount ?? 0;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
@@ -0,0 +1,51 @@
|
||||
using Raven.Client.Documents.Indexes;
|
||||
using System.Linq;
|
||||
using zero.Core.Entities;
|
||||
|
||||
namespace zero.Core.Database.Indexes
|
||||
{
|
||||
public class Media_ByChildren : AbstractMultiMapIndexCreationTask<Media_ByChildren.Result>
|
||||
{
|
||||
public class Result : IZeroIdEntity, IZeroDbConventions
|
||||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
public string ParentId { get; set; }
|
||||
|
||||
public int ChildrenCount { get; set; }
|
||||
|
||||
public string[] ChildrenIds { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public Media_ByChildren()
|
||||
{
|
||||
AddMap<IMedia>(items => items.Select(item => new Result()
|
||||
{
|
||||
Id = item.Id,
|
||||
ParentId = item.FolderId,
|
||||
ChildrenCount = 1,
|
||||
ChildrenIds = new string[] { }
|
||||
}));
|
||||
|
||||
AddMap<IMediaFolder>(items => items.Select(item => new Result()
|
||||
{
|
||||
Id = item.Id,
|
||||
ParentId = item.ParentId,
|
||||
ChildrenCount = 1,
|
||||
ChildrenIds = new string[] { }
|
||||
}));
|
||||
|
||||
Reduce = results => results.GroupBy(x => new { x.ParentId }).Select(group => new Result()
|
||||
{
|
||||
Id = null,
|
||||
ParentId = group.Key.ParentId,
|
||||
ChildrenCount = group.Sum(x => x.ChildrenCount),
|
||||
ChildrenIds = group.Select(x => x.Id).ToArray()
|
||||
});
|
||||
|
||||
StoreAllFields(FieldStorage.Yes);
|
||||
Index(x => x.ParentId, FieldIndexing.Exact);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -18,7 +18,9 @@ namespace zero.Core.Database.Indexes
|
||||
Name = item.Name,
|
||||
Image = null,
|
||||
Children = 0,
|
||||
Size = 0
|
||||
Size = 0,
|
||||
IsShared = item.Blueprint != null,
|
||||
AspectRatio = 0
|
||||
}));
|
||||
|
||||
AddMap<IMedia>(items => items.Select(item => new MediaListItem
|
||||
@@ -30,7 +32,9 @@ namespace zero.Core.Database.Indexes
|
||||
Name = item.Name,
|
||||
Image = item.PreviewSource,
|
||||
Children = 0,
|
||||
Size = item.Size
|
||||
Size = item.Size,
|
||||
IsShared = item.Blueprint != null,
|
||||
AspectRatio = item.ImageMeta != null ? (float)item.ImageMeta.Width / item.ImageMeta.Height : 0
|
||||
}));
|
||||
|
||||
StoreAllFields(FieldStorage.Yes);
|
||||
|
||||
@@ -21,5 +21,9 @@ namespace zero.Core.Entities
|
||||
public int Children { get; set; }
|
||||
|
||||
public bool HasTransparency { get; set; }
|
||||
|
||||
public float AspectRatio { get; set; }
|
||||
|
||||
public bool IsShared { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,5 @@
|
||||
public string FolderId { get; set; }
|
||||
|
||||
public bool SearchIsGlobal { get; set; }
|
||||
|
||||
public bool IsShared { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -303,6 +303,12 @@
|
||||
}
|
||||
}
|
||||
|
||||
this.$emit('select', this.selected, this);
|
||||
},
|
||||
|
||||
clearSelection()
|
||||
{
|
||||
this.selected = [];
|
||||
this.$emit('select', this.selected, this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,12 +87,11 @@
|
||||
|
||||
& + .ui-view-box
|
||||
{
|
||||
padding-top: 0;
|
||||
padding-top: 0;
|
||||
}
|
||||
|
||||
.app-tree &
|
||||
{
|
||||
height: 90px;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
}
|
||||
@@ -146,11 +145,6 @@
|
||||
margin: 0;
|
||||
font-size: var(--font-size-l);
|
||||
font-weight: 700;
|
||||
//display: flex;
|
||||
//align-items: center;
|
||||
font-size: var(--font-size-xl);
|
||||
font-weight: 900;
|
||||
//text-transform: uppercase;
|
||||
|
||||
&.is-empty, .-minor
|
||||
{
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="app-overlay-outer" :display="instance.display" v-for="(instance, index) in instances" :key="instance.id" :style="{ transform: instance.display !== 'editor' ? null : 'translateX(' + (editorLength - index - 1) * -60 + 'px)' }">
|
||||
<div class="app-overlay-bg" @click="close(instance)"></div>
|
||||
<dialog open class="app-overlay" :style="{ width: instance.width + 'px' }" :class="'theme-' + instance.theme" :display="instance.display">
|
||||
<component :is="instance.component" :model.sync="instance.model" :config="instance"></component>
|
||||
<component :is="instance.component" :model.sync="instance.model" :config="instance" v-bind="instance"></component>
|
||||
</dialog>
|
||||
</div>
|
||||
</transition-group>
|
||||
@@ -95,6 +95,15 @@
|
||||
font-size: var(--font-size);
|
||||
}
|
||||
|
||||
.app-overlay .ui-loading
|
||||
{
|
||||
position: relative;
|
||||
left: 50%;
|
||||
margin-left: -16px;
|
||||
margin-top: 20px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.app-overlay[display="dialog"] .ui-form-loading
|
||||
{
|
||||
height: 200px;
|
||||
|
||||
@@ -0,0 +1,167 @@
|
||||
<template>
|
||||
<div class="ui-select-overlay">
|
||||
<!--<h2 class="ui-headline" v-localize="configuration.title"></h2>-->
|
||||
<ui-loading v-if="loading" />
|
||||
<div v-if="!loading">
|
||||
<div v-if="list.length && configuration.parent" class="ui-select-overlay-parent">
|
||||
<span v-localize="title"></span>: <strong>{{configuration.parent.name}}</strong>
|
||||
</div>
|
||||
<div class="ui-select-overlay-items">
|
||||
<button type="button" v-for="item in list" class="ui-select-overlay-item" @click="onSelect(item)">
|
||||
<ui-icon class="ui-select-overlay-item-icon" :symbol="item[configuration.iconKey]" :size="22" />
|
||||
<span class="ui-select-overlay-item-text">
|
||||
{{item[configuration.labelKey] | localize}}
|
||||
<span v-if="item[configuration.descriptionKey]" v-localize="item[configuration.descriptionKey]"></span>
|
||||
</span>
|
||||
</button>
|
||||
</div>
|
||||
<ui-message type="error" v-if="!list.length" text="@page.create.nonavailable" />
|
||||
<!--<div class="app-confirm-buttons">
|
||||
<ui-button type="light" :label="config.closeLabel" @click="config.close"></ui-button>
|
||||
</div>-->
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
||||
<script>
|
||||
import ChannelsApi from 'shop/api/channels.js';
|
||||
import Overlay from 'zero/helpers/overlay.js';
|
||||
|
||||
const defaultConfig = {
|
||||
title: '@ui.create',
|
||||
labelKey: 'name',
|
||||
descriptionKey: 'description',
|
||||
iconKey: 'icon',
|
||||
items: null
|
||||
};
|
||||
|
||||
export default {
|
||||
|
||||
props: {
|
||||
config: Object
|
||||
},
|
||||
|
||||
data: () => ({
|
||||
configuration: defaultConfig,
|
||||
list: [],
|
||||
loading: false,
|
||||
disabled: false
|
||||
}),
|
||||
|
||||
|
||||
mounted()
|
||||
{
|
||||
this.configuration = { ...defaultConfig, ...this.config };
|
||||
this.loading = true;
|
||||
this.load();
|
||||
},
|
||||
|
||||
|
||||
methods: {
|
||||
load()
|
||||
{
|
||||
if (typeof this.configuration.items === 'function')
|
||||
{
|
||||
this.configuration.items().then(res =>
|
||||
{
|
||||
this.list = res;
|
||||
this.loading = false;
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
this.list = JSON.parse(JSON.stringify(this.configuration.items));
|
||||
this.loading = false;
|
||||
}
|
||||
},
|
||||
|
||||
onSelect(item)
|
||||
{
|
||||
this.config.confirm(item);
|
||||
},
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.ui-select-overlay
|
||||
{
|
||||
text-align: left;
|
||||
|
||||
.ui-message
|
||||
{
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.ui-select-overlay-parent
|
||||
{
|
||||
margin: 30px 0 -10px 0;
|
||||
border-radius: var(--radius);
|
||||
/*border: 1px solid var(--color-line-light);*/
|
||||
background: var(--color-box-nested);
|
||||
line-height: 1.4;
|
||||
color: var(--color-text-dim);
|
||||
padding: 14px 16px;
|
||||
font-size: var(--font-size);
|
||||
|
||||
strong
|
||||
{
|
||||
color: var(--color-text);
|
||||
}
|
||||
}
|
||||
|
||||
.ui-select-overlay-items
|
||||
{
|
||||
margin: 0 -16px;
|
||||
//margin-top: var(--padding);
|
||||
max-height: 490px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.ui-select-overlay-item
|
||||
{
|
||||
display: grid;
|
||||
width: 100%;
|
||||
grid-template-columns: 70px 1fr auto;
|
||||
gap: 12px;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
color: var(--color-text);
|
||||
padding: 16px;
|
||||
border-radius: var(--radius);
|
||||
|
||||
&:hover, &:focus
|
||||
{
|
||||
background: var(--color-tree-selected);
|
||||
}
|
||||
|
||||
& + .ui-select-overlay-item
|
||||
{
|
||||
margin-top: 2px;
|
||||
}
|
||||
}
|
||||
|
||||
.ui-select-overlay-item-text
|
||||
{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
span
|
||||
{
|
||||
color: var(--color-text-dim);
|
||||
margin-top: 3px;
|
||||
}
|
||||
}
|
||||
|
||||
.ui-select-overlay-item-icon
|
||||
{
|
||||
color: var(--color-text);
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
padding: 20px;
|
||||
border-radius: var(--radius);
|
||||
background: var(--color-bg-shade-3);
|
||||
}
|
||||
</style>
|
||||
@@ -1,24 +1,22 @@
|
||||
<template>
|
||||
<router-link :to="link" class="media-item">
|
||||
<div class="media-item-preview" :class="{'media-pattern': value.image }">
|
||||
<div class="media-item-preview" :class="{'media-pattern': value.image, 'is-covered': covered }">
|
||||
<span class="media-item-check"><ui-icon symbol="fth-check" :size="14" /></span>
|
||||
<img class="media-item-image" v-if="value.image" :src="value.image" />
|
||||
<span class="media-item-icon" v-if="!value.image"><ui-icon :symbol="shared ? 'fth-globe' : (value.isFolder ? 'fth-folder' : 'fth-file')" :size="36" :stroke-width="1.5" /></span>
|
||||
<span class="media-item-icon" v-if="!value.image"><ui-icon :symbol="(value.isFolder ? 'fth-folder' : 'fth-file')" :size="36" :stroke-width="1.5" /></span>
|
||||
</div>
|
||||
<p class="media-item-text" v-if="!shared">
|
||||
<span :title="value.name">{{value.name}}</span>
|
||||
<p class="media-item-text">
|
||||
<span :title="value.name">{{value.name}} <ui-icon symbol="fth-cloud" v-if="value.isShared" :size="15" class="media-item-shared" /></span>
|
||||
<span class="-minor" v-if="!value.isFolder"><br><span v-filesize="value.size"></span></span>
|
||||
<span class="-minor" v-if="value.isFolder"><br><span v-localize="{ key: value.children === 1 ? '@media.child_count_1' : '@media.child_count_x', tokens: { count: value.children }}"></span></span>
|
||||
</p>
|
||||
<p class="media-item-text" v-if="shared">
|
||||
<span :title="value.name">Shared</span>
|
||||
<span class="-minor"><br>Media for all apps</span>
|
||||
</p>
|
||||
</router-link>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'mediaItem',
|
||||
|
||||
props: {
|
||||
value: {
|
||||
type: Object,
|
||||
@@ -33,14 +31,6 @@
|
||||
computed: {
|
||||
link()
|
||||
{
|
||||
if (this.shared)
|
||||
{
|
||||
return {
|
||||
name: 'media',
|
||||
query: { scope: 'shared' }
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
name: this.value.isFolder ? 'media' : 'media-edit',
|
||||
params: {
|
||||
@@ -49,9 +39,9 @@
|
||||
query: this.$route.query
|
||||
};
|
||||
},
|
||||
shared()
|
||||
covered()
|
||||
{
|
||||
return this.value.id === 'shared';
|
||||
return this.value.aspectRatio < 1.2 && this.value.aspectRatio > 0.8;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -72,6 +62,16 @@
|
||||
border-radius: var(--radius);
|
||||
}
|
||||
|
||||
.media-items.is-selecting .media-item
|
||||
{
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.media-items.is-selecting .media-item.is-selected
|
||||
{
|
||||
opacity: 1;
|
||||
}
|
||||
|
||||
.media-item-preview
|
||||
{
|
||||
display: flex;
|
||||
@@ -90,37 +90,41 @@
|
||||
|
||||
.media-item.is-selected .media-item-preview
|
||||
{
|
||||
transform: scale(0.95);
|
||||
border: 3px solid var(--color-primary);
|
||||
//border: 3px solid var(--color-primary);
|
||||
}
|
||||
|
||||
.media-item-image
|
||||
{
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit: cover;
|
||||
object-fit: contain;
|
||||
position: relative;
|
||||
border-radius: var(--radius);
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.media-item-preview.is-covered .media-item-image
|
||||
{
|
||||
object-fit: cover;
|
||||
}
|
||||
|
||||
.media-item-check
|
||||
{
|
||||
display: none;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
border-radius: 20px;
|
||||
border: 5px solid var(--color-bg);
|
||||
position: absolute;
|
||||
z-index: 2;
|
||||
left: -12px;
|
||||
top: -12px;
|
||||
left: -13px;
|
||||
top: -13px;
|
||||
background: var(--color-primary);
|
||||
color: var(--color-primary-text);
|
||||
box-shadow: 1px 1px 0 1px var(--color-shadow);
|
||||
font-size: 11px;
|
||||
|
||||
.is-selected &
|
||||
{
|
||||
display: inline-flex;
|
||||
@@ -129,7 +133,7 @@
|
||||
|
||||
.media-item-text
|
||||
{
|
||||
white-space: nowrap;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
margin: 0;
|
||||
@@ -142,4 +146,12 @@
|
||||
color: var(--color-text-dim);
|
||||
}
|
||||
}
|
||||
|
||||
.media-item-shared
|
||||
{
|
||||
margin-left: .4em;
|
||||
color: var(--color-synchronized);
|
||||
position: relative;
|
||||
top: 2px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -1,39 +1,47 @@
|
||||
<template>
|
||||
<div class="media-content">
|
||||
<ui-header-bar :back-button="!!id || shared" :count="count">
|
||||
<ui-header-bar :back-button="!!id" :count="count">
|
||||
<template v-slot:title>
|
||||
<h2 class="ui-header-bar-title">
|
||||
<router-link :to="{ name: 'media' }" class="media-items-hierarchy-item" v-if="!!id"><i class="fth-home"></i></router-link>
|
||||
<router-link :to="{ name: 'media', params: { id: item.id } }" v-for="(item, index) in hierarchy" :key="item.id" class="media-items-hierarchy-item" v-localize="item.name"></router-link>
|
||||
<span v-for="(item, index) in hierarchy" :key="item.id" class="media-items-hierarchy-item">
|
||||
<router-link :to="{ name: 'media', params: { id: item.id } }" v-localize="item.name"></router-link>
|
||||
<ui-icon v-if="index < hierarchy.length - 1" symbol="fth-chevron-right" />
|
||||
</span>
|
||||
</h2>
|
||||
</template>
|
||||
<template>
|
||||
<ui-search v-if="!selecting" v-model="gridConfig.search" class="onbg" />
|
||||
<ui-dropdown v-if="!!id && !selecting" align="right" :disabled="!!gridConfig.search">
|
||||
<template v-slot:button>
|
||||
<ui-button type="light onbg" label="Folder" caret="down" :disabled="!!gridConfig.search" />
|
||||
</template>
|
||||
<ui-dropdown-button label="@ui.edit.title" icon="fth-edit-2" @click="edit(current, true)" />
|
||||
<ui-dropdown-button label="@ui.move.title" icon="fth-corner-down-right" @click="move(current, true)" />
|
||||
<ui-dropdown-separator />
|
||||
<ui-dropdown-button label="@ui.delete" icon="fth-trash" @click="remove(current, true)" />
|
||||
</ui-dropdown>
|
||||
<ui-dropdown v-if="selecting" align="right">
|
||||
<template v-slot:button>
|
||||
<ui-button type="light onbg" :label="selectedText" caret="down" />
|
||||
</template>
|
||||
<!--<slot name="actions"></slot>-->
|
||||
</ui-dropdown>
|
||||
<ui-button v-if="!selecting" type="primary" label="Add folder" @click="addFolder(id)" />
|
||||
<div v-if="!!id && !selecting" type="button" class="ui-button has-state type-primary state-default has-icon">
|
||||
<span class="ui-button-text" v-localize="'Add file'"></span>
|
||||
<input class="media-item-upload" type="file" multiple @change="onUpload" />
|
||||
</div>
|
||||
<template v-if="!selecting">
|
||||
<ui-search v-model="gridConfig.search" class="onbg" />
|
||||
<ui-dropdown v-if="!!id" align="right" :disabled="!!gridConfig.search">
|
||||
<template v-slot:button>
|
||||
<ui-button type="light onbg" label="@media.actions.folderdropdown" caret="down" :disabled="!!gridConfig.search" />
|
||||
</template>
|
||||
<ui-dropdown-button label="@ui.edit.title" icon="fth-edit-2" @click="edit(current, true)" />
|
||||
<ui-dropdown-button label="@ui.move.title" icon="fth-corner-down-right" @click="move(current, true)" />
|
||||
<ui-dropdown-separator />
|
||||
<ui-dropdown-button label="@ui.delete" icon="fth-trash" @click="remove(current, true)" />
|
||||
</ui-dropdown>
|
||||
<ui-button type="primary" label="@ui.add" @click="add" />
|
||||
<!--<div v-if="!!id" type="button" class="ui-button has-state type-primary state-default has-icon">
|
||||
<span class="ui-button-text" v-localize="'@media.actions.addfile'"></span>
|
||||
<input class="media-item-upload" type="file" multiple @change="onUpload" />
|
||||
</div>-->
|
||||
</template>
|
||||
<template v-if="selecting">
|
||||
<ui-button type="blank" label="@media.selection.clear" @click="clearSelection" />
|
||||
<ui-dropdown align="right">
|
||||
<template v-slot:button>
|
||||
<ui-button type="primary" :label="selectedText" caret="down" />
|
||||
</template>
|
||||
<ui-dropdown-button label="@ui.move.title" icon="fth-corner-down-right" @click="move(current, true)" />
|
||||
<ui-dropdown-button label="@ui.delete" icon="fth-trash" @click="remove(current, true)" />
|
||||
</ui-dropdown>
|
||||
</template>
|
||||
</template>
|
||||
</ui-header-bar>
|
||||
|
||||
<div class="ui-view-box">
|
||||
<div class="media-items">
|
||||
<div class="media-items" :class="{ 'is-selecting': selecting }">
|
||||
<ui-datagrid ref="grid" v-model="gridConfig" @select="onSelected" @count="count = $event">
|
||||
<template v-slot:actions="props">
|
||||
<ui-dropdown-button v-if="props.item && props.item.isFolder" label="@ui.open.title" icon="fth-arrow-right" @click="goToFolder(props.item.id)" />
|
||||
@@ -61,6 +69,7 @@
|
||||
import UploadStatusOverlay from './overlays/upload-status.vue';
|
||||
import EventHub from 'zero/helpers/eventhub.js';
|
||||
import Notification from 'zero/helpers/notification.js';
|
||||
import SelectOverlay from 'zero/components/overlays/select-overlay.vue';
|
||||
import { each as _each, extend as _extend, debounce as _debounce, isArray as _isArray } from 'underscore';
|
||||
|
||||
export default {
|
||||
@@ -88,10 +97,6 @@
|
||||
selecting()
|
||||
{
|
||||
return this.selectedCount > 0;
|
||||
},
|
||||
shared()
|
||||
{
|
||||
return this.$route.query.scope === 'shared';
|
||||
}
|
||||
},
|
||||
|
||||
@@ -106,6 +111,12 @@
|
||||
}
|
||||
},
|
||||
|
||||
//beforeRouteUpdate(to, from, next)
|
||||
//{
|
||||
// this.clearSelection();
|
||||
// next();
|
||||
//},
|
||||
|
||||
created()
|
||||
{
|
||||
this.gridConfig.items = this.getItems;
|
||||
@@ -116,6 +127,7 @@
|
||||
|
||||
initialize()
|
||||
{
|
||||
//this.clearSelection();
|
||||
//if (!this.scope)
|
||||
//{
|
||||
// this.$route.params.scope = 'local';
|
||||
@@ -134,11 +146,10 @@
|
||||
query.search = this.gridConfig.search;
|
||||
query.folderId = this.$route.params.id;
|
||||
query.searchIsGlobal = true;
|
||||
query.isShared = this.shared;
|
||||
|
||||
this.getFolderHierarchy(query.folderId, !!query.search);
|
||||
|
||||
return MediaApi.getListByQuery(query).then(response => // .scope(this.shared)
|
||||
return MediaApi.getListByQuery(query).then(response =>
|
||||
{
|
||||
return Promise.resolve(response);
|
||||
});
|
||||
@@ -166,8 +177,12 @@
|
||||
return;
|
||||
}
|
||||
|
||||
MediaFolderApi.getHierarchy(id, this.shared).then(res =>
|
||||
MediaFolderApi.getHierarchy(id).then(res =>
|
||||
{
|
||||
res.splice(0, 0, {
|
||||
id: null,
|
||||
name: '@media.list'
|
||||
});
|
||||
this.hierarchy = res;
|
||||
this.current = res[res.length - 1];
|
||||
});
|
||||
@@ -184,6 +199,36 @@
|
||||
},
|
||||
|
||||
|
||||
// shows add overlay
|
||||
add()
|
||||
{
|
||||
//< !--< div v -if= "!!id" type = "button" class="ui-button has-state type-primary state-default has-icon" >
|
||||
// <span class="ui-button-text" v-localize="'@media.actions.addfile'"></span>
|
||||
// <input class="media-item-upload" type="file" multiple @change="onUpload" />
|
||||
// </div > -->
|
||||
Overlay.open({
|
||||
component: SelectOverlay,
|
||||
width: 480,
|
||||
theme: 'dark',
|
||||
items: [
|
||||
{
|
||||
name: '@media.actions.addfile',
|
||||
description: '@media.actions.addfile_text',
|
||||
icon: 'fth-upload-cloud'
|
||||
},
|
||||
{
|
||||
name: '@media.actions.addfolder',
|
||||
description: '@media.actions.addfolder_text',
|
||||
icon: 'fth-folder-plus'
|
||||
}
|
||||
]
|
||||
}).then(item =>
|
||||
{
|
||||
|
||||
}, () => { });
|
||||
},
|
||||
|
||||
|
||||
// adds a new folder
|
||||
addFolder(parentId)
|
||||
{
|
||||
@@ -322,6 +367,15 @@
|
||||
}
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
clearSelection()
|
||||
{
|
||||
if (this.$refs.grid)
|
||||
{
|
||||
this.$refs.grid.clearSelection();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -365,25 +419,22 @@
|
||||
margin: 0;
|
||||
font-size: var(--font-size-l);
|
||||
font-weight: 400;
|
||||
color: var(--color-text-dim);
|
||||
&:last-child
|
||||
color: var(--color-text-dim);
|
||||
|
||||
{
|
||||
font-weight: 700;
|
||||
color: var(--color-text);
|
||||
}
|
||||
a
|
||||
{
|
||||
color: var(--color-text-dim);
|
||||
}
|
||||
|
||||
& + .media-items-hierarchy-item:before
|
||||
{
|
||||
content: '/';
|
||||
margin: 0 0.5em;
|
||||
color: var(--color-text-dim);
|
||||
font-weight: 400;
|
||||
}
|
||||
&:last-child a
|
||||
{
|
||||
font-weight: 700;
|
||||
color: var(--color-text);
|
||||
}
|
||||
|
||||
&:hover
|
||||
{
|
||||
color: var(--color-text);
|
||||
}
|
||||
a:hover
|
||||
{
|
||||
color: var(--color-text);
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="media-upload">
|
||||
|
||||
<div v-if="entity.source" class="media-upload-preview" :data-type="entity.type">
|
||||
<span ref="image" v-if="entity.type === 'image'" class="media-upload-preview-image media-bg-pattern" @click="setFocalPoint" @dblclick="entity.focalPoint = null">
|
||||
<span ref="image" v-if="entity.type === 'image'" class="media-upload-preview-image media-pattern" @click="setFocalPoint" @dblclick="entity.focalPoint = null">
|
||||
<span class="media-upload-preview-focal-point" :style="getFocalPointStyle(entity.focalPoint)"></span>
|
||||
<img :src="entity.previewSource" :alt="entity.name" />
|
||||
</span>
|
||||
@@ -125,7 +125,6 @@
|
||||
{
|
||||
padding: 0;
|
||||
border-radius: var(--radius);
|
||||
background: var(--color-bg-dim);
|
||||
display: inline-block;
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
|
||||
@@ -591,6 +591,16 @@
|
||||
"name": "Media",
|
||||
"addfolder": "Add a new folder",
|
||||
"editfolder": "Edit folder",
|
||||
"actions": {
|
||||
"folderdropdown": "Folder",
|
||||
"addfolder": "Create folder",
|
||||
"addfolder_text": "Adds a new folder in the current parent folder",
|
||||
"addfile": "Upload files",
|
||||
"addfile_text": "Add one or more files to the current filter"
|
||||
},
|
||||
"selection": {
|
||||
"clear": "Clear selection"
|
||||
},
|
||||
"fields": {
|
||||
"foldername_placeholder": "Enter a name ...",
|
||||
"caption": "Caption",
|
||||
|
||||
Reference in New Issue
Block a user