Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP PR for #122 Share Button #128

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions app-starter/components/AppHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -58,12 +58,14 @@ import LayerListToggleButton from '../../src/components/layerlist/ToggleButton'
import HelpWinToggleButton from '../../src/components/helpwin/ToggleButton'
import MeasureToolToggleButton from '../../src/components/measuretool/ToggleButton'
import InfoClickButton from '../../src/components/infoclick/ToggleButton'
import ShareButton from '../../src/components/sharebutton/ShareButton'
import ZoomToMaxExtentButton from '../../src/components/maxextentbutton/ZoomToMaxExtentButton'
import Geocoder from '../../src/components/geocoder/Geocoder'

export default {
name: 'wgu-app-header',
components: {
'wgu-share-btn': ShareButton,
'wgu-geocoder-btn': Geocoder,
'wgu-zoomtomaxextent-btn': ZoomToMaxExtentButton,
'wgu-layerlist-btn': LayerListToggleButton,
Expand Down
7 changes: 5 additions & 2 deletions app-starter/static/app-conf-projected.json
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
"layers": true,
"extent": true,
"paramPrefix": "pl_",
"history": true,
"history": false,
"precision": 6
},

Expand Down Expand Up @@ -161,7 +161,10 @@
"wgu-helpwin": {
"target": "toolbar",
"darkLayout": true
},
"wgu-share": {
"target": "toolbar",
"darkLayout": true
}
}

}
7 changes: 6 additions & 1 deletion app-starter/static/app-conf.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
"extent": false,
"projection": "EPSG:4326",
"paramPrefix": "",
"history": true
"history": true,
"precision": 6
},

"mapLayers": [
Expand Down Expand Up @@ -185,6 +186,10 @@
"wgu-helpwin": {
"target": "toolbar",
"darkLayout": true
},
"wgu-share": {
"target": "toolbar",
"darkLayout": true
}
}
}
12 changes: 12 additions & 0 deletions src/components/ol/Map.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import Vue from 'vue';
import Map from 'ol/Map'
import Group from 'ol/layer/Group'
import View from 'ol/View'
import Attribution from 'ol/control/Attribution';
import Zoom from 'ol/control/Zoom';
Expand Down Expand Up @@ -119,13 +120,24 @@ export default {
this.permalinkController.setup();
}
},
beforeDestroy () {
if (this.$appConfig.permalink) {
this.permalinkController.teardown();
this.permalinkController = undefined;
}
// Remove all Layers from Map.
this.map.setLayerGroup(new Group());
},

methods: {
/**
* Creates the OL layers due to the "mapLayers" array in app config.
* @return {ol.layer.Base[]} Array of OL layer instances
*/
createLayers () {
// Remove all Layers from Map.
this.map.setLayerGroup(new Group());

const me = this;
let layers = [];
const appConfig = this.$appConfig;
Expand Down
3 changes: 3 additions & 0 deletions src/components/ol/PermalinkController.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ export default class PermalinkController {
}
});
}
teardown () {
this.unsubscribeLayers();
}

