mirror of
https://github.com/Kovah/LinkAce.git
synced 2025-02-24 11:13:02 +01:00
commit
9cb4f25e4f
@ -231,6 +231,15 @@ Currently you can do this by using the command line:
|
||||
docker exec -it linkace-php bash -c "php artisan registeruser [user name] [user email]"
|
||||
```
|
||||
|
||||
|
||||
### Tests
|
||||
|
||||
You may run some existing tests with the following command:
|
||||
|
||||
```bash
|
||||
docker exec -it linkace-php bash -c "./vendor/bin/phpunit"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
LinkAce is a project by [Kovah](https://kovah.de) | [Contributors](https://github.com/Kovah/LinkAce/graphs/contributors)
|
||||
|
@ -17,10 +17,8 @@ class LinkAce
|
||||
*/
|
||||
public static function getMetaFromURL(string $url)
|
||||
{
|
||||
$title_fallback = parse_url($url, PHP_URL_HOST);
|
||||
|
||||
$fallback = [
|
||||
'title' => $title_fallback,
|
||||
'title' => parse_url($url, PHP_URL_HOST),
|
||||
'description' => null,
|
||||
];
|
||||
|
||||
@ -31,7 +29,14 @@ class LinkAce
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
if (!$html) {
|
||||
// Try to get the meta tags of that URL
|
||||
try {
|
||||
$tags = get_meta_tags($url);
|
||||
} catch (\Exception $e) {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
if (empty($html)) {
|
||||
return $fallback;
|
||||
}
|
||||
|
||||
@ -44,22 +49,15 @@ class LinkAce
|
||||
$title = trim($title);
|
||||
}
|
||||
|
||||
// Parse the HTML for the meta description, or alternatively for the og:description property
|
||||
$res = preg_match(
|
||||
'/<meta (?:property="og:description"|name="description") content="(.*?)"(?:\s\/)?>/i',
|
||||
$html,
|
||||
$description_matches
|
||||
);
|
||||
|
||||
if ($res) {
|
||||
// Clean up description: remove EOL's and excessive whitespace.
|
||||
$description = preg_replace('/\s+/', ' ', $description_matches[1]);
|
||||
$description = trim($description);
|
||||
}
|
||||
// Get the title or the og:description tag or the twitter:description tag
|
||||
$description = $tags['description']
|
||||
?? $tags['og:description']
|
||||
?? $tags['twitter:description']
|
||||
?? $fallback['description'];
|
||||
|
||||
return [
|
||||
'title' => $title ?? $title_fallback,
|
||||
'description' => $description ?? null,
|
||||
'title' => $title,
|
||||
'description' => $description,
|
||||
];
|
||||
}
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
namespace App\Http\Controllers\API;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Link;
|
||||
use App\Models\Tag;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
@ -43,4 +44,30 @@ class AjaxController extends Controller
|
||||
|
||||
return response()->json($tags);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function searchExistingUrls(Request $request)
|
||||
{
|
||||
$query = $request->get('query', false);
|
||||
|
||||
if (!$query) {
|
||||
return response()->json([]);
|
||||
}
|
||||
|
||||
// Search for tags
|
||||
$links = Link::byUser(auth()->user()->id)
|
||||
->where('url', trim($query))
|
||||
->first();
|
||||
|
||||
if (empty($links)) {
|
||||
// No links found
|
||||
return response()->json(['linkFound' => false]);
|
||||
}
|
||||
|
||||
// Link found
|
||||
return response()->json(['linkFound' => true]);
|
||||
}
|
||||
}
|
||||
|
@ -36,7 +36,7 @@ services:
|
||||
container_name: "linkace-nginx"
|
||||
image: bitnami/nginx:1.14
|
||||
ports:
|
||||
- "127.0.0.1:80:8085"
|
||||
- "80:8085"
|
||||
depends_on:
|
||||
- php
|
||||
volumes:
|
||||
|
63
package-lock.json
generated
63
package-lock.json
generated
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "linkace",
|
||||
"version": "0.0.13",
|
||||
"version": "0.0.14",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
@ -72,9 +72,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"ajv": {
|
||||
"version": "6.6.2",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.6.2.tgz",
|
||||
"integrity": "sha512-FBHEW6Jf5TB9MGBgUUA9XHkTbjXYfAUjY43ACMfmdMRHniyoMHjHjzD50OK8LGDWQwp4rWEsIq5kEqq7rvIM1g==",
|
||||
"version": "6.10.0",
|
||||
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.0.tgz",
|
||||
"integrity": "sha512-nffhOpkymDECQyR0mnsUtoCE8RlX38G0rYP+wgLWFyZuUyuuojSSvi/+euOiQBIn63whYwYVIIH1TvE3tu4OEg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"fast-deep-equal": "^2.0.1",
|
||||
@ -4879,9 +4879,9 @@
|
||||
"integrity": "sha512-ggRCXln9zEqv6OqAGXFEcshF5dSBvCkzj6Gm2gzuR5fWawaX8t7cxKVkkygKODrDAzKdoYw3l/e3pm3vlT4IbQ=="
|
||||
},
|
||||
"js-base64": {
|
||||
"version": "2.5.0",
|
||||
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.0.tgz",
|
||||
"integrity": "sha512-wlEBIZ5LP8usDylWbDNhKPEFVFdI5hCHpnVoT/Ysvoi/PRhJENm/Rlh9TvjYB38HFfKZN7OzEbRjmjvLkFw11g==",
|
||||
"version": "2.5.1",
|
||||
"resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.5.1.tgz",
|
||||
"integrity": "sha512-M7kLczedRMYX4L8Mdh4MzyAMM9O5osx+4FcOQuTvr3A9F2D9S5JXheN0ewNbrvK2UatkTRhL5ejGmGSjNMiZuw==",
|
||||
"dev": true
|
||||
},
|
||||
"js-tokens": {
|
||||
@ -5116,18 +5116,6 @@
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz",
|
||||
"integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg=="
|
||||
},
|
||||
"lodash.assign": {
|
||||
"version": "4.2.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz",
|
||||
"integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.clonedeep": {
|
||||
"version": "4.5.0",
|
||||
"resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz",
|
||||
"integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.isfinite": {
|
||||
"version": "3.3.2",
|
||||
"resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz",
|
||||
@ -5146,12 +5134,6 @@
|
||||
"integrity": "sha512-AOYza4+Hf5z1/0Hztxpm2/xiPZgi/cjMqdnKTUWTBSKchJlxXXuUSxCCl8rJlf4g6yww/j6mA8nC8Hw/EZWxKQ==",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.mergewith": {
|
||||
"version": "4.6.1",
|
||||
"resolved": "https://registry.npmjs.org/lodash.mergewith/-/lodash.mergewith-4.6.1.tgz",
|
||||
"integrity": "sha512-eWw5r+PYICtEBgrBE5hhlT6aAa75f411bgDz/ZL2KZqYV03USvucsxcHUIlGTDTECs1eunpI7HOV7U+WLDvNdQ==",
|
||||
"dev": true
|
||||
},
|
||||
"loose-envify": {
|
||||
"version": "1.4.0",
|
||||
"resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
|
||||
@ -5471,7 +5453,8 @@
|
||||
"version": "2.11.0",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.11.0.tgz",
|
||||
"integrity": "sha512-F4miItu2rGnV2ySkXOQoA8FKz/SR2Q2sWP0sbTxNxz/tuokeC8WxOhPMcwi0qIyGtVn/rrSeLbvVkznqCdwYnw==",
|
||||
"dev": true
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"nanomatch": {
|
||||
"version": "1.2.13",
|
||||
@ -5559,9 +5542,9 @@
|
||||
}
|
||||
},
|
||||
"node-sass": {
|
||||
"version": "4.11.0",
|
||||
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.11.0.tgz",
|
||||
"integrity": "sha512-bHUdHTphgQJZaF1LASx0kAviPH7sGlcyNhWade4eVIpFp6tsn7SV8xNMTbsQFpEV9VXpnwTTnNYlfsZXgGgmkA==",
|
||||
"version": "4.12.0",
|
||||
"resolved": "https://registry.npmjs.org/node-sass/-/node-sass-4.12.0.tgz",
|
||||
"integrity": "sha512-A1Iv4oN+Iel6EPv77/HddXErL2a+gZ4uBeZUy+a8O35CFYTXhgA8MgLCWBtwpGZdCvTvQ9d+bQxX/QC36GDPpQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"async-foreach": "^0.1.3",
|
||||
@ -5571,12 +5554,10 @@
|
||||
"get-stdin": "^4.0.1",
|
||||
"glob": "^7.0.3",
|
||||
"in-publish": "^2.0.0",
|
||||
"lodash.assign": "^4.2.0",
|
||||
"lodash.clonedeep": "^4.3.2",
|
||||
"lodash.mergewith": "^4.6.0",
|
||||
"lodash": "^4.17.11",
|
||||
"meow": "^3.7.0",
|
||||
"mkdirp": "^0.5.1",
|
||||
"nan": "^2.10.0",
|
||||
"nan": "^2.13.2",
|
||||
"node-gyp": "^3.8.0",
|
||||
"npmlog": "^4.0.0",
|
||||
"request": "^2.88.0",
|
||||
@ -5614,6 +5595,12 @@
|
||||
"which": "^1.2.9"
|
||||
}
|
||||
},
|
||||
"nan": {
|
||||
"version": "2.13.2",
|
||||
"resolved": "https://registry.npmjs.org/nan/-/nan-2.13.2.tgz",
|
||||
"integrity": "sha512-TghvYc72wlMGMVMluVo9WRJc0mB8KxxF/gZ4YYFy7V2ZQX9l7rgbPg7vjS9mt6U5HXODVFVI2bOduCzwOMv/lw==",
|
||||
"dev": true
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
|
||||
@ -7295,9 +7282,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"sshpk": {
|
||||
"version": "1.16.0",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.0.tgz",
|
||||
"integrity": "sha512-Zhev35/y7hRMcID/upReIvRse+I9SVhyVre/KTJSJQWMz3C3+G+HpO7m1wK/yckEtujKZ7dS4hkVxAnmHaIGVQ==",
|
||||
"version": "1.16.1",
|
||||
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
|
||||
"integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"asn1": "~0.2.3",
|
||||
@ -7558,7 +7545,7 @@
|
||||
},
|
||||
"chalk": {
|
||||
"version": "1.1.3",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"resolved": "http://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
|
||||
"integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
@ -8189,7 +8176,7 @@
|
||||
},
|
||||
"yargs": {
|
||||
"version": "6.4.0",
|
||||
"resolved": "https://registry.npmjs.org/yargs/-/yargs-6.4.0.tgz",
|
||||
"resolved": "http://registry.npmjs.org/yargs/-/yargs-6.4.0.tgz",
|
||||
"integrity": "sha1-gW4ahm1VmMzzTlWW3c4i2S2kkNQ=",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "linkace",
|
||||
"version": "0.0.13",
|
||||
"version": "0.0.14",
|
||||
"description": "A small, selfhosted bookmark manager with advanced features, built with Laravel and Docker",
|
||||
"homepage": "https://github.com/Kovah/LinkAce",
|
||||
"repository": {
|
||||
@ -34,7 +34,7 @@
|
||||
"grunt-postcss": "^0.9.0",
|
||||
"grunt-sass": "^3.0.2",
|
||||
"load-grunt-tasks": "^4.0.0",
|
||||
"node-sass": "^4.11.0",
|
||||
"node-sass": "^4.12.0",
|
||||
"postcss": "^6.0.23",
|
||||
"time-grunt": "^1.4.0",
|
||||
"uglifyify": "^5.0.1"
|
||||
|
28
resources/assets/js/app.js
vendored
28
resources/assets/js/app.js
vendored
@ -1,12 +1,20 @@
|
||||
// Set CSS based on
|
||||
const preferDarkmode = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
const darkmodeAuto = document.documentElement.querySelector('meta[name="darkmode"]');
|
||||
import { register } from './lib/views';
|
||||
|
||||
if (darkmodeAuto) {
|
||||
const stylesheet = document.documentElement.querySelector('[rel="stylesheet"]');
|
||||
if (preferDarkmode) {
|
||||
stylesheet.href = stylesheet.dataset.darkHref;
|
||||
} else {
|
||||
stylesheet.href = stylesheet.dataset.lightHref;
|
||||
}
|
||||
// Register components
|
||||
import Base from './components/Base';
|
||||
import UrlField from './components/UrlField';
|
||||
|
||||
// Register view components
|
||||
function registerViews () {
|
||||
// register component views
|
||||
register('#app', Base);
|
||||
register('input[id="url"]', UrlField);
|
||||
}
|
||||
|
||||
if (document.readyState !== 'loading') {
|
||||
// dom loaded event already fired
|
||||
registerViews();
|
||||
} else {
|
||||
// wait for the dom to load
|
||||
document.addEventListener('DOMContentLoaded', registerViews);
|
||||
}
|
||||
|
28
resources/assets/js/components/Base.js
vendored
Normal file
28
resources/assets/js/components/Base.js
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
export default class Base {
|
||||
|
||||
constructor ($el) {
|
||||
this.initAppData();
|
||||
this.initAutoDarkmode();
|
||||
}
|
||||
|
||||
initAppData () {
|
||||
// Load data passed by the backend to the JS
|
||||
let data = document.querySelector('meta[property="la-app-data"]').getAttribute('content');
|
||||
window.appData = JSON.parse(data);
|
||||
}
|
||||
|
||||
initAutoDarkmode () {
|
||||
// Set CSS based on user preference for dark mode
|
||||
const preferDarkmode = window.matchMedia('(prefers-color-scheme: dark)').matches;
|
||||
const darkmodeAuto = document.querySelector('meta[name="darkmode"]');
|
||||
|
||||
if (darkmodeAuto) {
|
||||
const stylesheet = document.querySelector('[rel="stylesheet"]');
|
||||
if (preferDarkmode) {
|
||||
stylesheet.href = stylesheet.dataset.darkHref;
|
||||
} else {
|
||||
stylesheet.href = stylesheet.dataset.lightHref;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
53
resources/assets/js/components/UrlField.js
vendored
Normal file
53
resources/assets/js/components/UrlField.js
vendored
Normal file
@ -0,0 +1,53 @@
|
||||
import { debounce } from '../lib/helper';
|
||||
|
||||
export default class UrlField {
|
||||
|
||||
constructor ($el) {
|
||||
this.$field = $el;
|
||||
|
||||
this.$field.addEventListener('keyup', this.onKeyup.bind(this));
|
||||
}
|
||||
|
||||
onKeyup () {
|
||||
// Debounce the keyup function to wait 500ms until the last input was typed
|
||||
debounce(() => {
|
||||
const value = this.$field.value;
|
||||
|
||||
// Check for existing links if the value is longer than http://
|
||||
if (value.length > 6) {
|
||||
this.checkforExistingUrl(value);
|
||||
} else {
|
||||
this.resetField();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
checkforExistingUrl (url) {
|
||||
const checkUrl = window.appData.routes.ajax.existingLinks;
|
||||
|
||||
fetch(checkUrl, {
|
||||
method: 'POST',
|
||||
credentials: 'same-origin',
|
||||
headers: {'Content-Type': 'application/json'},
|
||||
body: JSON.stringify({
|
||||
_token: window.appData.user.token,
|
||||
query: url
|
||||
})
|
||||
}).then((response) => {
|
||||
return response.json();
|
||||
}).then((result) => {
|
||||
|
||||
// If the link already exist, mark the field as invalid
|
||||
if (result.linkFound === true) {
|
||||
this.$field.classList.add('is-invalid');
|
||||
} else {
|
||||
this.$field.classList.remove('is-invalid');
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
resetField () {
|
||||
this.$field.classList.remove('is-invalid');
|
||||
}
|
||||
}
|
16
resources/assets/js/lib/helper.js
vendored
Normal file
16
resources/assets/js/lib/helper.js
vendored
Normal file
@ -0,0 +1,16 @@
|
||||
/**
|
||||
* Debounce a function with a given timeout
|
||||
*
|
||||
* @see https://gist.github.com/makenova/7885923
|
||||
* @param {CallableFunction} callback
|
||||
* @param {int} [timeout=500] timeout
|
||||
*/
|
||||
export function debounce (callback, timeout = 500) {
|
||||
if (window.timeoutId) {
|
||||
window.clearTimeout(window.timeoutId);
|
||||
}
|
||||
|
||||
window.timeoutId = window.setTimeout(function () {
|
||||
callback();
|
||||
}, timeout);
|
||||
}
|
46
resources/assets/js/lib/views.js
vendored
Normal file
46
resources/assets/js/lib/views.js
vendored
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* View elements
|
||||
* @type {HTMLElement[]}
|
||||
*/
|
||||
const $views = [];
|
||||
|
||||
/**
|
||||
* View instances
|
||||
* @type {object[]}
|
||||
*/
|
||||
const views = [];
|
||||
|
||||
/**
|
||||
* Registers a view to a name and saves a reference.
|
||||
* @param {string} name View name
|
||||
* @param {function} invokable View class
|
||||
* @param {HTMLElement} [$root=document.documentElement] Root element
|
||||
* @return {void}
|
||||
*/
|
||||
export function register (name, invokable, $root = document.documentElement) {
|
||||
// Retrieve all view elements in root
|
||||
const $elements = [...$root.querySelectorAll(`${name}`)];
|
||||
|
||||
// Create an instance for each view
|
||||
$elements.forEach($element => getInstance($element, invokable));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the view instance by given element.
|
||||
* @return {HTMLElement} $element Element
|
||||
* @return {function} invokable Element class
|
||||
* @return {object}|null View instance or null if there is none
|
||||
*/
|
||||
export function getInstance ($element, invokable = null) {
|
||||
const index = $views.indexOf($element);
|
||||
if (index !== -1) {
|
||||
return views[index];
|
||||
} else if (invokable !== null && $views.indexOf($element) === -1) {
|
||||
const view = new invokable($element);
|
||||
$views.push($element);
|
||||
views.push(view);
|
||||
return view;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
1
resources/assets/sass/custom/_app.scss
vendored
1
resources/assets/sass/custom/_app.scss
vendored
@ -10,6 +10,7 @@ body:not(.bookmarklet) {
|
||||
|
||||
.footer {
|
||||
opacity: .5;
|
||||
padding-bottom: ($spacer * 2);
|
||||
}
|
||||
|
||||
@media (max-width: 991px) {
|
||||
|
@ -13,6 +13,11 @@
|
||||
class="form-control form-control-lg{{ $errors->has('url') ? ' is-invalid' : '' }}"
|
||||
placeholder="@lang('link.url')" value="{{ old('url') ?: $bookmark_url ?? '' }}"
|
||||
required autofocus>
|
||||
|
||||
<p class="invalid-feedback {{ $errors->has('url') ? 'd-none' : '' }}">
|
||||
@lang('validation.unique', ['attribute' => trans('link.url')])
|
||||
</p>
|
||||
|
||||
@if ($errors->has('url'))
|
||||
<p class="invalid-feedback" role="alert">
|
||||
{{ $errors->first('url') }}
|
||||
@ -57,7 +62,7 @@
|
||||
class="{{ $errors->has('category_id') ? ' is-invalid' : '' }}">
|
||||
<option value="0">@lang('category.select_category')</option>
|
||||
@foreach($categories as $category)
|
||||
@if($category->childCategories)
|
||||
@if($category->childCategories->count() > 0)
|
||||
<optgroup label="{{ $category->name }}">
|
||||
<option value="{{ $category->id }}">
|
||||
{{ $category->name }}
|
||||
@ -77,7 +82,6 @@
|
||||
@endforeach
|
||||
</select>
|
||||
|
||||
|
||||
@if ($errors->has('category_id'))
|
||||
<p class="invalid-feedback" role="alert">
|
||||
{{ $errors->first('category_id') }}
|
||||
|
@ -32,7 +32,7 @@
|
||||
</div>
|
||||
|
||||
<button type="submit" class="btn btn-sm btn-primary">
|
||||
<i class="fa fa-save fa-mr"></i> @lang('link.add')
|
||||
<i class="fa fa-save fa-mr"></i> @lang('note.add')
|
||||
</button>
|
||||
|
||||
</div>
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
@if ($errors->any())
|
||||
<div class="alert alert-danger">
|
||||
<ul class="mb-0">
|
||||
<ul class="mb-0 list-unstyled">
|
||||
@foreach ($errors->all() as $error)
|
||||
<li>{{ $error }}</li>
|
||||
@endforeach
|
||||
|
@ -20,6 +20,17 @@
|
||||
|
||||
<link href="{{ asset('assets/dist/css/fa.min.css') }}" rel="stylesheet">
|
||||
|
||||
<meta property="la-app-data" content="{{ json_encode([
|
||||
'user' => [
|
||||
'token' => csrf_token()
|
||||
],
|
||||
'routes' => [
|
||||
'ajax' => [
|
||||
'existingLinks' => route('ajax-existing-links')
|
||||
]
|
||||
]
|
||||
]) }}">
|
||||
|
||||
<link rel="apple-touch-icon" sizes="57x57" href="{{ asset('assets/img/apple-icon-57x57.png') }}">
|
||||
<link rel="apple-touch-icon" sizes="60x60" href="{{ asset('assets/img/apple-icon-60x60.png') }}">
|
||||
<link rel="apple-touch-icon" sizes="72x72" href="{{ asset('assets/img/apple-icon-72x72.png') }}">
|
||||
|
@ -73,6 +73,7 @@ Route::group(['middleware' => ['auth']], function () {
|
||||
'App\SystemSettingsController@generateCronToken')->name('generate-cron-token');
|
||||
|
||||
Route::post('ajax/tags', 'API\AjaxController@getTags')->name('ajax-tags');
|
||||
Route::post('ajax/existing-links', 'API\AjaxController@searchExistingUrls')->name('ajax-existing-links');
|
||||
});
|
||||
|
||||
// Guest access routes
|
||||
|
Loading…
x
Reference in New Issue
Block a user