Currently we have some license issues. We are working on it.

Commit a76c71cc authored by zauberstuhl's avatar zauberstuhl
Browse files

Vuejs

parent 9f4a3d89
config.yml
*.db
vendor/
unmappd
.DS_Store
node_modules
/dist
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
FROM golang:buster
RUN apt-get update && apt-get install -y npm
RUN npm install --global yarn
ADD . /go/src/build
WORKDIR /go/src/build
RUN yarn build
RUN go build -o unmappd
FROM debian:buster
......@@ -12,13 +16,13 @@ RUN apt-get clean && apt-get autoclean
RUN adduser --disabled-password app
ADD . /home/app
COPY --from=0 /go/src/build/unmappd /home/app/unmappd
COPY --from=0 /go/src/build/dist/ /home/app/dist/
COPY --from=0 /go/src/build/unmappd /home/app/
COPY --from=0 /go/src/build/config.yml.example /home/app/config.yml
RUN chmod +x /home/app/unmappd
WORKDIR /home/app
RUN cp config.yml.example config.yml
RUN rm -rf vendor *.db
EXPOSE 8080
......
......@@ -2,6 +2,13 @@
## Build
### Compile assets
yarn install
yarn build
### Compile binary
go build -o unmappd
## Docker image
......
......@@ -94,7 +94,7 @@ func auth_handler(w http.ResponseWriter, r *http.Request) {
return
}
userParam := "/users/%s"
userParam := "#/map/%s"
err = db.First(&User{}, "username = ?", username).Error
if err == nil {
http.Redirect(w, r,
......@@ -135,7 +135,11 @@ func fetch_auth(code string) (string, error) {
var uauth Uauthresp
return uauth.Response.Access_token, get(fmt.Sprintf(
"https://untappd.com/oauth/authorize/?client_id=%s&client_secret=%s&response_type=code&redirect_url=%s&code=%s",
CLIENTID, CLIENTSECRET, REDIRECTURL, code), &uauth)
viper.GetString("clientID"),
viper.GetString("clientSecret"),
viper.GetString("redirectUrl"),
code,
), &uauth)
}
func fetch_user_info(token string) (info Uinfo, err error) {
......
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset'
]
}
redirectUrl: http://localhost:8080
redirectUrl: http://localhost:8080/api/v0/auth
# untappd app secret
clientID: 1234
......
......@@ -25,8 +25,6 @@ import (
"github.com/spf13/viper"
)
var CLIENTID, CLIENTSECRET, REDIRECTURL string
func init() {
viper.SetConfigName("config")
viper.AddConfigPath(".")
......@@ -44,10 +42,6 @@ func init() {
log.Print("Run migrations..")
db.AutoMigrate(&Location{})
db.AutoMigrate(&User{})
CLIENTID = viper.GetString("clientID")
CLIENTSECRET = viper.GetString("clientSecret")
REDIRECTURL = viper.GetString("redirectUrl")
}
func main() {
......@@ -55,12 +49,15 @@ func main() {
Addr: "0.0.0.0:8080",
}
http.HandleFunc("/", index_handler)
http.HandleFunc("/users/", user_handler)
http.HandleFunc("/api/v0/config", config_handler)
http.HandleFunc("/api/v0/users/", user_handler)
http.HandleFunc("/api/v0/locations/", location_handler)
http.HandleFunc("/api/v0/auth", auth_handler)
// NOTE will be obsolete in future
http.HandleFunc("/auth", auth_handler)
// assets directory
fs := http.FileServer(http.Dir("public"))
http.Handle("/assets/", http.StripPrefix("/assets/", fs))
fs := http.FileServer(http.Dir("dist"))
http.Handle("/", http.StripPrefix("/", fs))
log.Print("Listening on 0.0.0.0:8080 ..")
server.ListenAndServe()
......
......@@ -20,12 +20,9 @@ package main
import (
"time"
"html/template"
"strings"
"fmt"
"github.com/spf13/viper"
"github.com/microcosm-cc/bluemonday"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/sqlite"
_ "github.com/jinzhu/gorm/dialects/mysql"
......@@ -33,22 +30,22 @@ import (
)
type User struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
UpdatedAt time.Time
Username string `gorm:"unique_index;size:191"`
Token string `gorm:"index;size:191"`
TotalBadges int
TotalFriends int
TotalCheckins int
TotalBeers int
TotalCreatedBeers int
TotalFollowings int
TotalPhotos int
Locations Locations
ID uint `gorm:"primary_key" json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"-"`
Username string `gorm:"unique_index;size:191" json:"-"`
Token string `gorm:"index;size:191" json:"-"`
TotalBadges int `json:"totalBadges"`
TotalFriends int `json:"totalFriends"`
TotalCheckins int `json:"totalCheckins"`
TotalBeers int `json:"totalBeers"`
TotalCreatedBeers int `json:"totalCreatedBeers"`
TotalFollowings int `json:"totalFollowings"`
TotalPhotos int `json:"totalPhotos"`
Locations Locations `json:"-"`
}
type Users []User
......@@ -58,47 +55,22 @@ func (user *User) AfterFind(db *gorm.DB) error {
}
type Location struct {
ID uint `gorm:"primary_key"`
CreatedAt time.Time
ID uint `gorm:"primary_key" json:"id"`
CreatedAt time.Time `json:"-"`
UserID uint `gorm:"index"`
UserID uint `gorm:"index" json:"-"`
Lat, Lng float64
Url, Name, Category, Icon string
Lat float64 `json:"lat"`
Lng float64 `json:"lng"`
Url string `json:"url"`
Name string `json:"name"`
Category string `json:"category"`
Icon string `json:"icon"`
}
type Locations []Location
func (locations Locations) LatLngJSON() template.JS {
var result string
var format = `[%f,%f,{
timestamp:%d,
venue:{
icon:"%s",
name:"%s",
url:"%s",
category:"%s"
}
}],`
html := bluemonday.UGCPolicy()
for _, location := range locations {
result += fmt.Sprintf(format,
location.Lat,
location.Lng,
location.CreatedAt.Unix(),
location.Icon,
html.Sanitize(location.Name),
location.Url,
html.Sanitize(location.Category),
)
}
// trim last comma
result = strings.TrimRight(result, ",")
result = fmt.Sprintf("[%s]", result)
return template.JS(result)
}
func openDatabase() (*gorm.DB, error) {
driver := viper.GetString("db.driver")
url := viper.GetString("db.url")
......@@ -117,3 +89,18 @@ func openDatabase() (*gorm.DB, error) {
db.LogMode(true)
return db, err
}
func userByUsername(username string) (*User, error) {
db, err := openDatabase()
if err != nil {
return nil, err
}
defer db.Close()
var user User
err = db.First(&user, "username = ?", username).Error
if err == nil && viper.GetBool("worker") && len(user.Locations) == 0 {
go checkin_worker(&user, true)
}
return &user, err
}
{
"name": "unmappd",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"axios": "^0.21.1",
"bootstrap": "^4.6.0",
"bootstrap-vue": "^2.21.2",
"core-js": "^3.6.5",
"leaflet": "^1.7.1",
"leaflet-gesture-handling": "^1.2.1",
"vue": "^2.6.12",
"vue-router": "^3.5.1",
"vue2-leaflet": "^2.6.0",
"vue2-leaflet-markercluster": "^3.1.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
"@vue/cli-plugin-eslint": "~4.5.0",
"@vue/cli-service": "~4.5.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^6.2.2",
"vue-template-compiler": "^2.6.11"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>
html, body {
height: 100%;
}
#mapid {
height: calc(100% - 96px);
height: -o-calc(100% - 96px);
height: -webkit-calc(100% - 96px);
height: -moz-calc(100% - 96px);
}
This diff is collapsed.
.leaflet-control-playback{position:relative;background-color:#7cbdf5;padding:10px;}
.leaflet-control-playback .optionsContainer{position:relative;}
.leaflet-control-playback .optionsContainer > div {
display: inline-block;
}
.leaflet-control-playback .buttonContainer {}
.leaflet-control-playback .buttonContainer a {
display: inline-block;
width: 32px;
height: 32px;
text-decoration: none;
}
.leaflet-control-playback .buttonContainer .btn-stop {
background: url(../images/icon-play.png) no-repeat center;
}
.leaflet-control-playback .buttonContainer .btn-start {
background: url(../images/icon-stop.png) no-repeat center;
}
.leaflet-control-playback .buttonContainer .btn-restart {
background: url(../images/icon-restart.png) no-repeat center;
}
.leaflet-control-playback .buttonContainer .btn-slow {
background: url(../images/icon-slow.png) no-repeat center;
}
.leaflet-control-playback .buttonContainer .btn-quick {
background: url(../images/icon-quick.png) no-repeat center;
}
.leaflet-control-playback .buttonContainer .btn-close {
background: url(../images/icon-close.png) no-repeat center;
}
.leaflet-control-playback .infoContainer {}
.leaflet-control-playback .sliderContainer {}
/* required styles */
.leaflet-pane,
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow,
.leaflet-tile-container,
.leaflet-pane > svg,
.leaflet-pane > canvas,
.leaflet-zoom-box,
.leaflet-image-layer,
.leaflet-layer {
position: absolute;
left: 0;
top: 0;
}
.leaflet-container {
overflow: hidden;
}
.leaflet-tile,
.leaflet-marker-icon,
.leaflet-marker-shadow {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
-webkit-user-drag: none;
}
/* Prevents IE11 from highlighting tiles in blue */
.leaflet-tile::selection {
background: transparent;
}
/* Safari renders non-retina tile on retina better with this, but Chrome is worse */
.leaflet-safari .leaflet-tile {
image-rendering: -webkit-optimize-contrast;
}
/* hack that prevents hw layers "stretching" when loading new tiles */
.leaflet-safari .leaflet-tile-container {
width: 1600px;
height: 1600px;
-webkit-transform-origin: 0 0;
}
.leaflet-marker-icon,
.leaflet-marker-shadow {
display: block;
}
/* .leaflet-container svg: reset svg max-width decleration shipped in Joomla! (joomla.org) 3.x */
/* .leaflet-container img: map is broken in FF if you have max-width: 100% on tiles */
.leaflet-container .leaflet-overlay-pane svg,
.leaflet-container .leaflet-marker-pane img,
.leaflet-container .leaflet-shadow-pane img,
.leaflet-container .leaflet-tile-pane img,
.leaflet-container img.leaflet-image-layer,
.leaflet-container .leaflet-tile {
max-width: none !important;
max-height: none !important;
}
.leaflet-container.leaflet-touch-zoom {
-ms-touch-action: pan-x pan-y;
touch-action: pan-x pan-y;
}
.leaflet-container.leaflet-touch-drag {
-ms-touch-action: pinch-zoom;
/* Fallback for FF which doesn't support pinch-zoom */
touch-action: none;
touch-action: pinch-zoom;
}
.leaflet-container.leaflet-touch-drag.leaflet-touch-zoom {
-ms-touch-action: none;
touch-action: none;
}
.leaflet-container {
-webkit-tap-highlight-color: transparent;
}
.leaflet-container a {
-webkit-tap-highlight-color: rgba(51, 181, 229, 0.4);
}
.leaflet-tile {
filter: inherit;
visibility: hidden;
}
.leaflet-tile-loaded {
visibility: inherit;
}
.leaflet-zoom-box {
width: 0;
height: 0;
-moz-box-sizing: border-box;
box-sizing: border-box;
z-index: 800;
}
/* workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=888319 */
.leaflet-overlay-pane svg {
-moz-user-select: none;
}
.leaflet-pane { z-index: 400; }
.leaflet-tile-pane { z-index: 200; }
.leaflet-overlay-pane { z-index: 400; }
.leaflet-shadow-pane { z-index: 500; }
.leaflet-marker-pane { z-index: 600; }
.leaflet-tooltip-pane { z-index: 650; }
.leaflet-popup-pane { z-index: 700; }
.leaflet-map-pane canvas { z-index: 100; }
.leaflet-map-pane svg { z-index: 200; }
.leaflet-vml-shape {
width: 1px;
height: 1px;
}
.lvml {
behavior: url(#default#VML);
display: inline-block;
position: absolute;
}
/* control positioning */
.leaflet-control {
position: relative;
z-index: 800;
pointer-events: visiblePainted; /* IE 9-10 doesn't have auto */
pointer-events: auto;
}
.leaflet-top,
.leaflet-bottom {
position: absolute;
z-index: 1000;
pointer-events: none;
}
.leaflet-top {
top: 0;
}
.leaflet-right {
right: 0;
}
.leaflet-bottom {
bottom: 0;
}
.leaflet-left {
left: 0;
}
.leaflet-control {
float: left;
clear: both;
}
.leaflet-right .leaflet-control {
float: right;
}
.leaflet-top .leaflet-control {
margin-top: 10px;
}
.leaflet-bottom .leaflet-control {
margin-bottom: 10px;
}
.leaflet-left .leaflet-control {
margin-left: 10px;
}
.leaflet-right .leaflet-control {
margin-right: 10px;
}
/* zoom and fade animations */
.leaflet-fade-anim .leaflet-tile {
will-change: opacity;
}
.leaflet-fade-anim .leaflet-popup {
opacity: 0;
-webkit-transition: opacity 0.2s linear;
-moz-transition: opacity 0.2s linear;
transition: opacity 0.2s linear;
}
.leaflet-fade-anim .leaflet-map-pane .leaflet-popup {
opacity: 1;
}
.leaflet-zoom-animated {
-webkit-transform-origin: 0 0;
-ms-transform-origin: 0 0;
transform-origin: 0 0;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
will-change: transform;
}
.leaflet-zoom-anim .leaflet-zoom-animated {
-webkit-transition: -webkit-transform 0.25s cubic-bezier(0,0,0.25,1);
-moz-transition: -moz-transform 0.25s cubic-bezier(0,0,0.25,1);
transition: transform 0.25s cubic-bezier(0,0,0.25,1);
}
.leaflet-zoom-anim .leaflet-tile,
.leaflet-pan-anim .leaflet-tile {
-webkit-transition: none;
-moz-transition: none;
transition: none;
}
.leaflet-zoom-anim .leaflet-zoom-hide {
visibility: hidden;
}
/* cursors */
.leaflet-interactive {
cursor: pointer;
}
.leaflet-grab {
cursor: -webkit-grab;
cursor: -moz-grab;
cursor: grab;
}
.leaflet-crosshair,
.leaflet-crosshair .leaflet-interactive {
cursor: crosshair;
}
.leaflet-popup-pane,
.leaflet-control {
cursor: auto;
}
.leaflet-dragging .leaflet-grab,
.leaflet-dragging .leaflet-grab .leaflet-interactive,
.leaflet-dragging .leaflet-marker-draggable {
cursor: move;
cursor: -webkit-grabbing;
cursor: -moz-grabbing;
cursor: grabbing;
}