Migrate to pug

This commit is contained in:
soraefir 2023-06-25 12:26:17 +02:00
parent 0693d47939
commit 681975a44b
Signed by: sora
GPG Key ID: A362EA0491E2EEA0
54 changed files with 688 additions and 22868 deletions

6
.gitignore vendored
View File

@ -1,4 +1,4 @@
package-lock.json package-lock.json
node_modules/* node_modules/
auth/* auth/
db/* db/

View File

@ -1,62 +0,0 @@
const path = require('path');
const fs = require('fs');
const {mkdirp} = require('mkdirp');
const sass = require('node-sass');
const nodeEnv = process.env.NODE_ENV;
module.exports = {
compileSass,
compileSassProduction,
compileSassMain
};
function compileSass(sassFile) {
const sassOptions = {
file: sassFile
};
if (nodeEnv !== 'production') {
sassOptions.sourceMapEmbed = true;
}
else {
sassOptions.outputStyle = 'compressed';
}
return new Promise((resolve, reject) => {
sass.render(sassOptions, (error, result) => {
if (error) {
return reject(error);
}
resolve(result.css.toString());
});
}).catch(console.error);
}
function compileSassProduction(sassFile) {
const fullSassPath = path.join(__dirname, 'public/scss/', sassFile);
const cssFile = sassFile.replace('.scss', '.css');
const cssPath = path.join(__dirname, 'public/css/');
const fullCssPath = path.join(cssPath, cssFile);
return compileSass(fullSassPath).then(css =>
mkdirp(cssPath).then(() =>
new Promise((resolve, reject) => {
fs.writeFile(fullCssPath, css, error => {
if (error) {
return reject(error);
}
resolve(cssFile);
});
})
)
).catch(console.error);;
}
function compileSassMain() {
return compileSassProduction('index.scss').then(() => {
console.log('Created index.css');
}).catch(console.error);
}

View File

@ -17,10 +17,10 @@
"dependencies": { "dependencies": {
"@fastify/leveldb": "^5.0.1", "@fastify/leveldb": "^5.0.1",
"@fastify/static": "^6.10.2", "@fastify/static": "^6.10.2",
"@fastify/view": "^7.4.1",
"axios": "^1.4.0", "axios": "^1.4.0",
"fastify": "^4.18.0", "fastify": "^4.18.0",
"mkdirp": "^3.0.1", "nodemon": "^2.0.22",
"node-sass": "^9.0.0", "pug": "^3.0.2"
"nodemon": "^2.0.22"
} }
} }

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

Before

Width:  |  Height:  |  Size: 1.4 MiB

File diff suppressed because one or more lines are too long

View File

@ -58,12 +58,13 @@ const is_attraction_type = e => (["tourism", "leisure", "place", "amenity", "hig
const icon_type = (item)=>{ const icon_type = (item)=>{
let t = item.type let t = item.type
let c = item.category
const arr = ["restaurant", "cafe", "pub", "bar", "fast_food", "food_court"]; const arr = ["restaurant", "cafe", "pub", "bar", "fast_food", "food_court"];
if(arr.indexOf(t)!=-1){ if(arr.indexOf(t)!=-1){
return 'utensils'; return 'utensils';
}else if(t=='hotel' || t=='hostel'){ }else if(t=='hotel' || t=='hostel'){
return 'bed'; return 'bed';
}else if(t=='museum'){ }else if(t=='museum' || c=='historic' || t=='place_of_worship'){
return 'landmark'; return 'landmark';
}else if(t=='peak' || t=='viewpoint'){ }else if(t=='peak' || t=='viewpoint'){
return 'mountain'; return 'mountain';
@ -79,11 +80,11 @@ const icon_type = (item)=>{
return 'landmark'; return 'landmark';
}else if(t=='bridge'){ }else if(t=='bridge'){
return 'archway'; return 'archway';
}else if(t=='woodland'|| t=='shieling' || t=='national_park' || t=='zoo' || t=='park'){ }else if(t=='woodland'|| t=='shieling' || t=='national_park' || t=='zoo' || t=='park' || t=='garden' || 0){
return 'tree'; return 'tree';
}else if(t=='water_park', t=='theme_park'){ }else if(t=='water_park', t=='theme_park'){
return 'dice-five'; return 'dice-five';
}else if(t=='?'){ }else if(t=='?' || t=='neighbourhood' || t=='quarter' || c=='highway'){
return ''; return '';
}else{ }else{
console.log(item.display_name, item.category, item.type); console.log(item.display_name, item.category, item.type);
@ -112,7 +113,6 @@ const app = new Vue({
main:[], main:[],
step_title:[], step_title:[],
}, },
vtp: ['view','short'].indexOf(window.location.pathname.split('/')[1]),
query:{hotel:[],flight:[],nominatim:[]}, query:{hotel:[],flight:[],nominatim:[]},
querying:{hotel:false,flight:false,place:false,food:false}, querying:{hotel:false,flight:false,place:false,food:false},
impexp:"", impexp:"",
@ -264,7 +264,6 @@ const app = new Vue({
save_data: function(){ save_data: function(){
this.impexp = toEncoded(JSON.stringify(this.journey_data)); this.impexp = toEncoded(JSON.stringify(this.journey_data));
console.log(this.journey_data)
axios.post('/api/'+this.journey_id, this.journey_data).then(response => { axios.post('/api/'+this.journey_id, this.journey_data).then(response => {
console.log("Saved...") console.log("Saved...")
}).catch(error => { }).catch(error => {
@ -291,7 +290,6 @@ const app = new Vue({
}, },
created: function () { created: function () {
axios.get('/api/'+this.journey_id).then(response =>{ axios.get('/api/'+this.journey_id).then(response =>{
console.log(response)
if(response.data=='') throw "Invalid Journey Data Received"; if(response.data=='') throw "Invalid Journey Data Received";
app.journey_data = response.data; app.journey_data = response.data;

BIN
public/scss/.DS_Store vendored

Binary file not shown.

View File

@ -1,261 +0,0 @@
/**
* SETTINGS
*/
$enable-grid-classes: true !default; // generate grid classes
$enable-reset-defaults: true !default; // reset default browser values
// colors
$c-white: #fff !default;
$c-black: #000 !default;
$c-success: #4caf50 !default;
$c-info: #5bc0de !default;
$c-warning: #f0ad4e !default;
$c-error: #e74c3c !default;
$c-gray: #969da6 !default;
$c-gray-light: #eceff1 !default;
$c-primary: #03a9f4 !default;
$c-secondary: #e91e63 !default;
$c-dark: #18232f !default;
$c-light: $c-gray-light !default;
$c-text: #272727 !default;
$c-link: $c-primary !default;
$c-link-hover: rgba($c-primary, .8) !default;
$bgc-body: $c-white !default;
$c-map: (
'primary': $c-primary,
'dark': $c-dark,
'secondary': $c-secondary,
'white': $c-white,
'success': $c-success,
'info': $c-info,
'warning': $c-warning,
'error': $c-error,
'gray': $c-gray,
'gray-light': $c-gray-light
) !default;
// Social colors
$c-fb: rgb(59, 89, 182) !default;
$c-tw: rgb(64, 153, 255) !default;
$c-googleplus: rgb(215, 61, 50) !default;
$c-pinterest: rgb(203, 32, 39) !default;
$c-skype: rgb(18, 165, 244) !default;
$c-spotify: rgb(129, 183, 26) !default;
$c-instagram: #4e433c !default;
$c-tumblr: #2b4964 !default;
$c-vimeo: #86b32d !default;
$c-soundcloud: #f76600 !default;
$c-youtube: #ff3333 !default;
$c-linkedin: #4875b4 !default;
$c-flickr: #fe0883 !default;
$c-foursquare: #8fd400 !default;
// Shadows
$bxsh-base: 0 0 5px rgba(0, 0, 0, .2) !default;
$bxsh-medium: $bxsh-base !default;
// Typography
$fw-light: 300 !default;
$fw-normal: 400 !default;
$fw-bold: 600 !default;
$fw-headings: $fw-light !default;
$ff-base: 'IBM Plex Sans', sans-serif !default;
$fw-base: 400 !default;
$fz-base: 16px !default;
$lh-base: 1.5em !default;
$fz-huge: 36px !default;
$fz-big: 24px !default;
$fz-medium: $fz-base !default;
$fz-small: 12px !default;
$lh-huge: 1.3em !default;
$lh-big: 1.3em !default;
$lh-medium: $lh-base !default;
$lh-small: 1.3em !default;
// Body
$c-body: $c-text !default;
$ff-body: $ff-base !default;
$fz-body: $fz-base !default;
$fw-body: $fw-base !default;
$lh-body: $lh-base !default;
// Border
$bdc-base: #d5d9db !default;
$bd-medium: 1px solid $bdc-base !default;
$bdr-base: 3px !default;
$bdr-medium: $bdr-base !default;
$bdr-rounded-corners: 5px !default;
// Defaults (HTML elements)
$fw-strong: $fw-bold !default;
$mb-p: 1.5em !default;
$mb-ul: 1em !default;
$mb-li: .5em !default;
// Margin
$m-xsmall: 4px !default;
$m-small: 8px !default;
$m-medium: 16px !default;
$m-big: 36px !default;
$m-huge: 48px !default;
// Padding
$p-small: 4px !default;
$p-medium: 8px !default;
$p-big: 16px !default;
$p-huge: 36px !default;
// Layout
$bgc-container: transparent !default;
$mwi-container: 1380px !default;
$mwi-container-medium: 944px !default;
$mwi-container-small: 400px !default;
$w-gutter: 24px !default;
// Grid
$grid-breakpoints: (
xs: 0,
sm: 576px,
md: 768px,
lg: 992px,
xl: 1200px
) !default;
$grid-columns: 12 !default;
$grid-gutter-width: $w-gutter !default;
$container-max-widths: (
sm: 540px,
md: 720px,
lg: 960px,
xl: 1140px
) !default;
/**
* COMPONENTS
*/
// Badges
$c-badge: $c-text !default;
$c-badge-colored: $c-white !default;
$bg-badge: $c-light !default;
$bdr-badge: $bdr-medium !default;
$lh-badge: 1.2em !default;
$p-badge: $p-medium $p-big !default;
$fz-badge-big: 1.3em !default;
$fz-badge-small: .7em !default;
$badges-color-map: (
primary: $c-primary,
secondary: $c-secondary,
dark: $c-dark,
light: $c-gray,
success: $c-success,
error: $c-error,
warning: $c-warning
) !default;
// Buttons
$bg-button: $c-primary !default;
$c-button: $c-white !default;
$c-button-transparent: $c-primary !default;
$c-button-outlined: $c-primary !default;
$bdc-button: $bg-button !default;
$bd-button: 1px solid $bdc-button !default;
$bdr-button: 200px !default;
$ff-button: $ff-body !default;
$fz-button: $fz-medium !default;
$fw-button: $fw-bold !default;
$lh-button: $lh-body !default;
$m-button: 0 $m-small $m-medium $m-small !default;
$p-button: $p-medium $p-big !default;
$tt-button: uppercase !default;
$fz-button-big: $fz-big !default;
$p-button-big: $p-big $p-huge !default;
$fz-button-small: $fz-small !default;
$p-button-small: $p-small $p-big !default;
// Forms
$bgc-form: $c-light !default;
$c-form: $c-text !default;
$bdr-form: $bdr-medium !default;
$bd-form: $bd-medium !default;
$fz-form: $fz-body !default;
$bgc-form-focus: lighten($bgc-form, 5%) !default;
$trs-form: background-color .2s ease-in-out !default;
$c-form-placeholder: $c-gray !default;
$mih-form-textarea: 120px !default;
$p-form: $p-medium $p-big !default;
$size-form-input-icon: 16px !default;
$c-form-input-icon: $c-gray !default;
$bd-form-error: 1px solid $c-error !default;
$bgc-form-error: $bgc-form !default;
// Loading bar
$h-loading-bar: 6px !default;
$w-loading-bar: 300px !default;
$z-loading-bar: 1000 !default;
// Loading spinner
$bg-loading-spinner: $c-secondary !default;
$size-loading-spinner-inner: 9px !default;
$size-loading-spinner: 30px !default;
$z-loading-spinner: 1000 !default;
// Notification
$bdr-notification: $bdr-medium !default;
$c-notification: $c-white !default;
$mb-notification: $m-big !default;
$p-notification: $p-big !default;
// Paginator
$mr-paginator-item: $m-xsmall !default;
$bdr-paginator-item: $bdr-medium !default;
$bg-paginator-item: $c-light !default;
$c-paginator-item: $c-text !default;
$bg-paginator-item-active: $c-primary !default;
$c-paginator-item-active: $c-white !default;
$p-paginator-item: $p-medium $p-big !default;
// Table
$bgc-table-header: $bgc-body !default;
$bgc-table: $c-light !default;
$bd-table: $bd-medium !default;
$c-table-heading: $c-gray !default;
$c-table-text: $c-text !default;
$fw-table-heading: normal !default;
$mwi-table: 100% !default;
$p-table-cell: $p-medium !default;
$p-table-heading: $p-medium !default;
$w-table: 100% !default;
$fz-table-heading: $fz-small !default;
// Tabs
$bdb-tabs-item-selected: 3px solid $c-primary !default;
$bdb-tabs-item: 3px solid transparent !default;
$bdb-tabs: $bd-medium !default;
$c-tabs-item-hover: $c-primary !default;
$c-tabs-item-selected: $c-primary !default;
$c-tabs-item: $c-gray !default;
$m-tabs-item: 0 $m-medium 0 0 !default;
$miw-tabs-item: 70px !default;
$p-tabs-item: $p-big !default;
// Tags
$bg-tag-dot: $bgc-body !default;
$bg-tag: $c-light !default;
$bdr-tag: $bdr-medium 0 0 $bdr-medium !default;
$c-tag: $c-text !default;
$lh-tag: 16px !default;
$m-tag: 0 $m-medium $m-medium 0 !default;
$p-tag: $p-medium !default;
$size-tag-dot: 5px !default;

