Skip to content

Commit c5c53a4

Browse files
authored
Merge pull request #9 from themexpert/context-menu
Context menu Branch Merge
2 parents 5c94739 + 030be16 commit c5c53a4

File tree

16 files changed

+404
-91
lines changed

16 files changed

+404
-91
lines changed

.gitignore

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,4 @@
33
/dist/
44
/node_modules/
55
/yarn.lock
6-
/mix-manifest.json
7-
/src/plugins
6+
/mix-manifest.json

build.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import initFM from './src';
2+
import ImagePreview from "./src/plugins/ImagePreview";
23

34
window.openFileManager = initFM('/react-filemanager-server/', document.querySelector('.app'));
45

@@ -8,3 +9,5 @@ window.openFileManager = initFM('/react-filemanager-server/', document.querySele
89
link.href = href;
910
document.head.insertBefore(link, document.head.firstChild);
1011
});
12+
13+
window.ReactFileManager.registerPlugin(ImagePreview);

index.html

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,10 @@
99
</head>
1010
<body>
1111
<button onclick="openFileManager(callback)">Open File Manager</button>
12-
<div class="app"></div>
12+
<div class="app">
13+
<p>Hello</p>
14+
</div>
15+
<p>Hello</p>
1316
<script src="dist/build.js"></script>
1417
<script>
1518
function callback(list) {

src/core/PluginContainer.jsx

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,18 @@ import React, {Component} from 'react'
22
import {inject, observer} from "mobx-react";
33

44
const PluginContainer = class PluginContainer extends Component {
5-
constructor(props) {
6-
super(props);
7-
}
5+
constructor(props) {
6+
super(props);
7+
}
88

9-
render = () => {
10-
const store = this.props.fm_store;
11-
if(!store.plugin.component)
12-
return null;
13-
return (
14-
<store.plugin.component key={store.plugin.key} store={store}/>
15-
);
16-
};
9+
render = () => {
10+
const store = this.props.fm_store;
11+
if (!store.plugin.component)
12+
return null;
13+
return (
14+
<store.plugin.component key={store.plugin.key} store={store}/>
15+
);
16+
};
1717
};
1818

1919
export default inject("fm_store")(observer(PluginContainer))

src/core/file-manager.jsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ const FileManager = class FileManager extends Component {
2626
this.store.server = props.server;
2727
}
2828

29+
setMountPoint = dom_el => {
30+
this.store.mount_point = dom_el;
31+
};
32+
2933
openFileManager = (cb, config) => {
3034
this.store.openFileManager(cb, config);
3135
};
@@ -51,6 +55,7 @@ const FileManager = class FileManager extends Component {
5155
footer={null}
5256
onCancel={this.handleCancel}
5357
width={window.innerWidth/1.5}
58+
getContainer={this.store.mount_point}
5459
>
5560
{this.store.tabs.length ? <Tabs defaultActiveKey={this.store.tabs[0].hook} prefixCls="qxui-tabs">
5661
{this.store.tabs

src/core/file_types.js

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
module.exports = {
2+
text: ['txt', 'html', 'css', 'js', 'php', 'log', 'inc'],
3+
image: ['png', 'jpg', 'jpeg', 'bmp', 'webm', 'gif', 'svg'],
4+
video: ['mkv', 'flv', 'mp4', 'vob', '3gp'],
5+
audio: ['mp3', 'aac', 'ogg'],
6+
};

src/core/fm/action/index.jsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ const FMAction = class FMAction extends Component {
128128

129129
<Button icon="swap" onClick={this.props.fm_store.selectPlugin('move')} disabled={!selected}>Move</Button>
130130

131-
<Button icon="delete" onClick={this.showDeleteConfirmation} disabled={!selected}></Button>
131+
<Button icon="delete" onClick={this.showDeleteConfirmation} disabled={!selected}/>
132132

133133
<Button icon="reload" onClick={this.props.fm_store.refresh}>Refresh</Button>
134134

src/core/fm/content/index.jsx

Lines changed: 129 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -6,66 +6,148 @@ import throttle from 'debounce';
66
import Button from 'antd/lib/button'
77

88
import {viewport} from "../../Helper";
9+
import ContextMenu from "../context_menu";
910
const view_size = viewport();
1011

11-
const FMContent = class FMContent extends Component {
12-
constructor(props) {
13-
super(props);
12+
import file_types from '../../file_types';
1413

15-
this.props.fm_store.working_dir = '/';
16-
}
14+
const FMContent = class FMContent extends Component {
15+
constructor(props) {
16+
super(props);
1717

18-
componentDidMount = () => {
19-
document.getElementById('fm-content-holder').addEventListener('scroll', this.onScroll);
18+
this.state = {
19+
menu_items: [],
2020
};
2121

22-
componentWillUnmount = () => {
23-
document.getElementById('fm-content-holder').removeEventListener('scroll', this.onScroll);
24-
};
22+
this.props.fm_store.working_dir = '/';
23+
}
2524

26-
onContextMenu = e => {
27-
e.preventDefault();
28-
e.stopPropagation();
25+
componentDidMount = () => {
26+
document.getElementById('fm-content-holder').addEventListener('scroll', this.onScroll);
27+
};
2928

30-
console.log("Context Menu Content");
31-
};
29+
componentWillUnmount = () => {
30+
document.getElementById('fm-content-holder').removeEventListener('scroll', this.onScroll);
31+
};
3232

33-
onScroll = throttle(e => {
34-
const el = document.getElementById('fm-content-holder');
35-
const content = el.querySelector('#fm-content');
36-
const scrollTop = el.scrollTop;
37-
const offsetHeight = el.offsetHeight;
38-
const scrollHeight = content.scrollHeight;
33+
onContextMenu = (e, item) => {
34+
e.preventDefault();
35+
e.stopPropagation();
3936

40-
if (scrollHeight - offsetHeight < scrollTop + 10) {
41-
this.props.fm_store.fetch(true);
42-
}
43-
}, 100);
37+
const ext = item ? (item.is_dir ? 'dir' : item.extension) : 'screen';
4438

45-
hasMore = () => {
46-
return this.props.fm_store.list.length < this.props.fm_store.data.total;
47-
};
39+
const menu_items = this.getFilteredMenuItems(ext).map(menu_item => {
40+
const {callback} = menu_item;
41+
const n_menu_item = Object.assign({}, menu_item);
42+
n_menu_item.callback = () => {
43+
console.log('Inside callback', item);
44+
return callback.call(this, this.props.fm_store, item);
45+
};
46+
return n_menu_item;
47+
});
4848

49-
onClickLoadMore = () => {
50-
this.props.fm_store.fetch(true);
51-
};
49+
this.setState({menu_items});
50+
};
5251

53-
render = () => {
54-
return (
55-
<div id="fm-content-holder" onContextMenu={this.onContextMenu}>
56-
<div className="qx-row">
57-
<div id="fm-content" className="qx-col">
58-
{this.props.fm_store.list
59-
.map(item => {
60-
return <Item key={`${item.basename}-${item.selected}`} item={item} store={this.props.fm_store}/>
61-
})}
62-
{this.hasMore() ? <Button className="fm-loadmore" icon="appstore-o" type="primary" onClick={this.onClickLoadMore}>Load More</Button> : null}
63-
</div>
64-
<PluginContainer/>
65-
</div>
66-
</div>
67-
);
68-
};
52+
getFilteredMenuItems = ext => {
53+
const menu = this.props.fm_store.context_menu;
54+
/*[
55+
{
56+
scopes: ['image'],
57+
label: 'Preview',
58+
callback(item) {
59+
console.log('Clicked Details', item);
60+
},
61+
category: ['preview']
62+
},
63+
{
64+
scopes: ['audio'],
65+
label: 'Play',
66+
callback(item) {
67+
console.log('Clicked Details', item);
68+
},
69+
category: ['preview']
70+
},
71+
{
72+
scopes: ['dir', 'text'],
73+
label: 'Open',
74+
callback(item) {
75+
console.log('Clicked Details', item);
76+
},
77+
category: ['preview']
78+
},
79+
{
80+
scopes: ['dir', 'screen'],
81+
label: 'New Folder',
82+
callback(item) {
83+
console.log('Clicked Details', item);
84+
},
85+
category: ['new-item']
86+
},
87+
{
88+
scopes: ['all'],
89+
label: 'Details',
90+
callback(item) {
91+
console.log('Clicked Details', item);
92+
},
93+
category: ['general']
94+
},
95+
];*/
96+
const type = ['screen', 'dir'].indexOf(ext) >= 0 ? ext : Object.keys(file_types).find(type => {
97+
return file_types[type].indexOf(ext) >= 0;
98+
});
99+
return menu.filter(menu_item => {
100+
return menu_item.scopes.indexOf('all') >= 0 || menu_item.scopes.indexOf(type) >= 0;
101+
});
102+
};
103+
104+
clearContextMenu = () => {
105+
this.setState({menu_items: []});
106+
};
107+
108+
onScroll = throttle(e => {
109+
const el = document.getElementById('fm-content-holder');
110+
const content = el.querySelector('#fm-content');
111+
const scrollTop = el.scrollTop;
112+
const offsetHeight = el.offsetHeight;
113+
const scrollHeight = content.scrollHeight;
114+
115+
if (scrollHeight - offsetHeight < scrollTop + 10) {
116+
this.props.fm_store.fetch(true);
117+
}
118+
}, 100);
119+
120+
hasMore = () => {
121+
return this.props.fm_store.list.length < this.props.fm_store.data.total;
122+
};
123+
124+
onClickLoadMore = () => {
125+
this.props.fm_store.fetch(true);
126+
};
127+
128+
render = () => {
129+
return (
130+
<div id="fm-content-holder">
131+
<div className="qx-row">
132+
<div id="fm-content" className="qx-col" onContextMenu={this.onContextMenu}>
133+
{this.props.fm_store.list
134+
.map(item => {
135+
return <Item
136+
key={`${item.basename}-${item.selected}`}
137+
item={item}
138+
onContextMenu={e=>this.onContextMenu(e, item)}
139+
store={this.props.fm_store}/>
140+
})}
141+
{this.hasMore() ?
142+
<Button className="fm-loadmore" icon="appstore-o" type="primary" onClick={this.onClickLoadMore}>Load
143+
More</Button> : null}
144+
</div>
145+
<ContextMenu menu_items={this.state.menu_items} closeContextMenu={this.clearContextMenu}/>
146+
<PluginContainer/>
147+
</div>
148+
</div>
149+
);
150+
};
69151
};
70152

71153
export default inject("fm_store")(observer(FMContent));

src/core/fm/content/item/index.jsx

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export default class Item extends Component {
4444

4545
//what happens on double click on an item
4646
if (item.is_dir) {
47-
this.props.store.working_dir = this.props.store.working_dir + item.basename + '/';
47+
this.props.store.working_dir = this.props.store.working_dir + '/' + item.basename;
4848
this.props.store.fetch();
4949
}
5050
else {
@@ -119,13 +119,6 @@ export default class Item extends Component {
119119
}
120120
};
121121

122-
onContextMenu = e => {
123-
e.preventDefault();
124-
e.stopPropagation();
125-
126-
console.log("Context Menu Item");
127-
};
128-
129122
img = () => {
130123
const path = this.props.store.server;
131124
const query = ['working_dir=' + this.props.store.working_dir];
@@ -171,7 +164,7 @@ export default class Item extends Component {
171164
let mediaTypeClass = ' ' + mediaType;
172165
return (
173166
<div className="fm-grid-m">
174-
<div className={this.getMediaClass()} onDoubleClick={this.onDoubleClick} onClick={this.onClick} onContextMenu={this.onContextMenu}>
167+
<div className={this.getMediaClass()} onDoubleClick={this.onDoubleClick} onClick={this.onClick} onContextMenu={this.props.onContextMenu}>
175168
<div className="fm-media__thumb">
176169
<img src={this.img()} alt="icon"/>
177170
</div>

0 commit comments

Comments
 (0)