Skip to content
Permalink
Newer
Older
100644 189 lines (170 sloc) 5.64 KB
Oct 26, 2021
1
const getClient = (baseUrl, endpointName) => {
Oct 26, 2021
2
return {
3
baseUrl: baseUrl,
4
endpointName: endpointName,
5
getItems: function getItems(path) {
Oct 26, 2021
6
return clientFunctions.makeCall(this.baseUrl + '/.rest/delivery/' + endpointName + path + '@nodes').then(function (data) {
Oct 26, 2021
7
return JSON.parse(data);
Oct 26, 2021
8
}).then((json) => {
Oct 26, 2021
9
return json.map(jsonToItem);
10
});
11
}
12
};
13
};
14
Oct 26, 2021
15
const jsonToItem = (data) => {
16
var map = new Map(Object.entries(data)).set('isFolder', data['@nodeType'] === 'mgnl:folder');
17
map['delete']('@nodes');
18
map['delete']('@nodeType');
Oct 26, 2021
19
return map;
20
};
21
Oct 26, 2021
22
const makeCall = (url) => {
23
return new Promise((resolve, reject) => {
Oct 26, 2021
24
var request = new XMLHttpRequest();
25
request.open('GET', url);
Oct 26, 2021
26
request.onload = () => {
Oct 26, 2021
27
if (request.status === 200) {
28
resolve(request.response);
29
} else {
30
reject(Error('Error making call to ' + url + '; error code:' + request.statusText));
31
}
32
};
33
Oct 26, 2021
34
request.onerror = () => {
Oct 26, 2021
35
reject(Error('There was a network error making call to ' + url));
36
};
37
38
request.send();
39
});
40
};
41
Oct 26, 2021
42
const clientFunctions = {
Oct 26, 2021
43
makeCall: makeCall,
44
getClient: getClient
45
};
46
47
export default class HierarchicalBrowser extends HTMLElement {
48
constructor() {
49
super();
Oct 26, 2021
50
this.baseUrl = this.getAttribute('baseUrl');
51
this.endpoint = this.getAttribute('endpoint');
52
const columns = this.getAttribute('columns');
Oct 26, 2021
53
if (!columns) {
54
this.columns = ["@path", "@name"];
55
} else {
56
this.columns = columns.split(",");
57
}
Oct 26, 2021
58
this.shadow = this.attachShadow({mode: 'open'});
Oct 26, 2021
59
this.client = getClient(this.baseUrl, this.endpoint);
60
this.loadItems('/');
61
}
62
63
loadItems(path) {
Oct 26, 2021
64
if (path != '/') {
Oct 26, 2021
65
let parent = path.substring(0, path.length - 1);
66
const lastSlash = parent.lastIndexOf('/');
Oct 26, 2021
67
this.parent = lastSlash == 0 ? '/' : parent.substring(0, lastSlash);
Oct 26, 2021
68
} else {
69
this.parent = null;
70
}
71
this.path = path;
Oct 26, 2021
72
this.state = 'loading';
Oct 26, 2021
73
this.client.getItems(path).then(result => {
74
this.items = result;
75
this.state = 'ready';
76
}).catch(error => {
77
this.errorMessage = error.name + ": " + error.message;
78
this.state = 'error';
79
});
80
}
81
82
get state() {
83
return this.getAttribute('state');
84
}
85
86
set state(value) {
87
this.setAttribute('state', value);
88
}
89
90
static get observedAttributes() { return ['state']; }
91
92
attributeChangedCallback(name, oldValue, newValue) {
93
this.render();
94
}
95
96
render() {
Oct 26, 2021
97
this.shadow.innerHTML = '';
98
if (this.getAttribute('state') == 'loading') {
99
this.shadow.appendChild(this.loading());
Oct 26, 2021
100
}
Oct 26, 2021
101
if (this.getAttribute('state') == 'ready') {
102
this.shadow.appendChild(this.showItems());
Oct 26, 2021
103
}
Oct 26, 2021
104
if (this.getAttribute('state') == 'error') {
105
this.shadow.innerHTML = '<p class="error">' + this.errorMessage || 'Unknown Error' + '<p>';
Oct 26, 2021
106
}
107
}
108
109
loading() {
110
const template = document.getElementById('browser-loading');
111
const instance = document.importNode(template.content, true);
112
instance.querySelector('.endpoint-name').innerHTML = this.endpoint;
113
return instance;
114
}
115
116
showItems() {
117
const template = document.getElementById('browser-items');
118
const instance = document.importNode(template.content, true);
119
instance.querySelector('.items-path').innerHTML = this.path;
120
instance.querySelector('.content-list').innerHTML = this.getItemsHtml();
121
this.addFolderClickEvent(instance);
122
return instance;
123
}
124
125
getItemsHtml() {
126
if (this.items.size < 1) {
Oct 26, 2021
127
return '<thead><tr><th>empty</th></tr></thead>';
Oct 26, 2021
128
} else {
Oct 26, 2021
129
let result = '';
Oct 26, 2021
130
if (this.parent != null) {
131
result += '<thead><tr><td class="folder" folder="' + this.parent + '">Go to ' + this.parent + '</td></tr></thead>';
132
}
133
result += this.getItemsHeader(this.columns) + this.getItemsBody(this.items, this.columns);
134
return result;
135
}
136
}
137
138
getItemsHeader(columns) {
Oct 26, 2021
139
let headers = '';
140
columns.forEach(column => headers += '<td>' + column + '</td>');
141
return '<thead><tr>' + headers + '</tr></thead>';
Oct 26, 2021
142
}
143
144
getItemsBody(items, columns) {
Oct 26, 2021
145
let rows = '';
Oct 26, 2021
146
items.forEach(content => {
Oct 26, 2021
147
let row = '<tr>';
148
if (content.get('isFolder')) {
Oct 26, 2021
149
row = '<tr class="folder" folder="' + content.get('@path') + '">'
150
}
151
columns.forEach(column => {
152
const value = content.get(column);
153
if (value == undefined) {
Oct 26, 2021
154
row = row + '<td></td>';
Oct 26, 2021
155
} else {
Oct 26, 2021
156
row = row + '<td>' + content.get(column) + '</td>';
Oct 26, 2021
157
}
158
});
Oct 26, 2021
159
row = row + '</tr>';
Oct 26, 2021
160
rows = rows + row;
161
});
Oct 26, 2021
162
return '<tbody>' + rows + '</tbody>';
Oct 26, 2021
163
}
164
165
addFolderClickEvent(instance) {
166
if (instance.querySelector('.folder')) {
167
const that = this;
168
const elements = instance.querySelectorAll('.folder');
169
elements.forEach(element => {
Oct 26, 2021
170
element.addEventListener('click', (event) => {
Oct 26, 2021
171
event.preventDefault();
172
let row = event.target;
Oct 26, 2021
173
while (row.getAttribute('folder') == undefined) {
Oct 26, 2021
174
row = row.parentElement;
175
}
Oct 26, 2021
176
let path = row.getAttribute('folder');
177
if (!path.endsWith('/')) {
178
path = path + '/';
Oct 26, 2021
179
}
180
that.loadItems(path);
181
});
182
});
183
}
184
}
185
}
186
187
if (!customElements.get('hierarchical-browser')) {
188
customElements.define('hierarchical-browser', HierarchicalBrowser);
189
}