1 Commits

Author SHA1 Message Date
Bilal
c179e5e876 Merge pull request #1 from GotPPay/bilal-step3
Bilal step3
2017-12-03 18:48:42 +01:00
12 changed files with 2332 additions and 612 deletions

View File

@@ -1,60 +0,0 @@
{
"languageModel": {
"intents": [
{
"name": "AMAZON.CancelIntent",
"samples": []
},
{
"name": "AMAZON.HelpIntent",
"samples": []
},
{
"name": "AMAZON.StopIntent",
"samples": []
},
{
"name": "GetProcessIntent",
"samples": [
"tell me your process",
"what is your process",
"how do you work",
"about your proces"
],
"slots": []
},
{
"name": "GetProjectsIntent",
"samples": [
"list me your projects",
"show me what you have done",
"what did you do so far",
"what are your projects",
"your project"
],
"slots": []
},
{
"name": "GetServicesIntent",
"samples": [
"what are your services",
"what services do you ofer",
"what you do",
"your service",
"tell me service"
],
"slots": []
},
{
"name": "GetTechnologiesIntent",
"samples": [
"list me your technologies",
"give me your technologies",
"what you know"
],
"slots": []
}
],
"invocationName": "saburly"
}
}

View File

@@ -1,15 +0,0 @@
var config = {};
config.dbURL = 'mongodb://localhost:27017/tellall';
config.PORT = 5000;
config.TOKEN = 'Atza|IwEBIBe6gDqrrowEEav6N-_6s4NztYeP3oG8PGWmu8ZiZw6lbOh3wNla3TK6pY-VEpT1d8an-dVf_n3kXJzVFsNo_4xBfZyFHGoCTDTFjs3yBRul4PVdBOhwwiH3-sgRLcUofZbe2oE06GmTcbfYtaStfXpQI5dfpldfnsJg_CvhSA6AHb_snJT3F6lyXzbV076d_3cYUMJxFldJGnYcviNHHxjjmuQTD06hhGzCbAxxe9eBmkuopRsNfyedLT2UlKP_ublah9CUGA3AdIX_3Iuke82jMwGnNl9gv7pbaDNEjAbj7IQSl3B08uuREtJq-oTBOjALNXRvFxTJmQjZwXNf9eHC7fSHJDdEPdZQU0AcffRQObAyAkUuL6Jv39OHzhb3Q64-zzoyODqnJyLP5SQZ2JVF53Kc_cTBqjIc9pXljqe7yEVk6JDs7q1zKbBibx_AQm57TO79IzWyLBzBMlYL5HdTsqEfRzLeDw2tws-hGMgkx2HWfdbYnmf5Qb4SyIhzvmmdfPLg3MVKTxjIBu1rx0xf3n0PLZP1EO6jsJPoMRPg77Gm4oit5Zp6s37ek3A3Vxh-ntoASpkrkxGTG9kVtRNt';
config.REFRESH_TOKEN = 'Atzr|IwEBICA3kDhfSJxlwvnQp9AD1o115AC_KBbFd5GBg8oN_QHWn2or5xFQ09BruuK6a07tGHtTt_9q2Y21mnOMH4RDtYXTVG9ADgLE6mHWKZFxYVwt3kHMiUJdY5lJcsOtWLoblrS-bJ0BEXXK5nVDt_bSI5IB7NUf-9QVZxhovRH_ANSxdTjJT0_rMIAZY3WEj68FEap49q_pg72BhnxHVZD2TC3zvX96_DN65HE5SoSgT7OiMAeiJewB_SyemW_HxBwaB-_X-G1ifOtnrzZ4gXTpOrEUlHI2YPuvRMBMtmz1h-nXDZYv3vwU3RA57Qj_ZNVcScj8_RXf2xq8w48v0PzZFXYBSalfnqPq6eUvSSbAJUp6bB8y596JlvR5dFQe_Z--X0Gkfo85IcyrI9D44vK9sJhrGhCVi2FDDa8pHczmNSen99JYZvDif-zpYzgbcymAkOV0gC7JvYMxlZfETT3NTBy7eVA7fJI1SZaeA_qW49xRcBkZBu5gkqTpeGWUU1cGr2aXRVVmXGM22NfV5E7KzvEBsCeHml_tCfxZeKY8Msd8hJb0Cd59u-_hsuc8oNjsOpIdFF976dY3uTmAgHWpG2PH';
config.TOKEN_EXPIRES_IN = 1515100500;
config.SKILL_ID = 'amzn1.ask.skill.efbf0564-a732-4ba9-958f-57939138adae';
config.CLIENT_ID = 'amzn1.application-oa2-client.c748ca56ded04a95b236979898585ff7';
config.CLIENT_SECRET = '6dea8125cecd049d3c4cff7bb5bdfd3ff17bc6fed246c4c8f6b519d9ed08d0b3';
module.exports=config;