View File

@ -1,36 +0,0 @@
/**
* BADGE
*
* Markup:
* -------
*
* <ul>
* <li class="badge badge--primary">Badge 1</li>
* <li class="badge badge--secondary badge--big">Badge 1</li>
* </ul>
*
*/
.badge {
background-color: $bg-badge;
border-radius: $bdr-badge;
color: $c-badge;
display: inline-block;
line-height: $lh-badge;
padding: $p-badge;
&--big {
font-size: $fz-badge-big;
}
&--small {
font-size: $fz-badge-small;
}
@each $type, $color in $badges-color-map {
&--#{$type} {
background-color: $color;
color: $c-badge-colored;
}
}
}

View File

@ -1,149 +0,0 @@
/**
* BUTTON
*
* Markup:
* -------
*
* <button class="button">Default</button>
* <button class="button button--big">Button big</button>
* <button class="button button--secondary">Button secondary</button>
*
*/
// reset default buttons
button {
background-color: transparent;
cursor: pointer;
}
.button {
background-color: $bg-button;
border: 0;
border-radius: $bdr-button;
color: $c-button;
display: inline-block;
font-family: $ff-button;
font-size: $fz-button;
font-weight: $fw-button;
line-height: $lh-button;
margin: $m-button;
padding: $p-button;
text-align: center;
text-decoration: none;
text-transform: $tt-button;
transition: opacity .2s ease-in-out;
white-space: nowrap;
&:focus,
&:hover,
&:active {
color: $c-button;
}
&:hover {
background-color: rgba($c-primary, .8);
color: $c-white;
cursor: pointer;
text-decoration: none;
}
&:active {
opacity: 1;
}
&:first-child {
margin-left: 0;
}
&:last-child {
margin-right: 0;
}
// sizes
&--big {
font-size: $fz-button-big;
padding: $p-button-big;
}
&--small {
font-size: $fz-button-small;
padding: $p-button-small;
}
&--mobileFull {
@include media-breakpoint-down(md) {
margin-left: 0;
margin-right: 0;
width: 100%;
}
}
// colors
&--secondary {
background-color: $c-secondary;
color: $c-white;
&:hover {
background-color: rgba($c-secondary, .8);
color: $c-white;
}
}
&--white {
background-color: $c-white;
color: $c-primary;
&:hover {
background-color: rgba($c-white, .8);
color: rgba($c-primary, .8);
}
}
&--green {
background-color: $c-success;
color: $c-white;
&:hover {
background-color: rgba($c-success, .8);
color: $c-white;
}
}
&--red {
background-color: $c-error;
color: $c-white;
&:hover {
background-color: rgba($c-error, .8);
color: $c-white;
}
}
&--transparent {
background-color: transparent;
color: $c-button-transparent;
&:active,
&:hover,
&:focus {
background-color: transparent;
color: rgba($c-button-transparent, .8);
opacity: .8;
}
}
&--outlined {
background-color: transparent;
border: $bd-medium;
color: $c-button-outlined;
&:active,
&:hover,
&:focus {
background-color: transparent;
color: rgba($c-button-outlined, .8);
opacity: .8;
}
}
}

View File

@ -1,398 +0,0 @@
/**
* FORMS
*
* Markup:
* ---------
* <div class="input input-fullWidth">
* <input id="#" placeholder="#" type="text">
* </div>
*
* <div class="select select-fullWidth">
* <select name="#" id="#">
* <option>Option 1</option>
* <option>Option 2</option>
* </select>
* </div>
*
* <div class="textarea">
* <textarea id="#"></textarea>
* </div>
*
* <div class="radio">
* <input id="#" name="#" type="radio" value="">
* <label for="#">Radio button</label>
* </div>
*
* <div class="checkbox">
* <input id="#" name="#" type="checkbox" value="">
* <label for="#">Checkbox</label>
* </div>
*/
// prevent input default appearence on webkit
input,
textarea {
appearance: none;
}
label {
display: block;
font-weight: normal;
}
// Disable webkit background color
input:-webkit-autofill {
box-shadow: 0 0 0 1000px $bgc-form inset;
}
// Common styles
.textarea,
.input,
.select {
border: $bd-form;
border-radius: $bdr-form;
box-shadow: none;
display: inline-block;
font-weight: normal;
margin-bottom: 20px;
overflow: hidden;
:focus {
outline: none;
}
&.has-error {
background: $bgc-form-error;
border: $bd-form-error;
margin-bottom: 0; // we should display an error message
}
}
.select {
background-color: $bgc-form;
display: inline-block;
margin-right: $m-medium;
position: relative;
&:last-child {
margin-right: 0;
}
&-fullWidth {
display: block;
margin-left: 0;
margin-right: 0;
width: 100%;
}
select {
appearance: none;
background-color: transparent;
border: 0;
border-radius: 0;
color: $c-form;
display: block;
font-size: $fz-form;
line-height: $lh-medium;
margin: 0;
padding: $p-form;
padding-right: 30px;
transition: $trs-form;
width: 100%;
&:active,
&:focus {
background-color: $bgc-form-focus;
border: 0;
outline: none;
}
&::-ms-expand {
display: none;
}
}
&::after,
&::before {
background: $c-primary;
content: '';
display: block;
height: 2px;
margin-top: 2px;
position: absolute;
right: 5px;
top: 50%;
transform-origin: 1px;
width: 10px;
}
&::after {
transform: rotate(-135deg);
}
&::before {
transform: rotate(-45deg);
}
}
// textarea
.textarea {
background-color: $bgc-form;
padding: 0;
&-fullWidth {
display: block;
margin-left: 0;
margin-right: 0;
width: 100%;
}
textarea {
background: transparent;
border: 0;
color: $c-form;
display: block;
font-family: $ff-body;
font-size: $fz-form;
line-height: $lh-medium;
margin: 0;
min-height: $mih-form-textarea;
padding: $p-form;
transition: $trs-form;
width: 100%;
&::placeholder {
color: $c-form-placeholder;
}
&:focus,
&:active {
background-color: $bgc-form-focus;
border: 0;
outline: none;
}
}
}
.checkbox {
margin-bottom: $m-small;
position: relative;
input[type='checkbox'] {
display: none;
&:checked + label::after {
animation: checkboxAndRadioAnimation .25s;
content: '';
transform: scale(1) rotate(45deg);
}
& + label {
display: block;
overflow: hidden;
padding-left: 30px;
text-overflow: ellipsis;
white-space: nowrap;
&::before {
background-color: $bgc-form;
border: $bd-form;
border-radius: $bdr-medium;
content: '';
display: inline-block;
height: 20px;
left: 0;
margin-top: -10px;
position: absolute;
top: 50%;
width: 20px;
}
&::after {
border-bottom: 3px solid $c-primary;
border-right: 3px solid $c-primary;
display: block;
height: 12px;
left: 11px;
margin-left: -4px;
margin-top: -7px;
position: absolute;
top: 50%;
width: 7px;
z-index: 1;
}
}
}
}
.radio {
margin-bottom: $m-small;
position: relative;
input[type='radio'] {
display: none;
&:checked + label::after {
animation: checkboxAndRadioAnimation .25s;
content: '';
transform: scale(1) rotate(45deg);
}
& + label {
display: block;
overflow: hidden;
padding-left: 30px;
text-overflow: ellipsis;
white-space: nowrap;
&::before {
background-color: $bgc-form;
border: $bd-form;
border-radius: 20px;
content: '';
display: inline-block;
height: 20px;
left: 0;
margin-top: -10px;
position: absolute;
top: 50%;
width: 20px;
}
&::after {
background-color: $c-primary;
border-radius: 20px;
display: block;
height: 10px;
left: 11px;
margin-left: -6px;
margin-top: -6px;
position: absolute;
top: 13px;
width: 10px;
z-index: 1;
}
}
}
}
@keyframes checkboxAndRadioAnimation {
0% {
transform: scale(0) rotate(45deg);
}
50% {
transform: scale(1.5) rotate(45deg);
}
100% {
transform: scale(1) rotate(45deg);
}
}
.input {
background-color: $bgc-form;
margin-right: 10px;
padding: 0;
position: relative;
:focus,
:active {
background-color: $bgc-form-focus;
border-radius: $bdr-form;
}
input {
background: transparent;
border: 0;
box-shadow: none;
color: $c-form;
font-size: $fz-form;
line-height: $lh-medium;
margin: 0;
outline: none;
padding: $p-form;
width: 100%;
&::placeholder {
color: $c-form-placeholder;
}
}
&-withIcon {
input {
padding-right: $size-form-input-icon * 2;
}
}
&-icon {
fill: $c-form-input-icon;
height: $size-form-input-icon;
margin-top: -$size-form-input-icon / 2;
position: absolute;
right: $m-medium;
top: 50%;
width: $size-form-input-icon;
}
// input variations
&-fullWidth {
display: block;
margin-left: 0;
margin-right: 0;
width: 100%;
}
}
/**
* FORM COLLAPSED (items in row without gap between them)
*
* Markup:
* -------
*
* <div class="formCollapsed">
* <div class="input formCollapsed-item formCollapsed-itemPrimary">
* <input id="name" placeholder="Klingon search" type="text" />
* </div>
* <div class="select formCollapsed-item">
* <select name="country-code" id="country-code">
* <option value="AO"> Angola</option>
* </select>
* </div>
* <button class="formCollapsed-item button button-primary">
* Search
* </button>
* </div>
**/
.formCollapsed {
display: flex;
margin-bottom: 20px;
&-item {
border-radius: 0 !important;
margin: 0 !important;
&:first-child {
border-bottom-left-radius: $bdr-form !important;
border-top-left-radius: $bdr-form !important;
}
&:last-child {
border-bottom-right-radius: $bdr-form !important;
border-top-right-radius: $bdr-form !important;
}
&:not(:last-child) {
border-right: 0;
}
&Primary {
flex: 1;
}
}
}

View File

@ -1,57 +0,0 @@
/**
* LOADING BAR
*
* Markup:
* ---------
* <div class="loadingBar"></div>
*
*/
.loadingBar {
height: $h-loading-bar;
left: 0;
overflow: hidden;
position: fixed;
right: 0;
top: 0;
width: 100%;
z-index: $z-loading-bar;
&::before {
animation: loading 2s linear infinite;
background-color: $c-primary;
content: '';
display: block;
height: $h-loading-bar;
left: -$w-loading-bar;
position: absolute;
width: $w-loading-bar;
}
}
@keyframes loading {
from {
left: -$w-loading-bar;
width: 30%;
}
50% {
width: 30%;
}
70% {
width: 70%;
}
80% {
left: 50%;
}
95% {
left: 120%;
}
to {
left: 100%;
}
}

View File

