Using bootstrap-tour with Aurelia - aurelia

I have not been able to find a good example of how to use Bootstrap Tour with Aurelia. I installed it with yarn (yarn add bootstrap-tour) and added the dependencies in main.js as follows:
import 'bootstrap/dist/css/bootstrap.min.css';
import 'bootstrap-tour/build/css/bootstrap-tour.min.css';
import 'bootstrap/dist/js/bootstrap.min.js';
import 'bootstrap-tour/build/js/bootstrap-tour.min.js';
Now I would like to use it in one of my view-models. Here is what I've tried:
import { Tour } from 'bootstrap-tour';
In my class definition:
#inject(Store, EventAggregator, I18N, Router, Tour)
export default class {
constructor(store, events, i18n, router, tour) {
this.store = store;
this.events = events;
this.i18n = i18n;
this.router = router;
this.tour = tour;
}
// ... other methods and code
startTour() {
const tourNewReports = new this.tour({
steps: [
{
element: '#tour-btn-menu',
title: 'New reports!',
content: 'Check out new reports!',
},
{
element: '.tour-label-product',
title: 'Product report',
content: 'Click on a specific product to see more reports.',
},
],
});
tourNewReports.init();
tourNewReports.start();
}
}
However, this doesn't even compile and I get the following error:
Error: Error invoking _class3. Check the inner error for details.
------------------------------------------------
Inner Error:
Message: key/value cannot be null or undefined. Are you trying to inject/register something that doesn't exist with DI?
Inner Error Stack:
Error: key/value cannot be null or undefined. Are you trying to inject/register something that doesn't exist with DI?
I've also tried skipping the injection and just using const tourNewReports = new Tour({, but I get this error:
bootstrap_tour__WEBPACK_IMPORTED_MODULE_6__.Tour is not a constructor
at _class3.startTour
What am I doing wrong?

The comments from Cristián Ormazábal, avrahamcool and Rabah G helped me with this issue. The simplest solution was:
import Tour from 'bootstrap-tour';
Then, use it directly as follows:
startTour() {
const tourNewReports = new Tour({
steps: [
{
element: '#tour-btn-menu',
title: 'New reports!',
content: 'Check out new reports!',
},
{
element: '.tour-label-product',
title: 'Product report',
content: 'Click on a specific product to see more reports.',
},
],
});
tourNewReports.init();
tourNewReports.start();
}
However, in the end, it appears that bootstrap-tour may be an abandoned repo. It's currently incompatible with Bootstrap 3.4.1 (the latest v3 release), and therefore useless to me. If someone still wants to use it, there are a couple workarounds and an alternate forked repo posted here:
https://github.com/sorich87/bootstrap-tour/issues/723

Related

How to correctly register a CMS element with the Shopware 6 Admin SDK

With the Shopware 6 Admin SDK it's possible to add CMS Elements to the Shopware Admin from an external app via iFrame. However, by following the documentation there are some issues one might tackle along the way. If everything is done as stated in the docs following issues occur that I'd like to discuss:
First issue: If the newly registered CMS element is used more than once in a shopping experience layout the same config data is shared between all elements. This is the most severe issue that I need to solve. The second issue sounds kind of the reason for it. Therefore I attached my code at the end.
Second issue: Once the newly registered CMS element's config modal is opened the following error is thrown: The dataset id "swag-dailymotion__config-element" you tried to publish is already registered. The error is thrown in this file. I guess this has something to do in which I set up the element.
Third issue: If e.g. some text element is exchanged with the newly registered element the following console error is thrown once the element switch button is clicked and all element previews are visible: An error was captured in current module: TypeError: this.initElementConfig is not a function. Since there is a // #ts-expect-error in the responsible file I think this is not too important for the extension developer, since Shopware is already aware of it.
I have the following setup for implementing the CMS element. It differs in some way, since I am using .vue files instead of plain .ts as explained in the docs. However, except the mentioned issues, everything seems to be working fine:
This file is the entry point for the <base-app-url>
<template>
<view-renderer v-if="showViewRenderer"></view-renderer>
</template>
<script lang="ts">
import Vue from 'vue';
import { location, cms } from '#shopware-ag/admin-extension-sdk';
import viewRenderer from '#/components/cms/view-renderer.vue';
import { CONSTANTS } from '#/components/cms/index';
export default Vue.extend({
components: {
'view-renderer': viewRenderer
},
data() {
return {
showViewRenderer: false
};
},
created(): void {
if (location.isIframe()) {
if (location.is(location.MAIN_HIDDEN)) {
this.mainCommands();
} else {
this.showViewRenderer = true;
}
}
},
methods: {
mainCommands(): void {
this.registerCmsElements();
},
registerCmsElements(): void {
cms.registerCmsElement({
name: CONSTANTS.CMS_ELEMENT_NAME,
label: this.$t('cms.dailymotion.preview.label') as string,
defaultConfig: {
dailyUrl: {
source: 'static',
value: '',
},
},
});
}
}
});
</script>
#/components/cms/view-renderer.vue
<template>
<div>
<swag-dailymotion-config v-if="location.is('swag-dailymotion-config')"></swag-dailymotion-config>
<swag-dailymotion-element v-else-if="location.is('swag-dailymotion-element')"></swag-dailymotion-element>
<swag-dailymotion-preview v-else-if="location.is('swag-dailymotion-preview')"></swag-dailymotion-preview>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import { location } from '#shopware-ag/admin-extension-sdk';
import swagDailymotionConfig from '#/components/cms/swag-dailymotion/swag-dailymotion-config.vue';
import swagDailymotionElement from '#/components/cms/swag-dailymotion/swag-dailymotion-element.vue';
import swagDailymotionPreview from '#/components/cms/swag-dailymotion/swag-dailymotion-preview.vue';
export default Vue.extend({
components: {
'swag-dailymotion-config': swagDailymotionConfig,
'swag-dailymotion-element': swagDailymotionElement,
'swag-dailymotion-preview': swagDailymotionPreview
},
data() {
return {
location
};
},
created(): void {
location.startAutoResizer();
}
});
</script>
The individual components are not doing anything special. They are fetching the element with this.element = await data.get({ id: CONSTANTS.PUBLISHING_KEY }); as stated in the docs and doing some work with it. However, it's always fetching the same element without considering the slot the current element is in, therefore it's always fetching the same data set.
What am I doing wrong?