View File

@@ -1,7 +1,4 @@
var amazonHelper = require('./helpers/amazon');
var databaseHelper = require('./helpers/database');
const config = require('./config');
require('isomorphic-fetch');
@@ -10,75 +7,18 @@ var alexa = require('alexa-app');
var bodyParser = require('body-parser');
const dbURL = 'mongodb://localhost:27017/tellall';
const PORT = 5000;
const TOKEN = 'Atza|IwEBIMv0spn-eZhjP8-R2Jjkb4VUi-EY4V3MX-wlJyr2P6YBUmIChl7VKgRberEdQ-Wolp53SqfwHbxlSo4-rdUgFYFAxImB622boeqUBBCtwybP0OTBJBT1CVm_FBr48Li5LkwR9DxPciCnc052ddohpjGuGZxsCqIJo2c-7LPEhH0Lx63VOFgfPIfBsrVqjDbPNrr5ApPUijKYZWurktb6ytTks8eFUSTyv3FDbE5HEng0qpE4mgSjdgBkEc8BgUfpm2QGvctINH9SioUJOJonxgTPYhbD4BEd-jdQHsltKFzkb3-Rm3lFhEu3_CQFxCeQ6yGe1the_qID3vnPfpSY6hyblgF5L_5d7bE7BWg8fm6rSwXv67L2sMwBOji6cuR0wVVvXfYxmgGIMGkVQrq-SPSdtCpx2BvBz2SqqN6a_98svP8ukvhwc_oJsN6VwEmTDFgutNf-XuGkuVii-k9-DncwuwD00LvJG1FhBvbvSyuv-a3LAJSqTmroemTDG0xzLn7ULFY5p-93sM0_ZNGFeW-lL_r1ldqM_5lFRKDta1Tkg7lT9-rHftgnpGs4zv7vGLIPzHpNiXjsKyCk-wMQrihhWlR15kiz7oKDeTf6wCIETg';
const USER_ID = 'amzn1.ask.account.AGE34MG3VIQ75D4Q5CXFK25GUOXHZ2MIVSII3QUCOT3CP44IPE25PLD3DWW7HLWO2KVC7PC7VUXSZZEFPVHJ6PTDYVYYESJE35CE6VEXCE3BI3AK24TGO4CJXFF3SZ7IA4QVJRZC6EN4MUF2WUP4IB4CGDLRZZMYQENOFNBYWFXZHMZ5PA6S6ERK7NGEPUSDHXWKH26UGMIATMI';
var MongoClient = require ('mongodb').MongoClient;
var ObjectID = require ('mongodb').ObjectID;
const router = express.Router ();
var skillID = 'amzn1.ask.skill.7115bfc9-313e-4728-830b-ebd19ce96cb3';
var skillDbID = '5a232fb86ce046c749739455'; //_id in database
var app = express();
// ALWAYS setup the alexa app and attach it to express before anything else.
var alexaApp = new alexa.app('step3'); // this means we still work with one skill
alexaApp.express({
expressApp: app,
// verifies requests come from amazon alexa. Must be enabled for production.
// You can disable this if you're running a dev environment and want to POST
// things to test behavior. enabled by default.
checkCert: false,
// sets up a GET route when set to true. This is handy for testing in
// development, but not recommended for production. disabled by default
debug: true
});
// now POST calls to /test in express will be handled by the app.request() function
// from here on you can setup any other express routes or middlewares as normal
app.set("view engine", "ejs");
alexaApp.launch(function(request, response) {
console.log("Alexa launch");
console.log(request);
const skill = db.collection('skill_list').findOne({_id: ObjectID(skillDbID)}, (err,result)=>{
if (err){
response.say("I could not find desired skill")
}else{
response.say(skill.invocationAnswer);
}
});
});
var findElementByAttr = function (data, attr, val){
for(var i = 0; i < data.length; i ++) {
if(data[i][attr] === val) {
return i;
}
}
return -1;
}
alexaApp.request = (jsonRequest) => {
const alexaRequest = new alexa.request(jsonRequest);
if (alexaRequest.type() === "IntentRequest") {
const skill = db.collection('skill_list').findOne({
_id: skillDbID
});
if (skill) {
let intentId = findElementByAttr(skill.intents, 'intentName', alexaRequest.data.request.intent.name);
const response = new alexa.response(alexaRequest.getSession());
if (intentId !== -1){
return response.say(skill.intents[intentId].answer);
}else{
return response.say('Sorry, I could not find desired intent');
}
}
}
};
router.get ('/getSkill/:id', async (req, res, next) => {
try {
const id = req.params.id;
@@ -103,6 +43,7 @@ router.get ('/getSkill/:id', async (req, res, next) => {
}
});
router.get ('/deleteSkill/:skillID', async (req, res, next) => {
try {
let id = req.params.id;
@@ -117,36 +58,67 @@ router.get ('/deleteSkill/:skillID', async (req, res, next) => {
});
router.post ('/updateSkill/:id', async (req, res, next) => {
try {
let id = req.params.id;
let skill = req.body;
delete skill._id;
if (id !== '-1'){
amazonHelper.updateSkill(skill,db).then(amazonResult=>{
if (amazonResult===200 || amazonResult===202){
//Skill uploaded, it's ok to update database
let result = db.collection('skill_list').update({_id: ObjectID(id)}, skill,{upsert:true}, (err, result)=>{
if (JSON.parse(result).nModified===1){
//database update ok
res.json({result:0, message:'ok'});
}else{
res.json({result:-1, message:'ok'});
}
});
}else{
res.json({result:-1, message:'Amazon result ' + amazonResult});
}
}).catch(e=>{
//skill upload went wrong, don't update database, send error
res.json({result:-1, message:e});
});
let completeResult = {databaseUpdate:false, amazonUpdate:false, amazonMessage:''};
let result = db.collection('skill_list').update({_id: ObjectID(id)}, skill,{upsert:true}, (err, result)=>{
if (err) throw(err);
completeResult.databaseUpdate = (JSON.parse(result).nModified===1);
let generatedInteractionModel = amazonHelper.generateInteractionModel(skill);
fetch(`https://api.amazonalexa.com/v0/skills/${skill.skillID}/interactionModel/locales/en-US`, {
method: 'POST',
headers: {
Authorization: TOKEN
},
body: generatedInteractionModel
}).then(l=>l.text()).then(result=>{
completeResult.amazonUpdate = (JSON.stringify(result)===JSON.stringify({}));
completeResult.amazonMessage = JSON.stringify(result);
res.json(completeResult);
});
});
}else{
//no new skills for now
}
} catch (e) {
console.log ('error:', e);
next (e);
}
});
var app = express();
// ALWAYS setup the alexa app and attach it to express before anything else.
var alexaApp = new alexa.app('step3');
alexaApp.express({
expressApp: app,
// verifies requests come from amazon alexa. Must be enabled for production.
// You can disable this if you're running a dev environment and want to POST
// things to test behavior. enabled by default.
checkCert: false,
// sets up a GET route when set to true. This is handy for testing in
// development, but not recommended for production. disabled by default
debug: true
});
// now POST calls to /test in express will be handled by the app.request() function
// from here on you can setup any other express routes or middlewares as normal
app.use (function (req, res, next) {
res.header ('Access-Control-Allow-Origin', '*');
res.header (
@@ -162,16 +134,10 @@ app.use (bodyParser.json ());
app.use ('/', router);
MongoClient.connect (config.dbURL).then (database => {
MongoClient.connect (dbURL).then (database => {
db = database;
db.collection ('intent_list');
databaseHelper.initModule(db);
app.listen (config.PORT, () =>{
console.log ('Express server running on port ' + config.PORT);
databaseHelper.loadTokens();
});
}).catch(e=>{
console.log("error : " + e);
app.listen (PORT, () =>
console.log ('Express server running on port ' + PORT)
);
});

View File

@@ -1,7 +1,6 @@
require('isomorphic-fetch');
const config = require('../config');
var request = require("request");
var token = require('./token');
var ObjectID = require ('mongodb').ObjectID;
var getBuildStatus = function(skillID){
@@ -19,100 +18,45 @@ var getBuildStatus = function(skillID){
}
}
var refreshToken = function(db){
return new Promise((resolve, reject)=>{
var options = { method: 'POST',
url: 'https://api.amazon.com/auth/o2/token',
headers:
{ 'cache-control': 'no-cache',
'content-type': 'application/x-www-form-urlencoded' },
form:
{ grant_type: 'refresh_token',
refresh_token: config.REFRESH_TOKEN,
client_id: config.CLIENT_ID,
client_secret: config.CLIENT_SECRET } };
request(options, function (error, response, body) {
if (error) reject(error);
parsedResponse = JSON.parse(body);
if (parsedResponse.refresh_token){
try{
token.updateTokens(parsedResponse.refresh_token, parsedResponse.access_token, parsedResponse.expires_in,db);
resolve();
}catch(e){
reject(e);
}
}
});
});
}
var generateInteractionModel = function(skill){
let result = {};
let allIntents = [];
let defaultIntents = [{
name: "AMAZON.CancelIntent",
samples: []
},
{
name: "AMAZON.HelpIntent",
samples: []
},
{
name: "AMAZON.StopIntent",
samples: []
}];
/*
defaultIntents.map(intent=>{
allIntents.push(intent);
});
*/
skill.intents.map(intent=>{
allIntents.push({name: intent.intentName, samples: intent.questions});
});
result.interactionModel = {};
result.interactionModel.languageModel = {
invocationName: skill.invocationName,
intents: allIntents
};
return JSON.stringify(result);
}
var uploadSkill = function(skill){
return fetch(`https://api.amazonalexa.com/v0/skills/${skill.skillID}/interactionModel/locales/en-US`, {
method: 'POST',
headers: {
Authorization: config.TOKEN
},
body: generateInteractionModel(skill)
});
}
module.exports = {
updateSkill: function(skill, db){
return new Promise((resolve,reject)=>{
if (new Date() / 1000 > config.TOKEN_EXPIRES_IN){
refreshToken(db).then(()=>{
uploadSkill(skill).then(response=>{
resolve(response.status);
});
}).catch(e=>{
reject(e);
});
}else{
uploadSkill(skill).then(response=>{
resolve(response.status);
}).catch(e=>{
reject(e);
})
}
});
generateInteractionModel: function(skill){
try{
let result = {};
let allIntents = [];
let defaultIntents = [{
name: "AMAZON.CancelIntent",
samples: []
},
{
name: "AMAZON.HelpIntent",
samples: []
},
{
name: "AMAZON.StopIntent",
samples: []
}];
/*
defaultIntents.map(intent=>{
allIntents.push(intent);
});
*/
skill.intents.map(intent=>{
allIntents.push({name: intent.intentName, samples: intent.questions});
});
result.interactionModel = {};
result.interactionModel.languageModel = {
invocationName: skill.invocationName,
intents: allIntents
};
return JSON.stringify(result);
}catch(e){
console.log("error generate : " + e);
}
}
};

View File

@@ -1,27 +0,0 @@
const config = require('../config');
var db = null;
module.exports = {
initModule : function(databaseObject){
db=databaseObject;
},
loadTokens : function(){
db.collection('token_list').findOne().then(tokens=>{
if (tokens !== null){
config.TOKEN = tokens.access_token;
config.REFRESH_TOKEN = tokens.refresh_token;
config.TOKEN_EXPIRES_IN = tokens.expires_in;
}else{
//Cannot continue without tokens
console.log("Cannot continue without tokens in database");
process.exit(-1);
}
}).catch(e=>{
console.log("Error loading tokens ! Cannot continue without tokens in database");
process.exit(-1);
})
}
}

View File

@@ -1,19 +0,0 @@
const config = require('../config');
var ObjectID = require ('mongodb').ObjectID;
module.exports = {
updateTokens : function (refresh_token, access_token, expires_in, db){
let newTokenDocument = {
id:1,
refresh_token:refresh_token,
access_token: access_token,
expires_in: (new Date() / 1000) + expires_in
}
let result = db.collection('token_list').update({id:1}, newTokenDocument,{upsert:true}, (err, result)=>{
if (err) throw new Error(err);
config.REFRESH_TOKEN = refresh_token;
config.TOKEN = access_token;
config.TOKEN_EXPIRES_IN = newTokenDocument.expires_in;
});
}
};

View File

@@ -6,11 +6,9 @@
"dependencies": {
"alexa-app": "4.2.0",
"body-parser": "^1.13.1",
"ejs": "^2.5.7",
"ejs": "^2.3.1",
"express": "^4.13.0",
"isomorphic-fetch": "^2.2.1",
"mongodb": "^2.2.33",
"request": "^2.83.0"
"isomorphic-fetch": "^2.2.1"
},
"author": "Matt Kruse <github@mattkruse.com> (http://mattkruse.com/)",
"license": "MIT"

View File

@@ -1,10 +0,0 @@
<div style="white-space:pre;border:1px solid black;margin:5px;padding:5px;font-family:monospace;">
Schema:
<%=schema%>
Utterances:
<%=utterances%>
</div>

File diff suppressed because it is too large Load Diff

View File

@@ -3,11 +3,9 @@
"version": "0.1.0",
"private": true,
"dependencies": {
"keymaster": "^1.6.2",
"react": "^16.2.0",
"react-dom": "^16.2.0",
"react-md": "^1.2.8",
"react-popup": "^0.9.1",
"react-scripts": "1.0.17",
"webfontloader": "^1.6.28"
},

View File

@@ -1,10 +1,8 @@
import React, { Component } from 'react';
import './css/App.css';
import './css/popup.css';
import IntentList from './components/IntentList';
import IntentDetails from './components/IntentDetails';
import LaunchRequest from './components/LaunchRequest';
import Popup from 'react-popup';
import {getSkill, updateSkill} from './lib/api'
@@ -44,7 +42,6 @@ class App extends Component {
if(this.state.launchRequest){
return (
<div className="App">
<Popup/>
<div className="App-header">
<h1> Tell All </h1>
</div>
@@ -62,7 +59,6 @@ class App extends Component {
}else{
return (
<div className="App">
<Popup/>
<div className="App-header">
<h1> Tell All </h1>
</div>
@@ -101,19 +97,16 @@ class App extends Component {
handleSaveLaunchRequestClick(name, answer){
this.setState({invocationName: name, invocationAnswer: answer});
console.log("handleSaveLaunchRequest");
try{
updateSkill(this.createSkill(this.state.allIntents,name,answer)).then(l=>l.text()).then(result=>{
let jResult = JSON.parse(result);
if (jResult.result !== 0){
Popup.alert('Model was not saved. Please try again');
}else{
Popup.alert('Saved');
if (!(jResult.databaseUpdate && jResult.amazonUpdate)){
alert('Database update : ' + jResult.databaseUpdate + '\r\nAmazon update : ' + jResult.amazonUpdate + '\r\nMessage : ' + jResult.amazonMessage);
}
console.log(jResult.message);
}).catch(e=>{
console.log("Error :" + e);
Popup.alert('Model was not saved. Please try again');
});
}catch(e){
alert("exception");
}
}
handleDeleteIntentClick(selectedIntent){
@@ -127,18 +120,12 @@ class App extends Component {
this.setState({allIntents: newAllIntents, selectedIntent: {intentName:'', questions:[''],answer:''}});
updateSkill(this.createSkill(newAllIntents)).then(l=>l.text()).then(result=>{
let jResult = JSON.parse(result);
if (jResult.result !== 0){
Popup.alert('Model was not saved. Please try again');
}else{
Popup.alert('Saved');
if (!(jResult.databaseUpdate && jResult.amazonUpdate)){
alert('Database update : ' + jResult.databaseUpdate + '\r\nAmazon update : ' + jResult.amazonUpdate + '\r\nMessage : ' + jResult.amazonMessage);
}
console.log(jResult.message);
}).catch(e=>{
console.log("error : " + e);
Popup.alert('Model was not saved. Please try again');
});
}catch(e){
console.log("error : " + e);
alert("exception");
}
}
}
@@ -154,20 +141,16 @@ class App extends Component {
newAllIntents[this.state.selectedIndex] = selectedIntent;
this.setState({allIntents: newAllIntents, selectedIntent: selectedIntent});
}
updateSkill(this.createSkill(newAllIntents)).then(l=>l.text()).then(result=>{
let jResult = JSON.parse(result);
if (jResult.result !== 0){
Popup.alert('Model was not saved. Please try again');
}else{
Popup.alert('Saved');
}
console.log(jResult.message);
}).catch(e=>{
Popup.alert('Model was not saved. Please try again');
console.log("error : " + e);
});
try{
updateSkill(this.createSkill(newAllIntents)).then(l=>l.text()).then(result=>{
let jResult = JSON.parse(result);
if (!(jResult.databaseUpdate && jResult.amazonUpdate)){
alert('Database update : ' + jResult.databaseUpdate + '\r\nAmazon update : ' + jResult.amazonUpdate + '\r\nMessage : ' + jResult.amazonMessage);
}
});
}catch(e){
alert("exception");
}
}
handleAddIntentClick(){

View File

@@ -1,205 +0,0 @@
.mm-popup {
display: none;
}
.mm-popup--visible {
display: block;
}
.mm-popup__overlay {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 1000;
overflow: auto;
background: rgba(0, 0, 0, .1);
}
.mm-popup__close {
position: absolute;
top: 15px;
right: 20px;
padding: 0;
width: 20px;
height: 20px;
cursor: pointer;
outline: none;
text-align: center;
border-radius: 10px;
border: none;
text-indent: -9999px;
background: transparent url('data:image/png;base64,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') no-repeat center center;
background-size: 100%;
margin: 0;
}
.mm-popup__input {
display: block;
width: 100%;
height: 30px;
border-radius: 3px;
background: #f5f5f5;
border: 1px solid #e9ebec;
outline: none;
-moz-box-sizing: border-box !important;
-webkit-box-sizing: border-box !important;
box-sizing: border-box !important;
font-size: 14px;
padding: 0 12px;
color: #808080;
}
.mm-popup__btn {
border-radius: 3px;
-moz-box-sizing: border-box;
-webkit-box-sizing: border-box;
box-sizing: border-box;
padding: 0 10px;
margin: 0;
line-height: 32px;
height: 32px;
border: 1px solid #666;
text-align: center;
display: inline-block;
font-size: 12px;
font-weight: 400;
color: #333;
background: transparent;
outline: none;
text-decoration: none;
cursor: pointer;
font-family: "Open Sans", sans-serif;
}
.mm-popup__btn--success {
background-color: #27ae60;
border-color: #27ae60;
color: #fff;
}
.mm-popup__btn--danger {
background-color: #c5545c;
border-color: #c5545c;
color: #fff;
}
.mm-popup__box {
width: 350px;
position: fixed;
top: 10%;
left: 50%;
margin-left: -175px;
background: #fff;
box-shadow: 0px 5px 20px 0px rgba(126,137,140,0.20);
border-radius: 5px;
border: 1px solid #B8C8CC;
overflow: hidden;
z-index: 1001;
}
.mm-popup__box__header {
padding: 15px 20px;
background: #EDF5F7;
color: #454B4D;
}
.mm-popup__box__header__title {
margin: 0;
font-size: 16px;
text-align: left;
font-weight: 600;
}
.mm-popup__box__body {
padding: 20px;
line-height: 1.4;
font-size: 14px;
color: #454B4D;
background: #fff;
position: relative;
z-index: 2;
}
.mm-popup__box__body p {
margin: 0 0 5px;
}
.mm-popup__box__footer {
overflow: hidden;
padding: 40px 20px 20px;
}
.mm-popup__box__footer__right-space {
float: right;
}
.mm-popup__box__footer__right-space .mm-popup__btn {
margin-left: 5px;
}
.mm-popup__box__footer__left-space {
float: left;
}
.mm-popup__box__footer__left-space .mm-popup__btn {
margin-right: 5px;
}
.mm-popup__box--popover {
width: 300px;
margin-left: -150px;
}
.mm-popup__box--popover .mm-popup__close {
position: absolute;
top: 5px;
right: 5px;
padding: 0;
width: 20px;
height: 20px;
cursor: pointer;
outline: none;
text-align: center;
border-radius: 10px;
border: none;
text-indent: -9999px;
background: transparent url('data:image/png;base64,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') no-repeat center center;
background-size: 100%;
margin: 0;
z-index: 3;
}
.mm-popup__box--popover .mm-popup__box__body {
padding: 20px;
}
@media (max-width: 420px) {
.mm-popup__box {
width: auto;
left: 10px;
right: 10px;
top: 10px;
margin-left: 0;
}
.mm-popup__box__footer__left-space {
float: none;
}
.mm-popup__box__footer__right-space {
float: none;
}
.mm-popup__box__footer {
padding-top: 30px;
}
.mm-popup__box__footer .mm-popup__btn {
display: block;
width: 100%;
text-align: center;
margin-top: 10px;
}
}