@ -1,139 +0,0 @@
/**
* LOADING SPINNER
*
* Markup:
* ---------
* <div class='loadingSpinner'>
* <span class='loadingSpinner-inner'></span>
* <span class='loadingSpinner-inner'></span>
* <span class='loadingSpinner-inner'></span>
* <span class='loadingSpinner-inner'></span>
* </div>
*
*/
.loadingSpinner {
animation: rotateLoader 4s infinite;
animation-timing-function: ease-in-out;
display: block;
height: $size-loading-spinner;
left: 50%;
margin-left: -$size-loading-spinner / 2;
margin-top: -$size-loading-spinner / 2;
position: fixed;
top: 50%;
width: $size-loading-spinner;
z-index: $z-loading-spinner;
&-inner {
animation-timing-function: ease-in-out;
background-color: $bg-loading-spinner;
border-radius: 100%;
display: block;
height: $size-loading-spinner-inner;
position: absolute;
width: $size-loading-spinner-inner;
&:nth-child(1) {
animation: translateBall1 1s infinite;
left: 0;
top: 0;
transform: translate3d($size-loading-spinner-inner / 2, $size-loading-spinner-inner / 2, 0);
}
&:nth-child(2) {
animation: translateBall2 1s infinite;
right: 0;
top: 0;
}
&:nth-child(3) {
animation: translateBall3 1s infinite;
bottom: 0;
right: 0;
}
&:nth-child(4) {
animation: translateBall4 1s infinite;
bottom: 0;
left: 0;
}
}
}
@keyframes rotateLoader {
0% {
transform: rotate(0);
}
25% {
transform: rotate(90deg);
}
50% {
transform: rotate(180deg);
}
75% {
transform: rotate(270deg);
}
100% {
transform: rotate(360deg);
}
}
@keyframes translateBall1 {
0% {
transform: translate3d(0, 0, 0);
}
50% {
transform: translate3d($size-loading-spinner-inner / 2, $size-loading-spinner-inner / 2, 0);
}
100% {
transform: translate3d(0, 0, 0);
}
}
@keyframes translateBall2 {
0% {
transform: translate3d(0, 0, 0);
}
50% {
transform: translate3d(-$size-loading-spinner-inner / 2, $size-loading-spinner-inner / 2, 0);
}
100% {
transform: translate3d(0, 0, 0);
}
}
@keyframes translateBall3 {
0% {
transform: translate3d(0, 0, 0);
}
50% {
transform: translate3d(-$size-loading-spinner-inner / 2, -$size-loading-spinner-inner / 2, 0);
}
100% {
transform: translate3d(0, 0, 0);
}
}
@keyframes translateBall4 {
0% {
transform: translate3d(0, 0, 0);
}
50% {
transform: translate3d($size-loading-spinner-inner / 2, -$size-loading-spinner-inner / 2, 0);
}
100% {
transform: translate3d(0, 0, 0);
}
}

View File

@ -1,31 +0,0 @@
/**
* NOTIFICATION
*
* Markup:
* -------
*
* <div class="notification notification--sucess">Success notification</div>
* <div class="notification notification--info">Success info</div>
* <div class="notification notification--error">Success error</div>
* <div class="notification notification--warning">Success warning</div>
*
*/
.notification {
border-radius: $bdr-notification;
color: $c-notification;
margin-bottom: $mb-notification;
padding: $p-notification;
p {
&:last-child {
margin-bottom: 0;
}
}
@each $type, $color in $c-map {
&--#{$type} {
background-color: $color;
}
}
}

View File

@ -1,45 +0,0 @@
/**
* PAGINATOR
*
* Markup:
* -------
*
* <ul class="paginator">
* <li class="paginator-item">
* <a href="#" class="paginator-itemLink">< Prev</a>
* </li>
* <li class="paginator-item">
* <a href="#" class="paginator-itemLink">1</a>
* </li>
* <li class="paginator-item">
* <a href="#" class="paginator-itemLink is-active">2</a>
* </li>
* <li class="paginator-item">
* <a href="#" class="paginator-itemLink">3</a>
* </li>
* <li class="paginator-item">
* <a href="#" class="paginator-itemLink">Next ></a>
* </li>
* </ul>
*/
.paginator {
&-item {
display: inline-block;
margin-right: $mr-paginator-item;
&Link {
background-color: $bg-paginator-item;
border-radius: $bdr-paginator-item;
display: block;
padding: $p-paginator-item;
&.is-active {
background-color: $bg-paginator-item-active;
color: $c-paginator-item-active;
cursor: default;
}
}
}
}

View File

@ -1,123 +0,0 @@
/**
* TABLE
*
* Markup:
* -------
*
* <table class="table">
* <tr>
* <th>First column</th>
* <th>Second column</th>
* <th>Third column</th>
* </tr>
* <tr>
* <td="First column">Blue</td>
* <td="Second column">One</td>
* <td="Third column">My life fades</td>
* </tr>
* </table>
*
*/
.table {
background-color: $bgc-table;
border: $bd-table;
border-collapse: collapse;
color: $c-table-text;
max-width: $mwi-table;
width: $w-table;
th,
td {
border-bottom: $bd-table;
padding: $p-table-cell;
position: relative;
}
thead {
border-bottom: $bd-table;
}
th {
background-color: $bgc-table-header;
color: $c-table-heading;
font-size: $fz-table-heading;
font-weight: $fw-table-heading;
padding: $p-table-heading;
white-space: nowrap;
}
}
/**
* TABLE RESPONSIVE
*
* Markup:
* -------
*
* <table class="table table--responsive">
* <tr>
* <th>First column</th>
* <th>Second column</th>
* <th>Third column</th>
* </tr>
* <tr>
* <td data-th="First column">Blue</td>
* <td data-th="Second column">One</td>
* <td data-th="Third column">My life fades</td>
* </tr>
* <tr>
* <td data-th="First column">Green</td>
* <td data-th="Second column">Two</td>
* <td data-th="Third column">
* when the world was powered by the black fuel... and the desert
* sprouted great cities of pipe and steel.
* </td>
* </tr>
* <tr>
* <td data-th="First column">Yellow</td>
* <td data-th="Second column">Three</td>
* <td data-th="Third column">
* A whirlwind of looting, a firestorm of fear.
* </td>
* </tr>
* </table>
*
*/
.table--responsive {
th {
display: none;
}
td {
@include media-breakpoint-down(sm) {
border: 0;
}
display: block;
&::before {
@include media-breakpoint-up(sm) {
display: none;
}
color: $c-table-heading;
content: attr(data-th)': ';
display: block;
font-weight: normal;
}
&:first-child {
border-top: $bd-table;
}
}
th,
td {
@include media-breakpoint-up(sm) {
border-top: $bd-table;
display: table-cell;
}
text-align: left;
}
}

View File

@ -1,37 +0,0 @@
/**
* TABS
*
* Markup:
* -------
*
* <div class="tabs">
* <a href="#" title="#" class="tabs-item">[...]</a>
* <a href="#" title="#" class="tabs-item is-selected">[...]</a>
* </div>
*
*/
.tabs {
border-bottom: $bdb-tabs;
text-align: center;
&-item {
border-bottom: $bdb-tabs-item;
color: $c-tabs-item;
display: inline-block;
margin: $m-tabs-item;
min-width: $miw-tabs-item;
padding: $p-tabs-item;
position: relative;
&:hover {
color: $c-tabs-item-hover;
text-decoration: none;
}
&.is-selected {
border-bottom: $bdb-tabs-item-selected;
color: $c-tabs-item-selected;
}
}
}

View File

@ -1,62 +0,0 @@
/**
* TAG
*
* Markup:
* -------
*
* <ul>
* <li class="tag">Fantasy</li>
* <li class="tag">Fiction</li>
* <li class="tag">Contemporary</li>
* </ul>
*
* <ul>
* <li class="tag">
* <a href="#">Fantasy</a>
* </li>
* <li class="tag">
* <a href="#">Fiction</a>
* </li>
* <li class="tag">
* <a href="#">Contemporary</a>
* </li>
* </ul>
*
*/
.tag {
background-color: $bg-tag;
border-radius: $bdr-tag;
color: $c-tag;
display: inline-block;
line-height: $lh-tag;
margin: $m-tag;
padding: $p-tag;
position: relative;
// triangle arrow
&::before {
border-bottom: ($lh-tag / 2) + $p-tag solid transparent;
border-left: $p-tag solid $bg-tag;
border-top: ($lh-tag / 2) + $p-tag solid transparent;
content: '';
height: 0;
position: absolute;
right: -$p-tag;
top: 0;
width: 0;
}
// dot
&::after {
background: $bg-tag-dot;
border-radius: 100%;
content: '';
height: $size-tag-dot;
margin-top: -$size-tag-dot / 2;
position: absolute;
right: -$size-tag-dot / 2;
top: 50%;
width: $size-tag-dot;
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,69 +0,0 @@
// Framework grid generation
//
// Used only by Bootstrap to generate the correct number of grid classes given
// any value of `$grid-columns`.
@mixin make-grid-columns($columns: $grid-columns, $gutter: $grid-gutter-width, $breakpoints: $grid-breakpoints) {
// Common properties for all breakpoints
%grid-column {
position: relative;
width: 100%;
min-height: 1px; // Prevent columns from collapsing when empty
padding-right: ($gutter / 2);
padding-left: ($gutter / 2);
}
@each $breakpoint in map-keys($breakpoints) {
$infix: breakpoint-infix($breakpoint, $breakpoints);
// Allow columns to stretch full width below their breakpoints
@for $i from 1 through $columns {
.col#{$infix}-#{$i} {
@extend %grid-column;
}
}
.col#{$infix},
.col#{$infix}-auto {
@extend %grid-column;
}
@include media-breakpoint-up($breakpoint, $breakpoints) {
// Provide basic `.col-{bp}` classes for equal-width flexbox columns
.col#{$infix} {
flex-basis: 0;
flex-grow: 1;
max-width: 100%;
}
.col#{$infix}-auto {
flex: 0 0 auto;
width: auto;
max-width: none; // Reset earlier grid tiers
}
@for $i from 1 through $columns {
.col#{$infix}-#{$i} {
@include make-col($i, $columns);
}
}
.order#{$infix}-first {
order: -1;
}
@for $i from 1 through $columns {
.order#{$infix}-#{$i} {
order: $i;
}
}
// `$columns - 1` because offsetting by the width of an entire row isn't possible
@for $i from 0 through ($columns - 1) {
@if not ($infix == "" and $i == 0) { // Avoid emitting useless .offset-0
.offset#{$infix}-#{$i} {
@include make-col-offset($i, $columns);
}
}
}
}
}
}

View File

@ -1,52 +0,0 @@
/// Grid system
//
// Generate semantic grid columns with these mixins.
@mixin make-container() {
width: 100%;
padding-right: ($grid-gutter-width / 2);
padding-left: ($grid-gutter-width / 2);
margin-right: auto;
margin-left: auto;
}
// For each breakpoint, define the maximum width of the container in a media query
@mixin make-container-max-widths($max-widths: $container-max-widths, $breakpoints: $grid-breakpoints) {
@each $breakpoint, $container-max-width in $max-widths {
@include media-breakpoint-up($breakpoint, $breakpoints) {
max-width: $container-max-width;
}
}
}
@mixin make-row() {
display: flex;
flex-wrap: wrap;
margin-right: ($grid-gutter-width / -2);
margin-left: ($grid-gutter-width / -2);
}
@mixin make-col-ready() {
position: relative;
// Prevent columns from becoming too narrow when at smaller grid tiers by
// always setting `width: 100%;`. This works because we use `flex` values
// later on to override this initial width.
width: 100%;
min-height: 1px; // Prevent collapsing
padding-right: ($grid-gutter-width / 2);
padding-left: ($grid-gutter-width / 2);
}
@mixin make-col($size, $columns: $grid-columns) {
flex: 0 0 percentage($size / $columns);
// Add a `max-width` to ensure content within each column does not blow out
// the width of the column. Applies to IE10+ and Firefox. Chrome and Safari
// do not appear to require this.
max-width: percentage($size / $columns);
}
@mixin make-col-offset($size, $columns: $grid-columns) {
$num: $size / $columns;
margin-left: if($num == 0, 0, percentage($num));
}

View File

@ -1,34 +0,0 @@
@charset 'UTF-8';
// Settings
@import 'settings';
@import 'custom';
// Utils
@import 'utils/breakpoints';
@import 'utils/reset';
@import 'utils/default';
@import 'utils/background';
@import 'utils/border';
@import 'utils/aligner';
@import 'utils/helpers';
@import 'utils/layout';
@import 'utils/typography';
// Components
@import 'components/badge';
@import 'components/buttons';
@import 'components/forms';
@import 'components/loading-bar';
@import 'components/loading-spinner';
@import 'components/notification';
@import 'components/paginator';
@import 'components/table';
@import 'components/tabs';
@import 'components/tag';
// Twitter bootstrap's grid v4.1.0
// More info: https://getbootstrap.com/examples/grid/
@import 'grid/grid-framework';
@import 'grid/grid';
@import 'utils/grid';

View File

@ -1,48 +0,0 @@
/**
* ALIGNERS
*/
// container
.aligner {
display: flex;
&--spaceBetween {
justify-content: space-between;
width: 100%;
}
&--spaceAround {
justify-content: space-around;
width: 100%;
}
&--centerVertical {
align-items: center;
}
&--centerHoritzontal {
justify-content: center;
}
&--contentStart {
justify-content: flex-start;
}
&--contentEnd {
justify-content: flex-end;
}
}
// item
.aligner--itemTop {
align-self: flex-start;
}
.aligner--itemBottom {
align-self: flex-end;
}
.flex-grow, // deprecated
.aligner--grow {
flex-grow: 1;
}

View File

@ -1,11 +0,0 @@
/**
* BACKGROUND
*/
.bg {
@each $type, $color in $c-map {
&-#{$type} {
background-color: $color;
}
}
}

View File

@ -1,23 +0,0 @@
/**
* BORDER
*/
.border {
border: $bd-medium;
}
.border-bottom {
border-bottom: $bd-medium;
}
.border-left {
border-left: $bd-medium;
}
.border-right {
border-right: $bd-medium;
}
.border-top {
border-top: $bd-medium;
}

View File

@ -1,119 +0,0 @@
// Breakpoint viewport sizes and media queries.
//
// Breakpoints are defined as a map of (name: minimum width), order from small to large:
//
// (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px)
//
// The map defined in the `$grid-breakpoints` global variable is used as the `$breakpoints` argument by default.
// Name of the next breakpoint, or null for the last breakpoint.
//
// >> breakpoint-next(sm)
// md
// >> breakpoint-next(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// md
// >> breakpoint-next(sm, $breakpoint-names: (xs sm md lg xl))
// md
@function breakpoint-next($name, $breakpoints: $grid-breakpoints, $breakpoint-names: map-keys($breakpoints)) {
$n: index($breakpoint-names, $name);
@return if($n < length($breakpoint-names), nth($breakpoint-names, $n + 1), null);
}
// Minimum breakpoint width. Null for the smallest (first) breakpoint.
//
// >> breakpoint-min(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// 576px
@function breakpoint-min($name, $breakpoints: $grid-breakpoints) {
$min: map-get($breakpoints, $name);
@return if($min != 0, $min, null);
}
// Maximum breakpoint width. Null for the largest (last) breakpoint.
// The maximum value is calculated as the minimum of the next one less 0.1.
//
// >> breakpoint-max(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// 767px
@function breakpoint-max($name, $breakpoints: $grid-breakpoints) {
$next: breakpoint-next($name, $breakpoints);
@return if($next, breakpoint-min($next, $breakpoints) - 1px, null);
}
// Returns a blank string if smallest breakpoint, otherwise returns the name with a dash infront.
// Useful for making responsive utilities.
//
// >> breakpoint-infix(xs, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// "" (Returns a blank string)
// >> breakpoint-infix(sm, (xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px))
// "-sm"
@function breakpoint-infix($name, $breakpoints: $grid-breakpoints) {
@return if(breakpoint-min($name, $breakpoints) == null, "", "-#{$name}");
}
// Media of at least the minimum breakpoint width. No query for the smallest breakpoint.
// Makes the @content apply to the given breakpoint and wider.
@mixin media-breakpoint-up($name, $breakpoints: $grid-breakpoints) {
$min: breakpoint-min($name, $breakpoints);
@if $min {
@media (min-width: $min) {
@content;
}
} @else {
@content;
}
}
// Media of at most the maximum breakpoint width. No query for the largest breakpoint.
// Makes the @content apply to the given breakpoint and narrower.
@mixin media-breakpoint-down($name, $breakpoints: $grid-breakpoints) {
$max: breakpoint-max($name, $breakpoints);
@if $max {
@media (max-width: $max) {
@content;
}
} @else {
@content;
}
}
// Media that spans multiple breakpoint widths.
// Makes the @content apply between the min and max breakpoints
@mixin media-breakpoint-between($lower, $upper, $breakpoints: $grid-breakpoints) {
$min: breakpoint-min($lower, $breakpoints);
$max: breakpoint-max($upper, $breakpoints);
@if $min != null and $max != null {
@media (min-width: $min) and (max-width: $max) {
@content;
}
} @else if $max == null {
@include media-breakpoint-up($lower) {
@content;
}
} @else if $min == null {
@include media-breakpoint-down($upper) {
@content;
}
}
}
// Media between the breakpoint's minimum and maximum widths.
// No minimum for the smallest breakpoint, and no maximum for the largest one.
// Makes the @content apply only to the given breakpoint, not viewports any wider or narrower.
@mixin media-breakpoint-only($name, $breakpoints: $grid-breakpoints) {
$min: breakpoint-min($name, $breakpoints);
$max: breakpoint-max($name, $breakpoints);
@if $min != null and $max != null {
@media (min-width: $min) and (max-width: $max) {
@content;
}
} @else if $max == null {
@include media-breakpoint-up($name) {
@content;
}
} @else if $min == null {
@include media-breakpoint-down($name) {
@content;
}
}
}

View File

@ -1,39 +0,0 @@
/**
* MAIN RULES
*/
*,
*::after,
*::before {
box-sizing: border-box;
outline: none;
}
body {
background-color: $bgc-body;
min-height: 100%;
overflow-x: hidden;
position: relative;
}
p {
font-weight: normal;
margin-bottom: $mb-p;
}
img {
max-width: 100%;
}
strong {
font-weight: $fw-strong;
}
ul {
margin-bottom: $mb-ul;
}
li {
list-style: none;
margin-bottom: $mb-li;
}

View File

@ -1,52 +0,0 @@
// Container widths
//
// Set the container width, and override it for fixed navbars in media queries.
@if $enable-grid-classes {
.container {
@include make-container;
@include make-container-max-widths;
}
}
// Fluid container
//
// Utilizes the mixin meant for fixed width containers, but with 100% width for
// fluid, full width layouts.
@if $enable-grid-classes {
.container-fluid {
@include make-container;
}
}
// Row
//
// Rows contain and clear the floats of your columns.
@if $enable-grid-classes {
.row {
@include make-row;
}
// Remove the negative margin from default .row, then the horizontal padding
// from all immediate children columns (to prevent runaway style inheritance).
.no-gutters {
margin-left: 0;
margin-right: 0;
> .col,
> [class*='col-'] {
padding-left: 0;
padding-right: 0;
}
}
}
// Columns
//
// Common styles for small and large grid columns
@if $enable-grid-classes {
@include make-grid-columns;
}

View File

@ -1,126 +0,0 @@
/**
* FLOATS
*/
.fleft {
float: left;
}
.fright {
float: right;
}
.clearfix {
::after {
clear: both;
content: '';
display: table;
}
}
/**
* MARGINS
*/
.m-xsmall {
margin: $m-xsmall;
}
.mb-xsmall {
margin-bottom: $m-xsmall;
}
.m-small {
margin: $m-small;
}
.mb-small {
margin-bottom: $m-small;
}
.m-medium {
margin: $m-medium;
}
.mb-medium {
margin-bottom: $m-medium;
}
.m-big {
margin: $m-big;
}
.mb-big {
margin-bottom: $m-big;
}
.m-huge {
margin: $m-huge;
}
.mb-huge {
margin-bottom: $m-huge;
}
.m-none {
margin: 0 !important;
}
/**
* PADDINGS
*/
.p-small {
padding: $p-small;
}
.pb-small {
padding-bottom: $p-small;
}
.p-medium {
padding: $p-medium;
}
.pb-medium {
padding-bottom: $p-medium;
}
.p-big {
padding: $p-big;
}
.pb-big {
padding-bottom: $p-big;
}
.p-huge {
padding: $p-huge;
}
.pb-huge {
padding-bottom: $p-huge;
}
/**
* OTHERS
*/
.no-wrap {
white-space: nowrap;
}
.overflow-hidden {
overflow: hidden;
}
.opacity-low {
opacity: .5;
}
.rounded-corners {
border-radius: $bdr-rounded-corners;
}
.rounded {
border-radius: 100%;
}

View File

@ -1,51 +0,0 @@
/**
* LAYOUT
*/
.section {
@include media-breakpoint-up(md) {
padding-bottom: $p-huge * 2;
padding-top: $p-huge * 2;
}
padding-bottom: $p-huge;
padding-top: $p-huge;
& + & {
padding-top: 0;
}
}
.container {
@include media-breakpoint-up(md) {
padding-left: $w-gutter;
padding-right: $w-gutter;
}
background-color: $bgc-container;
margin: 0 auto;
max-width: $mwi-container;
padding-left: $w-gutter / 2;
padding-right: $w-gutter / 2;
width: 100%;
}
.container-medium {
@include media-breakpoint-up(md) {
padding-left: $w-gutter;
padding-right: $w-gutter;
}
margin: 0 auto;
max-width: $mwi-container-medium;
padding-left: $w-gutter / 2;
padding-right: $w-gutter / 2;
}
.container-small {
@include media-breakpoint-up(md) {
padding-left: $w-gutter;
padding-right: $w-gutter;
}
margin: 0 auto;
max-width: $mwi-container-small;
padding-left: $w-gutter / 2;
padding-right: $w-gutter / 2;
}

View File

@ -1,34 +0,0 @@
/**
* Reset
*/
@if $enable-reset-defaults {
html,body,body,div,span,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,abbr,address,cite,code,del,dfn,em,ins,kbd,q,samp,small,strong,sub,sup,var,b,i,dl,dt,dd,ol,ul,li,fieldset,form,label,legend,table,caption,tbody,tfoot,thead,tr,th,td,article,aside,figure,footer,header,hgroup,menu,nav,section,time,mark,audio,video {
background: transparent;
border: 0;
font-size: 100%;
margin: 0;
outline: 0;
padding: 0;
vertical-align: baseline;
}
article,
aside,
figure,
footer,
header,
main,
nav,
section {
display: block;
}
* {
&,
&:before,
&:after {
box-sizing: border-box;
}
}
}

View File

@ -1,124 +0,0 @@
/**
* TYPOGRAPHY
*/
body {
color: $c-body;
font-family: $ff-body;
font-size: $fz-body;
font-weight: $fw-body;
line-height: $lh-body;
}
a {
color: $c-link;
text-decoration: none;
&:hover {
color: $c-link-hover;
}
&:focus {
color: $c-primary;
}
}
// Sizes
.text {
&-huge, &-big, &-medium {
margin-bottom: 1em;
}
&-huge {
font-size: $fz-huge;
line-height: $lh-huge;
}
&-big {
font-size: $fz-big;
line-height: $lh-big;
}
&-medium {
font-size: $fz-medium;
line-height: $lh-medium;
}
&-small {
font-size: $fz-small;
line-height: $lh-small;
}
// set default font state.
&-body {
font-size: $fz-body;
line-height: $lh-body;
}
}
// Colors
.text {
@each $type, $color in $c-map {
&-#{$type} {
color: $color;
}
}
}
// Styles
.text-light {
font-weight: $fw-light;
}
.text-normal {
font-weight: $fw-normal;
}
.text-lineThrough {
text-decoration: line-through;
}
.text-italic {
font-style: italic;
}
.text-underline {
text-decoration: underline;
}
.text-uppercase {
text-transform: uppercase;
}
// titles after titles
.text-withSubtitle {
margin-bottom: 0 !important;
+ .text-huge,
+ .text-big,
+ .text-medium,
+ .text-small, {
margin-top: .5em;
}
}
h1,
h2,
h3,
h4 {
font-weight: $fw-headings;
}
// Aligners
.text-center {
text-align: center;
}
.text-right {
text-align: right;
}
.text-left {
text-align: left;
}

View File

@ -1,117 +0,0 @@
<!DOCTYPE html>
<html$if(lang)$ lang="$lang$"$endif$ >
<head>
<meta charset="utf-8">
<meta name="generator" content="pandoc">
<link rel='shortcut icon' href='/public/img/helcel.ico' type='image/x-icon'/>
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
$for(author-meta)$
<meta name="author" content="$author-meta$">
$endfor$
$if(date-meta)$
<meta name="dcterms.date" content="$date-meta$">
$endif$
<title>$if(title-prefix)$$title-prefix$ - $endif$$pagetitle$</title>
<style type="text/css">code{white-space: pre;}</style>
<!--[if lt IE 9]>
<script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></script>
<![endif]-->
$if(quotes)$
<style type="text/css">q { quotes: "“" "”" "" ""; }</style>
$endif$
$for(css)$
<link rel="stylesheet" href="$css$">
$endfor$
$for(header-includes)$
$header-includes$
$endfor$
</head>
<body>
<header itemscope itemtype="https://schema.org/Person" class="$if(photo)$with-photo$endif$">
<div id="title">
$if(qrcode)$
<img class="logo" src="$qrcode$" />
$endif$
<h1 class="fullname">
<span itemprop="givenName">$firstname$</span>
<span itemprop="familyName">$lastname$</span>
</h1>
<h2 class="title">$description$</h2>
</div>
$if(photo)$
<img class="portrait" src="$photo$"></div>
$endif$
<ul class="details">
<!-- phone -->
$if(phone)$
$if(settings.protect-phone)$
$if(privatecv)$
<li><a class='phone' href="phoneto:$phone$">$phone$</a></li>
$endif$
$else$
<li><a class='phone' href="phoneto:$phone$">$phone$</a></li>
$endif$
$endif$
<!-- mobile -->
$if(mobile)$
$if(settings.protect-mobile)$
$if(privatecv)$
<li><a class='mobile' href="phoneto:$mobile$">$mobile$</a></li>
$endif$
$else$
<li><a class='mobile' href="phoneto:$mobile$">$mobile$</a></li>
$endif$
$endif$
<!-- email -->
$if(email)$
$if(settings.protect-email)$
$if(privatecv)$
<li><a href="mailto:$email$">$email$</a></li>
$endif$
$else$
<li><a href="mailto:$email$">$email$</a></li>
$endif$
$endif$
<!-- homepage -->
$if(homepage)$
<li><a href="$homepage$" itemprop="url" title="homepage">$homepage$</a></li>
$endif$
<!--if(address)-->
$if(address)$
$if(settings.protect-address)$
$if(privatecv)$
<li itemprop="address" itemscope itemtype="http://schema.org/PostalAddress">
$if(address.city)$
<span itemprop="addressLocality">$address.city$</span>
$endif$
$if(address.country)$
<span itemprop="addressCountry">$address.country$</span>
$endif$
</li>
$endif$
$else$
<li itemprop="address" itemscope itemtype="http://schema.org/PostalAddress">
$if(address.city)$
<span itemprop="addressLocality">$address.city$</span>
$endif$
$if(address.country)$
<span itemprop="addressCountry">$address.country$</span>
$endif$
</li>
$endif$
$endif$
<!--endif-->
</ul>
</header>
$for(include-before)$
$include-before$
$endfor$
$body$
$for(include-after)$
$include-after$
$endfor$
<footer>
$footer$
</footer>
</body>
</html>

View File

@ -1,136 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Helcel-OTM</title>
<link rel='shortcut icon' href='/public/img/helcel.ico' type='image/x-icon'/>
<meta charset='utf-8'/>
<meta name='viewport' content='width=device-width, initial-scale=1'/>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=IBM+Plex+Sans:400,700,300" type="text/css">
<link rel='stylesheet' href='/public/css/index.css'/>
<link rel="stylesheet" href="https://unpkg.com/vue2-datepicker/index.css">
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<link rel="stylesheet" href="https://unpkg.com/vue-multiselect/dist/vue-multiselect.min.css">
</head>
<body>
<main id="app">
<!--<header class="header js-header">
<div class="header-inner container">
<a href="/" class="header-logo text-dark">
<img class="header-logoImage" src="/public/img/helcel.png" alt="Helcel logo" width="40">
<span class="hide-small">Helcel</span>
</a>
<ul class="header-nav">
<li class="header-navItem"><a class="text-dark" href="/">OTM</a></li>
</ul>
</div>
</header>-->
<div class="container">
<section class="mb-big">
<div class="text-center">
<img class="main-logo mb-medium" src="/public/img/helcel.png" alt="Helcel logo">
<div>
<h1 class="text-huge text-withSubtitle">Open Tourism Map</h1>
<h2 class="text-big text-gray">Collaborative Holiday Planner</h2>
</div>
<p id="js-header-waypoint" class="m-none">
<a class="button button--primary button--mobileFull" href="#go">Get started</a>
</p>
</div>
</section>
</div>
<div class="bg-dark">
<div class="container">
<div class="row text-center">
<div class="col-12 col-sm-3">
<div class="section">
<img src="/public/img/lightweight.png" alt="Lightweight" width="118"> <br>
<h2 class="text-withSubtitle text-big text-white">Lightweight <br>
<span class="text-medium text-gray">Powered By<br>Fastify & Sierra</span></h2>
</div>
</div>
<div class="col-12 col-sm-4">
<div class="section">
<img src="/public/img/customizable.png" alt="Customizable" width="118"> <br>
<h2 class="text-withSubtitle text-big text-white">Customizable<br>
<span class="text-medium text-gray">Many Templates<br>to choose from</span>
</h2>
</div>
</div>
<div class="col-12 col-sm-4">
<div class="section">
<h2 class="text-withSubtitle text-big text-white">
<img src="/public/img/opensource.png" alt="Open Source" width="118"> <br>
FOSS<br>
<span class="text-medium text-gray">:-)</span>
</h2>
</div>
</div>
</div>
</div>
</div>
<div id="go" class="container-medium section">
<h2 class="text-big">Your journey</h2>
<p>Browse hotels, restaurants and attractions,.... <br> Select and plan the varying elements of your journey</p>
<div class="aligner aligner--contentEnd">
<div class="input">
<input id="journey_id" v-model="journey_id" placeholder="ID" type="text">
</div>
<button class="button button--primary button--mobileFull" v-on:click="start_journey">Start the journey</button>
</div>
</div>
<!-- <div>
<div class="section bg-dark">
<div class="container text-center">
<h3 class="text-huge text-white text-withSubtitle">Developed entirely with Sierra library selectors</h3>
<h4 class="text-big text-gray">Just define your custom SCSS variables and compile</h4>
<p>
<p><a href="https://sierra-library.github.io/" class="button button--secondary button--medium button--mobileFull">Documentation</a> <a href="https://github.com/sierra-library/sierra-library.github.io/tree/master/examples/example1" class="button button--outlined button--medium button--mobileFull">View code</a></p>
</p>
</div>
</div>
</div>
<div class="container-medium section">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod
tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo
consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse
cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non
proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
</p>
<div class="aligner aligner--contentEnd">
<a href="https://github.com/sierra-library/sierra" class="button button--primary button--mobileFull">Visit Github Page</a>
</div>
</div> -->
</main>
<script src="https://unpkg.com/vue@2/dist/vue.min.js"></script>
<script src="https://unpkg.com/vue2-datepicker/index.min.js"></script>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script src="https://unpkg.com/vue2-leaflet"></script>
<script src="https://unpkg.com/leaflet.awesome-markers/dist/leaflet.awesome-markers.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://unpkg.com/lodash"></script>
<script src="https://unpkg.com/vue-multiselect"></script>
<script src="https://unpkg.com/vue-textarea-autosize/dist/vue-textarea-autosize.umd.min.js"></script>
<script src="/public/js/main.js" type="text/javascript" charset="utf-8"></script>
<footer class="bg-dark">
<div class="container">
<div class="section text-center text-small">
<p class="text-white">
<img src="/public/img/helcel.png" alt="helcel logo" width="100"><br><br>
Built with &nbsp;&nbsp; by Helcel <br><span class="text-small text-gray">v0.0.1</span>
</p>
<p class="text-gray"><a href="https://git.helcel.net">Helcel Git</a></p>
</div>
</div>
</footer>
</body>
</html>

View File

