mirror of
https://github.com/documize/community.git
synced 2025-07-19 13:19:43 +02:00
move documents new UX
This commit is contained in:
parent
bae1245d47
commit
aee9345886
14 changed files with 141 additions and 207 deletions
|
@ -10,11 +10,14 @@
|
|||
// https://documize.com
|
||||
|
||||
import { computed } from '@ember/object';
|
||||
import { A } from "@ember/array"
|
||||
import Component from '@ember/component';
|
||||
|
||||
export default Component.extend({
|
||||
showDeleteDialog: false,
|
||||
selectedDocuments: [],
|
||||
showMoveDialog: false,
|
||||
selectedDocuments: A([]),
|
||||
selectedCaption: 'document',
|
||||
|
||||
showAdd: computed('permissions', 'documents', function() {
|
||||
return this.get('documents.length') === 0 && this.get('permissions.documentAdd');
|
||||
|
@ -26,23 +29,50 @@ export default Component.extend({
|
|||
return this.get('permissions.documentDelete') || this.get('permissions.documentMove');
|
||||
}),
|
||||
|
||||
didReceiveAttrs() {
|
||||
this._super(...arguments);
|
||||
|
||||
let space = this.get('space');
|
||||
let targets = _.reject(this.get('spaces'), {id: space.get('id')});
|
||||
this.set('moveOptions', A(targets));
|
||||
this.set('selectedDocuments', A([]));
|
||||
},
|
||||
|
||||
actions: {
|
||||
onConfirmDeleteDocuments() {
|
||||
onShowDeleteDocuments() {
|
||||
this.set('showDeleteDialog', true);
|
||||
},
|
||||
|
||||
onDeleteDocuments() {
|
||||
this.set('showDeleteDialog', false);
|
||||
let list = this.get('selectedDocuments');
|
||||
|
||||
// list.forEach(d => {
|
||||
// let doc = this.get('documents').findBy('id', d);
|
||||
// doc.set('selected', false);
|
||||
// });
|
||||
this.set('selectedDocuments', A([]));
|
||||
this.set('showDeleteDialog', false);
|
||||
|
||||
this.attrs.onDeleteDocument(list);
|
||||
|
||||
this.set('selectedDocuments', []);
|
||||
return true;
|
||||
},
|
||||
|
||||
onShowMoveDocuments() {
|
||||
this.set('showMoveDialog', true);
|
||||
},
|
||||
|
||||
onMoveDocuments() {
|
||||
let list = this.get('selectedDocuments');
|
||||
let spaces = this.get('spaces');
|
||||
let moveSpaceId = '';
|
||||
|
||||
spaces.forEach(space => {
|
||||
if (space.get('selected')) {
|
||||
moveSpaceId = space.get('id');
|
||||
}
|
||||
});
|
||||
|
||||
if (moveSpaceId === '') return false;
|
||||
|
||||
this.set('showMoveDialog', false);
|
||||
this.set('selectedDocuments', A([]));
|
||||
this.attrs.onMoveDocument(list, moveSpaceId);
|
||||
|
||||
return true;
|
||||
},
|
||||
|
@ -59,7 +89,8 @@ export default Component.extend({
|
|||
list = _.without(list, documentId);
|
||||
}
|
||||
|
||||
this.set('selectedDocuments', list);
|
||||
this.set('selectedCaption', list.length > 1 ? 'documents' : 'document');
|
||||
this.set('selectedDocuments', A(list));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
|
@ -1,95 +0,0 @@
|
|||
// Copyright 2016 Documize Inc. <legal@documize.com>. All rights reserved.
|
||||
//
|
||||
// This software (Documize Community Edition) is licensed under
|
||||
// GNU AGPL v3 http://www.gnu.org/licenses/agpl-3.0.en.html
|
||||
//
|
||||
// You can operate outside the AGPL restrictions by purchasing
|
||||
// Documize Enterprise Edition and obtaining a commercial license
|
||||
// by contacting <sales@documize.com>.
|
||||
//
|
||||
// https://documize.com
|
||||
|
||||
import { computed } from '@ember/object';
|
||||
import Component from '@ember/component';
|
||||
import { inject as service } from '@ember/service';
|
||||
import NotifierMixin from '../../mixins/notifier';
|
||||
import TooltipMixin from '../../mixins/tooltip';
|
||||
import AuthMixin from '../../mixins/auth';
|
||||
|
||||
export default Component.extend(NotifierMixin, TooltipMixin, AuthMixin, {
|
||||
folderService: service('folder'),
|
||||
session: service(),
|
||||
appMeta: service(),
|
||||
pinned: service(),
|
||||
showToolbar: false,
|
||||
folder: {},
|
||||
busy: false,
|
||||
moveFolderId: "",
|
||||
drop: null,
|
||||
pinState : {
|
||||
isPinned: false,
|
||||
pinId: '',
|
||||
newName: ''
|
||||
},
|
||||
deleteSpaceName: '',
|
||||
spaceSettings: computed('permissions', function() {
|
||||
return this.get('permissions.spaceOwner') || this.get('permissions.spaceManage');
|
||||
}),
|
||||
|
||||
didReceiveAttrs() {
|
||||
this._super(...arguments);
|
||||
|
||||
let folder = this.get('folder');
|
||||
let targets = _.reject(this.get('folders'), {id: folder.get('id')});
|
||||
|
||||
this.set('movedFolderOptions', targets);
|
||||
},
|
||||
|
||||
didRender() {
|
||||
this._super(...arguments);
|
||||
this.renderTooltips();
|
||||
},
|
||||
|
||||
renderTooltips() {
|
||||
this.destroyTooltips();
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
this._super(...arguments);
|
||||
|
||||
if (this.get('isDestroyed') || this.get('isDestroying')) return;
|
||||
|
||||
if (is.not.null(this.get('drop'))) {
|
||||
this.get('drop').destroy();
|
||||
this.set('drop', null);
|
||||
}
|
||||
|
||||
this.destroyTooltips();
|
||||
},
|
||||
|
||||
actions: {
|
||||
setMoveFolder(folderId) {
|
||||
this.set('moveFolderId', folderId);
|
||||
|
||||
let folders = this.get('folders');
|
||||
|
||||
folders.forEach(folder => {
|
||||
folder.set('selected', folder.id === folderId);
|
||||
});
|
||||
},
|
||||
|
||||
moveDocuments() {
|
||||
if (this.get("moveFolderId") === "") {
|
||||
return false;
|
||||
}
|
||||
|
||||
this.attrs.onMoveDocument(this.get('moveFolderId'));
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
onStartDocument() {
|
||||
this.attrs.onStartDocument();
|
||||
}
|
||||
}
|
||||
});
|
|
@ -9,25 +9,19 @@
|
|||
//
|
||||
// https://documize.com
|
||||
|
||||
import { all } from 'rsvp';
|
||||
|
||||
import { schedule } from '@ember/runloop';
|
||||
import { gt } from '@ember/object/computed';
|
||||
import Component from '@ember/component';
|
||||
import { inject as service } from '@ember/service';
|
||||
import NotifierMixin from '../../mixins/notifier';
|
||||
import TooltipMixin from '../../mixins/tooltip';
|
||||
import { all } from 'rsvp';
|
||||
import { schedule } from '@ember/runloop';
|
||||
import { gt } from '@ember/object/computed';
|
||||
import AuthMixin from '../../mixins/auth';
|
||||
|
||||
export default Component.extend(NotifierMixin, TooltipMixin, AuthMixin, {
|
||||
export default Component.extend(AuthMixin, {
|
||||
router: service(),
|
||||
documentService: service('document'),
|
||||
folderService: service('folder'),
|
||||
localStorage: service('localStorage'),
|
||||
selectedDocuments: [],
|
||||
hasSelectedDocuments: gt('selectedDocuments.length', 0),
|
||||
hasCategories: gt('categories.length', 0),
|
||||
showStartDocument: false,
|
||||
filteredDocs: [],
|
||||
|
||||
didReceiveAttrs() {
|
||||
|
@ -41,20 +35,6 @@ export default Component.extend(NotifierMixin, TooltipMixin, AuthMixin, {
|
|||
this.set('filteredDocs', []);
|
||||
},
|
||||
|
||||
didRender() {
|
||||
this._super(...arguments);
|
||||
|
||||
if (this.get('rootDocCount') > 0) {
|
||||
this.addTooltip(document.getElementById("uncategorized-button"));
|
||||
}
|
||||
},
|
||||
|
||||
willDestroyElement() {
|
||||
this._super(...arguments);
|
||||
|
||||
this.destroyTooltips();
|
||||
},
|
||||
|
||||
setup() {
|
||||
let categories = this.get('categories');
|
||||
let categorySummary = this.get('categorySummary');
|
||||
|
@ -81,22 +61,42 @@ export default Component.extend(NotifierMixin, TooltipMixin, AuthMixin, {
|
|||
},
|
||||
|
||||
actions: {
|
||||
onMoveDocument(folder) {
|
||||
zonMoveDocumentz(documents, targetSpaceId) {
|
||||
let self = this;
|
||||
let documents = this.get('selectedDocuments');
|
||||
|
||||
documents.forEach(function (documentId) {
|
||||
self.get('documentService').getDocument(documentId).then(function (doc) {
|
||||
doc.set('folderId', folder);
|
||||
doc.set('selected', !doc.get('selected'));
|
||||
doc.set('folderId', targetSpaceId);
|
||||
doc.set('selected', false);
|
||||
self.get('documentService').save(doc).then(function () {
|
||||
self.attrs.onRefresh();
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
this.set('selectedDocuments', []);
|
||||
this.send("showNotification", "Moved");
|
||||
onMoveDocument(documents, targetSpaceId) {
|
||||
let self = this;
|
||||
let promises1 = [];
|
||||
let promises2 = [];
|
||||
|
||||
documents.forEach(function(documentId, index) {
|
||||
promises1[index] = self.get('documentService').getDocument(documentId);
|
||||
});
|
||||
|
||||
all(promises1).then(() => {
|
||||
promises1.forEach(function(doc, index) {
|
||||
doc.then((d) => {
|
||||
d.set('folderId', targetSpaceId);
|
||||
d.set('selected', false);
|
||||
promises2[index] = self.get('documentService').save(d);
|
||||
});
|
||||
});
|
||||
|
||||
all(promises2).then(() => {
|
||||
self.attrs.onRefresh();
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
onDeleteDocument(documents) {
|
||||
|
@ -114,7 +114,6 @@ export default Component.extend(NotifierMixin, TooltipMixin, AuthMixin, {
|
|||
});
|
||||
|
||||
this.set('documents', documents);
|
||||
this.set('selectedDocuments', []);
|
||||
this.attrs.onRefresh();
|
||||
});
|
||||
},
|
||||
|
|
|
@ -18,6 +18,7 @@ export default Component.extend({
|
|||
confirmCaption: 'OK',
|
||||
title: 'Confirm',
|
||||
show: false,
|
||||
buttonType: 'btn-secondary',
|
||||
|
||||
didInsertElement() {
|
||||
this._super(...arguments);
|
||||
|
@ -54,7 +55,8 @@ export default Component.extend({
|
|||
return;
|
||||
}
|
||||
|
||||
if (this.attrs.onAction()) {
|
||||
let result = this.attrs.onAction();
|
||||
if (result) {
|
||||
this.set('show', false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,10 +15,19 @@ import Component from '@ember/component';
|
|||
|
||||
export default Component.extend({
|
||||
nameField: 'category',
|
||||
singleSelect: false,
|
||||
items: [],
|
||||
|
||||
actions: {
|
||||
onToggle(item) {
|
||||
if (this.get('singleSelect')) {
|
||||
let items = this.get('items');
|
||||
items.forEach(item => {
|
||||
set(item, 'selected', false);
|
||||
});
|
||||
this.set('items', items);
|
||||
}
|
||||
|
||||
set(item, 'selected', !item.get('selected'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,11 +33,21 @@ export default Route.extend(AuthenticatedRouteMixin, {
|
|||
model() {
|
||||
this.get('browser').setTitle(this.modelFor('folder').folder.get('name'));
|
||||
|
||||
let folders = this.modelFor('folder').folders;
|
||||
folders.forEach(f => {
|
||||
f.set('selected', false);
|
||||
})
|
||||
|
||||
let documents = this.modelFor('folder').documents;
|
||||
documents.forEach(d => {
|
||||
d.set('selected', false);
|
||||
})
|
||||
|
||||
return hash({
|
||||
folder: this.modelFor('folder').folder,
|
||||
permissions: this.modelFor('folder').permissions,
|
||||
folders: this.modelFor('folder').folders,
|
||||
documents: this.modelFor('folder').documents,
|
||||
folders: folders,
|
||||
documents: documents,
|
||||
templates: this.modelFor('folder').templates,
|
||||
showStartDocument: false,
|
||||
rootDocCount: 0,
|
||||
|
|
|
@ -4,8 +4,8 @@
|
|||
{{toolbar/for-space spaces=model.folders space=model.folder permissions=model.permissions onDeleteSpace=(action 'onDeleteSpace')}}
|
||||
|
||||
{{folder/space-view
|
||||
folders=model.folders
|
||||
folder=model.folder
|
||||
spaces=model.folders
|
||||
space=model.folder
|
||||
templates=model.templates
|
||||
permissions=model.permissions
|
||||
documents=model.documents
|
||||
|
|
|
@ -434,6 +434,24 @@
|
|||
}
|
||||
}
|
||||
|
||||
.button-icon-green {
|
||||
display: inline-block;
|
||||
cursor: default;
|
||||
@include ease-in();
|
||||
|
||||
> i {
|
||||
color: $color-green;
|
||||
font-size: 2rem;
|
||||
@include ease-in();
|
||||
}
|
||||
|
||||
&:hover {
|
||||
> i {
|
||||
color: darken($color-green, 5%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.button-icon-small {
|
||||
> i {
|
||||
font-size: 1.3rem;
|
||||
|
|
|
@ -2,12 +2,11 @@
|
|||
margin: 10px 0;
|
||||
|
||||
> .options {
|
||||
width: 300px;
|
||||
max-height: 400px;
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
overflow: auto;
|
||||
|
||||
> .option {
|
||||
@include ease-in();
|
||||
margin: 0 0 5px 0;
|
||||
padding: 10px 15px;
|
||||
color: $color-gray;
|
||||
|
@ -16,13 +15,12 @@
|
|||
position: relative;
|
||||
|
||||
&:hover {
|
||||
color: $color-white;
|
||||
background-color: $color-gray;
|
||||
color: $color-black;
|
||||
// background-color: $color-primary-light;
|
||||
}
|
||||
|
||||
> .text {
|
||||
width: 220px;
|
||||
overflow: hidden;
|
||||
width: 80%;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
<ul class="documents">
|
||||
{{#each documents key="id" as |document|}}
|
||||
<li class="document {{if document.selected "selected"}}" id="document-{{document.id}}">
|
||||
|
||||
{{#link-to 'document.index' space.id space.slug document.id document.slug}}
|
||||
<div class="title">{{ document.name }}</div>
|
||||
<div class="snippet">{{ document.excerpt }}</div>
|
||||
{{folder/document-tags documentTags=document.tags}}
|
||||
{{/link-to}}
|
||||
|
||||
{{#if hasDocumentActions}}
|
||||
<div class="checkbox" {{action 'selectDocument' document.id}}>
|
||||
{{#if document.selected}}
|
||||
|
@ -15,30 +17,35 @@
|
|||
<i class="material-icons">check_box_outline_blank</i>
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
{{#if document.selected}}
|
||||
<div class="actions">
|
||||
{{#if permissions.documentMove}}
|
||||
<div class="move-documents-button button-icon-blue button-icon-small align-middle">
|
||||
<div class="move-documents-button button-icon-green button-icon-small align-middle" {{action 'onShowMoveDocuments'}}>
|
||||
<i class="material-icons">compare_arrows</i>
|
||||
</div>
|
||||
<div class="button-icon-gap" />
|
||||
{{/if}}
|
||||
{{#if permissions.documentDelete}}
|
||||
<div class="delete-documents-button button-icon-red button-icon-small align-middle" {{action 'onConfirmDeleteDocuments'}}>
|
||||
<div class="delete-documents-button button-icon-red button-icon-small align-middle" {{action 'onShowDeleteDocuments'}}>
|
||||
<i class="material-icons">delete</i>
|
||||
</div>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
{{#ui/ui-confirm-dialog title="Delete Documents" confirmCaption="Delete" show=showDeleteDialog onAction=(action 'onDeleteDocuments')}}
|
||||
<p>Are you sure you want to delete the {{selectedDocuments.length}} selected documents?</p>
|
||||
{{#ui/ui-confirm-dialog title="Delete Documents" confirmCaption="Delete" buttonType="btn-danger" show=showDeleteDialog onAction=(action 'onDeleteDocuments')}}
|
||||
<p>Are you sure you want to delete {{selectedDocuments.length}} {{selectedCaption}}?</p>
|
||||
{{/ui/ui-confirm-dialog}}
|
||||
|
||||
{{#ui/ui-confirm-dialog title="Move Documents" confirmCaption="Move" buttonType="btn-success" show=showMoveDialog onAction=(action 'onMoveDocuments')}}
|
||||
<p>Select space for {{selectedDocuments.length}} {{selectedCaption}}</p>
|
||||
{{ui/ui-list-picker items=moveOptions nameField='name' singleSelect=true}}
|
||||
{{/ui/ui-confirm-dialog}}
|
||||
|
||||
{{#if showAdd}}
|
||||
|
|
|
@ -1,41 +0,0 @@
|
|||
<div class="pull-right hidden-xs hidden-sm">
|
||||
{{#if hasSelectedDocuments}}
|
||||
|
||||
{{#if xxx}}
|
||||
{{#dropdown-dialog target="move-documents-button" position="bottom right" button="Move" color="flat-blue" onAction=(action 'moveDocuments')}}
|
||||
<p class="heading">Select destination space</p>
|
||||
<ul class="move-document-options">
|
||||
{{#each movedFolderOptions as |folder|}}
|
||||
<li class="option {{if folder.selected "selected"}}" {{action 'setMoveFolder' folder.id}}>
|
||||
{{#if folder.selected}}
|
||||
<i class="material-icons">radio_button_checked</i>
|
||||
{{else}}
|
||||
<i class="material-icons">radio_button_unchecked</i>
|
||||
{{/if}}
|
||||
{{ folder.name }}
|
||||
</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/dropdown-dialog}}
|
||||
{{/if}}
|
||||
|
||||
{{#if xxx}}
|
||||
{{#dropdown-dialog target="delete-documents-button" position="bottom right" button="Delete" color="flat-red" onAction=(action 'deleteDocuments')}}
|
||||
<p>Are you sure you want to delete selected documents?</p>
|
||||
<p>There is no undo!</p>
|
||||
{{/dropdown-dialog}}
|
||||
{{/if}}
|
||||
|
||||
{{else}}
|
||||
|
||||
{{#if permissions.documentAdd}}
|
||||
<div class="round-button button-green" id="document-add-button" data-tooltip="Create document" data-tooltip-position="top center" {{action 'onStartDocument'}}>
|
||||
<i class="material-icons">add</i>
|
||||
</div>
|
||||
<div class="button-gap"></div>
|
||||
{{/if}}
|
||||
|
||||
|
||||
{{/if}}
|
||||
</div>
|
||||
|
|
@ -24,19 +24,15 @@
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{{else}}
|
||||
<div class="view-space">
|
||||
<div class="filter-caption">{{documents.length}} documents</div>
|
||||
</div>
|
||||
{{/if}}
|
||||
|
||||
{{folder/documents-list documents=filteredDocs spaces=spaces space=space
|
||||
templates=templates permissions=permissions
|
||||
onDeleteDocument=(action 'onDeleteDocument')}}
|
||||
|
||||
{{#if showStartDocument}}
|
||||
{{folder/start-document folder=folder templates=templates permissions=permissions
|
||||
onImport=(action 'onImport') onHideStartDocument=(action 'onHideStartDocument')}}
|
||||
{{/if}}
|
||||
|
||||
{{folder/space-toolbar folders=folders folder=folder
|
||||
permissions=permissions
|
||||
onMoveDocument=(action 'onMoveDocument')
|
||||
onStartDocument=(action 'onStartDocument')}}
|
||||
onDeleteDocument=(action 'onDeleteDocument') onMoveDocument=(action 'onMoveDocument')}}
|
||||
|
||||
{{folder/start-document folder=space templates=templates permissions=permissions
|
||||
onImport=(action 'onImport') onHideStartDocument=(action 'onHideStartDocument')}}
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-light" data-dismiss="modal" {{action 'onCancel'}}>{{cancelCaption}}</button>
|
||||
<button type="button" class="btn btn-danger font-weight-bold" onclick={{action 'onAction'}}>{{confirmCaption}}</button>
|
||||
<button type="button" class="btn {{buttonType}} font-weight-bold" onclick={{action 'onAction'}}>{{confirmCaption}}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
<ul class="options">
|
||||
{{#each items as |item|}}
|
||||
<li class="option {{if item.selected 'selected'}}" {{action 'onToggle' item}}>
|
||||
<div class="text">{{get item nameField}}</div>
|
||||
<div class="text text-truncate">{{get item nameField}}</div>
|
||||
{{#if item.selected}}
|
||||
<i class="material-icons">check</i>
|
||||
{{/if}}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue