Toggle navigation
Toggle navigation
This project
Loading...
Sign in
Зуев Егор
/
wiki.dev
Go to a project
Toggle navigation
Toggle navigation pinning
Projects
Groups
Snippets
Help
Project
Activity
Repository
Pipelines
Graphs
Issues
0
Merge Requests
0
Wiki
Snippets
Network
Create a new issue
Commits
Issue Boards
Files
Commits
Network
Compare
Branches
Tags
Authored by
Dan Brown
2015-08-16 00:18:22 +0100
Browse Files
Options
Browse Files
Tag
Download
Email Patches
Plain Diff
Commit
e5a372ffbd8c4a3a801406fb83038f81433c2e62
e5a372ff
1 parent
b0808a1c
Added image name editing & deleting
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
201 additions
and
64 deletions
app/Http/Controllers/ImageController.php
app/Http/routes.php
app/Image.php
resources/assets/js/image-manager.js
resources/assets/sass/_animations.scss
resources/assets/sass/_forms.scss
resources/assets/sass/_text.scss
resources/assets/sass/image-manager.scss
resources/assets/sass/styles.scss
resources/views/pages/image-manager.blade.php
app/Http/Controllers/ImageController.php
View file @
e5a372f
...
...
@@ -10,6 +10,9 @@ use Intervention\Image\Facades\Image as ImageTool;
use
Illuminate\Support\Facades\DB
;
use
Oxbow\Http\Requests
;
use
Oxbow\Image
;
use
RecursiveDirectoryIterator
;
use
RecursiveIteratorIterator
;
use
RegexIterator
;
class
ImageController
extends
Controller
{
...
...
@@ -71,7 +74,7 @@ class ImageController extends Controller
*/
public
function
getAll
(
$page
=
0
)
{
$pageSize
=
25
;
$pageSize
=
30
;
$images
=
DB
::
table
(
'images'
)
->
orderBy
(
'created_at'
,
'desc'
)
->
skip
(
$page
*
$pageSize
)
->
take
(
$pageSize
)
->
get
();
foreach
(
$images
as
$image
)
{
...
...
@@ -146,5 +149,44 @@ class ImageController extends Controller
return
response
()
->
json
(
$this
->
image
);
}
/**
* Update image details
* @param $imageId
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public
function
update
(
$imageId
,
Request
$request
)
{
$this
->
validate
(
$request
,
[
'name'
=>
'required|min:2|string'
]);
$image
=
$this
->
image
->
findOrFail
(
$imageId
);
$image
->
fill
(
$request
->
all
());
$image
->
save
();
return
response
()
->
json
(
$this
->
image
);
}
/**
* Deletes an image and all thumbnail/image files
* @param $id
* @return \Illuminate\Http\JsonResponse
*/
public
function
destroy
(
$id
)
{
$image
=
$this
->
image
->
findOrFail
(
$id
);
// Delete files
$folder
=
public_path
()
.
dirname
(
$image
->
url
);
$pattern
=
'/'
.
preg_quote
(
basename
(
$image
->
url
))
.
'/'
;
$dir
=
new
RecursiveDirectoryIterator
(
$folder
);
$ite
=
new
RecursiveIteratorIterator
(
$dir
);
$files
=
new
RegexIterator
(
$ite
,
$pattern
,
RegexIterator
::
ALL_MATCHES
);
foreach
(
$files
as
$path
=>
$file
)
{
unlink
(
$path
);
}
$image
->
delete
();
return
response
()
->
json
(
'Image Deleted'
);
}
}
...
...
app/Http/routes.php
View file @
e5a372f
...
...
@@ -68,6 +68,8 @@ Route::group(['middleware' => 'auth'], function() {
// Image routes
Route
::
get
(
'/images/all'
,
'ImageController@getAll'
);
Route
::
put
(
'/images/update/{imageId}'
,
'ImageController@update'
);
Route
::
delete
(
'/images/{imageId}'
,
'ImageController@destroy'
);
Route
::
get
(
'/images/all/{page}'
,
'ImageController@getAll'
);
Route
::
get
(
'/images/{any}'
,
'ImageController@getImage'
)
->
where
(
'any'
,
'.*'
);
...
...
app/Image.php
View file @
e5a372f
...
...
@@ -6,6 +6,9 @@ use Illuminate\Database\Eloquent\Model;
class
Image
extends
Model
{
protected
$fillable
=
[
'name'
];
public
function
getFilePath
()
{
return
storage_path
()
.
$this
->
url
;
...
...
resources/assets/js/image-manager.js
View file @
e5a372f
jQuery
.
fn
.
showSuccess
=
function
(
message
)
{
var
elem
=
$
(
this
);
var
success
=
$
(
'<div class="text-pos" style="display:none;"><i class="zmdi zmdi-check-circle"></i>'
+
message
+
'</div>'
);
elem
.
after
(
success
);
success
.
slideDown
(
400
,
function
()
{
setTimeout
(
function
()
{
success
.
slideUp
(
400
,
function
()
{
success
.
remove
();
})},
2000
);
});
};
jQuery
.
fn
.
showFailure
=
function
(
messageMap
)
{
var
elem
=
$
(
this
);
$
.
each
(
messageMap
,
function
(
key
,
messages
)
{
var
input
=
elem
.
find
(
'[name="'
+
key
+
'"]'
).
last
();
var
fail
=
$
(
'<div class="text-neg" style="display:none;"><i class="zmdi zmdi-alert-circle"></i>'
+
messages
.
join
(
"\n"
)
+
'</div>'
);
input
.
after
(
fail
);
fail
.
slideDown
(
400
,
function
()
{
setTimeout
(
function
()
{
fail
.
slideUp
(
400
,
function
()
{
fail
.
remove
();
})},
2000
);
});
});
};
(
function
()
{
var
ImageManager
=
new
Vue
({
...
...
@@ -56,7 +82,7 @@
var
dblClickTime
=
380
;
var
cTime
=
(
new
Date
()).
getTime
();
var
timeDiff
=
cTime
-
this
.
cClickTime
;
if
(
this
.
cClickTime
!==
0
&&
timeDiff
<
dblClickTime
)
{
if
(
this
.
cClickTime
!==
0
&&
timeDiff
<
dblClickTime
&&
this
.
selectedImage
===
image
)
{
// DoubleClick
if
(
this
.
callback
)
{
this
.
callback
(
image
);
...
...
@@ -68,6 +94,13 @@
this
.
cClickTime
=
cTime
;
},
selectButtonClick
:
function
()
{
if
(
this
.
callback
)
{
this
.
callback
(
this
.
selectedImage
);
}
this
.
hide
();
},
show
:
function
(
callback
)
{
this
.
callback
=
callback
;
this
.
$$
.
overlay
.
style
.
display
=
'block'
;
...
...
@@ -81,6 +114,34 @@
hide
:
function
()
{
this
.
$$
.
overlay
.
style
.
display
=
'none'
;
},
saveImageDetails
:
function
(
e
)
{
e
.
preventDefault
();
var
_this
=
this
;
var
form
=
$
(
_this
.
$$
.
imageForm
);
$
.
ajax
(
'/images/update/'
+
_this
.
selectedImage
.
id
,
{
method
:
'PUT'
,
data
:
form
.
serialize
()
}).
done
(
function
()
{
form
.
showSuccess
(
'Image name updated'
);
}).
fail
(
function
(
jqXHR
)
{
form
.
showFailure
(
jqXHR
.
responseJSON
);
})
},
deleteImage
:
function
(
e
)
{
e
.
preventDefault
();
var
_this
=
this
;
var
form
=
$
(
_this
.
$$
.
imageDeleteForm
);
$
.
ajax
(
'/images/'
+
_this
.
selectedImage
.
id
,
{
method
:
'DELETE'
,
data
:
form
.
serialize
()
}).
done
(
function
()
{
_this
.
images
.
splice
(
_this
.
images
.
indexOf
(
_this
.
selectedImage
),
1
);
_this
.
selectedImage
=
false
;
$
(
_this
.
$$
.
imageTitle
).
showSuccess
(
'Image Deleted'
);
})
}
}
...
...
resources/assets/sass/_animations.scss
0 → 100644
View file @
e5a372f
.anim.fadeIn
{
opacity
:
0
;
animation-name
:
fadeIn
;
animation-duration
:
160ms
;
animation-timing-function
:
ease-in-out
;
animation-fill-mode
:
forwards
;
}
@keyframes
fadeIn
{
0
%
{
opacity
:
0
;
}
100
%
{
opacity
:
1
;
}
}
\ No newline at end of file
resources/assets/sass/_forms.scss
View file @
e5a372f
...
...
@@ -45,6 +45,12 @@ input[type="text"], input[type="number"], input[type="email"], input[type="searc
margin-bottom
:
$-s
;
}
.form-group
{
.text-pos
,
.text-neg
{
padding
:
$-xs
0
;
}
}
.inline-input-style
{
border
:
2px
dotted
#BBB
;
display
:
block
;
...
...
resources/assets/sass/_text.scss
View file @
e5a372f
...
...
@@ -82,7 +82,7 @@ hr {
&
.faded
{
background-image
:
linear-gradient
(
to
right
,
#FFF
,
#e3e0e0
20%
,
#e3e0e0
80%
,
#FFF
);
}
&
.margin-top
{
&
.margin-top
,
&
.even
{
margin-top
:
$-l
;
}
}
...
...
@@ -227,4 +227,11 @@ ul {
.list
>
*
{
display
:
block
;
}
/**
* Icons
*/
i
{
padding-right
:
$-xs
;
}
\ No newline at end of file
...
...
resources/assets/sass/image-manager.scss
View file @
e5a372f
.image-manager-body
{
background-color
:
rgb
(
37
,
37
,
37
);
max-width
:
90%
;
background-color
:
#FFF
;
max-height
:
90%
;
width
:
90%
;
height
:
90%
;
...
...
@@ -9,18 +8,7 @@
border-radius
:
4px
;
box-shadow
:
0
0
15px
0
rgba
(
0
,
0
,
0
,
0
.3
);
overflow
:
hidden
;
.image-manager-list
img
{
border-radius
:
0
;
float
:
left
;
margin
:
0
;
cursor
:
pointer
;
width
:
150px
;
height
:
150px
;
border
:
1px
solid
transparent
;
&
.selected
{
border
:
3px
solid
#EEE
;
}
}
max-width
:
1340px
;
position
:
fixed
;
top
:
0
;
bottom
:
0
;
...
...
@@ -28,34 +16,48 @@
z-index
:
999
;
display
:
flex
;
p
,
h1
,
h2
,
h3
,
h4
,
label
,
input
{
color
:
#
EEE
;
color
:
#
444
;
}
h1
,
h2
,
h3
{
font-weight
:
300
;
}
}
#image-manager
.dropzone-container
{
height
:
100px
;
position
:
relative
;
border
:
3px
dashed
#DDD
;
}
#container
{
height
:
90vh
;
.image-manager-bottom
{
position
:
absolute
;
bottom
:
0
;
right
:
0
;
}
.image-manager-list
img
{
display
:
block
;
border-radius
:
0
;
float
:
left
;
margin
:
0
;
cursor
:
pointer
;
width
:
(
100%
/
6
);
height
:
auto
;
border
:
1px
solid
#FFF
;
transition
:
all
cubic-bezier
(
.4
,
0
,
1
,
1
)
160ms
;
&
.selected
{
transform
:
scale3d
(
0
.92
,
0
.92
,
0
.92
);
}
}
#image-manager
.load-more
{
width
:
150px
;
height
:
150px
;
display
:
block
;
float
:
left
;
text-align
:
center
;
background-color
:
#
404040
;
margin
:
1px
;
color
:
#
FFF
;
line-height
:
140px
;
background-color
:
#
EEE
;
padding
:
$-s
$-m
;
color
:
#
AAA
;
clear
:
both
;
font-size
:
20px
;
cursor
:
pointer
;
font-style
:
italic
;
}
.image-manager-sidebar
{
...
...
@@ -75,6 +77,7 @@
.image-manager-list
{
overflow-y
:
scroll
;
flex
:
1
;
border-top
:
1px
solid
#ddd
;
}
.image-manager-content
{
...
...
@@ -93,19 +96,13 @@
* Copyright (c) 2012 Matias Meno <m@tias.me>
*/
.dz-message
{
font-size
:
1
.
6
em
;
font-size
:
1
.
4
em
;
font-style
:
italic
;
color
:
#aaa
;
text-align
:
center
;
line-height
:
90px
;
cursor
:
pointer
;
padding
:
$-xl
$-m
;
transition
:
all
ease-in-out
120ms
;
position
:
absolute
;
top
:
0
;
left
:
50%
;
max-width
:
400px
;
width
:
400px
;
margin-left
:
-200px
;
}
.dz-drag-hover
.dz-message
{
background-color
:
rgb
(
16
,
126
,
210
);
...
...
@@ -131,22 +128,10 @@
transform
:
translateY
(
0px
);
}
}
@keyframes
pulse
{
0
%
{
-webkit-transform
:
scale
(
1
);
-moz-transform
:
scale
(
1
);
-ms-transform
:
scale
(
1
);
-o-transform
:
scale
(
1
);
transform
:
scale
(
1
);
}
10
%
{
-webkit-transform
:
scale
(
1
.1
);
-moz-transform
:
scale
(
1
.1
);
-ms-transform
:
scale
(
1
.1
);
-o-transform
:
scale
(
1
.1
);
transform
:
scale
(
1
.1
);
}
20
%
{
-webkit-transform
:
scale
(
1
);
-moz-transform
:
scale
(
1
);
-ms-transform
:
scale
(
1
);
-o-transform
:
scale
(
1
);
transform
:
scale
(
1
);
}
}
.dropzone
,
.dropzone
*
{
box-sizing
:
border-box
;
}
...
...
@@ -171,10 +156,6 @@
.dz-preview.dz-image-preview
{
background
:
white
;
}
.dz-preview.dz-image-preview
.dz-details
{
-webkit-transition
:
opacity
0
.2s
linear
;
-moz-transition
:
opacity
0
.2s
linear
;
-ms-transition
:
opacity
0
.2s
linear
;
-o-transition
:
opacity
0
.2s
linear
;
transition
:
opacity
0
.2s
linear
;
}
.dz-preview
.dz-remove
{
font-size
:
14px
;
...
...
@@ -217,12 +198,6 @@
padding
:
0
0
.4em
;
border-radius
:
3px
;
}
.dz-preview
:hover
.dz-image
img
{
-webkit-transform
:
scale
(
1
.05
,
1
.05
);
-moz-transform
:
scale
(
1
.05
,
1
.05
);
-ms-transform
:
scale
(
1
.05
,
1
.05
);
-o-transform
:
scale
(
1
.05
,
1
.05
);
transform
:
scale
(
1
.05
,
1
.05
);
-webkit-filter
:
blur
(
8px
);
filter
:
blur
(
8px
);
}
.dz-preview
.dz-image
{
border-radius
:
4px
;
...
...
resources/assets/sass/styles.scss
View file @
e5a372f
...
...
@@ -8,6 +8,7 @@
@import
"buttons"
;
@import
"forms"
;
@import
"tables"
;
@import
"animations"
;
@import
"tinymce"
;
@import
"image-manager"
;
...
...
resources/views/pages/image-manager.blade.php
View file @
e5a372f
...
...
@@ -3,19 +3,42 @@
<div
class=
"overlay"
v-el=
"overlay"
v-on=
"click: overlayClick"
style=
"display:none;"
>
<div
class=
"image-manager-body"
>
<div
class=
"image-manager-content"
>
<div
class=
"dropzone-container"
v-el=
"dropZone"
>
<div
class=
"dz-message"
>
Drop files or click here to upload
</div>
</div>
<div
class=
"image-manager-list"
>
<div
v-repeat=
"image: images"
>
<img
v-class=
"selected: (image==selectedImage)"
v-attr=
"src: image.thumbnail"
v-on=
"click: imageClick(image)"
alt=
"@{{image.name}}"
>
<img
class=
"anim fadeIn"
v-class=
"selected: (image==selectedImage)"
v-attr=
"src: image.thumbnail, alt: image.name, title: image.name"
v-on=
"click: imageClick(image)"
v-style=
"animation-delay: ($index > 26) ? '160ms' : ($index * 25) + 'ms'"
>
</div>
<div
class=
"load-more"
v-show=
"hasMore"
v-on=
"click: fetchData"
>
Load More
</div>
</div>
</div>
<button
class=
"neg button image-manager-close"
v-on=
"click: hide()"
>
x
</button>
<div
class=
"image-manager-sidebar"
>
<button
class=
"neg button image-manager-close"
v-on=
"click: hide()"
>
x
</button>
<h2>
Images
</h2>
<h2
v-el=
"imageTitle"
>
Images
</h2>
<hr
class=
"even"
>
<div
class=
"dropzone-container"
v-el=
"dropZone"
>
<div
class=
"dz-message"
>
Drop files or click here to upload
</div>
</div>
<div
class=
"image-manager-details anim fadeIn"
v-show=
"selectedImage"
>
<hr
class=
"even"
>
<form
v-on=
"submit: saveImageDetails"
v-el=
"imageForm"
>
{{ csrf_field() }}
<div
class=
"form-group"
>
<label
for=
"name"
>
Image Name
</label>
<input
type=
"text"
id=
"name"
name=
"name"
v-model=
"selectedImage.name"
>
</div>
</form>
<hr
class=
"even"
>
<form
v-on=
"submit: deleteImage"
v-el=
"imageDeleteForm"
>
{{ csrf_field() }}
<button
class=
"button neg"
><i
class=
"zmdi zmdi-delete"
></i>
Delete Image
</button>
</form>
</div>
<div
class=
"image-manager-bottom"
>
<button
class=
"button pos anim fadeIn"
v-show=
"selectedImage"
v-on=
"click:selectButtonClick"
><i
class=
"zmdi zmdi-square-right"
></i>
Select Image
</button>
</div>
</div>
</div>
</div>
...
...
Please
register
or
sign in
to post a comment