@ -1,530 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<title>Helcel-OTM</title>
<link rel='shortcut icon' href='/public/img/helcel.ico' type='image/x-icon'/>
<meta charset='utf-8'/>
<meta name='viewport' content='width=device-width, initial-scale=1'/>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=IBM+Plex+Sans:400,700,300" type="text/css">
<link rel='stylesheet' href='/public/css/index.css'/>
<link rel="stylesheet" href="https://unpkg.com/vue2-datepicker/index.css">
<link rel="stylesheet" href="https://unpkg.com/leaflet/dist/leaflet.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet.awesome-markers/dist/leaflet.awesome-markers.css">
<link rel="stylesheet" href="https://unpkg.com/@fortawesome/fontawesome-free/css/all.min.css">
<link rel="stylesheet" href="https://unpkg.com/vue-multiselect/dist/vue-multiselect.min.css">
</head>
<body>
<main id="app">
<div v-if="vtp==-1" v-cloak>
<header class="header">
<div class="header-inner container">
<a href="/" class="header-logo text-dark">
<img class="header-logoImage" src="/public/img/helcel.png" alt="Helcel logo" width="40">
<span class="hide-small">HOTM</span>
</a>
<div class="input input-invis"><input class="small" v-model="journey_data.name" type="text" /></div>
<div class="row header-nav text-big" style="margin-bottom: 0;">
<div class="col-sm-2"><a :href="'/short/'+journey_id" ><i class="fas fa-file-contract"></i></a></div>
<div class="col-sm-2"><a :href="'/view/'+journey_id +'#0'" ><i class="fas fa-camera"></i></a></div>
<div class="col-sm-2"><a href="#main" v-on:click.prevent="first_step"><i class="fas fa-tools"></i></a></div>
<div class="col-sm-1 text-small"><a href="#prevprev" v-on:click.prevent="prevprev_step"><i class="fas fa-angle-double-left"></i></a></div>
<div class="col-sm-1"><a href="#prev" v-on:click.prevent="prev_step"><i class="fas fa-angle-left"></i></a></div>
<div class="col-sm-1"><a href="#next" v-on:click.prevent="next_step"><i class="fas fa-angle-right"></i></a></div>
<div class="col-sm-1 text-small"><a href="#nextnext" v-on:click.prevent="nextnext_step"><i class="fas fa-angle-double-right"></i></a></div>
</div>
</div>
</header>
<div v-if="journey_step==-1">
<div v-for="(item,idx) in journey_data.main" :class="idx%2===0 ? 'bg-dark text-white' : ''" v-cloak>
<div class="container section">
<div class="row text-center">
<div class="col-auto"><button class="button button--secondary button--mobileFull" v-on:click="rm_section(idx)">X</button></div>
<div class="col-auto"><button class="button button--secondary button--mobileFull" v-on:click="toggle_section_vis(idx)">-</button></div>
<div class="input col-sm-4"><input class="" v-model="item.title" type="text" /></div>
</div>
<div class="row" v-if="visible_step & (0x1 << idx)">
<div class="col-12 col-sm-8">
<l-map
:zoom.sync="item.map.zoom"
:center.sync="item.map.center"
style="padding-top: 100%;"
>
<l-tile-layer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
></l-tile-layer>
<l-control-scale position="topright" :imperial="false" :metric="true"></l-control-scale>
<l-marker v-if="item.hotel" :lat-lng.sync="item.hotel.latlon">
<l-icon>
<div v-html="generate_icon(item.hotel,'darkblue')"></div>
</l-icon>
<l-popup>
<h1 class="row text-medium text-center">{{item.hotel.sname}}</h1>
<span class="row text-small text-gray">{{item.hotel.display_name}}</span>
<div class="row input">
<textarea-autosize
class="col-12 col-sm-10 text-small"
placeholder="Notes"
v-model="item.hotel.notes"
:min-height="30"
:max-height="350"
/>
</div>
</l-popup>
<!-- <l-tooltip :options="{ permanent: true, interactive: true }">
<div>
H
</div>
</l-tooltip> -->
</l-marker>
<l-marker v-for="place in item.places.restaurants" :lat-lng.sync="place.latlon">
<l-icon>
<div v-html="generate_icon(place,'cadetblue')"></div>
</l-icon>
<l-popup>
<h1 class="row text-medium text-center">{{place.sname}}</h1>
<span class="row text-small text-gray">{{place.display_name}}</span>
<div class="row input">
<textarea-autosize
class="col-12 col-sm-10 text-small"
placeholder="Notes"
v-model="place.notes"
:min-height="30"
:max-height="350"
/>
</div>
</l-popup>
</l-marker>
<l-marker v-for="place in item.places.activities" :lat-lng.sync="place.latlon">
<l-icon>
<div v-html="generate_icon(place)"></div>
</l-icon>
<l-popup>
<h1 class="row text-medium text-center">{{place.sname}}</h1>
<span class="row text-small text-gray">{{place.display_name}}</span>
<div class="row input">
<textarea-autosize
class="col-12 col-sm-10 text-small"
placeholder="Notes"
v-model="place.notes"
:min-height="30"
:max-height="350"
/>
</div>
</l-popup>
</l-marker>
</l-map>
</div>
<div class="col-12 col-sm-4">
<div class="row text-center">
<div><label>Date Range</label></div>
<div class="input text-dark">
<date-picker :lang="lang" v-model="item.dateRange" range placeholder="Date Range"></date-picker>
</div>
</div>
<div class="row text-center">
<div><label>Hotel</label></div>
<multiselect v-model="item.hotel" id="ajax" label="sname" track-by="place_id" placeholder="Type to search" open-direction="bottom" :options="query.nominatim" :searchable="true" :loading="querying.hotel" :internal-search="false" :clear-on-select="false" :options-limit="50" :limit="1" :max-height="600" @search-change="debounceSearch.hotel"></multiselect>
</div>
<div class="row text-center">
<div><label>Fight</label></div>
<multiselect v-model="item.flightA" id="ajax" label="label" track-by="id" placeholder="Type to search" open-direction="bottom" :multiple="true" :options="query.flight" :searchable="true" :loading="querying.flight" :internal-search="false" :clear-on-select="false" :options-limit="50" :limit="10" :max-height="600" @search-change="debounceSearch.flight"></multiselect>
<multiselect v-model="item.flightB" id="ajax" label="label" track-by="id" placeholder="Type to search" open-direction="bottom" :multiple="true" :options="query.flight" :searchable="true" :loading="querying.flight" :internal-search="false" :clear-on-select="false" :options-limit="50" :limit="10" :max-height="600" @search-change="debounceSearch.flight"></multiselect>
</div>
<div class="row text-center">
<div><label>Restoration</label></div>
<multiselect v-model="item.places.restaurants" id="ajax" label="sname" track-by="place_id" placeholder="Type to search" open-direction="bottom" :multiple="true" :options="query.nominatim" :searchable="true" :loading="querying.food" :internal-search="false" :clear-on-select="false" :options-limit="50" :limit="10" :max-height="600" @search-change="debounceSearch.restaurants"></multiselect>
</div>
<div class="row text-center">
<div><label>Activities</label></div>
<multiselect v-model="item.places.activities" id="ajax" label="sname" track-by="place_id" placeholder="Type to search" open-direction="bottom" :multiple="true" :options="query.nominatim" :searchable="true" :loading="querying.place" :internal-search="false" :clear-on-select="false" :options-limit="50" :limit="10" :max-height="600" @search-change="debounceSearch.places"></multiselect>
</div>
<div class="row text-center">
<div><label>Notes</label></div>
<div class="input text-dark" style="width:100%;">
<textarea-autosize
v-model="item.notes"
class="text-small"
placeholder="Notes"
:min-height="30"
:max-height="350"
></textarea-autosize>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="">
<div class="container-medium section">
</div>
</div>
<div class="bg-dark">
<div id="go" class="container-medium section text-white">
<h2 class="text-big">Add new section</h2>
<p>Got an other flight and/or hotel ? Add a new section to register it</p>
<div class="aligner aligner--contentEnd">
<button class="button button--primary button--mobileFull" v-on:click="add_section">Add Section</button>
</div>
</div>
</div>
</div>
<div v-else-if="journey_step>=0 && journey_data.main[journey_step_data.section] != undefined">
<div class="bg-dark text-white">
<div class="container section">
<div class="row text-center">
<div class="input col-sm-4"><input disabled :value="journey_data.main[journey_step_data.section].title + ': Day ' + journey_step_data.day" /></div>
<div class="input col-sm-2"><input placeholder="Day title" v-model="journey_data.step_title[journey_step]" /></div>
<div class="col-sm-3"></div>
<div class="right input col-sm-2 "><input disabled :value="active_date()" /></div>
</div>
<div class="row">
<div class="col-12 col-sm-12">
<l-map
:zoom=" journey_data.main[journey_step_data.section].map.zoom"
:center="journey_data.main[journey_step_data.section].map.center"
style="padding-top: 100%;"
>
<l-tile-layer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
></l-tile-layer>
<l-control-scale position="topright" :imperial="false" :metric="true"></l-control-scale>
<l-marker v-if="journey_data.main[journey_step_data.section].hotel &&
journey_data.main[journey_step_data.section].hotel.icon"
:lat-lng="journey_data.main[journey_step_data.section].hotel.latlon">
<l-icon>
<div v-html="generate_icon(journey_data.main[journey_step_data.section].hotel,'darkblue')"></div>
</l-icon>
<l-popup>
<h1 class="row text-medium text-center">{{journey_data.main[journey_step_data.section].hotel.sname}}</h1>
<span class="row text-small text-gray">{{journey_data.main[journey_step_data.section].hotel.display_name}}</span>
<div class="row input">
<textarea-autosize
class="col-12 col-sm-10 text-small"
placeholder="Notes"
v-model="journey_data.main[journey_step_data.section].hotel.notes"
:min-height="30"
:max-height="350"
/>
</div>
</l-popup>
</l-marker>
<l-marker v-for="place in journey_data.main[journey_step_data.section].places.activities" :lat-lng="place.latlon">
<div v-if="place.step==journey_step">
<l-icon>
<div v-html="generate_icon(place)"></div>
</l-icon>
<l-popup>
<h1 class="row text-medium text-center">{{place.sname}}</h1>
<span class="row text-small text-gray">{{place.display_name}}</span>
<div class="row input">
<textarea-autosize
class="col-12 col-sm-10 text-small"
placeholder="Notes"
v-model="place.notes"
:min-height="30"
:max-height="350"
/>
</div>
<a class="leaflet-popup-close-button text-gray" style="bottom:9px;top:auto; " href="#rm" v-on:click.prevent="place.step=-1">-</a>
</l-popup>
</div>
<div v-else-if="place.step >= 0">
<l-icon>
<div v-html="generate_icon(place,'orange')"></div>
</l-icon>
<l-popup>
<h1 class="row text-medium text-center">{{place.sname}}</h1>
<span class="row text-small text-gray">{{place.display_name}}</span>
<div class="row input">
<textarea-autosize
class="col-12 col-sm-10 text-small"
placeholder="Notes"
v-model="place.notes"
:min-height="30"
:max-height="350"
/>
</div>
<a class="leaflet-popup-close-button text-gray" style="bottom:9px;top:auto; " href="#add" v-on:click.prevent="place.step=journey_step">+</a>
</l-popup>
</div>
<div v-else-if="place.step==undefined || place.step == -1">
<l-icon>
<div v-html="generate_icon(place,'red')"></div>
</l-icon>
<l-popup>
<h1 class="row text-medium text-center">{{place.sname}}</h1>
<span class="row text-small text-gray">{{place.display_name}}</span>
<div class="row input">
<textarea-autosize
class="col-12 col-sm-10 text-small"
placeholder="Notes"
v-model="place.notes"
:min-height="30"
:max-height="350"
/>
</div>
<a class="leaflet-popup-close-button text-gray" style="bottom:9px;top:auto; " href="#add" v-on:click.prevent="place.step=journey_step">+</a>
</l-popup>
</div>
<div v-else>
<l-icon>
<div v-html="generate_icon()"></div>
</l-icon>
<l-popup>
<h1 class="row text-medium text-center">{{place.sname}}</h1>
<span class="row text-small text-gray">{{place.display_name}}</span>
</l-popup>
</div>
</l-marker>
</l-map>
</div>
</div>
<div class="row">
<div class="col-12 col-sm-12">
<div class="container text-center" v-if="journey_step_data.start || journey_step_data.end">
<b>Flights</b>
<div v-if="journey_step_data.start">
<div v-for="element in journey_data.main[journey_step_data.section].flightA"><a href="#fligh" v-on:click.prevent="window.open('https://www.flightradar24.com/data/flights/'+element.id,'_blank')">{{ element.label }}</a></div>
</div>
<div v-if="journey_step_data.end">
<div v-for="element in journey_data.main[journey_step_data.section].flightB"><a href="#fligh" v-on:click.prevent="window.open('https://www.flightradar24.com/data/flights/'+element.id,'_blank')">{{ element.label }}</a></div>
</div>
</div>
<div class="container"></div>
</div>
</div>
</div>
</div>
<div class="">
<div class="container-medium section">
</div>
</div>
<div class="bg-dark">
</div>
</div>
<div class="">
<div class="container-medium section">
<div class="aligner">
<div class="input col-sm-4"><input class="" v-model="impexp" type="text" /></div>
<div class="col-sm-2"><button class="button button--primary button--mobileFull" v-on:click="import_data">Import</button></div>
<div class="col-sm-2"><button class="button button--primary button--mobileFull" v-on:click="export_data">Export</button></div>
</div>
</div>
</div>
</div>
<div v-if="vtp==0 && journey_data.main[journey_step_data.section] != undefined" v-cloak>
<div class="bg-dark text-white" v-cloak>
<div class="text-small fright" style="margin:6px 12px;"><a :href="'/'+journey_id" ><i class="fas fa-tools"></i></a></div>
<div class="container section">
<div class="aligner text-center text-white text-huge" style="margin-bottom:5px">
<div class="aligner--itemTop fleft"><a href="#prev" v-on:click.prevent="prev_step"><i class="fas fa-angle-left"></i></a></div>
<span class="container">
<div>{{journey_data.main[journey_step_data.section].title + ': Day ' + journey_step_data.day}}</div>
<div class="text-big text-gray">{{journey_data.step_title[journey_step]}}</div>
</span>
<div class="aligner--itemEnd fright"><a href="#next" v-on:click.prevent="next_step"><i class="fas fa-angle-right"></i></a></div>
</div>
<div class="row">
<div class="col-12 col-sm-12">
<l-map
:zoom=" journey_data.main[journey_step_data.section].map.zoom"
:center="journey_data.main[journey_step_data.section].map.center"
style="padding-top: 100%;"
>
<l-tile-layer
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png"
attribution='&copy; <a href="http://osm.org/copyright">OpenStreetMap</a> contributors'
></l-tile-layer>
<l-control-scale position="topright" :imperial="false" :metric="true"></l-control-scale>
<l-marker v-if="journey_data.main[journey_step_data.section].hotel &&
journey_data.main[journey_step_data.section].hotel.icon"
:lat-lng="journey_data.main[journey_step_data.section].hotel.latlon">
<l-icon>
<div v-html="generate_icon(journey_data.main[journey_step_data.section].hotel,'darkblue')"></div>
</l-icon>
<l-popup>
<h1 class="row text-medium text-center">{{journey_data.main[journey_step_data.section].hotel.sname}}</h1>
<span class="row text-small text-gray">{{journey_data.main[journey_step_data.section].hotel.display_name}}</span>
<span class="row text-small text-white">{{journey_data.main[journey_step_data.section].hotel.notes}}</span>
</l-popup>
</l-marker>
<l-marker v-for="place in journey_data.main[journey_step_data.section].places.activities" :lat-lng="place.latlon" v-if="place.step==journey_step" >
<l-icon>
<div v-html="generate_icon(place)"></div>
</l-icon>
<l-popup>
<h1 class="row text-medium text-center">{{place.sname}}</h1>
<span class="row text-small text-gray">{{place.display_name}}</span>
<span class="row text-small text-dark">{{place.notes}}</span>
</l-popup>
</l-marker>
<l-marker v-for="place in journey_data.main[journey_step_data.section].places.activities" :lat-lng="place.latlon" v-if="place.step==undefined || place.step==-1" >
<l-icon>
<div v-html="generate_icon(place,'gray')"></div>
</l-icon>
<l-popup>
<h1 class="row text-medium text-center">{{place.sname}}</h1>
<span class="row text-small text-gray">{{place.display_name}}</span>
<span class="row text-small text-dark">{{place.notes}}</span>
</l-popup>
</l-marker>
<l-marker v-for="place in journey_data.main[journey_step_data.section].places.restaurants" :lat-lng.sync="place.latlon">
<l-icon>
<div v-html="generate_icon(place,'cadetblue')"></div>
</l-icon>
<l-popup>
<h1 class="row text-medium text-center">{{place.sname}}</h1>
<span class="row text-small text-gray">{{place.display_name}}</span>
<span class="row text-small text-dark">{{place.notes}}</span>
</l-popup>
</l-marker>
</l-map>
</div>
</div>
<div class="row">
<div class="col-12 col-sm-12">
<div class="container text-center" v-if="journey_step_data.start || journey_step_data.end">
<b>Flights</b>
<div v-if="journey_step_data.start">
<div v-for="element in journey_data.main[journey_step_data.section].flightA"><a href="#fligh" v-on:click.prevent="window.open('https://www.flightradar24.com/data/flights/'+element.id,'_blank')">{{ element.label }}</a></div>
</div>
<div v-if="journey_step_data.end">
<div v-for="element in journey_data.main[journey_step_data.section].flightB"><a href="#fligh" v-on:click.prevent="window.open('https://www.flightradar24.com/data/flights/'+element.id,'_blank')">{{ element.label }}</a></div>
</div>
</div>
<div class="container"></div>
</div>
</div>
</div>
</div>
</div>
<div v-if="vtp==1" v-cloak>
<header class="header">
<div class="header-inner container">
<a href="/" class="header-logo text-dark">
<img class="header-logoImage" src="/public/img/helcel.png" alt="Helcel logo" width="40">
<span class="hide-small">HOTM</span>
</a>
<div class="input input-invis"><input class="small" :value="journey_data.name" type="text" disabled/></div>
<div class="row header-nav text-big" style="margin-bottom: 0;">
<div class="col-sm-3"><a :href="'/short/'+journey_id" ><i class="fas fa-file-contract"></i></a></div>
<div class="col-sm-3"><a :href="'/view/'+journey_id +'#0'" ><i class="fas fa-camera"></i></a></div>
</div>
</div>
</header>
<div v-for="(item,idx) in journey_data.main" :class="idx%2===0 ? 'bg-dark text-white' : ''">
<!-- <div class="bg-dark"> -->
<div class="container section">
<div class="row text-center">
<div class="input col-sm-2"><input class="" disabled :value="item.title"/></div>
<div class="input col-sm-4"><input disabled placeholder="No Dates" :value="item.dateRange? (format_date(item.dateRange[0]) + ' - '+ format_date(item.dateRange[1])):''"/></div>
<div class="input col-sm-2"><input disabled placeholder="No Hotel" :value="item.hotel.sname"/></div>
</div>
<div class="row text-center">
<div class="input col-sm-3" v-if="item.transit">
<div v-for="(item,idx) in item.transit">
<input disabled :value="item.map(v=>v.id).join(', ')"/>
</div>
</div>
<div class="input col-sm-3" v-if="item.flightA"><input disabled :value="item.flightA.map(v=>v.id).join(', ')"/></div>
<div class="input col-sm-3" v-if="item.flightB"><input disabled :value="item.flightB.map(v=>v.id).join(', ')"/></div>
</div>
<div class="row text-center">
<div class="input col-sm-8" v-if="item.places && item.places.restaurants">
<textarea-autosize
class="text-small"
placeholder="No Restaurants"
:value="item.places.restaurants.map(v=>v.sname+(v.notes?('('+v.notes+')'):'')).join(', ')"
:min-height="30"
:max-height="350"
disabled
/></div>
</div>
<div class="row text-center">
<div class="input col-sm-8" v-if="item.places && item.places.activities">
<textarea-autosize
class="text-small"
placeholder="No Activities"
:value="item.places.activities.map(v=>v.sname+(v.notes?('('+v.notes+')'):'')).join(', ')"
:min-height="30"
:max-height="350"
disabled
/></div>
</div>
<div class="row text-center">
<div class="input col-sm-8" v-if="item.notes">
<textarea-autosize
class="text-small"
placeholder="No Notes"
:value="item.notes"
:min-height="30"
:max-height="350"
disabled
/></div>
</div>
</div>
<!-- </div>
<div class="bg-white">
<div class="container section">
</div>
</div> -->
</div>
</div>
</main>
<script src="https://unpkg.com/vue@2/dist/vue.min.js"></script>
<script src="https://unpkg.com/vue2-datepicker/index.min.js"></script>
<script src="https://unpkg.com/leaflet/dist/leaflet.js"></script>
<script src="https://unpkg.com/vue2-leaflet"></script>
<script src="https://unpkg.com/leaflet.awesome-markers/dist/leaflet.awesome-markers.min.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://unpkg.com/lodash"></script>
<script src="https://unpkg.com/vue-multiselect"></script>
<script src="https://unpkg.com/vue-textarea-autosize/dist/vue-textarea-autosize.umd.min.js"></script>
<script src="/public/js/main.js" type="text/javascript" charset="utf-8"></script>
<footer class="bg-dark">
<div class="container">
<div class="section text-center text-small">
<p class="text-white">
<img src="/public/img/helcel.png" alt="helcel logo" width="100"><br><br>
Built with &nbsp;&nbsp; by Helcel <br><span class="text-small text-gray">v0.0.1</span>
</p>
</div>
</div>
</footer>
</body>
</html>