How to Load Custom Language in Monaco using VueJS/Webpack

I've created a custom language using this tool here. I don't know what to do to load it to my VueJS app. I tried the following and get no errors, but it also doesn't show seem to work, because in the Monarch tool thing I get blue text on known functions etc, but in my editor I don't. Other languages work as expected.
const MonacoWebpackPlugin = require('monaco-editor-webpack-plugin');
const path = require('path');
const main = path.resolve(__dirname, './src/test/test.ts');
module.exports = {
configureWebpack: {
plugins: [
new MonacoWebpackPlugin({
languages: ['javascript', 'typescript', 'python', 'java', 'python', 'json', 'vb'],
customLanguages: [
{
label: 'test',
entry: main
}
]
})
]
}
...
I made my .ts file essentially export a conf property with all the variables or whatever that are used in the tokenizer. I also exported a language property. I'm not totally sure that is the right format.
My .ts file essentially looks like:
export const conf = {...}
export const language = {...}
I'm not totally sure what to do here. Docs are sparse for custom languages and nothing seems to be working other than I think I at least have the first part of defining the language working.
That Webpack plugin isn't actually needed.
Based on the custom language example, you can register the language at runtime via monaco.languages.setMonarchTokensProvider(). The second function argument is an instance of IMonarchLanguage, which matches the language spec in the example you linked.
<script setup lang="ts">
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api'
import { ref, onMounted } from 'vue'
/**
* `customLangMonarch` contains the language spec example from
* https://microsoft.github.io/monaco-editor/monarch.html
*/
// #ts-ignore
import customLangMonarch from '#/custom-lang-monarch'
monaco.languages.register({ id: 'custom' })
monaco.languages.setMonarchTokensProvider('custom', customLangMonarch)
const editor = ref()
onMounted(() => {
monaco.editor.create(editor.value, {
language: 'custom',
})
})
</script>
demo w/Vue CLI
demo w/Vite

Svelte/ Rollup Error “missing global variable name”

When I am importing "AmazonCognitoIdentity" in my Routify project I am getting "missing global variable name" error.
Error message:
bundles src/main.js  dist\build\bundle.js...
LiveReload enabled
(!) Unresolved dependencies
https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency
/js/amazon-cognito-identity.min.js (imported by src\pages\_components\Login.svelte)
(!) Missing global variable name
Use output.globals to specify browser global variable names corresponding to external modules
/js/amazon-cognito-identity.min.js (guessing 'amazonCognitoIdentity_min_js')
created dist\build\bundle.js in 2.7s
bundles src/sw.js  dist\sw.js...
created dist\sw.js in 1.6s
Following is my code
import { AmazonCognitoIdentity } from "/js/amazon-cognito-identity.min.js";
const authenticationData = {
Username: userName,
Password: password,
};
const authenticationDetails = new AmazonCognitoIdentity.AuthenticationDetails(
authenticationData
);
console.log(authenticationDetails);
const poolData = {
UserPoolId: "xxxx”
ClientId: "xxxxxxx",
};
const userPool = new AmazonCognitoIdentity.CognitoUserPool(poolData);
const userData = {
Username: userName,
Pool: userPool,
};
console.log(userData);
const cognitoUser = new AmazonCognitoIdentity.CognitoUser(userData);
cognitoUser.authenticateUser(authenticationDetails, {
onSuccess: function (result) {
const accessToken = result.getAccessToken().getJwtToken();
console.log(`on sucess: ${accessToken}`);
},
onFailure: function (err) {
console.log(`onfailure: ${err}`);
console.log(err);
},
});
and also I’ve linked the following file in _index.html
<script src="./js/amazon-cognito-identity.min.js"></script>
<script src="./js/amazon-cognito-auth.min.js"></script>
<script src="https://sdk.amazonaws.com/js/aws-sdk-2.7.16.min.js"></script>
And the same process in working good in normal Html ad JavaScript files.
npm i amazon-cognito-identity-js
run this command first then update your import to this:
import { AmazonCognitoIdentity } from 'amazon-cognito-identity-js';
Flowing error is thrown after incorporating
npm i amazon-cognito-identity-js
import { AmazonCognitoIdentity } from 'amazon-cognito-identity-js';
ERROR:
(!) Plugin node-resolve: preferring built-in module 'buffer' over local alternative at 'E:\ec-website\htx-pp-client\node_modules\buffer\index.js', pass 'preferBuiltins: false' to disable this behavior or 'preferBuiltins: true' to disable this warning
(!) Unresolved dependencies
https://rollupjs.org/guide/en/#warning-treating-module-as-external-dependency
buffer (imported by node_modules\amazon-cognito-identity-js\es\AuthenticationHelper.js, node_modules\amazon-cognito-identity-js\es\CognitoUser.js, node_modules\amazon-cognito-identity-js\es\CognitoJwtToken.js)
[!] Error: 'AmazonCognitoIdentity' is not exported by node_modules\amazon-cognito-identity-js\es\index.js, imported by src\pages_components\Login.svelte
After adding this line to rollup.config.js
rollup.external = ["AmazonCognitoIdentity", "amazon-cognito-identity-js"];
rollup.output = {
file: "dist/build/bundle.js",
format: "umd",
interop: "esModule",
globals: {
"amazon-cognito-identity-js": "AmazonCognitoIdentity",
},
};
The above error is gone. But at run time throws a new error
Uncaught TypeError: Cannot read property 'AmazonCognitoIdentity' of undefined
I got past this error by adding
import polyfills from "rollup-plugin-node-polyfills";
...
plugins: [
polyfills(),
...
to my rollup.config.js
My guess is, you need to change the import statement so that it is relative:
import { AmazonCognitoIdentity } from "./js/amazon-cognito-identity.min.js";
I don't know where this file is, but you need to have . or .. at the start of the location.
As I'm not an expert I yet cannot explain you why.
import AmazonCognitoIdentity from 'amazon-cognito-identity-js';
Is your import correct?

Issues including Moment.js library for use with Tabulator in Vue.js

I am trying to use the Date Time functionality with Tabulator which requires the moment.js library. In my application before adding Tabulator, moment.js was already being used in certain components that level. I have a new test component that uses Tabulator and attempts to use datetime. Typically I would just import moment and use it here but it seems that moment is required within Tabulator itself.
My first thought is that Moment.js needs to be setup globally in my application so I did that.
Main.js:
```
import Vue from 'vue'
import App from './App'
import router from './router'
import { store } from './store'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css'
import moment from 'moment'
Vue.prototype.moment = moment
...............
new Vue({
el: '#app',
data () {
return {
info: null,
loading: true,
errored: false // this.$root.$data.errored
}
},
router,
components: { App },
template: '<App/>',
store
})
```
In my component (Testpage.vue)
```
<template>
<div>
<div ref="example_table"></div>
</div>
</template>
<script>
// import moment from 'moment'
var Tabulator = require('tabulator-tables')
export default {
name: 'Test',
data: function () {
return {
tabulator: null, // variable to hold your table
tableData: [{id: 1, date: '2019-01-10'}] // data for table to display
}
},
watch: {
// update table if data changes
tableData: {
handler: function (newData) {
this.tabulator.replaceData(newData)
},
deep: true
}
},
mounted () {
// instantiate Tabulator when element is mounted
this.tabulator = new Tabulator(this.$refs.example_table, {
data: this.tableData, // link data to table
columns: [
{title: 'Date', field: 'date', formatter: 'datetime', formatterParams: {inputFormat: 'YYYY-MM-DD', outputFormat: 'DD/MM/YY', invalidPlaceholder: '(invalid date)'}}
],
}
</script>
```
I receive the error: "Uncaught (in promise) Reference Error: moment is not defined at Format.datetime (tabulator.js?ab1f:14619)"
I am able to use moment in other components by using this.$moment() but I need for it to be available in node_modules\tabulator-tables\dist\js\tabulator.js
since thats where the error is happening. Any idea how to include the library?
Go back to the first option you were trying, because annotating the Vue prototype with moment is definitely not the right approach. Even if it was recommended (which it isn't), Tabulator would have to know to find it by looking for Vue.moment. It isn't coded to do that.
One of the things I love about Open Source is that you can see exactly what a library is doing to help fix the issue. A quick search of the Tabulator code base finds this:
https://github.com/olifolkerd/tabulator/blob/3aa6f17b04cccdd36a334768635a60770aa10e38/src/js/modules/format.js
var newDatetime = moment(value, inputFormat);
The formatter is just calling moment directly, without importing it. It's clearly designed around the old-school mechanism of expecting libraries to be available globally. In browser-land that means it's on the "window" object. Two quick options could resolve this:
Use a CDN-hosted version of Moment such as https://cdnjs.com/libraries/moment.js/ by putting something like this in the header of your page template:
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.23.0/moment.min.js"></script>
Adjust your code above to set moment on window:
window.moment = moment;
ohgodwhy's comment above isn't necessarily wrong from the perspective of date-fns being better in many ways. But it won't work for you because Tabulator is hard-coded to look for moment, so you'll need moment itself to work.

Vue Storybook Jest Addon configuration problem

I wonder if someone using the jest addon can share it's Vue Storybook configuration, since I can't seem to make it work. I've tried the global mode:
In Storybook's config.js:
import { withTests } from '#storybook/addon-jest';
import results from '../.jest-test-results.json';
addDecorator(
withTests({
results,
})
);
And inside my Story:
storiesOf('Elements/Tag', module)
.addParameters({ jest: ['ThuleTag'] })
.addDecorator(VueInfoAddon)
.addDecorator(withTests({ results })('ThuleTag'))
.add('Squared',
withNotes(_notes)(() => ({
components: {ThuleTag},
template: _template,
propsDescription: {
size: 'medium / small / mini',
type: 'success / info/warning / danger'
}
})),
)
I get this error:
TypeError: Object(...)(...).addParameters is not a function
I've also tried the local way:
In my Story:
import { storiesOf } from '#storybook/vue'
import { withNotes } from '#storybook/addon-notes'
import results from '../../../jest-test-results.json'
import { withTests } from '#storybook/addon-jest'
import ThuleTag from '../../components/ui/elements/ThuleTag.vue'
let _notes = `A simple wrapper for the Elements el-tag, that accepts the same <i>type</i> and <i>size</i> props`
let _template = `<thule-tag
size="small"
key="name">Tag Namez
</thule-tag>`
storiesOf('Elements/Tag', module)
.addDecorator(withTests({ results }))
.add('Squared',
withNotes(_notes)(() => ({
components: {ThuleTag},
template: _template,
propsDescription: {
size: 'medium / small / mini',
type: 'success / info/warning / danger'
}
})),
{
jest: ['ThuleTag.test.js'],
}
)
Here I get this error:
Error in render: "TypeError: Cannot read property '__esModule' of undefined"
And the Tests tab is shown with this message:
This story has tests configured, but no file was found
Can someone point me what's messing things up please?
It looks like storybook jest addon is not supported for Vue.js for now
https://github.com/storybooks/storybook/blob/master/ADDONS_SUPPORT.md
Ok, about first error
Error in render: "TypeError: Cannot read property '__esModule' of undefined"
I think that you should check your babel-config, It seems like you forget some presets for your framework.
About second question
This story has tests configured, but no file was found
That problem happens from Jest and storybook/addon-jest want to get with equals api, but they can't. In last versions of Jest, output file structure has options.testResults , but storybook/addon-jest wants options.results & options.results.testResults.
There are two possible solutions:
use appropriate version of Jest and storybook/addon-jest
apply huck in index.js of storybook-jest library, smth like that
if (testFiles && !testFiles.disable) {
//todo: HERE should be your storybook hack
options.results = options.tests.testResults;
options.results.testResults = options.results;
emitAddTests({
kind: kind,
story: story,
testFiles: testFiles,
options: options
});
}