aboutsummaryrefslogtreecommitdiffhomepage
path: root/frontend/js/public.js
blob: c295a05239a1d1509c8c7e2f21c9adab78c1d2a2 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
(function () {
    'use strict';

    /* global superagent */
    /* global Vue */
    /* global $ */
    /* global filesize */

    function sanitize(filePath) {
        filePath = '/' + filePath;
        return filePath.replace(/\/+/g, '/');
    }

    function encode(filePath) {
        return filePath.split('/').map(encodeURIComponent).join('/');
    }

    function decode(filePath) {
        return filePath.split('/').map(decodeURIComponent).join('/');
    }

    var mimeTypes = {
        images: [ '.png', '.jpg', '.jpeg', '.tiff', '.gif' ],
        text: [ '.txt', '.md' ],
        pdf: [ '.pdf' ],
        html: [ '.html', '.htm', '.php' ],
        video: [ '.mp4', '.mpg', '.mpeg', '.ogg', '.mkv', '.avi', '.mov' ]
    };

    function getPreviewUrl(entry, basePath) {
        var path = '/_admin/img/';

        if (entry.isDirectory) return path + 'directory.png';
        if (mimeTypes.images.some(function (e) { return entry.filePath.endsWith(e); })) return sanitize(basePath + '/' + entry.filePath);
        if (mimeTypes.text.some(function (e) { return entry.filePath.endsWith(e); })) return path +'text.png';
        if (mimeTypes.pdf.some(function (e) { return entry.filePath.endsWith(e); })) return path + 'pdf.png';
        if (mimeTypes.html.some(function (e) { return entry.filePath.endsWith(e); })) return path + 'html.png';
        if (mimeTypes.video.some(function (e) { return entry.filePath.endsWith(e); })) return path + 'video.png';

        return path + 'unknown.png';
    }

    // simple extension detection, does not work with double extension like .tar.gz
    function getExtension(entry) {
        if (entry.isFile) return entry.filePath.slice(entry.filePath.lastIndexOf('.') + 1);
        return '';
    }

    function loadDirectory() {
        app.busy = true;

        var filePath = sanitize(window.location.pathname);

        app.path = filePath;

        superagent.get('/api/files/' + encode(filePath)).query({ access_token: localStorage.accessToken }).end(function (error, result) {
            app.busy = false;

            if (result && result.statusCode === 401) return logout();
            if (error) return console.error(error);

            result.body.entries.sort(function (a, b) { return a.isDirectory && b.isFile ? -1 : 1; });
            app.entries = result.body.entries.map(function (entry) {
                entry.previewUrl = getPreviewUrl(entry, filePath);
                entry.extension = getExtension(entry);
                entry.rename = false;
                entry.filePathNew = entry.filePath;
                return entry;
            });
            app.path = filePath;
            app.pathParts = decode(filePath).split('/').filter(function (e) { return !!e; }).map(function (e, i, a) {
                return {
                    name: e,
                    link: '#' + sanitize('/' + a.slice(0, i).join('/') + '/' + e)
                };
            });
        });
    }

    function open(row, column, event) {
        var fullPath = encode(sanitize(app.path + '/' + row.filePath));

        if (row.isDirectory) return window.location.href = fullPath;

        app.activeEntry = row;
        app.activeEntry.fullPath = fullPath;
        app.previewDrawerVisible = true

        // need to wait for DOM element to exist
        setTimeout(function () {
            $('iframe').on('load', function (e) {
                if (!e.target.contentWindow.document.body) return;

                e.target.contentWindow.document.body.style.display = 'flex'
                e.target.contentWindow.document.body.style.justifyContent = 'center'
            });
        }, 0);
    }

    var app = new Vue({
        el: '#app',
        data: {
            ready: false,
            busy: false,
            path: '',
            previewDrawerVisible: false,
            activeEntry: {},
            entries: []
        },
        methods: {
            onDownload: function (entry) {
                if (entry.isDirectory) return;
                window.location.href = encode('/api/files/' + sanitize(this.path + '/' + entry.filePath)) + '?access_token=' + localStorage.accessToken;
            },
            prettyDate: function (row, column, cellValue, index) {
                var date = new Date(cellValue),
                diff = (((new Date()).getTime() - date.getTime()) / 1000),
                day_diff = Math.floor(diff / 86400);

                if (isNaN(day_diff) || day_diff < 0)
                    return;

                return day_diff === 0 && (
                    diff < 60 && 'just now' ||
                    diff < 120 && '1 minute ago' ||
                    diff < 3600 && Math.floor( diff / 60 ) + ' minutes ago' ||
                    diff < 7200 && '1 hour ago' ||
                    diff < 86400 && Math.floor( diff / 3600 ) + ' hours ago') ||
                    day_diff === 1 && 'Yesterday' ||
                    day_diff < 7 && day_diff + ' days ago' ||
                    day_diff < 31 && Math.ceil( day_diff / 7 ) + ' weeks ago' ||
                    day_diff < 365 && Math.round( day_diff / 30 ) +  ' months ago' ||
                    Math.round( day_diff / 365 ) + ' years ago';
            },
            prettyFileSize: function (row, column, cellValue, index) {
                return filesize(cellValue);
            },
            loadDirectory: loadDirectory,
            open: open,
        }
    });

    loadDirectory();
})();