Add Facebook and Instagram links
This commit is contained in:
@@ -6,8 +6,10 @@ import activity from 'feather-icons/dist/icons/activity.svg?raw';
|
||||
import bookmark from 'feather-icons/dist/icons/bookmark.svg?raw';
|
||||
import clock from 'feather-icons/dist/icons/clock.svg?raw';
|
||||
import edit from 'feather-icons/dist/icons/edit.svg?raw';
|
||||
import facebook from 'feather-icons/dist/icons/facebook.svg?raw';
|
||||
import globe from 'feather-icons/dist/icons/globe.svg?raw';
|
||||
import home from 'feather-icons/dist/icons/home.svg?raw';
|
||||
import instagram from 'feather-icons/dist/icons/instagram.svg?raw';
|
||||
import logIn from 'feather-icons/dist/icons/log-in.svg?raw';
|
||||
import logOut from 'feather-icons/dist/icons/log-out.svg?raw';
|
||||
import map from 'feather-icons/dist/icons/map.svg?raw';
|
||||
@@ -31,8 +33,10 @@ const ICONS = {
|
||||
bookmark,
|
||||
clock,
|
||||
edit,
|
||||
facebook,
|
||||
globe,
|
||||
home,
|
||||
instagram,
|
||||
'log-in': logIn,
|
||||
'log-out': logOut,
|
||||
map,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { on } from '@ember/modifier';
|
||||
import { htmlSafe } from '@ember/template';
|
||||
import { humanizeOsmTag } from '../utils/format-text';
|
||||
import { getLocalizedName, getPlaceType } from '../utils/osm';
|
||||
import { getSocialInfo } from '../utils/social-links';
|
||||
import Icon from '../components/icon';
|
||||
import PlaceEditForm from './place-edit-form';
|
||||
|
||||
@@ -159,6 +160,14 @@ export default class PlaceDetails extends Component {
|
||||
.join(', ');
|
||||
}
|
||||
|
||||
get facebook() {
|
||||
return getSocialInfo(this.tags, 'facebook');
|
||||
}
|
||||
|
||||
get instagram() {
|
||||
return getSocialInfo(this.tags, 'instagram');
|
||||
}
|
||||
|
||||
get wikipedia() {
|
||||
const val = this.tags.wikipedia;
|
||||
if (!val) return null;
|
||||
@@ -292,6 +301,36 @@ export default class PlaceDetails extends Component {
|
||||
</p>
|
||||
{{/if}}
|
||||
|
||||
{{#if this.facebook}}
|
||||
<p class="content-with-icon">
|
||||
<Icon @name="facebook" @title="Facebook" />
|
||||
<span>
|
||||
<a
|
||||
href={{this.facebook.url}}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{{this.facebook.username}}
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
{{/if}}
|
||||
|
||||
{{#if this.instagram}}
|
||||
<p class="content-with-icon">
|
||||
<Icon @name="instagram" @title="Instagram" />
|
||||
<span>
|
||||
<a
|
||||
href={{this.instagram.url}}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
>
|
||||
{{this.instagram.username}}
|
||||
</a>
|
||||
</span>
|
||||
</p>
|
||||
{{/if}}
|
||||
|
||||
{{#if this.wikipedia}}
|
||||
<p class="content-with-icon">
|
||||
<Icon @name="wikipedia" @title="Wikipedia" @filled={{true}} />
|
||||
|
||||
52
app/utils/social-links.js
Normal file
52
app/utils/social-links.js
Normal file
@@ -0,0 +1,52 @@
|
||||
// Helper to get value from multiple keys
|
||||
const get = (tags, ...keys) => {
|
||||
for (const k of keys) {
|
||||
if (tags[k]) return tags[k];
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export function getSocialInfo(tags, platform) {
|
||||
if (!tags) return null;
|
||||
|
||||
const key = platform;
|
||||
const domain = `${platform}.com`;
|
||||
const val = get(tags, `contact:${key}`, key);
|
||||
|
||||
if (!val) return null;
|
||||
|
||||
// Check if it's a full URL
|
||||
if (val.startsWith('http')) {
|
||||
try {
|
||||
const url = new URL(val);
|
||||
|
||||
// Handle Facebook profile.php?id=...
|
||||
if (
|
||||
platform === 'facebook' &&
|
||||
url.pathname === '/profile.php' &&
|
||||
url.searchParams.has('id')
|
||||
) {
|
||||
return {
|
||||
url: val,
|
||||
username: url.searchParams.get('id'),
|
||||
};
|
||||
}
|
||||
|
||||
// Clean up pathname to get username
|
||||
let username = url.pathname.replace(/^\/|\/$/g, '');
|
||||
return {
|
||||
url: val,
|
||||
username: username || val, // Fallback to full URL if path is empty
|
||||
};
|
||||
} catch {
|
||||
return { url: val, username: val };
|
||||
}
|
||||
}
|
||||
|
||||
// Assume it's a username
|
||||
const username = val.replace(/^@/, ''); // Remove leading @
|
||||
return {
|
||||
url: `https://${domain}/${username}`,
|
||||
username: username,
|
||||
};
|
||||
}
|
||||
66
tests/unit/utils/social-links-test.js
Normal file
66
tests/unit/utils/social-links-test.js
Normal file
@@ -0,0 +1,66 @@
|
||||
import { getSocialInfo } from 'marco/utils/social-links';
|
||||
import { module, test } from 'qunit';
|
||||
|
||||
module('Unit | Utility | social-links', function () {
|
||||
test('it returns null if tags are missing', function (assert) {
|
||||
let result = getSocialInfo({}, 'facebook');
|
||||
assert.strictEqual(result, null);
|
||||
});
|
||||
|
||||
test('it returns null if specific platform tags are missing', function (assert) {
|
||||
let result = getSocialInfo({ twitter: 'foo' }, 'facebook');
|
||||
assert.strictEqual(result, null);
|
||||
});
|
||||
|
||||
test('it handles simple usernames', function (assert) {
|
||||
let result = getSocialInfo({ facebook: 'foo' }, 'facebook');
|
||||
assert.deepEqual(result, {
|
||||
url: 'https://facebook.com/foo',
|
||||
username: 'foo',
|
||||
});
|
||||
|
||||
result = getSocialInfo({ 'contact:instagram': '@bar' }, 'instagram');
|
||||
assert.deepEqual(result, {
|
||||
url: 'https://instagram.com/bar',
|
||||
username: 'bar',
|
||||
});
|
||||
});
|
||||
|
||||
test('it handles full URLs', function (assert) {
|
||||
let result = getSocialInfo(
|
||||
{ facebook: 'https://www.facebook.com/foo' },
|
||||
'facebook'
|
||||
);
|
||||
assert.deepEqual(result, {
|
||||
url: 'https://www.facebook.com/foo',
|
||||
username: 'foo',
|
||||
});
|
||||
});
|
||||
|
||||
test('it handles Facebook profile.php URLs', function (assert) {
|
||||
let result = getSocialInfo(
|
||||
{ facebook: 'https://www.facebook.com/profile.php?id=12345' },
|
||||
'facebook'
|
||||
);
|
||||
assert.deepEqual(result, {
|
||||
url: 'https://www.facebook.com/profile.php?id=12345',
|
||||
username: '12345',
|
||||
});
|
||||
});
|
||||
|
||||
test('it falls back gracefully for malformed URLs', function (assert) {
|
||||
let result = getSocialInfo({ facebook: 'http://' }, 'facebook');
|
||||
assert.deepEqual(result, {
|
||||
url: 'http://',
|
||||
username: 'http://',
|
||||
});
|
||||
});
|
||||
|
||||
test('it prioritizes contact:tag over tag', function (assert) {
|
||||
let result = getSocialInfo(
|
||||
{ 'contact:facebook': 'priority', facebook: 'fallback' },
|
||||
'facebook'
|
||||
);
|
||||
assert.strictEqual(result.username, 'priority');
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user