/**
* Subscribe to Layer visibility changes.
Expand Down
174 changes: 174 additions & 0 deletions src/components/sharebutton/ShareButton.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<template>
<div class="text-xs-center">
<v-menu>
<template #activator="{ on: menu }">
<v-tooltip bottom>
<template #activator="{ on: tooltip }">
<v-btn icon :dark="dark" v-on="{ ...tooltip, ...menu }">
<v-icon medium>{{icon}}</v-icon>
{{text}}
</v-btn>
<textarea id="textstore" ref="textstore" style="display: none; position: relative"></textarea>
</template>
<span>{{hoverText}}</span>
</v-tooltip>
</template>
<v-list>
<v-list-tile @click="onCopyUrl()">
<v-list-tile-action>
<v-icon medium>link</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>{{copyUrlText}}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-list-tile @click="onCopyEmbedHTML()">
<v-list-tile-action>
<v-icon medium>code</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title>{{copyEmbedHtmlText}}</v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
<v-list-tile>
<v-list-tile-action>
<v-icon medium>email</v-icon>
</v-list-tile-action>
<v-list-tile-content>
<v-list-tile-title><a :href="mailToUrl">{{emailUrlText}}</a></v-list-tile-title>
</v-list-tile-content>
</v-list-tile>
</v-list>
</v-menu>
<v-alert
class="wgu-alert"
:value="alert"
:dark="dark"
type="info"
transition="fade-transition"
>
{{alertText}}
</v-alert>
</div>
</template>

<script>

import { Mapable } from '../../mixins/Mapable';
import {WguEventBus} from '../../WguEventBus';

export default {
name: 'wgu-share-btn',
mixins: [Mapable],
props: {
icon: {type: String, required: false, default: 'share'},
text: {type: String, required: false, default: ''},
hoverText: {type: String, required: false, default: 'Share permalink'},
alertTimeMillis: {type: Number, required: false, default: 1000},
alertCopiedText: {type: String, required: false, default: 'Copied'},
alertErrorText: {type: String, required: false, default: 'An error occurred'},
dark: {type: Boolean, required: false, default: false},
copyUrlText: {type: String, required: false, default: 'Copy Hyperlink'},
copyEmbedHtmlText: {type: String, required: false, default: 'Copy HTML Embed Code'},
emailUrlText: {type: String, required: false, default: 'Email Hyperlink'},
emailSubjectText: {type: String, required: false, default: 'Wegue Url Share'}
},
data () {
return {
alert: false,
alertText: this.alertCopiedText,
mailToUrl: this.emailUrlText
}
},
mounted () {
// Listen to the ol-map-mounted event and receive the OL map instance
WguEventBus.$on('ol-map-mounted', (olMap) => {
// Listen to map state changes (pan, zoom)
this.map.on('moveend', () => {
this.onMapChange();
});
});
},
methods: {
showAlert (text) {
// Show short alert
this.alertText = text || this.alertCopiedText;
this.alert = true;
window.setTimeout(() => {
this.alert = false;
}, this.alertTimeMillis);
},
copyToClipboard (text) {
const textArea = this.$refs.textstore;
// Show and select textarea
textArea.style.display = 'block';
textArea.value = text;
textArea.select();

// Copy to clipboard
document.execCommand('copy');

// Hide textarea
textArea.value = '';
textArea.style.display = 'none';
},
onCopyUrl () {
// Get permalink URL and copy to clipboard
try {
// Copy to clipboard: selected text needs to be visible so
// toggle textarea short time
const permalinkController = this.map.get('permalinkcontroller');
this.copyToClipboard(permalinkController.getShareUrl());
this.showAlert();
} catch (error) {
this.showAlert(this.alertErrorText);
}
},
onCopyEmbedHTML () {
// Get permalink URL and copy to clipboard
try {
const permalinkController = this.map.get('permalinkcontroller');
this.copyToClipboard(permalinkController.getEmbedHTML());
this.showAlert();
} catch (error) {
this.showAlert(this.alertErrorText);
}
},
setMailtoUrl: function () {
// if (!this.map) {
// return 'Waiting for Map...';
// }
// https://css-tricks.com/snippets/html/mailto-links/
// Get permalink URL and add to email Body
try {
const permalinkController = this.map.get('permalinkcontroller');
const url = encodeURIComponent(permalinkController.getShareUrl());
this.mailToUrl = `mailto:?subject=${this.emailSubjectText}&body=${url}`;
} catch (error) {
this.showAlert(this.alertErrorText);
}
},
/**
* Callback when Map View has changed, e.g. 'moveend'.
*/
onMapChange () {
this.setMailtoUrl();
}
}
}

</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
.v-alert.wgu-alert {
position: fixed;
top: 5em;
right: 4em;
z-index: 1;
}
a {
color: inherit;
text-decoration: none !important;
}
</style>
5 changes: 4 additions & 1 deletion test/unit/specs/components/ol/PermalinkController.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Vue from 'vue';
import { shallowMount } from '@vue/test-utils';
import {enableAutoDestroy, shallowMount} from '@vue/test-utils';
import Map from '@/components/ol/Map';
import VectorLayer from 'ol/layer/Vector';
const permalinkDef = {
Expand Down Expand Up @@ -39,6 +39,9 @@ const permalinkDef = {
}
};

// calls wrapper.destroy() after each test
enableAutoDestroy(afterEach);

describe('ol/Map.vue', () => {
describe('data - Map NOT Provides PermalinkController when NOT defined', () => {
let comp;
Expand Down