nodebb-plugin-facebook-post 1.0.32 → 1.0.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/library.js +15 -95
- package/package.json +1 -1
- package/plugin.json +1 -1
- package/static/lib/composer.js +8 -132
- package/static/templates/admin/facebook-post.tpl +6 -20
package/library.js
CHANGED
|
@@ -14,7 +14,6 @@ const DEFAULT_SETTINGS = {
|
|
|
14
14
|
categoriesWhitelist: '',
|
|
15
15
|
minimumReputation: 0,
|
|
16
16
|
maxImages: 4,
|
|
17
|
-
enablePlaceTagging: false,
|
|
18
17
|
};
|
|
19
18
|
|
|
20
19
|
function bool(v) {
|
|
@@ -52,7 +51,6 @@ async function loadSettings() {
|
|
|
52
51
|
settings.minimumReputation = int(settings.minimumReputation, 0);
|
|
53
52
|
settings.maxImages = int(settings.maxImages, DEFAULT_SETTINGS.maxImages);
|
|
54
53
|
settings.categoriesWhitelist = trimStr(settings.categoriesWhitelist);
|
|
55
|
-
settings.enablePlaceTagging = bool(settings.enablePlaceTagging);
|
|
56
54
|
|
|
57
55
|
const env = readEnv();
|
|
58
56
|
settings.fbGraphVersion = env.fbGraphVersion;
|
|
@@ -153,7 +151,7 @@ async function userIsAllowed(uid) {
|
|
|
153
151
|
const ok = await Groups.isMember(uid, groupName);
|
|
154
152
|
if (ok) return true;
|
|
155
153
|
} catch {
|
|
156
|
-
// ignore
|
|
154
|
+
// ignore individual group check errors
|
|
157
155
|
}
|
|
158
156
|
}
|
|
159
157
|
return false;
|
|
@@ -209,14 +207,13 @@ async function uploadPhotoToFacebook(urlAbs) {
|
|
|
209
207
|
return resp.data && resp.data.id;
|
|
210
208
|
}
|
|
211
209
|
|
|
212
|
-
async function publishFeedPost({ message, link, photoIds
|
|
210
|
+
async function publishFeedPost({ message, link, photoIds }) {
|
|
213
211
|
const endpoint = `https://graph.facebook.com/${settings.fbGraphVersion}/${settings.fbPageId}/feed`;
|
|
214
212
|
|
|
215
213
|
const form = new URLSearchParams();
|
|
216
214
|
form.append('message', String(message || ''));
|
|
217
215
|
form.append('access_token', String(settings.fbPageAccessToken));
|
|
218
216
|
if (link) form.append('link', String(link));
|
|
219
|
-
if (placeId) form.append('place', String(placeId));
|
|
220
217
|
if (Array.isArray(photoIds) && photoIds.length) {
|
|
221
218
|
photoIds.forEach((id, idx) => {
|
|
222
219
|
form.append(`attached_media[${idx}]`, JSON.stringify({ media_fbid: id }));
|
|
@@ -255,7 +252,7 @@ async function postToFacebook(ctx) {
|
|
|
255
252
|
if (id) photoIds.push(id);
|
|
256
253
|
}
|
|
257
254
|
|
|
258
|
-
return publishFeedPost({ message, link, photoIds
|
|
255
|
+
return publishFeedPost({ message, link, photoIds });
|
|
259
256
|
}
|
|
260
257
|
|
|
261
258
|
const Plugin = {};
|
|
@@ -303,37 +300,11 @@ Plugin.init = async function (params) {
|
|
|
303
300
|
const allowedGroups = parseAllowedGroupsList();
|
|
304
301
|
if (!allowedGroups.length) return res.json({ allowed: false, reason: 'no_groups_configured' });
|
|
305
302
|
const ok = await userIsAllowed(uid);
|
|
306
|
-
return res.json({ allowed: ok, reason: ok ? 'ok' : 'not_in_group'
|
|
303
|
+
return res.json({ allowed: ok, reason: ok ? 'ok' : 'not_in_group' });
|
|
307
304
|
} catch {
|
|
308
305
|
return res.json({ allowed: false, reason: 'error' });
|
|
309
306
|
}
|
|
310
307
|
});
|
|
311
|
-
|
|
312
|
-
router.get('/api/facebook-post/search-place', middleware.ensureLoggedIn, async (req, res) => {
|
|
313
|
-
res.set('Cache-Control', 'no-store');
|
|
314
|
-
try {
|
|
315
|
-
await loadSettings();
|
|
316
|
-
if (!settings.enabled || !settings.enablePlaceTagging || !settings.fbPageAccessToken) {
|
|
317
|
-
return res.json({ results: [] });
|
|
318
|
-
}
|
|
319
|
-
const q = trimStr(req.query.q);
|
|
320
|
-
if (q.length < 2) return res.json({ results: [] });
|
|
321
|
-
const resp = await axios.get(`https://graph.facebook.com/${settings.fbGraphVersion}/search`, {
|
|
322
|
-
params: {
|
|
323
|
-
type: 'place',
|
|
324
|
-
q,
|
|
325
|
-
fields: 'name,location,id',
|
|
326
|
-
access_token: settings.fbPageAccessToken,
|
|
327
|
-
limit: 8,
|
|
328
|
-
},
|
|
329
|
-
timeout: 8000,
|
|
330
|
-
});
|
|
331
|
-
return res.json({ results: (resp.data && resp.data.data) || [] });
|
|
332
|
-
} catch {
|
|
333
|
-
return res.json({ results: [] });
|
|
334
|
-
}
|
|
335
|
-
});
|
|
336
|
-
|
|
337
308
|
};
|
|
338
309
|
|
|
339
310
|
Plugin.addAdminNavigation = async function (header) {
|
|
@@ -347,94 +318,43 @@ Plugin.addAdminNavigation = async function (header) {
|
|
|
347
318
|
};
|
|
348
319
|
|
|
349
320
|
Plugin.onPostCreate = async function (hookData) {
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
if (!hookData?.post || !hookData?.data) {
|
|
353
|
-
winston.info('[facebook-post] onPostCreate: hookData manquant (post ou data absent)');
|
|
354
|
-
return hookData;
|
|
355
|
-
}
|
|
356
|
-
hookData.post.fbPostEnabled = bool(hookData.data.fbPostEnabled);
|
|
357
|
-
const fbPlaceId = trimStr(hookData.data.fbPlaceId);
|
|
358
|
-
if (fbPlaceId) hookData.post.fbPlaceId = fbPlaceId;
|
|
359
|
-
winston.info(`[facebook-post] onPostCreate: pid=${hookData.post.pid} fbPostEnabled=${hookData.post.fbPostEnabled} fbPlaceId=${hookData.post.fbPlaceId || '(none)'}`);
|
|
360
|
-
} catch (e) {
|
|
361
|
-
winston.error(`[facebook-post] onPostCreate erreur: ${e?.message || e}`);
|
|
362
|
-
}
|
|
321
|
+
if (!hookData?.post || !hookData?.data) return hookData;
|
|
322
|
+
hookData.post.fbPostEnabled = bool(hookData.data.fbPostEnabled);
|
|
363
323
|
return hookData;
|
|
364
324
|
};
|
|
365
325
|
|
|
366
326
|
Plugin.onPostSave = async function (hookData) {
|
|
367
327
|
const winston = require.main.require('winston');
|
|
368
|
-
winston.info('[facebook-post] onPostSave: hook déclenché');
|
|
369
328
|
try {
|
|
370
329
|
await loadSettings();
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
if (!settings.enabled) {
|
|
374
|
-
winston.info('[facebook-post] onPostSave: abandon — plugin désactivé dans les paramètres');
|
|
375
|
-
return;
|
|
376
|
-
}
|
|
330
|
+
if (!settings.enabled) return;
|
|
377
331
|
|
|
378
332
|
const rawPost = hookData && hookData.post ? hookData.post : hookData;
|
|
379
|
-
winston.info(`[facebook-post] onPostSave: données brutes reçues — pid=${rawPost?.pid} fbPostEnabled=${rawPost?.fbPostEnabled}`);
|
|
380
|
-
|
|
381
333
|
const ctx = await getPostContext(rawPost);
|
|
382
|
-
if (!ctx)
|
|
383
|
-
winston.warn('[facebook-post] onPostSave: abandon — impossible de récupérer le contexte du post (pid invalide ?)');
|
|
384
|
-
return;
|
|
385
|
-
}
|
|
334
|
+
if (!ctx) return;
|
|
386
335
|
|
|
387
|
-
// Restore ephemeral
|
|
336
|
+
// Restore ephemeral field set by onPostCreate (not persisted to DB)
|
|
388
337
|
ctx.post.fbPostEnabled = rawPost.fbPostEnabled;
|
|
389
|
-
if (rawPost.fbPlaceId) ctx.post.fbPlaceId = rawPost.fbPlaceId;
|
|
390
338
|
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
const allowed = await userIsAllowed(ctx.post.uid);
|
|
394
|
-
if (!allowed) {
|
|
395
|
-
const groups = parseAllowedGroupsList();
|
|
396
|
-
winston.info(`[facebook-post] onPostSave: abandon — uid=${ctx.post.uid} n'est pas dans les groupes autorisés: [${groups.join(', ')}]`);
|
|
397
|
-
return;
|
|
398
|
-
}
|
|
399
|
-
winston.info(`[facebook-post] onPostSave: uid=${ctx.post.uid} autorisé par les groupes`);
|
|
400
|
-
|
|
401
|
-
const process = shouldProcessPost(ctx);
|
|
402
|
-
if (!process) {
|
|
403
|
-
const isFirstPost = (ctx.post.isMainPost === true) || (ctx.post.index === 0) || (String(ctx.post.pid) === String(ctx.topic.mainPid));
|
|
404
|
-
const fbEnabled = bool(ctx.post.fbPostEnabled);
|
|
405
|
-
const repOk = (ctx.user.reputation || 0) >= settings.minimumReputation;
|
|
406
|
-
const whitelist = parseCsvInts(settings.categoriesWhitelist);
|
|
407
|
-
const catOk = whitelist.length === 0 || whitelist.includes(parseInt(ctx.topic.cid, 10));
|
|
408
|
-
winston.info(`[facebook-post] onPostSave: abandon — shouldProcessPost=false. Détail: isFirstPost=${isFirstPost} fbPostEnabled=${fbEnabled} reputationOk=${repOk}(${ctx.user.reputation}>=${settings.minimumReputation}) categoryOk=${catOk}(cid=${ctx.topic.cid} whitelist=[${whitelist}])`);
|
|
409
|
-
return;
|
|
410
|
-
}
|
|
411
|
-
winston.info('[facebook-post] onPostSave: shouldProcessPost=true, publication en cours…');
|
|
339
|
+
if (!(await userIsAllowed(ctx.post.uid))) return;
|
|
340
|
+
if (!shouldProcessPost(ctx)) return;
|
|
412
341
|
|
|
413
342
|
const Posts = require.main.require('./src/posts');
|
|
414
343
|
|
|
415
344
|
const already = await Posts.getPostField(ctx.post.pid, 'fbPostedId');
|
|
416
|
-
if (already)
|
|
417
|
-
winston.info(`[facebook-post] onPostSave: abandon — déjà publié (fbPostedId=${already})`);
|
|
418
|
-
return;
|
|
419
|
-
}
|
|
420
|
-
|
|
421
|
-
const imageUrls = extractImageUrlsFromContent(ctx.post.content || '').filter(isForumHosted);
|
|
422
|
-
winston.info(`[facebook-post] onPostSave: images hébergées sur le forum trouvées: ${imageUrls.length} [${imageUrls.join(', ')}]`);
|
|
345
|
+
if (already) return;
|
|
423
346
|
|
|
424
347
|
const fbId = await postToFacebook(ctx);
|
|
425
348
|
if (fbId) {
|
|
426
349
|
await Posts.setPostField(ctx.post.pid, 'fbPostedId', fbId);
|
|
427
350
|
await Posts.setPostField(ctx.post.pid, 'fbPostedAt', Date.now());
|
|
428
|
-
winston.info(`[facebook-post]
|
|
351
|
+
winston.info(`[facebook-post] published pid=${ctx.post.pid} fbId=${fbId}`);
|
|
429
352
|
} else {
|
|
430
|
-
winston.warn(
|
|
353
|
+
winston.warn(`[facebook-post] postToFacebook returned no id for pid=${ctx.post.pid}`);
|
|
431
354
|
}
|
|
432
355
|
} catch (e) {
|
|
433
356
|
const detail = e?.response ? JSON.stringify(e.response.data) : (e?.message || e);
|
|
434
|
-
winston.error(`[facebook-post] onPostSave
|
|
435
|
-
if (e?.response?.config?.url) {
|
|
436
|
-
winston.error(`[facebook-post] onPostSave: URL appelée: ${e.response.config.url} — status: ${e.response.status}`);
|
|
437
|
-
}
|
|
357
|
+
winston.error(`[facebook-post] onPostSave error: ${detail}`);
|
|
438
358
|
}
|
|
439
359
|
};
|
|
440
360
|
|
package/package.json
CHANGED
package/plugin.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"id": "nodebb-plugin-facebook-post",
|
|
3
3
|
"name": "Facebook Post",
|
|
4
|
-
"description": "Publie automatiquement les nouveaux topics NodeBB sur une Page Facebook fixe (images uploads
|
|
4
|
+
"description": "Publie automatiquement les nouveaux topics NodeBB sur une Page Facebook fixe (images uploads).",
|
|
5
5
|
"url": "https://example.invalid/nodebb-plugin-facebook-post",
|
|
6
6
|
"hooks": [
|
|
7
7
|
{
|
package/static/lib/composer.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
/* global
|
|
1
|
+
/* global $ */
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
4
|
(function () {
|
|
5
|
-
const DEBOUNCE_MS = 400;
|
|
6
|
-
|
|
7
5
|
async function canPost() {
|
|
8
6
|
try {
|
|
9
7
|
const res = await fetch('/api/facebook-post/can-post?_=' + Date.now(), {
|
|
@@ -17,36 +15,12 @@
|
|
|
17
15
|
}
|
|
18
16
|
}
|
|
19
17
|
|
|
20
|
-
|
|
21
|
-
try {
|
|
22
|
-
const res = await fetch('/api/facebook-post/search-place?q=' + encodeURIComponent(q), {
|
|
23
|
-
credentials: 'same-origin',
|
|
24
|
-
cache: 'no-store',
|
|
25
|
-
});
|
|
26
|
-
if (!res.ok) return [];
|
|
27
|
-
const data = await res.json();
|
|
28
|
-
return data.results || [];
|
|
29
|
-
} catch {
|
|
30
|
-
return [];
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
function resetPlace($panel) {
|
|
35
|
-
$panel.find('.fb-place-search').removeClass('d-none').val('');
|
|
36
|
-
$panel.find('.fb-place-id').val('');
|
|
37
|
-
$panel.find('.fb-place-selected').removeClass('d-inline-flex').addClass('d-none');
|
|
38
|
-
$panel.find('.fb-place-results').hide().empty();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
function injectUI($composer, perm) {
|
|
18
|
+
function injectUI($composer) {
|
|
42
19
|
if ($composer.find('[data-fbpost-btn]').length) return;
|
|
43
20
|
|
|
44
|
-
const showPlace = !!perm.enablePlaceTagging;
|
|
45
|
-
|
|
46
|
-
// ── Bouton dans la toolbar — même structure que les boutons natifs ──
|
|
47
21
|
const $li = $(`
|
|
48
22
|
<li aria-label="Publier sur Facebook" data-bs-original-title="Publier sur Facebook" data-fbpost-btn>
|
|
49
|
-
<button type="button" class="btn btn-sm btn-link text-reset
|
|
23
|
+
<button type="button" class="btn btn-sm btn-link text-reset"
|
|
50
24
|
aria-label="Publier sur Facebook" style="opacity:0.45;">
|
|
51
25
|
<i class="fab fa-facebook-f"></i>
|
|
52
26
|
</button>
|
|
@@ -54,122 +28,24 @@
|
|
|
54
28
|
`);
|
|
55
29
|
const $btn = $li.find('button');
|
|
56
30
|
|
|
57
|
-
// ── Panneau lieu (affiché sous la toolbar quand FB est actif) ──
|
|
58
|
-
const $placePanel = $(`
|
|
59
|
-
<div class="fb-place-panel d-none align-items-center gap-2 px-2 py-1"
|
|
60
|
-
style="font-size:0.85em; border-top:1px solid rgba(128,128,128,.2);">
|
|
61
|
-
<i class="fab fa-facebook-f" style="color:#1877F2; flex-shrink:0;"></i>
|
|
62
|
-
<span class="text-muted">Publier sur Facebook</span>
|
|
63
|
-
${showPlace ? `
|
|
64
|
-
<div class="position-relative flex-grow-1 ms-2">
|
|
65
|
-
<input type="text" class="form-control form-control-sm fb-place-search"
|
|
66
|
-
placeholder="Lieu (optionnel)…" autocomplete="off">
|
|
67
|
-
<ul class="fb-place-results dropdown-menu p-1"
|
|
68
|
-
style="display:none; position:absolute; z-index:9999; top:100%; left:0;
|
|
69
|
-
min-width:220px; max-height:200px; overflow-y:auto;"></ul>
|
|
70
|
-
</div>
|
|
71
|
-
<span class="fb-place-selected d-none align-items-center gap-1 text-nowrap">
|
|
72
|
-
<i class="fa fa-map-marker" style="color:#1877F2;"></i>
|
|
73
|
-
<span class="fb-place-name fw-semibold"></span>
|
|
74
|
-
<a href="#" class="fb-place-clear ms-1 text-danger" title="Effacer">
|
|
75
|
-
<i class="fa fa-times"></i>
|
|
76
|
-
</a>
|
|
77
|
-
</span>
|
|
78
|
-
<input type="hidden" class="fb-place-id" value="">
|
|
79
|
-
` : ''}
|
|
80
|
-
</div>
|
|
81
|
-
`);
|
|
82
|
-
|
|
83
|
-
// ── Toggle actif/inactif ──
|
|
84
31
|
$btn.on('click', function () {
|
|
85
32
|
const active = !$(this).data('fbpost-active');
|
|
86
33
|
$(this).data('fbpost-active', active);
|
|
87
|
-
|
|
88
|
-
$(this).css({ color: '#1877F2', opacity: '1' });
|
|
89
|
-
$placePanel.removeClass('d-none').addClass('d-flex');
|
|
90
|
-
} else {
|
|
91
|
-
$(this).css({ color: '', opacity: '0.45' });
|
|
92
|
-
$placePanel.removeClass('d-flex').addClass('d-none');
|
|
93
|
-
if (showPlace) resetPlace($placePanel);
|
|
94
|
-
}
|
|
34
|
+
$(this).css({ color: active ? '#1877F2' : '', opacity: active ? '1' : '0.45' });
|
|
95
35
|
});
|
|
96
36
|
|
|
97
|
-
// ── Recherche de lieu avec debounce ──
|
|
98
|
-
if (showPlace) {
|
|
99
|
-
let debounceTimer;
|
|
100
|
-
|
|
101
|
-
$placePanel.find('.fb-place-search').on('input', function () {
|
|
102
|
-
const q = $(this).val().trim();
|
|
103
|
-
const $results = $placePanel.find('.fb-place-results');
|
|
104
|
-
clearTimeout(debounceTimer);
|
|
105
|
-
if (q.length < 2) { $results.hide().empty(); return; }
|
|
106
|
-
|
|
107
|
-
debounceTimer = setTimeout(async () => {
|
|
108
|
-
const places = await searchPlace(q);
|
|
109
|
-
$results.empty();
|
|
110
|
-
if (!places.length) { $results.hide(); return; }
|
|
111
|
-
|
|
112
|
-
places.forEach(p => {
|
|
113
|
-
const loc = p.location
|
|
114
|
-
? [p.location.city, p.location.country].filter(Boolean).join(', ')
|
|
115
|
-
: '';
|
|
116
|
-
$('<li>').append(
|
|
117
|
-
$('<a href="#" class="dropdown-item rounded-1 py-1">')
|
|
118
|
-
.attr({ 'data-place-id': p.id, 'data-place-name': p.name })
|
|
119
|
-
.append($('<div class="fw-semibold lh-sm">').text(p.name))
|
|
120
|
-
.append(loc ? $('<div class="text-muted small lh-sm">').text(loc) : null)
|
|
121
|
-
.on('click', function (e) {
|
|
122
|
-
e.preventDefault();
|
|
123
|
-
$placePanel.find('.fb-place-id').val($(this).data('place-id'));
|
|
124
|
-
$placePanel.find('.fb-place-name').text($(this).data('place-name'));
|
|
125
|
-
$placePanel.find('.fb-place-selected').removeClass('d-none').addClass('d-inline-flex');
|
|
126
|
-
$placePanel.find('.fb-place-search').addClass('d-none');
|
|
127
|
-
$results.hide().empty();
|
|
128
|
-
})
|
|
129
|
-
).appendTo($results);
|
|
130
|
-
});
|
|
131
|
-
$results.show();
|
|
132
|
-
}, DEBOUNCE_MS);
|
|
133
|
-
});
|
|
134
|
-
|
|
135
|
-
$placePanel.find('.fb-place-clear').on('click', function (e) {
|
|
136
|
-
e.preventDefault();
|
|
137
|
-
$placePanel.find('.fb-place-id').val('');
|
|
138
|
-
$placePanel.find('.fb-place-selected').removeClass('d-inline-flex').addClass('d-none');
|
|
139
|
-
$placePanel.find('.fb-place-search').removeClass('d-none').val('').trigger('focus');
|
|
140
|
-
});
|
|
141
|
-
|
|
142
|
-
// Fermer le dropdown si clic ailleurs
|
|
143
|
-
$(document).off('click.fbpost').on('click.fbpost', function (e) {
|
|
144
|
-
if (!$(e.target).closest('.fb-place-panel').length) {
|
|
145
|
-
$placePanel.find('.fb-place-results').hide().empty();
|
|
146
|
-
}
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
// ── Injection dans la toolbar ──
|
|
151
37
|
const $toolbar = $composer.find('ul.formatting-group').first();
|
|
152
38
|
if ($toolbar.length) {
|
|
153
39
|
$toolbar.append($li);
|
|
154
|
-
$toolbar.after($placePanel);
|
|
155
40
|
} else {
|
|
156
|
-
|
|
157
|
-
const $write = $composer.find('.write').first();
|
|
158
|
-
$write.before($placePanel);
|
|
159
|
-
$placePanel.before($li);
|
|
41
|
+
$composer.find('.write').first().before($li);
|
|
160
42
|
}
|
|
161
43
|
|
|
162
|
-
// ── Hook submit ──
|
|
163
44
|
$(window).off('action:composer.submit.fbpost')
|
|
164
|
-
.on('action:composer.submit.fbpost', function (
|
|
165
|
-
const enabled = !!$btn.data('fbpost-active');
|
|
45
|
+
.on('action:composer.submit.fbpost', function (ev, data) {
|
|
166
46
|
const postData = (data && data.composerData) || (data && data.postData) || data;
|
|
167
47
|
if (!postData || typeof postData !== 'object') return;
|
|
168
|
-
postData.fbPostEnabled =
|
|
169
|
-
if (enabled && showPlace) {
|
|
170
|
-
const placeId = $placePanel.find('.fb-place-id').val();
|
|
171
|
-
if (placeId) postData.fbPlaceId = placeId;
|
|
172
|
-
}
|
|
48
|
+
postData.fbPostEnabled = !!$btn.data('fbpost-active');
|
|
173
49
|
});
|
|
174
50
|
}
|
|
175
51
|
|
|
@@ -179,7 +55,7 @@
|
|
|
179
55
|
if (!$composer || !$composer.length) return;
|
|
180
56
|
const perm = await canPost();
|
|
181
57
|
if (!perm.allowed) return;
|
|
182
|
-
injectUI($composer
|
|
58
|
+
injectUI($composer);
|
|
183
59
|
} catch {
|
|
184
60
|
// ignore
|
|
185
61
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<div class="acp-page-container">
|
|
2
|
-
<h2>Facebook
|
|
2
|
+
<h2>Facebook Post</h2>
|
|
3
3
|
|
|
4
4
|
<form class="facebook-post-settings" role="form">
|
|
5
5
|
<div class="form-check mb-3">
|
|
@@ -7,15 +7,10 @@
|
|
|
7
7
|
<label class="form-check-label" for="enabled">Activer</label>
|
|
8
8
|
</div>
|
|
9
9
|
|
|
10
|
-
<div class="form-check mb-3">
|
|
11
|
-
<input type="checkbox" class="form-check-input" id="publishInstagram" name="publishInstagram">
|
|
12
|
-
<label class="form-check-label" for="publishInstagram">Publier aussi sur Instagram (uniquement si une image est présente)</label>
|
|
13
|
-
</div>
|
|
14
|
-
|
|
15
10
|
<hr/>
|
|
16
11
|
|
|
17
12
|
<h4>Accès</h4>
|
|
18
|
-
<p class="text-muted">Sélectionne les groupes autorisés à voir la case
|
|
13
|
+
<p class="text-muted">Sélectionne les groupes autorisés à voir la case "Publier sur Facebook" dans le composer.</p>
|
|
19
14
|
|
|
20
15
|
<div class="mb-3">
|
|
21
16
|
<label class="form-label" for="allowedGroupsSelect">Groupes autorisés</label>
|
|
@@ -25,7 +20,7 @@
|
|
|
25
20
|
<!-- END allGroups -->
|
|
26
21
|
</select>
|
|
27
22
|
<input type="hidden" id="allowedGroups" name="allowedGroups" value="">
|
|
28
|
-
<p class="form-text">Sans fallback : si aucun groupe n
|
|
23
|
+
<p class="form-text">Sans fallback : si aucun groupe n'est sélectionné, personne ne verra la case.</p>
|
|
29
24
|
</div>
|
|
30
25
|
|
|
31
26
|
<hr/>
|
|
@@ -38,7 +33,7 @@
|
|
|
38
33
|
</div>
|
|
39
34
|
|
|
40
35
|
<div class="mb-3">
|
|
41
|
-
<label class="form-label" for="excerptMaxLen">Longueur max de l
|
|
36
|
+
<label class="form-label" for="excerptMaxLen">Longueur max de l'extrait</label>
|
|
42
37
|
<input type="number" class="form-control" id="excerptMaxLen" name="excerptMaxLen" min="50" max="5000">
|
|
43
38
|
</div>
|
|
44
39
|
|
|
@@ -62,19 +57,10 @@
|
|
|
62
57
|
<h4>Images</h4>
|
|
63
58
|
|
|
64
59
|
<div class="mb-3">
|
|
65
|
-
<label class="form-label" for="maxImages">Nombre max d
|
|
60
|
+
<label class="form-label" for="maxImages">Nombre max d'images (uploads du forum)</label>
|
|
66
61
|
<input type="number" class="form-control" id="maxImages" name="maxImages" min="0" max="20">
|
|
67
62
|
</div>
|
|
68
63
|
|
|
69
|
-
<
|
|
70
|
-
|
|
71
|
-
<h4>Lieu / Géolocalisation</h4>
|
|
72
|
-
|
|
73
|
-
<div class="form-check mb-3">
|
|
74
|
-
<input type="checkbox" class="form-check-input" id="enablePlaceTagging" name="enablePlaceTagging">
|
|
75
|
-
<label class="form-check-label" for="enablePlaceTagging">Activer le tag de lieu (Place ID / location_id)</label>
|
|
76
|
-
</div>
|
|
77
|
-
|
|
78
|
-
<button type="button" id="save" class="btn btn-primary">Enregistrer</button>
|
|
64
|
+
<button type="button" id="save" class="btn btn-primary mt-2">Enregistrer</button>
|
|
79
65
|
</form>
|
|
80
66
|
</div>
|