File diff suppressed because it is too large Load Diff

View File

@ -41,9 +41,8 @@ module.exports = (fastify, opts, done) => {
fastify.level.db.get(req.params.id, (err, val) => { fastify.level.db.get(req.params.id, (err, val) => {
if(err){ if(err){
console.warn(err); console.warn(err);
reply.send({name:"New Journey", main:[]}); reply.code(500).send();
} else { } else {
console.log(JSON.parse(val))
reply.send(JSON.parse(val)); reply.send(JSON.parse(val));
} }
}); });

View File

@ -1,8 +1,6 @@
const fastify = require('fastify')();//{ logger: true }); const fastify = require('fastify')();//{ logger: true });
const path = require('path'); const path = require('path');
const csass = require("./compile_sass").compileSassMain();
fastify.register(require('@fastify/static'), { fastify.register(require('@fastify/static'), {
root: path.join(__dirname, 'public'), root: path.join(__dirname, 'public'),
prefix: '/public/', prefix: '/public/',
@ -14,37 +12,21 @@ fastify.register(require('@fastify/leveldb'), {
if (err) throw err if (err) throw err
}); });
fastify.register(require("@fastify/view"), {
engine: {
pug: require("pug"),
},
});
fastify.get('/', (req, reply) => reply.sendFile('/template/home.html'));
fastify.register(require('./router/api'), { prefix: '/api' }); fastify.register(require('./router/api'), { prefix: '/api' });
fastify.get('/:id', (req, reply) => {
try{
const ec = parseInt(req.params.id);
switch(ec){
case 400:
case 401:
case 402:
case 403:
case 404:
case 405:
reply.code(ec).send("Client Error");
break;
case 500:
reply.code(ec).send("Internal Error");
break;
default:
throw undefined;
}
}catch(e){
reply.sendFile('/template/journey.html');
}
});
fastify.get('/view/:id', (req, reply) => reply.sendFile('/template/journey.html'));
fastify.get('/short/:id', (req, reply) => reply.sendFile('/template/journey.html'));
fastify.get('/', (req, reply) => reply.view("/template/home.pug", ));
fastify.get('/:id', (req, reply) => reply.view('/template/journey.pug'));
fastify.get('/view/:id', (req, reply) => reply.view('/template/view.pug'));
fastify.get('/short/:id', (req, reply) => reply.view('/template/short.pug'));
fastify.listen({port:8080,host:'0.0.0.0'} ,(err,address) => { fastify.listen({port:8080,host:'0.0.0.0'} ,(err,address) => {

59
template/home.pug Normal file
View File

@ -0,0 +1,59 @@
doctype html
include module/head.pug
main#app
.container
section.mb-big
.text-center
img.main-logo.mb-medium(src='/public/img/helcel.png' alt='Helcel logo')
div
h1.text-huge.text-withSubtitle Open Tourism Map
h2.text-big.text-gray Collaborative Holiday Planner
p#js-header-waypoint.m-none
a.button.button--primary.button--mobileFull(href='#go') Get started
.bg-dark
.container
.row.text-center
.col-12.col-sm-3
.section
img(src='/public/img/lightweight.png' alt='Lightweight' width='118')
br
h2.text-withSubtitle.text-big.text-white
| Lightweight
br
span.text-medium.text-gray
| Powered By
br
| Fastify &amp; Sierra
.col-12.col-sm-4
.section
img(src='/public/img/customizable.png' alt='Customizable' width='118')
br
h2.text-withSubtitle.text-big.text-white
| Customizable
br
span.text-medium.text-gray
| Many Templates
br
| to choose from
.col-12.col-sm-4
.section
h2.text-withSubtitle.text-big.text-white
img(src='/public/img/opensource.png' alt='Open Source' width='118')
br
| FOSS
br
span.text-medium.text-gray :-)
#go.container-medium.section
h2.text-big Your journey
p
| Browse hotels, restaurants and attractions,....
br
| Select and plan the varying elements of your journey
.aligner.aligner--contentEnd
.input
input#journey_id(v-model='journey_id' placeholder='ID' type='text')
button.button.button--primary.button--mobileFull(v-on:click='start_journey') Start the journey
include module/foot.pug

14
template/journey.pug Normal file
View File

@ -0,0 +1,14 @@
doctype html
include module/head.pug
main#app
include module/nav.pug
div(v-if='journey_step==-1')
div(v-for='(item,idx) in journey_data.main' :class="idx%2===0 ? 'bg-dark text-white' : ''" v-cloak='')
include module/journey_sec.pug
include module/journey_sec_add.pug
div(v-else)
include module/journey_step.pug
include module/importexport.pug
include module/foot.pug

22
template/module/foot.pug Normal file
View File

@ -0,0 +1,22 @@
script(src='https://unpkg.com/vue@2/dist/vue.min.js')
script(src='https://unpkg.com/vue2-datepicker/index.min.js')
script(src='https://unpkg.com/leaflet/dist/leaflet.js')
script(src='https://unpkg.com/vue2-leaflet')
script(src='https://unpkg.com/leaflet.awesome-markers/dist/leaflet.awesome-markers.min.js')
script(src='https://unpkg.com/axios/dist/axios.min.js')
script(src='https://unpkg.com/lodash')
script(src='https://unpkg.com/vue-multiselect')
script(src='https://unpkg.com/vue-textarea-autosize/dist/vue-textarea-autosize.umd.min.js')
script(src='/public/js/main.js' type='text/javascript' charset='utf-8')
footer.bg-dark
.container
.section.text-center.text-small
p.text-white
img(src='/public/img/helcel.png' alt='helcel logo' width='100')
br
br
| Built with &nbsp; &#x2764; &nbsp; by Helcel
br
span.text-small.text-gray v0.0.1
p.text-gray
a(href='https://git.helcel.net') Helcel Git

13
template/module/head.pug Normal file
View File

@ -0,0 +1,13 @@
head
title Helcel-OTM
link(rel='shortcut icon' href='/public/img/helcel.ico' type='image/x-icon')
meta(charset='utf-8')
meta(name='viewport' content='width=device-width, initial-scale=1')
link(rel='stylesheet' href='https://fonts.googleapis.com/css?family=IBM+Plex+Sans:400,700,300' type='text/css')
link(rel='stylesheet' href='/public/css/index.css')
link(rel='stylesheet' href='https://unpkg.com/vue2-datepicker/index.css')
link(rel='stylesheet' href='https://unpkg.com/vue-multiselect/dist/vue-multiselect.min.css')
link(rel='stylesheet' href='https://unpkg.com/leaflet/dist/leaflet.css')
link(rel='stylesheet' href='https://unpkg.com/leaflet.awesome-markers/dist/leaflet.awesome-markers.css')
link(rel='stylesheet' href='https://unpkg.com/@fortawesome/fontawesome-free/css/all.min.css')

View File

@ -0,0 +1,9 @@
div
.container-medium.section
.aligner
.input.col-sm-4
input(v-model='impexp' type='text')
.col-sm-2
button.button.button--primary.button--mobileFull(v-on:click='import_data') Import
.col-sm-2
button.button.button--primary.button--mobileFull(v-on:click='export_data') Export

View File

@ -0,0 +1,71 @@
.container.section
.row.text-center
.col-auto
button.button.button--secondary.button--mobileFull(v-on:click='rm_section(idx)') X
.col-auto
button.button.button--secondary.button--mobileFull(v-on:click='toggle_section_vis(idx)') -
.input.col-sm-4
input(v-model='item.title' type='text')
.row(v-if='visible_step & (0x1 << idx)')
.col-12.col-sm-8
l-map(:zoom.sync='item.map.zoom' :center.sync='item.map.center' style='padding-top: 100%;')
l-tile-layer(url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png' attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors')
l-control-scale(position='topright' :imperial='false' :metric='true')
l-marker(v-if='item.hotel' :lat-lng.sync='item.hotel.latlon')
l-icon
div(v-html="generate_icon(item.hotel,'darkblue')")
l-popup
h1.row.text-medium.text-center {{item.hotel.sname}}
span.row.text-small.text-gray {{item.hotel.display_name}}
.row.input
textarea-autosize.col-12.col-sm-10.text-small(placeholder='Notes' v-model='item.hotel.notes' :min-height='30' :max-height='350')
//
<l-tooltip :options="{ permanent: true, interactive: true }">
<div>
H
</div>
</l-tooltip>
l-marker(v-for='place in item.places.restaurants' :lat-lng.sync='place.latlon')
l-icon
div(v-html="generate_icon(place,'cadetblue')")
l-popup
h1.row.text-medium.text-center {{place.sname}}
span.row.text-small.text-gray {{place.display_name}}
.row.input
textarea-autosize.col-12.col-sm-10.text-small(placeholder='Notes' v-model='place.notes' :min-height='30' :max-height='350')
l-marker(v-for='place in item.places.activities' :lat-lng.sync='place.latlon')
l-icon
div(v-html='generate_icon(place)')
l-popup
h1.row.text-medium.text-center {{place.sname}}
span.row.text-small.text-gray {{place.display_name}}
.row.input
textarea-autosize.col-12.col-sm-10.text-small(placeholder='Notes' v-model='place.notes' :min-height='30' :max-height='350')
.col-12.col-sm-4
.row.text-center
div
label Date Range
.input.text-dark
date-picker(:lang='lang' v-model='item.dateRange' range='' placeholder='Date Range')
.row.text-center
div
label Hotel
multiselect#ajax(v-model='item.hotel' label='sname' track-by='place_id' placeholder='Type to search' open-direction='bottom' :options='query.nominatim' :searchable='true' :loading='querying.hotel' :internal-search='false' :clear-on-select='false' :options-limit='50' :limit='1' :max-height='600' @search-change='debounceSearch.hotel')
.row.text-center
div
label Fight
multiselect#ajax(v-model='item.flightA' label='label' track-by='id' placeholder='Type to search' open-direction='bottom' :multiple='true' :options='query.flight' :searchable='true' :loading='querying.flight' :internal-search='false' :clear-on-select='false' :options-limit='50' :limit='10' :max-height='600' @search-change='debounceSearch.flight')
multiselect#ajax(v-model='item.flightB' label='label' track-by='id' placeholder='Type to search' open-direction='bottom' :multiple='true' :options='query.flight' :searchable='true' :loading='querying.flight' :internal-search='false' :clear-on-select='false' :options-limit='50' :limit='10' :max-height='600' @search-change='debounceSearch.flight')
.row.text-center
div
label Restoration
multiselect#ajax(v-model='item.places.restaurants' label='sname' track-by='place_id' placeholder='Type to search' open-direction='bottom' :multiple='true' :options='query.nominatim' :searchable='true' :loading='querying.food' :internal-search='false' :clear-on-select='false' :options-limit='50' :limit='10' :max-height='600' @search-change='debounceSearch.restaurants')
.row.text-center
div
label Activities
multiselect#ajax(v-model='item.places.activities' label='sname' track-by='place_id' placeholder='Type to search' open-direction='bottom' :multiple='true' :options='query.nominatim' :searchable='true' :loading='querying.place' :internal-search='false' :clear-on-select='false' :options-limit='50' :limit='10' :max-height='600' @search-change='debounceSearch.places')
.row.text-center
div
label Notes
.input.text-dark(style='width:100%;')
textarea-autosize.text-small(v-model='item.notes' placeholder='Notes' :min-height='30' :max-height='350')

View File

@ -0,0 +1,4 @@
.bg-dark
.container-medium.section
#go.container-medium.section.text-white
button.button.button--primary.button--mobileFull(v-on:click='add_section') Add Section

View File

@ -0,0 +1,72 @@
.bg-dark.text-white
.container.section
.row.text-center
.input.col-sm-4
input(disabled='' :value="journey_data.main[journey_step_data.section].title + ': Day ' + journey_step_data.day")
.input.col-sm-2
input(placeholder='Day title' v-model='journey_data.step_title[journey_step]')
.col-sm-3
.right.input.col-sm-2
input(disabled='' :value='active_date()')
.row
.col-12.col-sm-12
l-map(:zoom=' journey_data.main[journey_step_data.section].map.zoom' :center='journey_data.main[journey_step_data.section].map.center' style='padding-top: 100%;')
l-tile-layer(url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png' attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors')
l-control-scale(position='topright' :imperial='false' :metric='true')
l-marker(v-if='journey_data.main[journey_step_data.section].hotel && \
journey_data.main[journey_step_data.section].hotel.icon' :lat-lng='journey_data.main[journey_step_data.section].hotel.latlon')
l-icon
div(v-html="generate_icon(journey_data.main[journey_step_data.section].hotel,'darkblue')")
l-popup
h1.row.text-medium.text-center {{journey_data.main[journey_step_data.section].hotel.sname}}
span.row.text-small.text-gray {{journey_data.main[journey_step_data.section].hotel.display_name}}
.row.input
textarea-autosize.col-12.col-sm-10.text-small(placeholder='Notes' v-model='journey_data.main[journey_step_data.section].hotel.notes' :min-height='30' :max-height='350')
l-marker(v-for='place in journey_data.main[journey_step_data.section].places.activities' :lat-lng='place.latlon')
div(v-if='place.step==journey_step')
l-icon
div(v-html='generate_icon(place)')
l-popup
h1.row.text-medium.text-center {{place.sname}}
span.row.text-small.text-gray {{place.display_name}}
.row.input
textarea-autosize.col-12.col-sm-10.text-small(placeholder='Notes' v-model='place.notes' :min-height='30' :max-height='350')
a.leaflet-popup-close-button.text-gray(style='bottom:9px;top:auto; ' href='#rm' v-on:click.prevent='place.step=-1') -
div(v-else-if='place.step >= 0')
l-icon
div(v-html="generate_icon(place,'orange')")
l-popup
h1.row.text-medium.text-center {{place.sname}}
span.row.text-small.text-gray {{place.display_name}}
.row.input
textarea-autosize.col-12.col-sm-10.text-small(placeholder='Notes' v-model='place.notes' :min-height='30' :max-height='350')
a.leaflet-popup-close-button.text-gray(style='bottom:9px;top:auto; ' href='#add' v-on:click.prevent='place.step=journey_step') +
div(v-else-if='place.step==undefined || place.step == -1')
l-icon
div(v-html="generate_icon(place,'red')")
l-popup
h1.row.text-medium.text-center {{place.sname}}
span.row.text-small.text-gray {{place.display_name}}
.row.input
textarea-autosize.col-12.col-sm-10.text-small(placeholder='Notes' v-model='place.notes' :min-height='30' :max-height='350')
a.leaflet-popup-close-button.text-gray(style='bottom:9px;top:auto; ' href='#add' v-on:click.prevent='place.step=journey_step') +
div(v-else='')
l-icon
div(v-html='generate_icon()')
l-popup
h1.row.text-medium.text-center {{place.sname}}
span.row.text-small.text-gray {{place.display_name}}
.row
.col-12.col-sm-12
.container.text-center(v-if='journey_step_data.start || journey_step_data.end')
b Flights
div(v-if='journey_step_data.start')
div(v-for='element in journey_data.main[journey_step_data.section].flightA')
a(href='#fligh' v-on:click.prevent="window.open('https://www.flightradar24.com/data/flights/'+element.id,'_blank')") {{ element.label }}
div(v-if='journey_step_data.end')
div(v-for='element in journey_data.main[journey_step_data.section].flightB')
a(href='#fligh' v-on:click.prevent="window.open('https://www.flightradar24.com/data/flights/'+element.id,'_blank')") {{ element.label }}
.container
div
.container-medium.section
.bg-dark

29
template/module/nav.pug Normal file
View File

@ -0,0 +1,29 @@
header.header
.header-inner.container
a.header-logo.text-dark(href='/')
img.header-logoImage(src='/public/img/helcel.png' alt='Helcel logo' width='40')
span.hide-small HOTM
.input.input-invis
input.small(v-model='journey_data.name' type='text')
.row.header-nav.text-big(style='margin-bottom: 0;')
.col-sm-2
a(:href="'/short/'+journey_id")
i.fas.fa-file-contract
.col-sm-2
a(:href="'/view/'+journey_id +'#0'")
i.fas.fa-camera
.col-sm-2
a(href='#main' v-on:click.prevent='first_step')
i.fas.fa-tools
.col-sm-1.text-small
a(href='#prevprev' v-on:click.prevent='prevprev_step')
i.fas.fa-angle-double-left
.col-sm-1
a(href='#prev' v-on:click.prevent='prev_step')
i.fas.fa-angle-left
.col-sm-1
a(href='#next' v-on:click.prevent='next_step')
i.fas.fa-angle-right
.col-sm-1.text-small
a(href='#nextnext' v-on:click.prevent='nextnext_step')
i.fas.fa-angle-double-right

View File

@ -0,0 +1,14 @@
header.header
.header-inner.container
a.header-logo.text-dark(href='/')
img.header-logoImage(src='/public/img/helcel.png' alt='Helcel logo' width='40')
span.hide-small HOTM
.input.input-invis
input.small(:value='journey_data.name' type='text' disabled='')
.row.header-nav.text-big(style='margin-bottom: 0;')
.col-sm-3
a(:href="'/short/'+journey_id")
i.fas.fa-file-contract
.col-sm-3
a(:href="'/view/'+journey_id +'#0'")
i.fas.fa-camera

View File

@ -0,0 +1,21 @@
.container.section
.row.text-center
.input.col-sm-2
input(disabled='' :value='item.title')
.input.col-sm-4
input(disabled='' placeholder='No Dates' :value="item.dateRange? (format_date(item.dateRange[0]) + ' - '+ format_date(item.dateRange[1])):''")
.input.col-sm-2
input(disabled='' placeholder='No Hotel' :value='item.hotel.sname')
.row.text-center
.input.col-sm-3(v-if='item.transit')
div(v-for='(item,idx) in item.transit')
input(disabled='' :value="item.map(v=>v.id).join(', ')")
.row.text-center
.input.col-sm-8(v-if='item.places && item.places.restaurants')
textarea-autosize.text-small(placeholder='No Restaurants' :value="item.places.restaurants.map(v=>v.sname+(v.notes?('('+v.notes+')'):'')).join(', ')" :min-height='30' :max-height='350' disabled='')
.row.text-center
.input.col-sm-8(v-if='item.places && item.places.activities')
textarea-autosize.text-small(placeholder='No Activities' :value="item.places.activities.map(v=>v.sname+(v.notes?('('+v.notes+')'):'')).join(', ')" :min-height='30' :max-height='350' disabled='')
.row.text-center
.input.col-sm-8(v-if='item.notes')
textarea-autosize.text-small(placeholder='No Notes' :value='item.notes' :min-height='30' :max-height='350' disabled='')

View File

@ -0,0 +1,53 @@
.bg-dark.text-white(v-cloak='')
.text-small.fright(style='margin:6px 12px;')
a(:href="'/'+journey_id")
i.fas.fa-tools
.container.section
.aligner.text-center.text-white.text-huge(style='margin-bottom:5px')
.aligner--itemTop.fleft
a(href='#prev' v-on:click.prevent='prev_step')
i.fas.fa-angle-left
span.container
div
| {{journey_data.main[journey_step_data.section].title + &apos;: Day &apos; + journey_step_data.day}}
.text-big.text-gray {{journey_data.step_title[journey_step]}}
.aligner--itemEnd.fright
a(href='#next' v-on:click.prevent='next_step')
i.fas.fa-angle-right
.row
.col-12.col-sm-12
l-map(:zoom=' journey_data.main[journey_step_data.section].map.zoom' :center='journey_data.main[journey_step_data.section].map.center' style='padding-top: 100%;')
l-tile-layer(url='https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png' attribution='© <a href="http://osm.org/copyright">OpenStreetMap</a> contributors')
l-control-scale(position='topright' :imperial='false' :metric='true')
l-marker(v-if='journey_data.main[journey_step_data.section].hotel && \
journey_data.main[journey_step_data.section].hotel.icon' :lat-lng='journey_data.main[journey_step_data.section].hotel.latlon')
l-icon
div(v-html="generate_icon(journey_data.main[journey_step_data.section].hotel,'darkblue')")
l-popup
h1.row.text-medium.text-center {{journey_data.main[journey_step_data.section].hotel.sname}}
span.row.text-small.text-gray {{journey_data.main[journey_step_data.section].hotel.display_name}}
span.row.text-small.text-white {{journey_data.main[journey_step_data.section].hotel.notes}}
l-marker(v-for='place in journey_data.main[journey_step_data.section].places.activities' :lat-lng='place.latlon' v-if='place.step==journey_step')
l-icon
div(v-html='generate_icon(place)')
l-popup
h1.row.text-medium.text-center {{place.sname}}
span.row.text-small.text-gray {{place.display_name}}
span.row.text-small.text-dark {{place.notes}}
l-marker(v-for='place in journey_data.main[journey_step_data.section].places.activities' :lat-lng='place.latlon' v-if='place.step==undefined || place.step==-1')
l-icon
div(v-html="generate_icon(place,'gray')")
l-popup
h1.row.text-medium.text-center {{place.sname}}
span.row.text-small.text-gray {{place.display_name}}
span.row.text-small.text-dark {{place.notes}}
l-marker(v-for='place in journey_data.main[journey_step_data.section].places.restaurants' :lat-lng.sync='place.latlon')
l-icon
div(v-html="generate_icon(place,'cadetblue')")
l-popup
h1.row.text-medium.text-center {{place.sname}}
span.row.text-small.text-gray {{place.display_name}}
span.row.text-small.text-dark {{place.notes}}
.row
.col-12.col-sm-12
.container

7
template/short.pug Normal file
View File

@ -0,0 +1,7 @@
doctype html
include module/head.pug
main#app
include module/nav_pub.pug
div(v-for='(item,idx) in journey_data.main' :class="idx%2===0 ? 'bg-dark text-white' : ''")
include module/short_sec.pug
include module/foot.pug

6
template/view.pug Normal file
View File

@ -0,0 +1,6 @@
doctype html
include module/head.pug
main#app
div(v-if='journey_data.main[journey_step_data.section] != undefined' v-cloak='')
include module/view_step.pug
include module/foot.pug

1536
yarn.lock

File diff suppressed because it is too large Load Diff