mirror of
https://github.com/cydrobolt/polr.git
synced 2024-11-09 11:42:28 +01:00
Merge branch 'master' into delete-link-confirm
This commit is contained in:
commit
40e961e6fe
1
.github/ISSUE_TEMPLATE.md
vendored
1
.github/ISSUE_TEMPLATE.md
vendored
@ -1,4 +1,5 @@
|
||||
<!--- Provide a general summary of the issue in the Title above -->
|
||||
<!--- IMPORTANT: Please follow the format displayed in this template, or your ticket may be ignored. -->
|
||||
|
||||
## Expected Behavior
|
||||
<!--- If you're describing a bug, tell us what should happen -->
|
||||
|
17
README.md
17
README.md
@ -1,10 +1,11 @@
|
||||
# [![Logo](http://i.imgur.com/aOtrJNz.png)](https://polrproject.org)
|
||||
<img src="https://i.imgur.com/ckI6GTu.png" width="350px" alt="Polr Logo" />
|
||||
|
||||
|
||||
:aerial_tramway: A modern, minimalist, and lightweight URL shortener.
|
||||
|
||||
[![GitHub license](https://img.shields.io/badge/license-GPLv2%2B-blue.svg)]()
|
||||
[![GitHub release](https://img.shields.io/github/release/cydrobolt/polr.svg)](https://github.com/cydrobolt/polr/releases)
|
||||
[![Builds status](https://travis-ci.org/cydrobolt/polr.svg)](https://travis-ci.org/cydrobolt/polr)
|
||||
[![Builds status](https://travis-ci.org/cydrobolt/polr.svg)](https://travis-ci.org/cydrobolt/polr)
|
||||
[![Docs](https://img.shields.io/badge/docs-latest-brightgreen.svg?style=flat)](http://polr.readthedocs.org/en/latest/)
|
||||
|
||||
|
||||
@ -16,7 +17,7 @@ Polr is an intrepid, self-hostable open-source link shortening web application w
|
||||
|
||||
Polr is written in PHP and Lumen, using MySQL as its primary database.
|
||||
|
||||
- To get started with Polr on your server, check out the [installation guide](http://docs.polrproject.org/en/latest/user-guide/installation/). You can clone this repository, or download a [release](https://github.com/cydrobolt/polr/releases).
|
||||
- To get started with Polr on your server, check out the [installation guide](http://docs.polrproject.org/en/latest/user-guide/installation/). You can clone this repository, or download a [release](https://github.com/cydrobolt/polr/releases).
|
||||
- To get started with the Polr API, check out the [API guide](http://docs.polrproject.org/en/latest/developer-guide/api/).
|
||||
|
||||
|
||||
@ -44,11 +45,17 @@ There are breaking changes between 2.x and 1.x; it is not yet possible to automa
|
||||
|
||||
* Safari - [Polr.safariextension](https://github.com/cleverdevil/Polr.safariextension)
|
||||
|
||||
#### Sponsors
|
||||
#### Libraries
|
||||
|
||||
* Python - [mypolr](https://github.com/fauskanger/mypolr)
|
||||
|
||||
#### Acknowledgements
|
||||
We would like to thank Oregon State University's Open Source Lab for providing resources for our infrastructure. The Polr website and demo are hosted on their infrastructure.
|
||||
|
||||
<a href="//osuosl.org"><img height="100em" src="http://i.imgur.com/1VtLxyX.png" /></a>
|
||||
|
||||
Thank you to [lastspark](https://thenounproject.com/lastspark/) for providing our logo's icon.
|
||||
|
||||
#### Versioning
|
||||
|
||||
Polr uses [Semantic Versioning](http://semver.org/)
|
||||
@ -57,7 +64,7 @@ Polr uses [Semantic Versioning](http://semver.org/)
|
||||
#### License
|
||||
|
||||
|
||||
Copyright (C) 2013-2017 Chaoyi Zha
|
||||
Copyright (C) 2013-2018 Chaoyi Zha
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
|
@ -51,7 +51,7 @@ class Handler extends ExceptionHandler {
|
||||
return redirect()->to(env('SETTING_INDEX_REDIRECT'));
|
||||
}
|
||||
// Otherwise, show a nice error page
|
||||
return view('errors.404');
|
||||
return response(view('errors.404'), 404);
|
||||
}
|
||||
if ($e instanceof HttpException) {
|
||||
// Handle HTTP exceptions thrown by public-facing controllers
|
||||
@ -60,11 +60,15 @@ class Handler extends ExceptionHandler {
|
||||
|
||||
if ($status_code == 500) {
|
||||
// Render a nice error page for 500s
|
||||
return view('errors.500');
|
||||
return response(view('errors.500'), 500);
|
||||
}
|
||||
else {
|
||||
// If not 500, render generic page
|
||||
return response(view('errors.generic', ['status_code' => $status_code, 'status_message' => $status_message]), $status_code);
|
||||
return response(
|
||||
view('errors.generic', [
|
||||
'status_code' => $status_code,
|
||||
'status_message' => $status_message
|
||||
]), $status_code);
|
||||
}
|
||||
}
|
||||
if ($e instanceof ApiException) {
|
||||
|
@ -23,11 +23,15 @@ class ApiHelper {
|
||||
$api_quota = env('SETTING_ANON_API_QUOTA') ?: 5;
|
||||
}
|
||||
|
||||
if ($api_quota < 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$links_last_minute = Link::where('is_api', 1)
|
||||
->where('creator', $username)
|
||||
->where('created_at', '>=', $last_minute)
|
||||
->count();
|
||||
|
||||
return ($api_quota > -1 && $links_last_minute >= $api_quota);
|
||||
return $links_last_minute >= $api_quota;
|
||||
}
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ class AdminPaginationController extends Controller {
|
||||
/* Cell rendering functions */
|
||||
|
||||
public function renderLongUrlCell($link) {
|
||||
return '<a target="_blank" title="' . e($link->long_url) . '" href="'. $link->long_url .'">' . str_limit($link->long_url, 50) . '</a>
|
||||
<a class="btn btn-primary btn-xs edit-long-link-btn" ng-click="editLongLink(\'' . $link->short_url . '\', \'' . $link->long_url . '\')"><i class="fa fa-edit edit-link-icon"></i></a>';
|
||||
return '<a target="_blank" title="' . e($link->long_url) . '" href="'. e($link->long_url) .'">' . e(str_limit($link->long_url, 50)) . '</a>
|
||||
<a class="btn btn-primary btn-xs edit-long-link-btn" ng-click="editLongLink(\'' . e($link->short_url) . '\', \'' . e($link->long_url) . '\')"><i class="fa fa-edit edit-link-icon"></i></a>';
|
||||
}
|
||||
|
||||
public function renderClicksCell($link) {
|
||||
@ -123,6 +123,12 @@ class AdminPaginationController extends Controller {
|
||||
</a>';
|
||||
}
|
||||
|
||||
public function renderControlLinkCell($link){
|
||||
return '<div class="btn-group" role="group">
|
||||
' . $this->renderToggleLinkActiveCell($link) . $this->renderDeleteLinkCell($link) . '
|
||||
</div>';
|
||||
}
|
||||
|
||||
/* DataTables bindings */
|
||||
|
||||
public function paginateAdminUsers(Request $request) {
|
||||
@ -143,8 +149,7 @@ class AdminPaginationController extends Controller {
|
||||
|
||||
$admin_links = Link::select(['short_url', 'long_url', 'clicks', 'created_at', 'creator', 'is_disabled']);
|
||||
return Datatables::of($admin_links)
|
||||
->addColumn('disable', [$this, 'renderToggleLinkActiveCell'])
|
||||
->addColumn('delete', [$this, 'renderDeleteLinkCell'])
|
||||
->addColumn('control', [$this, 'renderControlLinkCell'])
|
||||
->editColumn('clicks', [$this, 'renderClicksCell'])
|
||||
->editColumn('long_url', [$this, 'renderLongUrlCell'])
|
||||
->escapeColumns(['short_url', 'creator'])
|
||||
|
@ -30,6 +30,7 @@ class UserController extends Controller {
|
||||
|
||||
public function performLogoutUser(Request $request) {
|
||||
$request->session()->forget('username');
|
||||
$request->session()->forget('role');
|
||||
return redirect()->route('index');
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,36 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class CreateApiQuotaIndex extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('links', function (Blueprint $table)
|
||||
{
|
||||
$table->index(
|
||||
['created_at', 'creator', 'is_api'],
|
||||
'api_quota_index'
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('links', function (Blueprint $table)
|
||||
{
|
||||
$table->dropIndex('api_quota_index');
|
||||
});
|
||||
}
|
||||
}
|
@ -5,9 +5,6 @@ To interact with Polr's API, you may opt to use a library or write your own inte
|
||||
As not all languages and frameworks are currently supported by a library, it is encouraged
|
||||
that you take a look at the [API documentation](api/) to integrate Polr into your application.
|
||||
|
||||
### Official Libraries
|
||||
- there are no official libraries for Polr 2.0 yet.
|
||||
|
||||
### Unofficial libraries
|
||||
- there are no unofficial libraries for Polr 2.0 yet.
|
||||
- perhaps you'd like to write one? Send a PR to add your library to this page.
|
||||
## Unofficial libraries
|
||||
### Python
|
||||
- [mypolr](https://github.com/fauskanger/mypolr) is a Python 3 package for interacting with the Polr 2.0 API. ([Documentation](https://mypolr.readthedocs.io))
|
||||
|
BIN
docs/logo.png
BIN
docs/logo.png
Binary file not shown.
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 9.2 KiB |
@ -17,11 +17,11 @@
|
||||
}
|
||||
|
||||
.logo-img {
|
||||
width: 18em;
|
||||
width: 17em;
|
||||
}
|
||||
|
||||
.logo-well {
|
||||
width: 19em;
|
||||
width: 20.5em;
|
||||
|
||||
-webkit-animation: colorpulse 20s infinite;
|
||||
animation: colorpulse 20s infinite;
|
||||
|
@ -37,7 +37,7 @@ input.api-quota {
|
||||
display: inline;
|
||||
width: 9em;
|
||||
font-size: .85em;
|
||||
height: .85em;
|
||||
height: auto;
|
||||
padding-left: 0.8em;
|
||||
}
|
||||
|
||||
|
@ -5,10 +5,29 @@
|
||||
|
||||
}
|
||||
|
||||
.back-btn {
|
||||
.btn {
|
||||
margin-top: 30px;
|
||||
}
|
||||
|
||||
.content-div {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.qr-code-container {
|
||||
display: none;
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
.qr-code-container img {
|
||||
display: inline !important;
|
||||
}
|
||||
|
||||
.input-group {
|
||||
width: 40vw;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.input-group-addon {
|
||||
padding: 0px 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
Binary file not shown.
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 9.8 KiB |
@ -152,15 +152,12 @@ polr.controller('AdminCtrl', function($scope, $compile, $timeout) {
|
||||
"ajax": BASE_API_PATH + 'admin/get_admin_links',
|
||||
|
||||
"columns": [
|
||||
{className: 'wrap-text', data: 'short_url', name: 'short_url'},
|
||||
{className: 'wrap-text', data: 'short_url', name: 'short_url', width: '10%'},
|
||||
{className: 'wrap-text', data: 'long_url', name: 'long_url'},
|
||||
{data: 'clicks', name: 'clicks'},
|
||||
{data: 'created_at', name: 'created_at'},
|
||||
{data: 'creator', name: 'creator'},
|
||||
|
||||
{data: 'disable', name: 'disable', orderable: false, searchable: false},
|
||||
{data: 'delete', name: 'delete', orderable: false, searchable: false}
|
||||
|
||||
{data: 'clicks', name: 'clicks', width: '10%'},
|
||||
{data: 'created_at', name: 'created_at', width: '18%'},
|
||||
{data: 'creator', name: 'creator', width: '20%'},
|
||||
{data: 'control', name: 'control', orderable: false, searchable: false, width: '15%'},
|
||||
]
|
||||
}, datatables_config));
|
||||
}
|
||||
|
7
public/js/clipboard.min.js
vendored
Normal file
7
public/js/clipboard.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
1
public/js/qrcode.min.js
vendored
Normal file
1
public/js/qrcode.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@ -9,6 +9,32 @@ $('.result-box').change(function () {
|
||||
$(this).val(original_link);
|
||||
});
|
||||
|
||||
|
||||
$('#generate-qr-code').click(function () {
|
||||
var container = $('.qr-code-container');
|
||||
container.empty();
|
||||
new QRCode(container.get(0), {
|
||||
text: original_link,
|
||||
width: 280,
|
||||
height: 280
|
||||
});
|
||||
container.find('img').attr('alt', original_link);
|
||||
container.show();
|
||||
});
|
||||
|
||||
|
||||
var clipboard = new Clipboard('#clipboard-copy');
|
||||
clipboard.on('success', function(e) {
|
||||
e.clearSelection();
|
||||
$('#clipboard-copy').tooltip('show');
|
||||
});
|
||||
|
||||
$('#clipboard-copy').on('blur',function () {
|
||||
$(this).tooltip('destroy');
|
||||
}).on('mouseleave',function () {
|
||||
$(this).tooltip('destroy');
|
||||
});
|
||||
|
||||
$(function () {
|
||||
original_link = $('.result-box').val();
|
||||
select_text();
|
||||
|
@ -6,10 +6,22 @@
|
||||
|
||||
@section('content')
|
||||
<h3>Shortened URL</h3>
|
||||
<input type='text' class='result-box form-control' value='{{$short_url}}' />
|
||||
<a href='{{route('index')}}' class='btn btn-info back-btn'>Shorten another</a>
|
||||
<div class="input-group">
|
||||
<input type='text' class='result-box form-control' value='{{$short_url}}' id='short_url' />
|
||||
<div class='input-group-addon' id='clipboard-copy' data-clipboard-target='#short_url' data-toggle='tooltip' data-placement='bottom' data-title='Copied!'>
|
||||
<i class='fa fa-clipboard' aria-hidden='true' title='Copy to clipboard'></i>
|
||||
</div>
|
||||
</div>
|
||||
<a id="generate-qr-code" class='btn btn-primary'>Generate QR Code</a>
|
||||
<a href='{{route('index')}}' class='btn btn-info'>Shorten another</a>
|
||||
|
||||
<div class="qr-code-container"></div>
|
||||
|
||||
@endsection
|
||||
|
||||
|
||||
@section('js')
|
||||
<script src='/js/qrcode.min.js'></script>
|
||||
<script src='/js/clipboard.min.js'></script>
|
||||
<script src='/js/shorten_result.js'></script>
|
||||
@endsection
|
||||
|
@ -8,8 +8,7 @@
|
||||
@if ($table_id == "admin_links_table")
|
||||
{{-- Show action buttons only if admin view --}}
|
||||
<th>Creator</th>
|
||||
<th>Disable</th>
|
||||
<th>Delete</th>
|
||||
<th>Control</th>
|
||||
@endif
|
||||
</tr>
|
||||
</thead>
|
||||
|
Loading…
Reference in New Issue
Block a user